diff --git a/app/Http/Controllers/Api/MaintenancesController.php b/app/Http/Controllers/Api/MaintenancesController.php index 86f561c86c34..1d75f5aab246 100644 --- a/app/Http/Controllers/Api/MaintenancesController.php +++ b/app/Http/Controllers/Api/MaintenancesController.php @@ -34,7 +34,7 @@ public function index(Request $request) : JsonResponse | array $this->authorize('view', Asset::class); $maintenances = Maintenance::select('maintenances.*') - ->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'adminuser'); + ->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'adminuser', 'userResponsible'); if ($request->filled('search')) { $maintenances = $maintenances->TextSearch($request->input('search')); @@ -56,6 +56,10 @@ public function index(Request $request) : JsonResponse | array $maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type')); } + if ($request->filled('user_responsible_id')) { + $maintenances->where('user_responsible_id', '=', $request->input('user_responsible_id')); + } + // 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')); @@ -78,6 +82,7 @@ public function index(Request $request) : JsonResponse | array 'location', 'is_warranty', 'status_label', + 'user_responsible_id' ]; $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; diff --git a/app/Http/Controllers/MaintenancesController.php b/app/Http/Controllers/MaintenancesController.php index e893b75f39e3..172ab4e05542 100644 --- a/app/Http/Controllers/MaintenancesController.php +++ b/app/Http/Controllers/MaintenancesController.php @@ -78,6 +78,7 @@ public function store(ImageUploadRequest $request) : RedirectResponse $maintenance->is_warranty = $request->input('is_warranty'); $maintenance->cost = $request->input('cost'); $maintenance->notes = $request->input('notes'); + $maintenance->user_responsible_id = $request->input('user_responsible_id'); // Save the asset maintenance data $maintenance->asset_id = $asset->id; @@ -152,6 +153,7 @@ public function update(ImageUploadRequest $request, Maintenance $maintenance) : $maintenance->name = $request->input('name'); $maintenance->start_date = $request->input('start_date'); $maintenance->completion_date = $request->input('completion_date'); + $maintenance->user_responsible_id = $request->input('user_responsible_id'); // Todo - put this in a getter/setter? diff --git a/app/Http/Transformers/MaintenancesTransformer.php b/app/Http/Transformers/MaintenancesTransformer.php index c20c2548697e..6bb42d732590 100644 --- a/app/Http/Transformers/MaintenancesTransformer.php +++ b/app/Http/Transformers/MaintenancesTransformer.php @@ -24,7 +24,7 @@ public function transformMaintenances(Collection $maintenances, $total) public function transformMaintenance(Maintenance $assetmaintenance) { $array = [ - 'id' => (int) $assetmaintenance->id, + 'id' => (int) $assetmaintenance->id, 'asset' => ($assetmaintenance->asset) ? [ 'id' => (int) $assetmaintenance->asset->id, 'name'=> ($assetmaintenance->asset->name) ? e($assetmaintenance->asset->name) : null, @@ -82,6 +82,17 @@ public function transformMaintenance(Maintenance $assetmaintenance) 'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'), 'is_warranty'=> $assetmaintenance->is_warranty, + 'user_responsible' => ($assetmaintenance->userResponsible) ? [ + 'id' => (int) $assetmaintenance->userResponsible->id, + 'username' => e($assetmaintenance->userResponsible->username), + 'name' => e($assetmaintenance->userResponsible->getFullNameAttribute()), + 'first_name'=> e($assetmaintenance->userResponsible->first_name), + 'last_name'=> ($assetmaintenance->userResponsible->last_name) ? e($assetmaintenance->userResponsible->last_name) : null, + 'email'=> ($assetmaintenance->userResponsible->email) ? e($assetmaintenance->userResponsible->email) : null, + 'employee_number' => ($assetmaintenance->userResponsible->employee_num) ? e($assetmaintenance->userResponsible->employee_num) : null, + 'jobtitle' => $assetmaintenance->userResponsible->jobtitle ? e($assetmaintenance->userResponsible->jobtitle) : null, + 'type' => 'user', + ] : null, ]; diff --git a/app/Models/Maintenance.php b/app/Models/Maintenance.php index 942fdb122a03..4b6128c92204 100644 --- a/app/Models/Maintenance.php +++ b/app/Models/Maintenance.php @@ -38,6 +38,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild 'completion_date' => 'date_format:Y-m-d|nullable|after_or_equal:start_date', 'notes' => 'string|nullable', 'cost' => 'numeric|nullable|gte:0|max:99999999999999999.99', + 'user_responsible_id' => 'nullable|integer' ]; @@ -57,6 +58,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild 'asset_maintenance_time', 'notes', 'cost', + 'user_responsible_id', ]; use Searchable; @@ -87,6 +89,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild 'asset.supplier' => ['name'], 'asset.assetstatus' => ['name'], 'supplier' => ['name'], + 'user_responsible' => ['first_name', 'last_name'], ]; public function getCompanyableParents() @@ -185,7 +188,15 @@ public function assetlog() ->orderBy('created_at', 'desc') ->withTrashed(); } - + + /** + * Get the user responsible for this maintenance. + * + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function userResponsible() { + return $this->belongsTo(\App\Models\User::class, 'user_responsible_id')->withTrashed(); + } /** * Get the admin who created the maintenance diff --git a/app/Models/User.php b/app/Models/User.php index dd3bbfec5792..c1b381120459 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -433,6 +433,19 @@ public function maintenances() return $this->hasMany(\App\Models\Maintenance::class, 'user_id')->withTrashed(); } + /** + * Establishes the user -> maintenances relationship + * + * This would only be used to return maintenances that this user + * is responsible for. + * + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function maintenanceCausedBy() + { + return $this->hasMany(\App\Models\Maintenance::class, 'user_responsible_id')->withTrashed(); + } + /** * Establishes the user -> accessories relationship * diff --git a/app/Presenters/MaintenancesPresenter.php b/app/Presenters/MaintenancesPresenter.php index 41ff927f677f..5190dfd2c933 100644 --- a/app/Presenters/MaintenancesPresenter.php +++ b/app/Presenters/MaintenancesPresenter.php @@ -94,6 +94,12 @@ public static function dataTableLayout() 'sortable' => true, 'title' => trans('general.location'), 'formatter' => 'locationsLinkObjFormatter', + ], [ + 'field' => 'user_responsible', + 'searchable' => 'true', + 'sortable' => 'true', + 'title' => trans('admin/maintenances/table.user_responsible'), + 'formatter' => 'usersLinkObjFormatter', ], [ 'field' => 'asset_maintenance_type', 'searchable' => true, diff --git a/database/factories/MaintenanceFactory.php b/database/factories/MaintenanceFactory.php index e07de8d24d3a..ea6f37982f76 100644 --- a/database/factories/MaintenanceFactory.php +++ b/database/factories/MaintenanceFactory.php @@ -5,6 +5,7 @@ use App\Models\Asset; use App\Models\Maintenance; use App\Models\Supplier; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; class MaintenanceFactory extends Factory @@ -31,6 +32,7 @@ public function definition() 'start_date' => $this->faker->date(), 'is_warranty' => $this->faker->boolean(), 'notes' => $this->faker->paragraph(), + 'user_responsible_id' => User::factory(), ]; } } diff --git a/database/migrations/2025_09_21_003823_add_user_responsible_to_maintenances.php b/database/migrations/2025_09_21_003823_add_user_responsible_to_maintenances.php new file mode 100644 index 000000000000..0007c44656c1 --- /dev/null +++ b/database/migrations/2025_09_21_003823_add_user_responsible_to_maintenances.php @@ -0,0 +1,30 @@ +integer('user_responsible_id')->nullable()->default(null); + } + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('maintenances', function (Blueprint $table) { + $table->dropColumn('user_responsible_id'); + }); + } +}; diff --git a/resources/lang/en-US/admin/maintenances/form.php b/resources/lang/en-US/admin/maintenances/form.php index c69921b214b7..5372196d91fb 100644 --- a/resources/lang/en-US/admin/maintenances/form.php +++ b/resources/lang/en-US/admin/maintenances/form.php @@ -11,5 +11,6 @@ 'asset_maintenance_time' => 'Asset Maintenance Time (in days)', 'notes' => 'Notes', 'update' => 'Update Asset Maintenance', - 'create' => 'Create Asset Maintenance' + 'create' => 'Create Asset Maintenance', + 'user_responsible' => 'User responsible', ]; diff --git a/resources/lang/en-US/admin/maintenances/table.php b/resources/lang/en-US/admin/maintenances/table.php index 3ba895038d49..fa14d421a3bb 100644 --- a/resources/lang/en-US/admin/maintenances/table.php +++ b/resources/lang/en-US/admin/maintenances/table.php @@ -5,4 +5,5 @@ 'asset_name' => 'Asset Name', 'is_warranty' => 'Warranty', 'dl_csv' => 'Download CSV', + 'user_responsible' => 'User responsible', ]; diff --git a/resources/lang/en-US/admin/users/general.php b/resources/lang/en-US/admin/users/general.php index fa0f478d4bb0..6527710e4f84 100644 --- a/resources/lang/en-US/admin/users/general.php +++ b/resources/lang/en-US/admin/users/general.php @@ -53,4 +53,5 @@ 'all_assigned_list_generation' => 'Generated on:', 'email_user_creds_on_create' => 'Email this user their credentials?', 'department_manager' => 'Department Manager', + 'maintenance_caused_by_user' => 'Maintenance caused by user', ]; diff --git a/resources/views/maintenances/edit.blade.php b/resources/views/maintenances/edit.blade.php index 436b1c657596..d0b911949386 100644 --- a/resources/views/maintenances/edit.blade.php +++ b/resources/views/maintenances/edit.blade.php @@ -105,7 +105,7 @@ @include ('partials.forms.edit.maintenance_type') - + @include ('partials.forms.edit.user-select', ['fieldname' => 'user_responsible_id', 'translated_name' => trans('admin/maintenances/table.user_responsible')] )