From 57af507170c97db6210a5862d2efc81e8cd360dd Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 9 Sep 2025 12:20:34 +0100 Subject: [PATCH] Added deleted button to locations, check for additional relations Signed-off-by: snipe --- .../Controllers/Api/LocationsController.php | 9 ++++- app/Http/Controllers/LocationsController.php | 38 ++++++++++--------- .../Transformers/LocationsTransformer.php | 3 +- app/Models/Location.php | 12 +++++- .../lang/en-US/admin/locations/message.php | 3 +- resources/views/locations/index.blade.php | 2 +- resources/views/locations/view.blade.php | 38 +++++++++++++++---- .../views/partials/bootstrap-table.blade.php | 14 ++++++- 8 files changed, 87 insertions(+), 32 deletions(-) diff --git a/app/Http/Controllers/Api/LocationsController.php b/app/Http/Controllers/Api/LocationsController.php index b5c911a6ca..0890fed08d 100644 --- a/app/Http/Controllers/Api/LocationsController.php +++ b/app/Http/Controllers/Api/LocationsController.php @@ -79,8 +79,9 @@ class LocationsController extends Controller 'locations.currency', 'locations.company_id', 'locations.notes', + 'locations.created_by', + 'locations.deleted_at', ]) - ->withCount('assignedAssets as assigned_assets_count') ->withCount('assignedAssets as assigned_assets_count') ->withCount('assets as assets_count') ->withCount('assignedAccessories as assigned_accessories_count') @@ -88,6 +89,8 @@ class LocationsController extends Controller ->withCount('rtd_assets as rtd_assets_count') ->withCount('children as children_count') ->withCount('users as users_count') + ->withCount('consumables as consumables_count') + ->withCount('components as components_count') ->with('adminuser'); // Only scope locations if the setting is enabled @@ -131,6 +134,10 @@ class LocationsController extends Controller $locations->where('locations.company_id', '=', $request->input('company_id')); } + if ($request->input('status') == 'deleted') { + $locations->onlyTrashed(); + } + // Make sure the offset and limit are actually integers and do not exceed system limits $offset = ($request->input('offset') > $locations->count()) ? $locations->count() : app('api_offset_value'); $limit = app('api_limit_value'); diff --git a/app/Http/Controllers/LocationsController.php b/app/Http/Controllers/LocationsController.php index 46eff73df7..b7d0283213 100755 --- a/app/Http/Controllers/LocationsController.php +++ b/app/Http/Controllers/LocationsController.php @@ -193,26 +193,21 @@ class LocationsController extends Controller return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.does_not_exist')); } - if ($location->users()->count() > 0) { - return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users')); - } elseif ($location->children()->count() > 0) { - return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_child_loc')); - } elseif ($location->assets()->count() > 0) { - return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets')); - } elseif ($location->assignedassets()->count() > 0) { - return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets')); - } + if ($location->isDeletable()) { - if ($location->image) { - try { - Storage::disk('public')->delete('locations/'.$location->image); - } catch (\Exception $e) { - Log::error($e); + if ($location->image) { + try { + Storage::disk('public')->delete('locations/'.$location->image); + } catch (\Exception $e) { + Log::error($e); + } } + $location->delete(); + return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success')); + } else { + return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users')); } - $location->delete(); - return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success')); } /** @@ -321,7 +316,6 @@ class LocationsController extends Controller return redirect()->route('locations.index')->with('success', trans('admin/locations/message.restore.success')); } - // Check validation return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.location'), 'error' => $location->getErrors()->first()])); } @@ -366,8 +360,12 @@ class LocationsController extends Controller $locations = Location::whereIn('id', $locations_raw_array) ->withCount('assignedAssets as assigned_assets_count') ->withCount('assets as assets_count') + ->withCount('assignedAccessories as assigned_accessories_count') + ->withCount('accessories as accessories_count') ->withCount('rtd_assets as rtd_assets_count') ->withCount('children as children_count') + ->withCount('consumables as consumables_count') + ->withCount('components as components_count') ->withCount('users as users_count')->get(); $valid_count = 0; @@ -400,9 +398,13 @@ class LocationsController extends Controller $locations = Location::whereIn('id', $locations_raw_array) ->withCount('assignedAssets as assigned_assets_count') ->withCount('assets as assets_count') + ->withCount('assignedAccessories as assigned_accessories_count') + ->withCount('accessories as accessories_count') ->withCount('rtd_assets as rtd_assets_count') ->withCount('children as children_count') - ->withCount('users as users_count')->get(); + ->withCount('users as users_count') + ->withCount('consumables as consumables_count') + ->withCount('components as components_count')->get(); $success_count = 0; $error_count = 0; diff --git a/app/Http/Transformers/LocationsTransformer.php b/app/Http/Transformers/LocationsTransformer.php index 4965ff99d5..c77206c73d 100644 --- a/app/Http/Transformers/LocationsTransformer.php +++ b/app/Http/Transformers/LocationsTransformer.php @@ -76,12 +76,13 @@ class LocationsTransformer ]; $permissions_array['available_actions'] = [ - 'update' => Gate::allows('update', Location::class) ? true : false, + 'update' => (Gate::allows('update', Location::class) && ($location->deleted_at == '')), 'delete' => $location->isDeletable(), 'bulk_selectable' => [ 'delete' => $location->isDeletable() ], 'clone' => (Gate::allows('create', Location::class) && ($location->deleted_at == '')), + 'restore' => (Gate::allows('create', Location::class) && ($location->deleted_at != '')), ]; $array += $permissions_array; diff --git a/app/Models/Location.php b/app/Models/Location.php index 352ffd1201..deda1ae633 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -43,6 +43,8 @@ class Location extends SnipeModel 'company_id' => 'integer', ]; + + /** * Whether the model should inject its identifier to the unique * validation rules before attempting validation. If this property @@ -113,13 +115,19 @@ class Location extends SnipeModel { return Gate::allows('delete', $this) - && ($this->assets_count == 0) + && ($this->deleted_at == '') && ($this->assigned_assets_count == 0) - && ($this->children_count == 0) + && ($this->assets_count == 0) + && ($this->assigned_accessories_count == 0) && ($this->accessories_count == 0) + && ($this->rtd_assets_count == 0) + && ($this->children_count == 0) + && ($this->consumables_count == 0) + && ($this->componments_count == 0) && ($this->users_count == 0); } + /** * Establishes the user -> location relationship * diff --git a/resources/lang/en-US/admin/locations/message.php b/resources/lang/en-US/admin/locations/message.php index b21c70ad89..4f0b7b2cfe 100644 --- a/resources/lang/en-US/admin/locations/message.php +++ b/resources/lang/en-US/admin/locations/message.php @@ -3,12 +3,13 @@ return array( 'does_not_exist' => 'Location does not exist.', - 'assoc_users' => 'This location is not currently deletable because it is the location of record for at least one asset or user, has assets assigned to it, or is the parent location of another location. Please update your records to no longer reference this location and try again ', + 'assoc_users' => 'This location is not currently deletable because it is the location of record for at least one item or user, has assets assigned to it, or is the parent location of another location. Please update your records to no longer reference this location and try again ', 'assoc_assets' => 'This location is currently associated with at least one asset and cannot be deleted. Please update your assets to no longer reference this location and try again. ', 'assoc_child_loc' => 'This location is currently the parent of at least one child location and cannot be deleted. Please update your locations to no longer reference this location and try again. ', 'assigned_assets' => 'Assigned Assets', 'current_location' => 'Current Location', 'open_map' => 'Open in :map_provider_icon Maps', + 'deleted_warning' => 'This location has been deleted. Please restore it before attempting to make any changes.', 'create' => array( diff --git a/resources/views/locations/index.blade.php b/resources/views/locations/index.blade.php index 4dd16d7ed1..9ffaec7e41 100755 --- a/resources/views/locations/index.blade.php +++ b/resources/views/locations/index.blade.php @@ -26,7 +26,7 @@ data-buttons="locationButtons" id="locationTable" class="table table-striped snipe-table" - data-url="{{ route('api.locations.index', array('company_id'=>e(Request::get('company_id')))) }}" + data-url="{{ route('api.locations.index', ['company_id'=>e(request('company_id')), 'status' => e(request('status'))]) }}" data-export-options='{ "fileName": "export-locations-{{ date('Y-m-d') }}", "ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"] diff --git a/resources/views/locations/view.blade.php b/resources/views/locations/view.blade.php index 3b4a53aefc..418ab2138c 100644 --- a/resources/views/locations/view.blade.php +++ b/resources/views/locations/view.blade.php @@ -17,8 +17,21 @@ @section('content')
+ + @if ($location->deleted_at!='') +
+
+ + {{ trans('admin/locations/message.deleted_warning') }} +
+
+ @endif + +
+ + @can('update', $location) - + @if ($location->deleted_at=='') + + @else + + @endif @endcan + @if ($location->deleted_at=='') + @endif @can('delete', $location)
@@ -483,7 +507,7 @@ @else
@csrf - diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 1491be10a4..b325e89f1b 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -1289,7 +1289,7 @@ btnShowDeleted: { text: '{{ (request()->input('status') == "deleted") ?trans('admin/users/table.show_current') : trans('admin/users/table.show_deleted') }}', - icon: 'fa-solid fa-user-slash {{ (request()->input('status') == "deleted") ? ' text-danger' : ' fa-user-slash' }}', + icon: 'fa-solid fa-trash {{ (request()->input('status') == "deleted") ? ' text-danger' : ' fa-user-trash' }}', event () { window.location.href = '{{ (request()->input('status') == "deleted") ? route('users.index') : route('users.index', ['status' => 'deleted']) }}'; }, @@ -1398,6 +1398,18 @@ @endif } }, + + btnShowDeleted: { + text: '{{ (request()->input('status') == "deleted") ? trans('admin/users/table.show_current') : trans('admin/users/table.show_deleted') }}', + icon: 'fa-solid fa-trash {{ (request()->input('status') == "deleted") ? ' text-danger' : ' fa-user-trash' }}', + event () { + window.location.href = '{{ (request()->input('status') == "deleted") ? route('locations.index') : route('locations.index', ['status' => 'deleted']) }}'; + }, + attributes: { + title: '{{ (request()->input('status') == "deleted") ? trans('admin/users/table.show_current') : trans('admin/users/table.show_deleted') }}', + + } + }, }); @endcan