mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 20:52:15 -08:00
Merge pull request #15847 from NebelKreis/feature/hardware-label-generation-api
Some checks are pending
Crowdin Action / upload-sources-to-crowdin (push) Waiting to run
Docker images (Alpine) / docker (push) Waiting to run
Docker images / docker (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.1) (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.2) (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.3) (push) Waiting to run
Tests in SQLite / PHP ${{ matrix.php-version }} (8.1.1) (push) Waiting to run
Some checks are pending
Crowdin Action / upload-sources-to-crowdin (push) Waiting to run
Docker images (Alpine) / docker (push) Waiting to run
Docker images / docker (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.1) (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.2) (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.3) (push) Waiting to run
Tests in SQLite / PHP ${{ matrix.php-version }} (8.1.1) (push) Waiting to run
Added #15677: API Route for Generating Asset Labels
This commit is contained in:
commit
8cd4b3303e
|
@ -33,6 +33,8 @@ use Illuminate\Http\Request;
|
|||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\View\Label;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -126,8 +128,19 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo', 'adminuser','model.depreciation',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
|
||||
->with(
|
||||
'location',
|
||||
'assetstatus',
|
||||
'company',
|
||||
'defaultLoc',
|
||||
'assignedTo',
|
||||
'adminuser',
|
||||
'model.depreciation',
|
||||
'model.category',
|
||||
'model.manufacturer',
|
||||
'model.fieldset',
|
||||
'supplier'
|
||||
); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
|
||||
|
||||
|
||||
if ($filter_non_deprecable_assets) {
|
||||
|
@ -265,7 +278,6 @@ class AssetsController extends Controller
|
|||
$join->on('status_alias.id', '=', 'assets.status_id');
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,7 +411,6 @@ class AssetsController extends Controller
|
|||
} else {
|
||||
$assets->orderBy($sort_override, $order);
|
||||
}
|
||||
|
||||
} else {
|
||||
$assets->orderBy($column_sort, $order);
|
||||
}
|
||||
|
@ -463,12 +474,10 @@ class AssetsController extends Controller
|
|||
} else {
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If there are 0 results, return the "no such asset" response
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -495,7 +504,6 @@ class AssetsController extends Controller
|
|||
|
||||
// If there are 0 results, return the "no such asset" response
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -510,13 +518,13 @@ class AssetsController extends Controller
|
|||
{
|
||||
if ($asset = Asset::with('assetstatus')
|
||||
->with('assignedTo')->withTrashed()
|
||||
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->find($id)) {
|
||||
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->find($id)
|
||||
) {
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
return (new AssetsTransformer)->transformAsset($asset, $request->input('components'));
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
|
||||
}
|
||||
|
||||
public function licenses(Request $request, $id): array
|
||||
|
@ -827,7 +835,6 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -875,14 +882,12 @@ class AssetsController extends Controller
|
|||
$asset->location_id = ($target) ? $target->id : '';
|
||||
$error_payload['target_id'] = $request->input('assigned_location');
|
||||
$error_payload['target_type'] = 'location';
|
||||
|
||||
} elseif (request('checkout_to_type') == 'asset') {
|
||||
$target = Asset::where('id', '!=', $asset_id)->find(request('assigned_asset'));
|
||||
// Override with the asset's location_id if it has one
|
||||
$asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : '';
|
||||
$error_payload['target_id'] = $request->input('assigned_asset');
|
||||
$error_payload['target_type'] = 'asset';
|
||||
|
||||
} elseif (request('checkout_to_type') == 'user') {
|
||||
// Fetch the target and set the asset's new location_id
|
||||
$target = User::find(request('assigned_user'));
|
||||
|
@ -987,7 +992,8 @@ class AssetsController extends Controller
|
|||
[Asset::class],
|
||||
function (Builder $query) use ($asset) {
|
||||
$query->where('id', $asset->id);
|
||||
})
|
||||
}
|
||||
)
|
||||
->get()
|
||||
->map(function ($acceptance) {
|
||||
$acceptance->delete();
|
||||
|
@ -1108,7 +1114,6 @@ class AssetsController extends Controller
|
|||
'asset_tag' => e($asset->asset_tag),
|
||||
'error' => $asset->getErrors()->first(),
|
||||
], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1117,8 +1122,6 @@ class AssetsController extends Controller
|
|||
'asset_tag' => e($request->input('asset_tag')),
|
||||
'error' => trans('admin/hardware/message.audit.error'),
|
||||
], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1150,8 +1153,18 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests');
|
||||
->with(
|
||||
'location',
|
||||
'assetstatus',
|
||||
'assetlog',
|
||||
'company',
|
||||
'assignedTo',
|
||||
'model.category',
|
||||
'model.manufacturer',
|
||||
'model.fieldset',
|
||||
'supplier',
|
||||
'requests'
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
@ -1200,4 +1213,89 @@ class AssetsController extends Controller
|
|||
|
||||
return (new AssetsTransformer)->transformRequestedAssets($assets, $total);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate asset labels by tag
|
||||
*
|
||||
* @author [Nebelkreis] [https://github.com/NebelKreis]
|
||||
*
|
||||
* @param Request $request Contains asset_tags array of asset tags to generate labels for
|
||||
* @return JsonResponse Returns base64 encoded PDF on success, error message on failure
|
||||
*/
|
||||
public function getLabels(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
// Validate that asset tags were provided in the request
|
||||
if (!$request->filled('asset_tags')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null,
|
||||
trans('admin/hardware/message.no_assets_selected')), 400);
|
||||
}
|
||||
|
||||
// Convert asset tags from request into collection and fetch matching assets
|
||||
$asset_tags = collect($request->input('asset_tags'));
|
||||
$assets = Asset::whereIn('asset_tag', $asset_tags)->get();
|
||||
|
||||
// Return error if no assets were found for the provided tags
|
||||
if ($assets->isEmpty()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null,
|
||||
trans('admin/hardware/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
try {
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
// Check if logo file exists in storage and disable logo if not found
|
||||
// This prevents errors when trying to include a non-existent logo in the PDF
|
||||
$settings->label_logo = ($original_logo = $settings->label_logo) && !Storage::disk('public')->exists('/' . $original_logo) ? null : $settings->label_logo;
|
||||
|
||||
|
||||
$label = new Label();
|
||||
|
||||
if (!$label) {
|
||||
throw new \Exception('Label object could not be created');
|
||||
}
|
||||
|
||||
// Configure label with assets and settings
|
||||
// bulkedit=false and count=0 are default values for label generation
|
||||
$label = $label->with('assets', $assets)
|
||||
->with('settings', $settings)
|
||||
->with('bulkedit', false)
|
||||
->with('count', 0);
|
||||
|
||||
// Generate PDF using callback function
|
||||
// The callback captures the PDF content in $pdf_content variable
|
||||
$pdf_content = '';
|
||||
$label->render(function($pdf) use (&$pdf_content) {
|
||||
$pdf_content = $pdf->Output('', 'S');
|
||||
return $pdf;
|
||||
});
|
||||
|
||||
// Verify PDF was generated successfully
|
||||
if (empty($pdf_content)) {
|
||||
throw new \Exception('PDF content is empty');
|
||||
}
|
||||
|
||||
$encoded_content = base64_encode($pdf_content);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', [
|
||||
'pdf' => $encoded_content
|
||||
], trans('admin/hardware/message.labels_generated')));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||
'error_message' => $e->getMessage(),
|
||||
'error_line' => $e->getLine(),
|
||||
'error_file' => $e->getFile()
|
||||
], trans('admin/hardware/message.error_generating_labels')), 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||
'error_message' => $e->getMessage(),
|
||||
'error_line' => $e->getLine(),
|
||||
'error_file' => $e->getFile()
|
||||
], $e->getMessage()), 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ return [
|
|||
'does_not_exist_or_not_requestable' => 'That asset does not exist or is not requestable.',
|
||||
'assoc_users' => 'This asset is currently checked out to a user and cannot be deleted. Please check the asset in first, and then try deleting again. ',
|
||||
'warning_audit_date_mismatch' => 'This asset\'s next audit date (:next_audit_date) is before the last audit date (:last_audit_date). Please update the next audit date.',
|
||||
'labels_generated' => 'Labels were successfully generated.',
|
||||
'error_generating_labels' => 'Error while generating labels.',
|
||||
'no_assets_selected' => 'No assets selected.',
|
||||
|
||||
'create' => [
|
||||
'error' => 'Asset was not created, please try again. :(',
|
||||
|
|
|
@ -1282,4 +1282,14 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi
|
|||
], 404);
|
||||
}); // end fallback routes
|
||||
|
||||
/**
|
||||
* Generate label routes
|
||||
*/
|
||||
Route::post('hardware/labels', [
|
||||
Api\AssetsController::class,
|
||||
'getLabels'
|
||||
])->name('api.assets.labels');
|
||||
// end generate label routes
|
||||
|
||||
|
||||
}); // end API routes
|
||||
|
|
Loading…
Reference in a new issue