Feature: Added API endpoint for generating asset labels

This commit is contained in:
NebelKreis 2024-11-19 14:13:05 +01:00
parent 940f1c2ecc
commit 889aff43c2

View file

@ -33,6 +33,8 @@ use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest; use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\View\Label;
use Illuminate\Support\Facades\Storage;
/** /**
@ -80,10 +82,10 @@ class AssetsController extends Controller
$this->authorize('reports.view'); $this->authorize('reports.view');
} else { } else {
$transformer = 'App\Http\Transformers\AssetsTransformer'; $transformer = 'App\Http\Transformers\AssetsTransformer';
$this->authorize('index', Asset::class); $this->authorize('index', Asset::class);
} }
$settings = Setting::getSettings(); $settings = Setting::getSettings();
$allowed_columns = [ $allowed_columns = [
@ -126,8 +128,19 @@ class AssetsController extends Controller
} }
$assets = Asset::select('assets.*') $assets = Asset::select('assets.*')
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo', 'adminuser','model.depreciation', ->with(
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users. '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) { if ($filter_non_deprecable_assets) {
@ -159,8 +172,8 @@ class AssetsController extends Controller
* Handle due and overdue audits and checkin dates * Handle due and overdue audits and checkin dates
*/ */
switch ($action) { switch ($action) {
// Audit (singular) is left over from earlier legacy APIs // Audit (singular) is left over from earlier legacy APIs
case 'audits' : case 'audits':
switch ($upcoming_status) { switch ($upcoming_status) {
case 'due': case 'due':
$assets->DueForAudit($settings); $assets->DueForAudit($settings);
@ -187,7 +200,7 @@ class AssetsController extends Controller
break; break;
} }
break; break;
} }
/** /**
* End handling due and overdue audits and checkin dates * End handling due and overdue audits and checkin dates
@ -265,7 +278,6 @@ class AssetsController extends Controller
$join->on('status_alias.id', '=', 'assets.status_id'); $join->on('status_alias.id', '=', 'assets.status_id');
}); });
} }
} }
@ -345,7 +357,7 @@ class AssetsController extends Controller
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at'; $column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
$order = $request->input('order') === 'asc' ? 'asc' : 'desc'; $order = $request->input('order') === 'asc' ? 'asc' : 'desc';
switch ($sort_override) { switch ($sort_override) {
case 'model': case 'model':
$assets->OrderModels($order); $assets->OrderModels($order);
@ -399,7 +411,6 @@ class AssetsController extends Controller
} else { } else {
$assets->orderBy($sort_override, $order); $assets->orderBy($sort_override, $order);
} }
} else { } else {
$assets->orderBy($column_sort, $order); $assets->orderBy($column_sort, $order);
} }
@ -413,11 +424,11 @@ class AssetsController extends Controller
$total = $assets->count(); $total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get(); $assets = $assets->skip($offset)->take($limit)->get();
/** /**
* Include additional associated relationships * Include additional associated relationships
*/ */
if ($request->input('components')) { if ($request->input('components')) {
$assets->loadMissing(['components' => function ($query) { $assets->loadMissing(['components' => function ($query) {
$query->orderBy('created_at', 'desc'); $query->orderBy('created_at', 'desc');
@ -441,7 +452,7 @@ class AssetsController extends Controller
* @since [v4.2.1] * @since [v4.2.1]
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
*/ */
public function showByTag(Request $request, $tag) : JsonResponse | array public function showByTag(Request $request, $tag): JsonResponse | array
{ {
$this->authorize('index', Asset::class); $this->authorize('index', Asset::class);
$assets = Asset::where('asset_tag', $tag)->with('assetstatus')->with('assignedTo'); $assets = Asset::where('asset_tag', $tag)->with('assetstatus')->with('assignedTo');
@ -463,12 +474,10 @@ class AssetsController extends Controller
} else { } else {
return (new AssetsTransformer)->transformAssets($assets, $assets->count()); return (new AssetsTransformer)->transformAssets($assets, $assets->count());
} }
} }
// If there are 0 results, return the "no such asset" response // 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); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
} }
/** /**
@ -479,7 +488,7 @@ class AssetsController extends Controller
* @since [v4.2.1] * @since [v4.2.1]
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function showBySerial(Request $request, $serial) : JsonResponse | array public function showBySerial(Request $request, $serial): JsonResponse | array
{ {
$this->authorize('index', Asset::class); $this->authorize('index', Asset::class);
$assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo'); $assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo');
@ -488,14 +497,13 @@ class AssetsController extends Controller
if ($request->input('deleted', 'false') == 'true') { if ($request->input('deleted', 'false') == 'true') {
$assets = $assets->withTrashed(); $assets = $assets->withTrashed();
} }
if (($assets = $assets->get()) && ($assets->count()) > 0) { if (($assets = $assets->get()) && ($assets->count()) > 0) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count()); return (new AssetsTransformer)->transformAssets($assets, $assets->count());
} }
// If there are 0 results, return the "no such asset" response // 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); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
} }
/** /**
@ -506,20 +514,20 @@ class AssetsController extends Controller
* @since [v4.0] * @since [v4.0]
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function show(Request $request, $id) : JsonResponse | array public function show(Request $request, $id): JsonResponse | array
{ {
if ($asset = Asset::with('assetstatus') if ($asset = Asset::with('assetstatus')
->with('assignedTo')->withTrashed() ->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); $this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset, $request->input('components') ); return (new AssetsTransformer)->transformAsset($asset, $request->input('components'));
} }
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
} }
public function licenses(Request $request, $id) : array public function licenses(Request $request, $id): array
{ {
$this->authorize('view', Asset::class); $this->authorize('view', Asset::class);
$this->authorize('view', License::class); $this->authorize('view', License::class);
@ -527,7 +535,7 @@ class AssetsController extends Controller
$licenses = $asset->licenses()->get(); $licenses = $asset->licenses()->get();
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count()); return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
} }
/** /**
@ -537,7 +545,7 @@ class AssetsController extends Controller
* @since [v4.0.16] * @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer * @see \App\Http\Transformers\SelectlistTransformer
*/ */
public function selectlist(Request $request) : array public function selectlist(Request $request): array
{ {
$assets = Asset::select([ $assets = Asset::select([
@ -548,7 +556,7 @@ class AssetsController extends Controller
'assets.assigned_to', 'assets.assigned_to',
'assets.assigned_type', 'assets.assigned_type',
'assets.status_id', 'assets.status_id',
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(); ])->with('model', 'assetstatus', 'assignedTo')->NotArchived();
if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') { if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
$assets = $assets->RTD(); $assets = $assets->RTD();
@ -570,12 +578,12 @@ class AssetsController extends Controller
$asset->use_text = $asset->present()->fullName; $asset->use_text = $asset->present()->fullName;
if (($asset->checkedOutToUser()) && ($asset->assigned)) { if (($asset->checkedOutToUser()) && ($asset->assigned)) {
$asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute(); $asset->use_text .= ' → ' . $asset->assigned->getFullNameAttribute();
} }
if ($asset->assetstatus->getStatuslabelType() == 'pending') { if ($asset->assetstatus->getStatuslabelType() == 'pending') {
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')'; $asset->use_text .= '(' . $asset->assetstatus->getStatuslabelType() . ')';
} }
$asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null; $asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null;
@ -601,12 +609,12 @@ class AssetsController extends Controller
$asset->created_by = auth()->id(); $asset->created_by = auth()->id();
/** /**
* this is here just legacy reasons. Api\AssetController * this is here just legacy reasons. Api\AssetController
* used image_source once to allow encoded image uploads. * used image_source once to allow encoded image uploads.
*/ */
if ($request->has('image_source')) { if ($request->has('image_source')) {
$request->offsetSet('image', $request->offsetGet('image_source')); $request->offsetSet('image', $request->offsetGet('image_source'));
} }
$asset = $request->handleImages($asset); $asset = $request->handleImages($asset);
@ -623,9 +631,9 @@ class AssetsController extends Controller
// If input value is null, use custom field's default value // If input value is null, use custom field's default value
if ($field_val == null) { if ($field_val == null) {
Log::debug('Field value for '.$field->db_column.' is null'); Log::debug('Field value for ' . $field->db_column . ' is null');
$field_val = $field->defaultValue($request->get('model_id')); $field_val = $field->defaultValue($request->get('model_id'));
Log::debug('Use the default fieldset value of '.$field->defaultValue($request->get('model_id'))); Log::debug('Use the default fieldset value of ' . $field->defaultValue($request->get('model_id')));
} }
// if the field is set to encrypted, make sure we encrypt the value // if the field is set to encrypted, make sure we encrypt the value
@ -643,7 +651,7 @@ class AssetsController extends Controller
} }
} }
if ($field->element == 'checkbox') { if ($field->element == 'checkbox') {
if(is_array($field_val)) { if (is_array($field_val)) {
$field_val = implode(',', $field_val); $field_val = implode(',', $field_val);
} }
} }
@ -702,59 +710,59 @@ class AssetsController extends Controller
} }
/** /**
* this is here just legacy reasons. Api\AssetController * this is here just legacy reasons. Api\AssetController
* used image_source once to allow encoded image uploads. * used image_source once to allow encoded image uploads.
*/ */
if ($request->has('image_source')) { if ($request->has('image_source')) {
$request->offsetSet('image', $request->offsetGet('image_source')); $request->offsetSet('image', $request->offsetGet('image_source'));
} }
$asset = $request->handleImages($asset); $asset = $request->handleImages($asset);
$model = $asset->model; $model = $asset->model;
// Update custom fields
$problems_updating_encrypted_custom_fields = false;
if (($model) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
$field_val = $request->input($field->db_column, null);
if ($request->has($field->db_column)) { // Update custom fields
if ($field->element == 'checkbox') { $problems_updating_encrypted_custom_fields = false;
if(is_array($field_val)) { if (($model) && (isset($model->fieldset))) {
$field_val = implode(',', $field_val); foreach ($model->fieldset->fields as $field) {
} $field_val = $request->input($field->db_column, null);
if ($request->has($field->db_column)) {
if ($field->element == 'checkbox') {
if (is_array($field_val)) {
$field_val = implode(',', $field_val);
} }
if ($field->field_encrypted == '1') {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
$field_val = Crypt::encrypt($field_val);
} else {
$problems_updating_encrypted_custom_fields = true;
continue;
}
}
$asset->{$field->db_column} = $field_val;
} }
if ($field->field_encrypted == '1') {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
$field_val = Crypt::encrypt($field_val);
} else {
$problems_updating_encrypted_custom_fields = true;
continue;
}
}
$asset->{$field->db_column} = $field_val;
} }
} }
if ($asset->save()) { }
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) { if ($asset->save()) {
$location = $target->location_id; if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) { $location = $target->location_id;
$location = $target->location_id; } elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
Asset::where('assigned_type', \App\Models\Asset::class)->where('assigned_to', $asset->id) Asset::where('assigned_type', \App\Models\Asset::class)->where('assigned_to', $asset->id)
->update(['location_id' => $target->location_id]); ->update(['location_id' => $target->location_id]);
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) { } elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
$location = $target->id; $location = $target->id;
} }
if (isset($target)) { if (isset($target)) {
$asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location); $asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
} }
if ($asset->image) { if ($asset->image) {
$asset->image = $asset->getImageUrl(); $asset->image = $asset->getImageUrl();
} }
if ($problems_updating_encrypted_custom_fields) { if ($problems_updating_encrypted_custom_fields) {
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning'))); return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
@ -773,7 +781,7 @@ class AssetsController extends Controller
* @param int $assetId * @param int $assetId
* @since [v4.0] * @since [v4.0]
*/ */
public function destroy($id) : JsonResponse public function destroy($id): JsonResponse
{ {
$this->authorize('delete', Asset::class); $this->authorize('delete', Asset::class);
@ -799,7 +807,7 @@ class AssetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
} }
/** /**
* Restore a soft-deleted asset. * Restore a soft-deleted asset.
@ -808,7 +816,7 @@ class AssetsController extends Controller
* @param int $assetId * @param int $assetId
* @since [v5.1.18] * @since [v5.1.18]
*/ */
public function restore(Request $request, $assetId = null) : JsonResponse public function restore(Request $request, $assetId = null): JsonResponse
{ {
if ($asset = Asset::withTrashed()->find($assetId)) { if ($asset = Asset::withTrashed()->find($assetId)) {
@ -827,7 +835,6 @@ class AssetsController extends Controller
} }
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
} }
/** /**
@ -837,7 +844,7 @@ class AssetsController extends Controller
* @param string $tag * @param string $tag
* @since [v6.0.5] * @since [v6.0.5]
*/ */
public function checkoutByTag(AssetCheckoutRequest $request, $tag) : JsonResponse public function checkoutByTag(AssetCheckoutRequest $request, $tag): JsonResponse
{ {
if ($asset = Asset::where('asset_tag', $tag)->first()) { if ($asset = Asset::where('asset_tag', $tag)->first()) {
return $this->checkout($request, $asset->id); return $this->checkout($request, $asset->id);
@ -852,13 +859,13 @@ class AssetsController extends Controller
* @param int $assetId * @param int $assetId
* @since [v4.0] * @since [v4.0]
*/ */
public function checkout(AssetCheckoutRequest $request, $asset_id) : JsonResponse public function checkout(AssetCheckoutRequest $request, $asset_id): JsonResponse
{ {
$this->authorize('checkout', Asset::class); $this->authorize('checkout', Asset::class);
$asset = Asset::findOrFail($asset_id); $asset = Asset::findOrFail($asset_id);
if (! $asset->availableForCheckout()) { if (! $asset->availableForCheckout()) {
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.not_available'))); return response()->json(Helper::formatStandardApiResponse('error', ['asset' => e($asset->asset_tag)], trans('admin/hardware/message.checkout.not_available')));
} }
$this->authorize('checkout', $asset); $this->authorize('checkout', $asset);
@ -875,14 +882,12 @@ class AssetsController extends Controller
$asset->location_id = ($target) ? $target->id : ''; $asset->location_id = ($target) ? $target->id : '';
$error_payload['target_id'] = $request->input('assigned_location'); $error_payload['target_id'] = $request->input('assigned_location');
$error_payload['target_type'] = 'location'; $error_payload['target_type'] = 'location';
} elseif (request('checkout_to_type') == 'asset') { } elseif (request('checkout_to_type') == 'asset') {
$target = Asset::where('id', '!=', $asset_id)->find(request('assigned_asset')); $target = Asset::where('id', '!=', $asset_id)->find(request('assigned_asset'));
// Override with the asset's location_id if it has one // Override with the asset's location_id if it has one
$asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : ''; $asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : '';
$error_payload['target_id'] = $request->input('assigned_asset'); $error_payload['target_id'] = $request->input('assigned_asset');
$error_payload['target_type'] = 'asset'; $error_payload['target_type'] = 'asset';
} elseif (request('checkout_to_type') == 'user') { } elseif (request('checkout_to_type') == 'user') {
// Fetch the target and set the asset's new location_id // Fetch the target and set the asset's new location_id
$target = User::find(request('assigned_user')); $target = User::find(request('assigned_user'));
@ -896,7 +901,7 @@ class AssetsController extends Controller
} }
if (! isset($target)) { if (! isset($target)) {
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.')); return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset ' . e($asset->asset_tag) . ' is invalid - ' . $error_payload['target_type'] . ' does not exist.'));
} }
$checkout_at = request('checkout_at', date('Y-m-d H:i:s')); $checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
@ -910,15 +915,15 @@ class AssetsController extends Controller
// TODO: Follow up here. WTF. Commented out for now. // TODO: Follow up here. WTF. Commented out for now.
// if ((isset($target->rtd_location_id)) && ($asset->rtd_location_id!='')) { // if ((isset($target->rtd_location_id)) && ($asset->rtd_location_id!='')) {
// $asset->location_id = $target->rtd_location_id; // $asset->location_id = $target->rtd_location_id;
// } // }
if ($asset->checkOut($target, auth()->user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) { if ($asset->checkOut($target, auth()->user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success'))); return response()->json(Helper::formatStandardApiResponse('success', ['asset' => e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
} }
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.error'))); return response()->json(Helper::formatStandardApiResponse('error', ['asset' => e($asset->asset_tag)], trans('admin/hardware/message.checkout.error')));
} }
@ -929,7 +934,7 @@ class AssetsController extends Controller
* @param int $assetId * @param int $assetId
* @since [v4.0] * @since [v4.0]
*/ */
public function checkin(Request $request, $asset_id) : JsonResponse public function checkin(Request $request, $asset_id): JsonResponse
{ {
$asset = Asset::with('model')->findOrFail($asset_id); $asset = Asset::with('model')->findOrFail($asset_id);
$this->authorize('checkin', $asset); $this->authorize('checkin', $asset);
@ -937,7 +942,7 @@ class AssetsController extends Controller
$target = $asset->assignedTo; $target = $asset->assignedTo;
if (is_null($target)) { if (is_null($target)) {
return response()->json(Helper::formatStandardApiResponse('error', [ return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> e($asset->asset_tag), 'asset_tag' => e($asset->asset_tag),
'model' => e($asset->model->name), 'model' => e($asset->model->name),
'model_number' => e($asset->model->model_number) 'model_number' => e($asset->model->model_number)
], trans('admin/hardware/message.checkin.already_checked_in'))); ], trans('admin/hardware/message.checkin.already_checked_in')));
@ -960,7 +965,7 @@ class AssetsController extends Controller
if ($request->filled('location_id')) { if ($request->filled('location_id')) {
$asset->location_id = $request->input('location_id'); $asset->location_id = $request->input('location_id');
if ($request->input('update_default_location')){ if ($request->input('update_default_location')) {
$asset->rtd_location_id = $request->input('location_id'); $asset->rtd_location_id = $request->input('location_id');
} }
} }
@ -968,8 +973,8 @@ class AssetsController extends Controller
if ($request->filled('status_id')) { if ($request->filled('status_id')) {
$asset->status_id = $request->input('status_id'); $asset->status_id = $request->input('status_id');
} }
$checkin_at = $request->filled('checkin_at') ? $request->input('checkin_at').' '. date('H:i:s') : date('Y-m-d H:i:s'); $checkin_at = $request->filled('checkin_at') ? $request->input('checkin_at') . ' ' . date('H:i:s') : date('Y-m-d H:i:s');
$originalValues = $asset->getRawOriginal(); $originalValues = $asset->getRawOriginal();
if (($request->filled('checkin_at')) && ($request->get('checkin_at') != date('Y-m-d'))) { if (($request->filled('checkin_at')) && ($request->get('checkin_at') != date('Y-m-d'))) {
@ -987,7 +992,8 @@ class AssetsController extends Controller
[Asset::class], [Asset::class],
function (Builder $query) use ($asset) { function (Builder $query) use ($asset) {
$query->where('id', $asset->id); $query->where('id', $asset->id);
}) }
)
->get() ->get()
->map(function ($acceptance) { ->map(function ($acceptance) {
$acceptance->delete(); $acceptance->delete();
@ -997,13 +1003,13 @@ class AssetsController extends Controller
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues)); event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
return response()->json(Helper::formatStandardApiResponse('success', [ return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag), 'asset_tag' => e($asset->asset_tag),
'model' => e($asset->model->name), 'model' => e($asset->model->name),
'model_number' => e($asset->model->model_number) 'model_number' => e($asset->model->model_number)
], trans('admin/hardware/message.checkin.success'))); ], trans('admin/hardware/message.checkin.success')));
} }
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error'))); return response()->json(Helper::formatStandardApiResponse('error', ['asset' => e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
} }
/** /**
@ -1012,7 +1018,7 @@ class AssetsController extends Controller
* @author [A. Janes] [<ajanes@adagiohealth.org>] * @author [A. Janes] [<ajanes@adagiohealth.org>]
* @since [v6.0] * @since [v6.0]
*/ */
public function checkinByTag(Request $request, $tag = null) : JsonResponse public function checkinByTag(Request $request, $tag = null): JsonResponse
{ {
$this->authorize('checkin', Asset::class); $this->authorize('checkin', Asset::class);
if (null == $tag && null !== ($request->input('asset_tag'))) { if (null == $tag && null !== ($request->input('asset_tag'))) {
@ -1025,8 +1031,8 @@ class AssetsController extends Controller
} }
return response()->json(Helper::formatStandardApiResponse('error', [ return response()->json(Helper::formatStandardApiResponse('error', [
'asset'=> e($tag) 'asset' => e($tag)
], 'Asset with tag '.e($tag).' not found')); ], 'Asset with tag ' . e($tag) . ' not found'));
} }
@ -1037,7 +1043,7 @@ class AssetsController extends Controller
* @param int $id * @param int $id
* @since [v4.0] * @since [v4.0]
*/ */
public function audit(Request $request) : JsonResponse public function audit(Request $request): JsonResponse
{ {
$this->authorize('audit', Asset::class); $this->authorize('audit', Asset::class);
@ -1048,8 +1054,8 @@ class AssetsController extends Controller
// No tag passed - return an error // No tag passed - return an error
if (!$request->filled('asset_tag')) { if (!$request->filled('asset_tag')) {
return response()->json(Helper::formatStandardApiResponse('error', [ return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> '', 'asset_tag' => '',
'error'=> trans('admin/hardware/message.no_tag'), 'error' => trans('admin/hardware/message.no_tag'),
], trans('admin/hardware/message.no_tag')), 200); ], trans('admin/hardware/message.no_tag')), 200);
} }
@ -1097,28 +1103,25 @@ class AssetsController extends Controller
$asset->logAudit(request('note'), request('location_id')); $asset->logAudit(request('note'), request('location_id'));
return response()->json(Helper::formatStandardApiResponse('success', [ return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag), 'asset_tag' => e($asset->asset_tag),
'note'=> e($request->input('note')), 'note' => e($request->input('note')),
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date), 'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
], trans('admin/hardware/message.audit.success'))); ], trans('admin/hardware/message.audit.success')));
} }
// Asset failed validation or was not able to be saved // Asset failed validation or was not able to be saved
return response()->json(Helper::formatStandardApiResponse('error', [ return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> e($asset->asset_tag), 'asset_tag' => e($asset->asset_tag),
'error'=> $asset->getErrors()->first(), 'error' => $asset->getErrors()->first(),
], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200); ], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200);
} }
// No matching asset for the asset tag that was passed. // No matching asset for the asset tag that was passed.
return response()->json(Helper::formatStandardApiResponse('error', [ return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> e($request->input('asset_tag')), 'asset_tag' => e($request->input('asset_tag')),
'error'=> trans('admin/hardware/message.audit.error'), 'error' => trans('admin/hardware/message.audit.error'),
], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200); ], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200);
} }
@ -1129,7 +1132,7 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0] * @since [v4.0]
*/ */
public function requestable(Request $request) : JsonResponse | array public function requestable(Request $request): JsonResponse | array
{ {
$this->authorize('viewRequestable', Asset::class); $this->authorize('viewRequestable', Asset::class);
@ -1150,8 +1153,18 @@ class AssetsController extends Controller
} }
$assets = Asset::select('assets.*') $assets = Asset::select('assets.*')
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo', ->with(
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests'); 'location',
'assetstatus',
'assetlog',
'company',
'assignedTo',
'model.category',
'model.manufacturer',
'model.fieldset',
'supplier',
'requests'
);
@ -1159,7 +1172,7 @@ class AssetsController extends Controller
if ($request->filled('search')) { if ($request->filled('search')) {
$assets->TextSearch($request->input('search')); $assets->TextSearch($request->input('search'));
} }
// Search custom fields by column name // Search custom fields by column name
foreach ($all_custom_fields as $field) { foreach ($all_custom_fields as $field) {
if ($request->filled($field->db_column_name())) { if ($request->filled($field->db_column_name())) {
@ -1200,4 +1213,95 @@ class AssetsController extends Controller
return (new AssetsTransformer)->transformRequestedAssets($assets, $total); 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,
'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,
'Asset does not exist.'), 404);
}
try {
$settings = Setting::getSettings();
if (!$settings) {
throw new \Exception('Settings could not be loaded');
}
// 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
$original_logo = $settings->label_logo;
if ($original_logo && !Storage::disk('public')->exists('/' . $original_logo)) {
$settings->label_logo = null;
}
$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
], 'Labels were successfully generated.'));
} catch (\Exception $e) {
return response()->json(Helper::formatStandardApiResponse('error', [
'error_message' => $e->getMessage(),
'error_line' => $e->getLine(),
'error_file' => $e->getFile()
], 'Error while 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);
}
}
} }