* * @version v1.0 * * @since [v1.8] */ public function index(FilterRequest $request): JsonResponse|array { $this->authorize('view', Asset::class); $maintenances = Maintenance::select('maintenances.*') ->whereHas('asset') ->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.status', 'adminuser', 'asset.assignedTo', 'maintenanceType', 'responsibleParty', 'completedByUser'); // This invokes the Searchable model trait scopeTextSearch and will handle input by search or by advanced search filter if ($request->filled('filter') || $request->filled('search')) { $maintenances->TextSearch($request->input('filter') ? $request->input('filter') : $request->input('search')); } if ($request->filled('asset_id')) { $maintenances->where('asset_id', '=', $request->input('asset_id')); } if ($request->filled('supplier_id')) { $maintenances->where('maintenances.supplier_id', '=', $request->input('supplier_id')); } if ($request->filled('created_by')) { $maintenances->where('maintenances.created_by', '=', $request->input('created_by')); } if ($request->filled('url')) { $maintenances->where('maintenances.url', '=', $request->input('url')); } if ($request->filled('maintenance_type')) { $maintenances->where('maintenance_type', '=', $request->input('maintenance_type')); } if ($request->filled('maintenance_type_id')) { $maintenances->where('maintenance_type_id', '=', $request->input('maintenance_type_id')); } if ($request->filled('responsible_party_id')) { $maintenances->where('responsible_party_id', '=', $request->input('responsible_party_id')); } if ($request->filled('completed')) { if ($request->input('completed') === 'true') { $maintenances->completed(); } else { $maintenances->active(); } } if ($request->filled('upcoming_status')) { $settings = Setting::getSettings(); switch ($request->input('upcoming_status')) { case 'due': $maintenances->dueForCompletion($settings); break; case 'overdue': $maintenances->overdueForCompletion(); break; case 'due-or-overdue': $maintenances->dueOrOverdueForCompletion($settings); break; } } // Make sure the offset and limit are actually integers and do not exceed system limits $offset = ($request->input('offset') > $maintenances->count()) ? $maintenances->count() : abs($request->input('offset')); $limit = app('api_limit_value'); $allowed_columns = [ 'id', 'name', 'asset_maintenance_time', 'cost', 'start_date', 'completion_date', 'completed_at', 'notes', 'asset_tag', 'asset_name', 'serial', 'created_by', 'supplier', 'location', 'is_warranty', 'status_label', 'model', 'model_number', 'maintenance_type', ]; $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at'; switch ($sort) { case 'created_by': $maintenances = $maintenances->orderByCreatedBy($order); break; case 'supplier': $maintenances = $maintenances->orderBySupplier($order); break; case 'asset_tag': $maintenances = $maintenances->orderByTag($order); break; case 'asset_name': $maintenances = $maintenances->orderByAssetName($order); break; case 'model': $maintenances = $maintenances->orderByAssetModelName($order); break; case 'model_number': $maintenances = $maintenances->orderByAssetModelNumber($order); break; case 'serial': $maintenances = $maintenances->orderByAssetSerial($order); break; case 'location': $maintenances = $maintenances->orderLocationName($order); break; case 'status_label': $maintenances = $maintenances->orderStatusName($order); break; case 'maintenance_type': $maintenances = $maintenances->orderByMaintenanceType($order); break; case 'completed_at': $maintenances = $maintenances->orderByCompletedAt($order); break; default: $maintenances = $maintenances->orderBy($sort, $order); break; } $total = $maintenances->count(); $maintenances = $maintenances->skip($offset)->take($limit)->get(); if (request()->input('format') == 'flat') { return (new MaintenancesTransformer)->transformMaintenancesFlat($maintenances, $total); } return (new MaintenancesTransformer)->transformMaintenances($maintenances, $total); } /** * Validates and stores the new asset maintenance * * @see MaintenancesController::getCreate() method for the form * * @author Vincent Sposato * * @version v1.0 * * @since [v1.8] */ public function store(ImageUploadRequest $request): JsonResponse|array { $this->authorize('update', Asset::class); $isBulk = $request->has('asset_ids'); $assetIds = $isBulk ? array_values(array_filter((array) $request->input('asset_ids'))) : [$request->input('asset_id')]; $created = new EloquentCollection; $errors = []; foreach ($assetIds as $assetId) { $asset = Asset::find($assetId); if (! $asset) { $errors[] = trans('general.item_not_found', ['item_type' => trans('general.asset'), 'id' => $assetId]); continue; } if (! Company::isCurrentUserHasAccess($asset)) { $errors[] = trans('general.action_permission_denied', ['item_type' => trans('general.asset'), 'id' => $assetId, 'action' => trans('general.create')]); continue; } $maintenance = new Maintenance; $maintenance->fill($request->except(['asset_id', 'asset_ids'])); $maintenance->asset_id = $assetId; $maintenance->created_by = auth()->id(); $request->handleImages($maintenance); if ($maintenance->save()) { $created->push($maintenance->fresh()); } else { $errors[] = $maintenance->getErrors(); } } if ($isBulk) { if ($created->isEmpty()) { return response()->json(Helper::formatStandardApiResponse('error', null, count($errors) === 1 ? $errors[0] : $errors)); } return response()->json(Helper::formatStandardApiResponse( 'success', (new MaintenancesTransformer)->transformMaintenances($created, $created->count()), trans('admin/maintenances/message.create.success') )); } // Single asset_id path — backward compatible response shape if ($created->isNotEmpty()) { return response()->json(Helper::formatStandardApiResponse('success', $created->first(), trans('admin/maintenances/message.create.success'))); } return response()->json(Helper::formatStandardApiResponse('error', null, ! empty($errors) ? $errors[0] : null)); } /** * Validates and stores an update to an asset maintenance * * @author A. Gianotto * * @param int $id * @param int $request * * @version v1.0 * * @since [v4.0] */ public function update(Request $request, $id): JsonResponse|array { $this->authorize('update', Asset::class); if ($maintenance = Maintenance::with('asset')->find($id)) { // Can this user manage this asset? if (! Company::isCurrentUserHasAccess($maintenance->asset)) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $id, 'action' => trans('general.edit')]))); } // The asset this miantenance is attached to is not valid or has been deleted if (! $maintenance->asset) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.item_not_found', ['item_type' => trans('general.asset'), 'id' => $id]))); } $maintenance->fill($request->all()); if ($maintenance->save()) { return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.edit.success'))); } return response()->json(Helper::formatStandardApiResponse('error', null, $maintenance->getErrors())); } return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.item_not_found', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $id]))); } /** * Delete an asset maintenance * * @author A. Gianotto * * @param int $maintenanceId * * @version v1.0 * * @since [v4.0] */ public function destroy($maintenanceId): JsonResponse|array { $this->authorize('update', Asset::class); // Check if the asset maintenance exists $maintenance = Maintenance::findOrFail($maintenanceId); $maintenance->delete(); return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.delete.success'))); } /** * View an asset maintenance * * @author A. Gianotto * * @param int $maintenanceId * * @version v1.0 * * @since [v4.0] */ public function show($maintenanceId): JsonResponse|array { $this->authorize('view', Asset::class); $maintenance = Maintenance::findOrFail($maintenanceId); if (! Company::isCurrentUserHasAccess($maintenance->asset)) { return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot view a maintenance for that asset')); } return (new MaintenancesTransformer)->transformMaintenance($maintenance); } public function complete(Request $request, Maintenance $maintenance): JsonResponse { $this->authorize('update', Asset::class); if (! Company::isCurrentUserHasAccess($maintenance->asset)) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $maintenance->id, 'action' => trans('admin/maintenances/form.mark_complete')]))); } if ($maintenance->completed_at) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/maintenances/form.already_complete'))); } $maintenance->completed_at = now(); $maintenance->completed_by = auth()->id(); $maintenance->asset_maintenance_time = (int) $maintenance->created_at->diffInDays(now(), true); $maintenance->saveQuietly(); $logAction = new Actionlog; $logAction->item_type = Maintenance::class; $logAction->item_id = $maintenance->id; $logAction->target_type = Asset::class; $logAction->target_id = $maintenance->asset_id; $logAction->created_by = auth()->id(); $logAction->note = $request->input('note'); $logAction->logaction(ActionType::MaintenanceComplete); return response()->json(Helper::formatStandardApiResponse('success', (new MaintenancesTransformer)->transformMaintenance($maintenance->fresh()), trans('admin/maintenances/message.complete.success'))); } public function history(Request $request, Maintenance $maintenance): JsonResponse|array { $this->authorize('history', $maintenance); $historyQuery = $maintenance->getHistory($request); $total = (clone $historyQuery)->count(); $offset = ($request->input('offset') > $total) ? $total : app('api_offset_value'); $limit = app('api_limit_value'); $history = (clone $historyQuery)->skip($offset)->take($limit)->get(); return response()->json((new ActionlogsTransformer)->transformActionlogs($history, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE); } public function notesIndex(Maintenance $maintenance): JsonResponse { $this->authorize('journal', $maintenance); $notes = Actionlog::with('user:id,username') ->where('item_type', Maintenance::class) ->where('item_id', $maintenance->id) ->where('action_type', 'note added') ->orderBy('created_at', 'desc') ->get(['id', 'created_at', 'note', 'created_by', 'item_id', 'item_type', 'action_type']); $notesArray = $notes->map(fn ($note) => [ 'id' => $note->id, 'created_at' => $note->created_at, 'note' => $note->note, 'created_by' => $note->created_by, 'username' => $note->user?->username, 'item_id' => $note->item_id, 'item_type' => $note->item_type, 'action_type' => $note->action_type, ]); return response()->json(Helper::formatStandardApiResponse('success', ['notes' => $notesArray, 'maintenance_id' => $maintenance->id])); } public function notesStore(Request $request, Maintenance $maintenance): JsonResponse { $this->authorize('update', $maintenance); if (! $request->filled('note')) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('validation.required', ['attribute' => 'note'])), 422); } $logaction = new Actionlog; $logaction->item_type = Maintenance::class; $logaction->created_by = auth()->id(); $logaction->item_id = $maintenance->id; $logaction->note = $request->input('note'); if ($logaction->logaction('note added')) { return response()->json(Helper::formatStandardApiResponse('success', ['note' => $logaction->note, 'item_id' => $maintenance->id], trans('general.note_added'))); } return response()->json(Helper::formatStandardApiResponse('error', null, 'Something went wrong'), 500); } }