Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - Improve assets bulk checkin/checkout #15479

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ tests/coverage/*
/storage/oauth-public.key
logs/*
*.cache
*.swp

.vagrant
*.log
Expand All @@ -70,4 +71,4 @@ storage/ldap_client_tls.cert
storage/ldap_client_tls.key
/storage/framework/testing

/.phpunit.cache
/.phpunit.cache
85 changes: 62 additions & 23 deletions app/Http/Controllers/Api/AssetsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class AssetsController extends Controller
* @param int $assetId
* @since [v4.0]
*/
public function index(Request $request, $action = null, $upcoming_status = null) : JsonResponse | array
public function index(Request $request, $action = null, $upcoming_status = null): JsonResponse | array
{


Expand Down Expand Up @@ -562,6 +562,10 @@ public function selectlist(Request $request): array
$assets = $assets->RTD();
}

if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'Deployed') {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already handle this case here I think.

status has a switch case for Deployed on line 239

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure to get the point, as index() and selectlist() functions are not calling each other. Or perhaps that's your point? Calling index() from selectlist()?

$assets = $assets->Deployed();
}

if ($request->filled('search')) {
$assets = $assets->AssignedSearch($request->input('search'));
}
Expand All @@ -587,6 +591,10 @@ public function selectlist(Request $request): array
}

$asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null;

// Include checkability of the asset
$asset->user_can_checkout = ($asset->availableForCheckout()) ? $asset->availableForCheckout() : null;
$asset->assigned_to = ($asset->assigned_to) ? $asset->assigned_to : null;
}

return (new SelectlistTransformer)->transformSelectlist($assets);
Expand Down Expand Up @@ -844,12 +852,19 @@ public function restore(Request $request, $assetId = null): JsonResponse
* @param string $tag
* @since [v6.0.5]
*/
public function checkoutByTag(AssetCheckoutRequest $request, $tag): JsonResponse
public function checkoutByTag(AssetCheckoutRequest $request, $tag = null): JsonResponse
{
if ($asset = Asset::where('asset_tag', $tag)->first()) {
$this->authorize('checkout', Asset::class);
if(null == $tag && null !== ($request->input('asset_tag'))) {
$tag = $request->input('asset_tag');
}
$asset = Asset::where('asset_tag', $tag)->first();

if ($asset) {
return $this->checkout($request, $asset->id);
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);

return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag' => e($tag)], 'Asset with tag '.e($tag).' not found'));
}

/**
Expand All @@ -859,23 +874,34 @@ public function checkoutByTag(AssetCheckoutRequest $request, $tag): JsonResponse
* @param int $assetId
* @since [v4.0]
*/
public function checkout(AssetCheckoutRequest $request, $asset_id): JsonResponse
public function checkout(AssetCheckoutRequest $request, $asset_id = null): JsonResponse
{
$this->authorize('checkout', Asset::class);

// If api call, get value from the request
if(null == $asset_id && null !== ($request->input('asset_id'))) {
$asset_id = $request->input('asset_id');
}
$asset = Asset::findOrFail($asset_id);

// payload with asset attributes
$payload = [
'id' => e($asset->id),
'asset_tag'=> e($asset->asset_tag),
'name'=> e($asset->name),
'model' => e($asset->model->name),
'model_number' => e($asset->model->model_number)
];

// errors payload
$error_payload = [];

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', $payload, trans('admin/hardware/message.checkout.not_available')));
}

$this->authorize('checkout', $asset);

$error_payload = [];
$error_payload['asset'] = [
'id' => $asset->id,
'asset_tag' => $asset->asset_tag,
];

// This item is checked out to a location
if (request('checkout_to_type') == 'location') {
$target = Location::find(request('assigned_location'));
Expand All @@ -901,7 +927,7 @@ public function checkout(AssetCheckoutRequest $request, $asset_id): JsonResponse
}

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', $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'));
Expand All @@ -920,10 +946,10 @@ public function checkout(AssetCheckoutRequest $request, $asset_id): JsonResponse
// }

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', $payload, 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', $payload, trans('admin/hardware/message.checkout.error')));
}


Expand All @@ -934,18 +960,28 @@ public function checkout(AssetCheckoutRequest $request, $asset_id): JsonResponse
* @param int $assetId
* @since [v4.0]
*/
public function checkin(Request $request, $asset_id): JsonResponse
public function checkin(Request $request, $asset_id = null): JsonResponse
{
$this->authorize('checkin', Asset::class);

if(null == $asset_id && null !== ($request->input('asset_id'))) {
$asset_id = $request->input('asset_id');
}
$asset = Asset::with('model')->findOrFail($asset_id);
$this->authorize('checkin', $asset);

// payload with asset attributes
$payload = [
'id'=> e($asset->id),
'asset_tag'=> e($asset->asset_tag),
'name'=> e($asset->name),
'model' => e($asset->model->name),
'model_number' => e($asset->model->model_number)
];

$target = $asset->assignedTo;
if (is_null($target)) {
return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag' => e($asset->asset_tag),
'model' => e($asset->model->name),
'model_number' => e($asset->model->model_number)
], trans('admin/hardware/message.checkin.already_checked_in')));
return response()->json(Helper::formatStandardApiResponse('error', $payload, trans('admin/hardware/message.checkin.already_checked_in')));
}

