Skip to content

Commit

Permalink
Add ability to tie locations to companies
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Toreg87 committed Feb 28, 2023
1 parent 23fe11c commit 6bbc7aa
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 21 deletions.
40 changes: 36 additions & 4 deletions app/Http/Controllers/Api/LocationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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',
Expand All @@ -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'));
}
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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()) {
Expand All @@ -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',
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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');
Expand Down
30 changes: 19 additions & 11 deletions app/Http/Controllers/LocationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -211,35 +214,40 @@ 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)
{
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'));



}
}
4 changes: 4 additions & 0 deletions app/Http/Transformers/LocationsTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
];
Expand Down
30 changes: 29 additions & 1 deletion app/Models/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
];

/**
Expand Down Expand Up @@ -69,6 +71,7 @@ class Location extends SnipeModel
'currency',
'manager_id',
'image',
'company_id',
];
protected $hidden = ['user_id'];

Expand All @@ -87,7 +90,8 @@ class Location extends SnipeModel
* @var array
*/
protected $searchableRelations = [
'parent' => ['name'],
'parent' => ['name'],
'company' => ['name']
];


Expand Down Expand Up @@ -205,6 +209,17 @@ public function parent()
->with('parent');
}

/**
* Establishes the locations -> company relationship
*
* @author [T. Regnery] [<[email protected]>]
* @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
Expand Down Expand Up @@ -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);
}
}
9 changes: 9 additions & 0 deletions app/Presenters/LocationPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddCompanyIdToLocations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('locations', function (Blueprint $table) {
$table->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');
});
}
}

3 changes: 3 additions & 0 deletions resources/views/locations/edit.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<!-- Manager-->
@include ('partials.forms.edit.user-select', ['translated_name' => trans('admin/users/table.manager'), 'fieldname' => 'manager_id'])

<!-- Company -->
@include ('partials.forms.edit.company-select', ['translated_name' => trans('general.company'), 'fieldname' => 'company_id'])

<!-- Currency -->
<div class="form-group {{ $errors->has('currency') ? ' has-error' : '' }}">
<label for="currency" class="col-md-3 control-label">
Expand Down
2 changes: 1 addition & 1 deletion resources/views/locations/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
data-sort-order="asc"
id="locationTable"
class="table table-striped snipe-table"
data-url="{{ route('api.locations.index') }}"
data-url="{{ route('api.locations.index', array('company_id'=>e(Request::get('company_id')))) }}"
data-export-options='{
"fileName": "export-locations-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
Expand Down
6 changes: 5 additions & 1 deletion resources/views/locations/print.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@
@if ($parent)
{{ $parent->present()->fullName() }}
@endif

<br>
@if ($company)
<b>{{ trans('admin/companies/table.name') }}:</b> {{ $company->present()->Name() }}</b>
<br>
@endif
@if ($manager)
<b>{{ trans('general.manager') }}</b> {{ $manager->present()->fullName() }}<br>
@endif
Expand Down
3 changes: 3 additions & 0 deletions resources/views/locations/view.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ class="table table-striped snipe-table"
@if ($location->manager)
<li>{{ trans('admin/users/table.manager') }}: {!! $location->manager->present()->nameUrl() !!}</li>
@endif
@if ($location->company)
<li>{{ trans('admin/companies/table.name') }}: {!! $location->company->present()->nameUrl() !!}</li>
@endif
@if ($location->parent)
<li>{{ trans('admin/locations/table.parent') }}: {!! $location->parent->present()->nameUrl() !!}</li>
@endif
Expand Down
17 changes: 14 additions & 3 deletions resources/views/modals/location.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,30 @@
<form action="{{ route('api.locations.store') }}" onsubmit="return false">
<div class="alert alert-danger" id="modal_error_msg" style="display:none">
</div>

<!-- Setup of default company, taken from asset creator -->
@if ($user->company)
<input type="hidden" name="company_id" id='modal-company' value='{{ $user->company->id }}' class="form-control">
@endif

<!-- Select company, only for users with multicompany access - replace default company -->
<div class="dynamic-form-row">
@include ('partials.forms.edit.company-select', ['translated_name' => trans('general.company'), 'fieldname' => 'company_id'])
</div>

<div class="dynamic-form-row">
<div class="col-md-4 col-xs-12"><label for="modal-name">{{ trans('general.name') }}:
<div class="col-md-3 col-xs-12"><label for="modal-name">{{ trans('general.name') }}:
</label></div>
<div class="col-md-8 col-xs-12 required"><input type='text' name="name" id='modal-name' class="form-control"></div>
</div>

<div class="dynamic-form-row">
<div class="col-md-4 col-xs-12"><label for="modal-city">{{ trans('general.city') }}:</label></div>
<div class="col-md-3 col-xs-12"><label for="modal-city">{{ trans('general.city') }}:</label></div>
<div class="col-md-8 col-xs-12 required"><input type='text' name="city" id='modal-city' class="form-control"></div>
</div>

<div class="dynamic-form-row">
<div class="col-md-4 col-xs-12 country"><label for="modal-country">{{ trans('general.country') }}:</label></div>
<div class="col-md-3 col-xs-12 country"><label for="modal-country">{{ trans('general.country') }}:</label></div>
<div class="col-md-8 col-xs-12">{!! Form::countries('country', Request::old('country'), 'select2 country',"modal-country") !!}</div>
</div>
</form>
Expand Down
Loading

0 comments on commit 6bbc7aa

Please sign in to comment.