] * @internal param int $assetId * @since [v2.0] */ public function edit(Request $request) : View | RedirectResponse { $this->authorize('view', Asset::class); /** * No asset IDs were passed */ if (! $request->filled('ids')) { return redirect()->back()->with('error', trans('admin/hardware/message.update.no_assets_selected')); } $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'); session(['bulk_back_url' => $bulk_back_url]); $allowed_columns = [ 'id', 'name', 'asset_tag', 'serial', 'model_number', 'last_checkout', 'notes', 'expected_checkin', 'order_number', 'image', 'assigned_to', 'created_at', 'updated_at', 'purchase_date', 'purchase_cost', 'last_audit_date', 'next_audit_date', 'warranty_months', 'checkout_counter', 'checkin_counter', 'requests_counter', 'byod', 'asset_eol_date', ]; /** * Make sure the column is allowed, and if it's a custom field, make sure we strip the custom_fields. prefix */ $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; $sort_override = str_replace('custom_fields.', '', $request->input('sort')); // This handles all of the pivot sorting below (versus the assets.* fields in the allowed_columns array) $column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.id'; $assets = Asset::with('assignedTo', 'location', 'model') ->whereIn('assets.id', $asset_ids) ->withTrashed(); $assets = $assets->get(); if ($assets->isEmpty()) { Log::debug('No assets were found for the provided IDs', ['ids' => $asset_ids]); return redirect()->back()->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid')); } $models = $assets->unique('model_id'); $modelNames = []; foreach($models as $model) { $modelNames[] = $model->model->name; } if ($request->filled('bulk_actions')) { switch ($request->input('bulk_actions')) { case 'labels': $this->authorize('view', Asset::class); return (new Label) ->with('assets', $assets) ->with('settings', Setting::getSettings()) ->with('bulkedit', true) ->with('count', 0); case 'delete': $this->authorize('delete', Asset::class); $assets->each(function ($assets) { $this->authorize('delete', $assets); }); return view('hardware/bulk-delete')->with('assets', $assets); case 'restore': $this->authorize('update', Asset::class); $assets = Asset::withTrashed()->find($asset_ids); $assets->each(function ($asset) { $this->authorize('delete', $asset); }); return view('hardware/bulk-restore')->with('assets', $assets); case 'edit': $this->authorize('update', Asset::class); return view('hardware/bulk') ->with('assets', $asset_ids) ->with('statuslabel_list', Helper::statusLabelList()) ->with('models', $models->pluck(['model'])) ->with('modelNames', $modelNames); } } switch ($sort_override) { case 'model': $assets->OrderModels($order); break; case 'model_number': $assets->OrderModelNumber($order); break; case 'category': $assets->OrderCategory($order); break; case 'manufacturer': $assets->OrderManufacturer($order); break; case 'company': $assets->OrderCompany($order); break; case 'location': $assets->OrderLocation($order); case 'rtd_location': $assets->OrderRtdLocation($order); break; case 'status_label': $assets->OrderStatus($order); break; case 'supplier': $assets->OrderSupplier($order); break; case 'assigned_to': $assets->OrderAssigned($order); break; default: $assets->orderBy($column_sort, $order); break; } return redirect()->back()->with('error', 'No action selected'); } /** * Save bulk edits * * @author [A. Gianotto] [] * @internal param array $assets * @since [v2.0] */ public function update(ImageUploadRequest $request): RedirectResponse { // this should be in request, but request weird, need to think it through a little $this->authorize('update', Asset::class); // Get the back url from the session and then destroy the session $bulk_back_url = route('hardware.index'); // is this necessary? if (!$request->filled('ids') || count($request->input('ids')) == 0) { return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.update.no_assets_selected')); } if ($request->session()->has('bulk_back_url')) { $bulk_back_url = $request->session()->pull('bulk_back_url'); } // find and update assets $assets = Asset::whereIn('id', $request->input('ids'))->get(); $errors = []; foreach ($assets as $key => $asset) { try { $updatedAsset = UpdateAssetAction::run( asset: $asset, request: $request, status_id: $request->input('status_id'), warranty_months: $request->input('warranty_months'), purchase_cost: $request->input('purchase_cost'), purchase_date: $request->filled('null_purchase_date') ? null : $request->input('purchase_date'), next_audit_date: $request->filled('null_next_audit_date') ? null : $request->input('next_audit_date'), supplier_id: $request->input('supplier_id'), expected_checkin: $request->filled('null_expected_checkin_date') ? null : $request->input('expected_checkin'), requestable: $request->input('requestable'), rtd_location_id: $request->input('rtd_location_id'), name: $request->filled('null_name') ? null : $request->input('name'), company_id: $request->input('company_id'), model_id: $request->input('model_id'), order_number: $request->input('order_number'), isBulk: true, ); // catch exceptions } catch (ValidationException $e) { $errors[$key] = $e->getMessage(); } catch (\Exception $e) { report($e); $errors[$key] = trans('general.something_went_wrong'); } } if (!empty($errors)) { return redirect($bulk_back_url)->with('bulk_asset_errors', $errors); } return redirect($bulk_back_url)->with('success', trans('bulk.update.success')); } /** * Array to store update data per item * @var array */ private $update_array; /** * Adds parameter to update array for an item if it exists in request * @param string $field field name */ protected function conditionallyAddItem($field) : BulkAssetsController { if (request()->filled($field)) { $this->update_array[$field] = request()->input($field); } return $this; } /** * Save bulk deleted. * * @author [A. Gianotto] [] * @param Request $request * @internal param array $assets * @since [v2.0] */ public function destroy(Request $request) : RedirectResponse { $this->authorize('delete', Asset::class); $bulk_back_url = route('hardware.index'); if ($request->session()->has('bulk_back_url')) { $bulk_back_url = $request->session()->pull('bulk_back_url'); } if ($request->filled('ids')) { $assets = Asset::find($request->get('ids')); foreach ($assets as $asset) { $asset->delete(); } // endforeach return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.delete.success')); // no values given, nothing to update } return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.delete.nothing_updated')); } /** * Show Bulk Checkout Page */ public function showCheckout() : View { $this->authorize('checkout', Asset::class); return view('hardware/bulk-checkout'); } /** * Process Multiple Checkout Request */ public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse | ModelNotFoundException { $this->authorize('checkout', Asset::class); try { $admin = auth()->user(); $target = $this->determineCheckoutTarget(); if (! is_array($request->get('selected_assets'))) { return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans('admin/hardware/message.checkout.no_assets_selected')); } $asset_ids = array_filter($request->get('selected_assets')); if (request('checkout_to_type') == 'asset') { foreach ($asset_ids as $asset_id) { if ($target->id == $asset_id) { return redirect()->back()->with('error', 'You cannot check an asset out to itself.'); } } } $checkout_at = date('Y-m-d H:i:s'); if (($request->filled('checkout_at')) && ($request->get('checkout_at') != date('Y-m-d'))) { $checkout_at = e($request->get('checkout_at')); } $expected_checkin = ''; if ($request->filled('expected_checkin')) { $expected_checkin = e($request->get('expected_checkin')); } $errors = []; DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference! foreach ($asset_ids as $asset_id) { $asset = Asset::findOrFail($asset_id); $this->authorize('checkout', $asset); $checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null); //TODO - I think this logic is duplicated in the checkOut method? if ($target->location_id != '') { $asset->location_id = $target->location_id; // TODO - I don't know why this is being saved without events $asset::withoutEvents(function () use ($asset) { $asset->save(); }); } if (!$checkout_success) { $errors = array_merge_recursive($errors, $asset->getErrors()->toArray()); } } }); if (! $errors) { // Redirect to the new asset page return redirect()->to('hardware')->with('success', trans_choice('admin/hardware/message.multi-checkout.success', $asset_ids)); } // 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()); } } public function restore(Request $request) : RedirectResponse { $this->authorize('update', Asset::class); $assetIds = $request->get('ids'); if (empty($assetIds)) { return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.restore.nothing_updated')); } else { foreach ($assetIds as $key => $assetId) { $asset = Asset::withTrashed()->find($assetId); $asset->restore(); } return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success')); } } }