$asset->expected_checkin = null;
Expand Down Expand Up @@ -974,11 +1010,13 @@ public function checkin(Request $request, $asset_id): JsonResponse
$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');
$originalValues = $asset->getRawOriginal();

if (($request->filled('checkin_at')) && ($request->get('checkin_at') != date('Y-m-d'))) {
// Fixed non-matching condition for bulk-checkin
$checkin_at = date('Y-m-d H:i:s');
if (($request->filled('checkin_at')) && ($request->input('checkin_at') != date('Y-m-d'))) {
$originalValues['action_date'] = $checkin_at;
$checkin_at = $request->input('checkin_at');
}

$asset->licenseseats->each(function (LicenseSeat $seat) {
Expand All @@ -1004,6 +1042,7 @@ function (Builder $query) use ($asset) {

return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag' => e($asset->asset_tag),
'name' => e($asset->name),
'model' => e($asset->model->name),
'model_number' => e($asset->model->model_number)
], trans('admin/hardware/message.checkin.success')));
Expand Down
21 changes: 16 additions & 5 deletions app/Http/Controllers/Assets/BulkAssetsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ public function edit(Request $request) : View | RedirectResponse
}

$asset_ids = $request->input('ids');
if ($request->input('bulk_actions') === 'checkout') {
$request->session()->flashInput(['selected_assets' => $asset_ids]);
return redirect()->route('hardware.bulkcheckout.show');
}

// Figure out where we need to send the user after the update is complete, and store that in the session
$bulk_back_url = request()->headers->get('referer');
Expand Down Expand Up @@ -151,6 +147,20 @@ public function edit(Request $request) : View | RedirectResponse
->with('statuslabel_list', Helper::statusLabelList())
->with('models', $models->pluck(['model']))
->with('modelNames', $modelNames);

case 'checkin':
$this->authorize('checkin', Asset::class);

return view('hardware/quickscan-checkin')
->with('assets', $assets)
->with('statusLabel_list', Helper::statusLabelList());

case 'checkout':
$this->authorize('checkout', Asset::class);

return view('hardware/bulk-checkout')
->with('assets', $assets)
->with('statusLabel_list', Helper::deployableStatusLabelList());
}
}

Expand All @@ -172,6 +182,7 @@ public function edit(Request $request) : View | RedirectResponse
break;
case 'location':
$assets->OrderLocation($order);
break;
case 'rtd_location':
$assets->OrderRtdLocation($order);
break;
Expand Down Expand Up @@ -618,7 +629,7 @@ public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse
// Redirect to the asset management page with error
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors);
} catch (ModelNotFoundException $e) {
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
return redirect()->route('hardware.bulkcheckout.show')->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid'));
}

}
Expand Down
9 changes: 8 additions & 1 deletion app/Http/Transformers/SelectlistTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@ public function transformSelectlist(LengthAwarePaginator $select_items)
foreach ($select_items as $select_item) {
$items_array[] = [
'id' => (int) $select_item->id,
'name' => ($select_item->name) ? $select_item->name : null,
'text' => ($select_item->use_text) ? $select_item->use_text : $select_item->name,
'image' => ($select_item->use_image) ? $select_item->use_image : null,

// checkability of the asset
'user_can_checkout' => ($select_item->user_can_checkout) ? $select_item->user_can_checkout : null,
'assigned_to' => ($select_item->assigned_to) ? $select_item->assigned_to : null,
// other useful attributes
'asset_tag' => ($select_item->asset_tag) ? $select_item->asset_tag : null,
'model' => ($select_item->model && $select_item->model->name) ? $select_item->model->name : null,
'model_number' => ($select_item->model && $select_item->model->model_number) ? $select_item->model->model_number : null
];
}

Expand Down
2 changes: 1 addition & 1 deletion app/Models/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,7 @@ public function scopeArchived($query)

public function scopeDeployed($query)
{
return $query->where('assigned_to', '>', '0');
return $query->whereNotNull('assets.assigned_to');
}

/**
Expand Down
3 changes: 2 additions & 1 deletion app/Models/Loggable.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ public function logCheckin($target, $note, $action_date = null, $originalValues
if ($key == 'action_date' && $value != $action_date) {
$changed[$key]['old'] = $value;
$changed[$key]['new'] = is_string($action_date) ? $action_date : $action_date->format('Y-m-d H:i:s');
} elseif ($value != $this->getAttributes()[$key]) {
// Make sure the key exists to prevent php error
} elseif (array_key_exists($key, $this->getAttributes()) && $value != $this->getAttributes()[$key]) {
$changed[$key]['old'] = $value;
$changed[$key]['new'] = $this->getAttributes()[$key];
}
Expand Down
Loading
Loading