From 6bbc7aa233946131ca23bc78ee0fbd77b6ed3323 Mon Sep 17 00:00:00 2001 From: Tobias Regnery Date: Thu, 10 Feb 2022 11:36:36 +0100 Subject: [PATCH] Add ability to tie locations to companies Locations are the last big part of the application that can't be tied to companies. This can be a problem with FullMultipleCompanySupport, because you can't restrict the visibility of locations to the company of the users. In order to change this, add a company_id to the locations table and wire everything up in the views and controllers. Aditionally add a new formatter to filter the locations to a specific company, like it is done for assets. Locations are properly scoped to the users company if FullMultipleCompanySupport is enabled. If a parent location of a location has a different company than the user, the location does not show up. --- .../Controllers/Api/LocationsController.php | 40 +++++++++++++++++-- app/Http/Controllers/LocationsController.php | 30 +++++++++----- .../Transformers/LocationsTransformer.php | 4 ++ app/Models/Location.php | 30 +++++++++++++- app/Presenters/LocationPresenter.php | 9 +++++ ..._10_110210_add_company_id_to_locations.php | 35 ++++++++++++++++ resources/views/locations/edit.blade.php | 3 ++ resources/views/locations/index.blade.php | 2 +- resources/views/locations/print.blade.php | 6 ++- resources/views/locations/view.blade.php | 3 ++ resources/views/modals/location.blade.php | 17 ++++++-- .../views/partials/bootstrap-table.blade.php | 8 ++++ 12 files changed, 166 insertions(+), 21 deletions(-) create mode 100644 database/migrations/2022_02_10_110210_add_company_id_to_locations.php diff --git a/app/Http/Controllers/Api/LocationsController.php b/app/Http/Controllers/Api/LocationsController.php index 3a8df10587d0..ae9a0085e29f 100644 --- a/app/Http/Controllers/Api/LocationsController.php +++ b/app/Http/Controllers/Api/LocationsController.php @@ -5,6 +5,7 @@ use App\Helpers\Helper; use App\Http\Requests\ImageUploadRequest; use App\Http\Controllers\Controller; +use App\Models\Company; use App\Http\Transformers\LocationsTransformer; use App\Http\Transformers\SelectlistTransformer; use App\Models\Location; @@ -25,9 +26,23 @@ public function index(Request $request) { $this->authorize('view', Location::class); $allowed_columns = [ - 'id', 'name', 'address', 'address2', 'city', 'state', 'country', 'zip', 'created_at', - 'updated_at', 'manager_id', 'image', - 'assigned_assets_count', 'users_count', 'assets_count','assigned_assets_count', 'assets_count', 'rtd_assets_count', 'currency', 'ldap_ou', ]; + 'id', + 'name', + 'address', + 'address2', + 'city', + 'state', + 'country', + 'zip', + 'created_at', + 'updated_at', + 'manager_id', + 'image', + 'assigned_assets_count', + 'users_count','assets_count', + 'currency', + 'ldap_ou', + 'company_id']; $locations = Location::with('parent', 'manager', 'children')->select([ 'locations.id', @@ -45,11 +60,14 @@ public function index(Request $request) 'locations.image', 'locations.ldap_ou', 'locations.currency', + 'locations.company_id', ])->withCount('assignedAssets as assigned_assets_count') ->withCount('assets as assets_count') ->withCount('rtd_assets as rtd_assets_count') ->withCount('users as users_count'); + $locations = Company::scopeCompanyables($locations); + if ($request->filled('search')) { $locations = $locations->TextSearch($request->input('search')); } @@ -78,6 +96,10 @@ public function index(Request $request) $locations->where('locations.country', '=', $request->input('country')); } + if ($request->filled('company_id')) { + $locations->where('locations.company_id', '=', $request->input('company_id')); + } + $offset = (($locations) && (request('offset') > $locations->count())) ? $locations->count() : request('offset', 0); // Check to make sure the limit is not higher than the max allowed @@ -93,6 +115,9 @@ public function index(Request $request) case 'manager': $locations->OrderManager($order); break; + case 'company': + $locations->OrderCompany($order); + break; default: $locations->orderBy($sort, $order); break; @@ -119,6 +144,7 @@ public function store(ImageUploadRequest $request) $this->authorize('create', Location::class); $location = new Location; $location->fill($request->all()); + $location->company_id = Company::getIdForCurrentUser($request->get('company_id')); $location = $request->handleImages($location); if ($location->save()) { @@ -139,7 +165,7 @@ public function store(ImageUploadRequest $request) public function show($id) { $this->authorize('view', Location::class); - $location = Location::with('parent', 'manager', 'children') + $location = Location::with('parent', 'manager', 'children', 'company') ->select([ 'locations.id', 'locations.name', @@ -183,6 +209,10 @@ public function update(ImageUploadRequest $request, $id) $location->fill($request->all()); $location = $request->handleImages($location); + if ($request->filled('company_id')) { + $location->company_id = Company::getIdForCurrentUser($request->get('company_id')); + } + if ($location->isValid()) { $location->save(); @@ -260,6 +290,8 @@ public function selectlist(Request $request) 'locations.image', ]); + $locations = Company::scopeCompanyables($locations); + $page = 1; if ($request->filled('page')) { $page = $request->input('page'); diff --git a/app/Http/Controllers/LocationsController.php b/app/Http/Controllers/LocationsController.php index 9524abf6eedc..1cac1464204c 100755 --- a/app/Http/Controllers/LocationsController.php +++ b/app/Http/Controllers/LocationsController.php @@ -4,6 +4,7 @@ use App\Http\Requests\ImageUploadRequest; use App\Models\Asset; +use App\Models\Company; use App\Models\Location; use App\Models\User; use Illuminate\Support\Facades\Auth; @@ -78,6 +79,7 @@ public function store(ImageUploadRequest $request) $location->zip = $request->input('zip'); $location->ldap_ou = $request->input('ldap_ou'); $location->manager_id = $request->input('manager_id'); + $location->company_id = Company::getIdForCurrentUser($request->input('company_id')); $location->user_id = Auth::id(); $location = $request->handleImages($location); @@ -141,6 +143,7 @@ public function update(ImageUploadRequest $request, $locationId = null) $location->zip = $request->input('zip'); $location->ldap_ou = $request->input('ldap_ou'); $location->manager_id = $request->input('manager_id'); + $location->company_id = Company::getIdForCurrentUser($request->input('company_id')); $location = $request->handleImages($location); @@ -211,20 +214,22 @@ public function show($id = null) public function print_assigned($id) { - if ($location = Location::where('id', $id)->first()) { $parent = Location::where('id', $location->parent_id)->first(); $manager = User::where('id', $location->manager_id)->first(); + $company = Company::where('id', $location->company_id)->first(); $users = User::where('location_id', $id)->with('company', 'department', 'location')->get(); $assets = Asset::where('assigned_to', $id)->where('assigned_type', Location::class)->with('model', 'model.category')->get(); - return view('locations/print')->with('assets', $assets)->with('users', $users)->with('location', $location)->with('parent', $parent)->with('manager', $manager); - + return view('locations/print') + ->with('assets', $assets) + ->with('users',$users) + ->with('location', $location) + ->with('parent', $parent) + ->with('manager', $manager) + ->with('company', $company); } return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist')); - - - } public function print_all_assigned($id) @@ -232,14 +237,17 @@ public function print_all_assigned($id) if ($location = Location::where('id', $id)->first()) { $parent = Location::where('id', $location->parent_id)->first(); $manager = User::where('id', $location->manager_id)->first(); + $company = Company::where('id', $location->company_id)->first(); $users = User::where('location_id', $id)->with('company', 'department', 'location')->get(); $assets = Asset::where('location_id', $id)->with('model', 'model.category')->get(); - return view('locations/print')->with('assets', $assets)->with('users', $users)->with('location', $location)->with('parent', $parent)->with('manager', $manager); - + return view('locations/print') + ->with('assets', $assets) + ->with('users',$users) + ->with('location', $location) + ->with('parent', $parent) + ->with('manager', $manager) + ->with('company', $company); } return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist')); - - - } } diff --git a/app/Http/Transformers/LocationsTransformer.php b/app/Http/Transformers/LocationsTransformer.php index a55c41b35042..0448c1eac118 100644 --- a/app/Http/Transformers/LocationsTransformer.php +++ b/app/Http/Transformers/LocationsTransformer.php @@ -56,6 +56,10 @@ public function transformLocation(Location $location = null) 'name'=> e($location->parent->name), ] : null, 'manager' => ($location->manager) ? (new UsersTransformer)->transformUser($location->manager) : null, + 'company' => ($location->company) ? [ + 'id' => (int) $location->company->id, + 'name'=> e($location->company->name) + ] : null, 'children' => $children_arr, ]; diff --git a/app/Models/Location.php b/app/Models/Location.php index 8181f406cde5..caef676092ae 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -33,11 +33,13 @@ class Location extends SnipeModel 'zip' => 'min:3|max:10|nullable', 'manager_id' => 'exists:users,id|nullable', 'parent_id' => 'non_circular:locations,id', + 'company_id' => 'integer|nullable' ]; protected $casts = [ 'parent_id' => 'integer', 'manager_id' => 'integer', + 'company_id' => 'integer', ]; /** @@ -69,6 +71,7 @@ class Location extends SnipeModel 'currency', 'manager_id', 'image', + 'company_id', ]; protected $hidden = ['user_id']; @@ -87,7 +90,8 @@ class Location extends SnipeModel * @var array */ protected $searchableRelations = [ - 'parent' => ['name'], + 'parent' => ['name'], + 'company' => ['name'] ]; @@ -205,6 +209,17 @@ public function parent() ->with('parent'); } + /** + * Establishes the locations -> company relationship + * + * @author [T. Regnery] [] + * @since [v6.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function company() + { + return $this->belongsTo('\App\Models\Company', 'company_id'); + } /** * Find the manager of a location @@ -304,4 +319,17 @@ public function scopeOrderManager($query, $order) { return $query->leftJoin('users as location_user', 'locations.manager_id', '=', 'location_user.id')->orderBy('location_user.first_name', $order)->orderBy('location_user.last_name', $order); } + + /** + * Query builder scope to order on company + * + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param text $order Order + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeOrderCompany($query, $order) + { + return $query->leftJoin('companies as company_sort', 'locations.company_id', '=', 'company_sort.id')->orderBy('company_sort.name', $order); + } } diff --git a/app/Presenters/LocationPresenter.php b/app/Presenters/LocationPresenter.php index d4281839a140..cb4d1da62811 100644 --- a/app/Presenters/LocationPresenter.php +++ b/app/Presenters/LocationPresenter.php @@ -23,6 +23,15 @@ public static function dataTableLayout() 'title' => trans('general.id'), 'visible' => false, ], + [ + 'field' => 'company', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.company'), + 'visible' => false, + 'formatter' => 'locationCompanyObjFilterFormatter' + ], [ 'field' => 'name', 'searchable' => true, diff --git a/database/migrations/2022_02_10_110210_add_company_id_to_locations.php b/database/migrations/2022_02_10_110210_add_company_id_to_locations.php new file mode 100644 index 000000000000..8ef5822812fd --- /dev/null +++ b/database/migrations/2022_02_10_110210_add_company_id_to_locations.php @@ -0,0 +1,35 @@ +integer('company_id')->unsigned()->nullable(); + $table->index(['company_id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('locations', function (Blueprint $table) { + $table->dropIndex(['company_id']); + $table->dropColumn('company_id'); + }); + } +} + diff --git a/resources/views/locations/edit.blade.php b/resources/views/locations/edit.blade.php index 0c93c83a81e3..be96abf91717 100755 --- a/resources/views/locations/edit.blade.php +++ b/resources/views/locations/edit.blade.php @@ -17,6 +17,9 @@ @include ('partials.forms.edit.user-select', ['translated_name' => trans('admin/users/table.manager'), 'fieldname' => 'manager_id']) + +@include ('partials.forms.edit.company-select', ['translated_name' => trans('general.company'), 'fieldname' => 'company_id']) +