From c2cf7de41b469b42582b939ab1fa3d1660f113ae Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 17:12:16 +0100 Subject: [PATCH 1/8] Use presenter for suppliers Signed-off-by: snipe --- app/Presenters/SupplierPresenter.php | 293 ++++++++++++++++++++++ resources/views/suppliers/index.blade.php | 23 +- 2 files changed, 294 insertions(+), 22 deletions(-) create mode 100644 app/Presenters/SupplierPresenter.php diff --git a/app/Presenters/SupplierPresenter.php b/app/Presenters/SupplierPresenter.php new file mode 100644 index 0000000000..a56fd4b635 --- /dev/null +++ b/app/Presenters/SupplierPresenter.php @@ -0,0 +1,293 @@ + 'id', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.id'), + 'visible' => false, + ], + [ + 'field' => 'name', + 'searchable' => true, + 'sortable' => true, + 'switchable' => false, + 'title' => trans('general.name'), + 'visible' => true, + 'formatter' => 'suppliersLinkFormatter', + ], [ + 'field' => 'image', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.image'), + 'visible' => true, + 'formatter' => 'imageFormatter', + ], + [ + 'field' => 'assets_count', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.assets'), + 'titleTooltip' => trans('general.assets'), + 'visible' => true, + 'class' => 'css-barcode', + ], [ + 'field' => 'accessories_count', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.accessories'), + 'titleTooltip' => trans('general.accessories'), + 'visible' => true, + 'class' => 'css-accessory', + ], + [ + 'field' => 'licenses_count', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.licenses'), + 'titleTooltip' => trans('general.licenses'), + 'visible' => true, + 'class' => 'css-license', + ], [ + 'field' => 'components_count', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.components'), + 'titleTooltip' => trans('general.components'), + 'visible' => true, + 'class' => 'css-component', + ], [ + 'field' => 'consumables_count', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.consumables'), + 'titleTooltip' => trans('general.consumables'), + 'visible' => true, + 'class' => 'css-consumable', + ], [ + 'field' => 'url', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.url'), + 'visible' => true, + 'formatter' => 'externalLinkFormatter', + ], [ + 'field' => 'address', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/locations/table.address'), + 'visible' => true, + ], [ + 'field' => 'address2', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/locations/table.address2'), + 'visible' => false, + ], [ + 'field' => 'city', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/locations/table.city'), + 'visible' => true, + ], [ + 'field' => 'state', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/locations/table.state'), + 'visible' => true, + ], [ + 'field' => 'zip', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/locations/table.zip'), + 'visible' => false, + ], [ + 'field' => 'country', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/locations/table.country'), + 'visible' => false, + ], [ + 'field' => 'phone', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/users/table.phone'), + 'visible' => false, + 'formatter' => 'phoneFormatter', + ], [ + 'field' => 'fax', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/suppliers/table.fax'), + 'visible' => false, + 'formatter' => 'phoneFormatter', + ], [ + 'field' => 'notes', + 'searchable' => true, + 'sortable' => true, + 'visible' => false, + 'title' => trans('general.notes'), + ], [ + 'field' => 'created_at', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.created_at'), + 'visible' => false, + 'formatter' => 'dateDisplayFormatter', + ], [ + 'field' => 'created_by', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.created_by'), + 'visible' => false, + 'formatter' => 'usersLinkObjFormatter', + ], [ + 'field' => 'actions', + 'searchable' => false, + 'sortable' => false, + 'switchable' => false, + 'title' => trans('table.actions'), + 'visible' => true, + 'formatter' => 'suppliersActionsFormatter', + ], + ]; + + return json_encode($layout); + } + + public static function assignedAccessoriesDataTableLayout() + { + $layout = [ + [ + 'field' => 'id', + 'searchable' => false, + 'sortable' => false, + 'switchable' => true, + 'title' => trans('general.id'), + 'visible' => false, + ], + [ + 'field' => 'accessory', + 'searchable' => false, + 'sortable' => false, + 'switchable' => true, + 'title' => trans('general.accessory'), + 'visible' => true, + 'formatter' => 'accessoriesLinkObjFormatter', + ], + [ + 'field' => 'image', + 'searchable' => false, + 'sortable' => false, + 'switchable' => true, + 'title' => trans('general.image'), + 'visible' => true, + 'formatter' => 'imageFormatter', + ], + [ + 'field' => 'note', + 'searchable' => false, + 'sortable' => false, + 'switchable' => true, + 'title' => trans('general.notes'), + 'visible' => true, + ], + [ + 'field' => 'created_at', + 'searchable' => false, + 'sortable' => false, + 'switchable' => true, + 'title' => trans('admin/hardware/table.checkout_date'), + 'visible' => true, + 'formatter' => 'dateDisplayFormatter', + ], + [ + 'field' => 'created_by', + 'searchable' => false, + 'sortable' => false, + 'title' => trans('general.created_by'), + 'visible' => false, + 'formatter' => 'usersLinkObjFormatter', + ], + [ + 'field' => 'available_actions', + 'searchable' => false, + 'sortable' => false, + 'switchable' => false, + 'title' => trans('table.actions'), + 'formatter' => 'accessoriesInOutFormatter', + ], + ]; + + return json_encode($layout); + } + + /** + * Link to this locations name + * @return string + */ + public function nameUrl() + { + return (string) link_to_route('locations.show', $this->name, $this->id); + } + + /** + * Getter for Polymorphism. + * @return mixed + */ + public function name() + { + return $this->model->name; + } + + /** + * Url to view this item. + * @return string + */ + public function viewUrl() + { + return route('locations.show', $this->id); + } + + public function glyph() + { + return ''; + } + + public function fullName() + { + return $this->name; + } +} diff --git a/resources/views/suppliers/index.blade.php b/resources/views/suppliers/index.blade.php index f35ad983d8..918166ea6f 100755 --- a/resources/views/suppliers/index.blade.php +++ b/resources/views/suppliers/index.blade.php @@ -21,6 +21,7 @@
- - - - - - - - - - - - - - - - - - - - - -
{{ trans('admin/suppliers/table.id') }}{{ trans('general.image') }}{{ trans('admin/suppliers/table.name') }}{{ trans('admin/suppliers/table.address') }}{{ trans('admin/suppliers/table.contact') }}{{ trans('admin/suppliers/table.email') }}{{ trans('admin/suppliers/table.phone') }}{{ trans('admin/suppliers/table.fax') }}{{ trans('general.url') }}{{ trans('admin/suppliers/table.assets') }}{{ trans('general.accessories') }}{{ trans('admin/suppliers/table.licenses') }}{{ trans('general.components') }}{{ trans('general.consumables') }}{{ trans('general.notes') }}{{ trans('general.created_at') }}{{ trans('general.created_by') }}{{ trans('table.actions') }}
From ed9dbcc7777d7463103309c2ee9edcb358a00d1a Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 17:12:33 +0100 Subject: [PATCH 2/8] Added created_by to location presenter Signed-off-by: snipe --- app/Presenters/LocationPresenter.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/Presenters/LocationPresenter.php b/app/Presenters/LocationPresenter.php index af02aa2420..52076e06c1 100644 --- a/app/Presenters/LocationPresenter.php +++ b/app/Presenters/LocationPresenter.php @@ -208,7 +208,16 @@ class LocationPresenter extends Presenter 'title' => trans('general.created_at'), 'visible' => false, 'formatter' => 'dateDisplayFormatter', - ], [ + ], + [ + 'field' => 'created_by', + 'searchable' => true, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.created_by'), + 'visible' => false, + 'formatter' => 'usersLinkObjFormatter', + ],[ 'field' => 'actions', 'searchable' => false, 'sortable' => false, From 6efd323fbf407f871e1a0e177fa45fed5bdef812 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 17:12:48 +0100 Subject: [PATCH 3/8] Added adminuser method Signed-off-by: snipe --- app/Models/Location.php | 11 +++++++++++ app/Models/Supplier.php | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/app/Models/Location.php b/app/Models/Location.php index 9b1ed02f43..a3b047579d 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -135,6 +135,17 @@ class Location extends SnipeModel return $this->hasMany(\App\Models\User::class, 'location_id'); } + /** + * Establishes the location -> admin user relationship + * + * @author A. Gianotto + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function adminuser() + { + return $this->belongsTo(\App\Models\User::class, 'created_by'); + } + /** * Find assets with this location as their location_id * diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index e198d10c10..1d667f700e 100755 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -128,6 +128,18 @@ class Supplier extends SnipeModel return $this->hasMany(\App\Models\Consumable::class, 'supplier_id'); } + + /** + * Establishes the supplier -> admin user relationship + * + * @author A. Gianotto + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function adminuser() + { + return $this->belongsTo(\App\Models\User::class, 'created_by'); + } + /** * Establishes the supplier -> asset maintenances relationship * From 7ae4a4177fc1b474a890add70cf8131a57d1936d Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 17:13:05 +0100 Subject: [PATCH 4/8] Added created_by to transformer Signed-off-by: snipe --- app/Http/Transformers/LocationsTransformer.php | 4 ++++ app/Http/Transformers/SuppliersTransformer.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/Http/Transformers/LocationsTransformer.php b/app/Http/Transformers/LocationsTransformer.php index b1553c69f4..4965ff99d5 100644 --- a/app/Http/Transformers/LocationsTransformer.php +++ b/app/Http/Transformers/LocationsTransformer.php @@ -57,6 +57,10 @@ class LocationsTransformer 'ldap_ou' => ($location->ldap_ou) ? e($location->ldap_ou) : null, 'notes' => Helper::parseEscapedMarkedownInline($location->notes), 'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'), + 'created_by' => $location->adminuser ? [ + 'id' => (int) $location->adminuser->id, + 'name'=> e($location->adminuser->present()->fullName), + ]: null, 'updated_at' => Helper::getFormattedDateObject($location->updated_at, 'datetime'), 'parent' => ($location->parent) ? [ 'id' => (int) $location->parent->id, diff --git a/app/Http/Transformers/SuppliersTransformer.php b/app/Http/Transformers/SuppliersTransformer.php index 1fdc93c193..750c969c63 100644 --- a/app/Http/Transformers/SuppliersTransformer.php +++ b/app/Http/Transformers/SuppliersTransformer.php @@ -45,6 +45,10 @@ class SuppliersTransformer 'components_count' => (int) $supplier->components_count, 'notes' => ($supplier->notes) ? Helper::parseEscapedMarkedownInline($supplier->notes) : null, 'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'), + 'created_by' => $supplier->adminuser ? [ + 'id' => (int) $supplier->adminuser->id, + 'name'=> e($supplier->adminuser->present()->fullName), + ]: null, 'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'), ]; From 40c31a1ad7fdbc3e532606e41ff8bdf173f3bf31 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 17:13:16 +0100 Subject: [PATCH 5/8] Eager load adminuser method Signed-off-by: snipe --- app/Http/Controllers/Api/LocationsController.php | 3 ++- app/Http/Controllers/Api/SuppliersController.php | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Api/LocationsController.php b/app/Http/Controllers/Api/LocationsController.php index 66a68f9458..b5c911a6ca 100644 --- a/app/Http/Controllers/Api/LocationsController.php +++ b/app/Http/Controllers/Api/LocationsController.php @@ -87,7 +87,8 @@ class LocationsController extends Controller ->withCount('accessories as accessories_count') ->withCount('rtd_assets as rtd_assets_count') ->withCount('children as children_count') - ->withCount('users as users_count'); + ->withCount('users as users_count') + ->with('adminuser'); // Only scope locations if the setting is enabled if (Setting::getSettings()->scope_locations_fmcs) { diff --git a/app/Http/Controllers/Api/SuppliersController.php b/app/Http/Controllers/Api/SuppliersController.php index f752f22241..10efd923b6 100644 --- a/app/Http/Controllers/Api/SuppliersController.php +++ b/app/Http/Controllers/Api/SuppliersController.php @@ -39,15 +39,17 @@ class SuppliersController extends Controller 'components_count', 'consumables_count', 'url', + 'notes', ]; $suppliers = Supplier::select( - ['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'updated_at', 'deleted_at', 'image', 'notes', 'url']) + ['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'created_by', 'updated_at', 'deleted_at', 'image', 'notes', 'url']) ->withCount('assets as assets_count') ->withCount('licenses as licenses_count') ->withCount('accessories as accessories_count') ->withCount('components as components_count') - ->withCount('consumables as consumables_count'); + ->withCount('consumables as consumables_count') + ->with('adminuser'); if ($request->filled('search')) { From 4c7b6d130fb279dc0638c9ef5eaecf5aa25683b3 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 21:13:08 +0100 Subject: [PATCH 6/8] Added additional search and display fields for suppliers and locations Signed-off-by: snipe --- .../Controllers/Api/SuppliersController.php | 24 +++++++++++++++---- app/Models/Location.php | 9 +++++++ app/Models/Supplier.php | 11 ++++++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Api/SuppliersController.php b/app/Http/Controllers/Api/SuppliersController.php index 10efd923b6..ab0db67909 100644 --- a/app/Http/Controllers/Api/SuppliersController.php +++ b/app/Http/Controllers/Api/SuppliersController.php @@ -24,10 +24,15 @@ class SuppliersController extends Controller public function index(Request $request): array { $this->authorize('view', Supplier::class); - $allowed_columns = [' - id', + $allowed_columns = [ + 'id', 'name', 'address', + 'address2', + 'city', + 'state', + 'country', + 'zip', 'phone', 'contact', 'fax', @@ -43,7 +48,7 @@ class SuppliersController extends Controller ]; $suppliers = Supplier::select( - ['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'created_by', 'updated_at', 'deleted_at', 'image', 'notes', 'url']) + ['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'created_by', 'updated_at', 'deleted_at', 'image', 'notes', 'url', 'zip']) ->withCount('assets as assets_count') ->withCount('licenses as licenses_count') ->withCount('accessories as accessories_count') @@ -53,9 +58,10 @@ class SuppliersController extends Controller if ($request->filled('search')) { - $suppliers = $suppliers->TextSearch($request->input('search')); + $suppliers->TextSearch($request->input('search')); } + if ($request->filled('name')) { $suppliers->where('name', '=', $request->input('name')); } @@ -102,7 +108,15 @@ class SuppliersController extends Controller $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at'; - $suppliers->orderBy($sort, $order); + + switch ($request->input('sort')) { + case 'created_by': + $suppliers->OrderByCreatedByName($order); + break; + default: + $suppliers->orderBy($sort, $order); + break; + } $total = $suppliers->count(); $suppliers = $suppliers->skip($offset)->take($limit)->get(); diff --git a/app/Models/Location.php b/app/Models/Location.php index a3b047579d..52236092d3 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -385,4 +385,13 @@ class Location extends SnipeModel { return $query->leftJoin('companies as company_sort', 'locations.company_id', '=', 'company_sort.id')->orderBy('company_sort.name', $order); } + + /** + * Query builder scope to order on the user that created it + */ + public function scopeOrderByCreatedByName($query, $order) + { + return $query->leftJoin('users as admin_sort', 'locations.created_by', '=', 'admin_sort.id')->select('locations.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order); + } + } diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index 1d667f700e..0166229f89 100755 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -48,7 +48,7 @@ class Supplier extends SnipeModel * * @var array */ - protected $searchableAttributes = ['name']; + protected $searchableAttributes = ['name', 'notes', 'phone', 'fax', 'url', 'email', 'contact', 'address', 'address2', 'city', 'state', 'country', 'zip']; /** * The relations and their attributes that should be included when searching the model. @@ -209,4 +209,13 @@ class Supplier extends SnipeModel return $url; } + + /** + * Query builder scope to order on the user that created it + */ + public function scopeOrderByCreatedByName($query, $order) + { + return $query->leftJoin('users as admin_sort', 'suppliers.created_by', '=', 'admin_sort.id')->select('suppliers.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order); + } + } From 930842e6858d012493592c9feddcdcba384f1589 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 21:18:19 +0100 Subject: [PATCH 7/8] Removed unused method Signed-off-by: snipe --- app/Presenters/SupplierPresenter.php | 74 ++-------------------------- 1 file changed, 4 insertions(+), 70 deletions(-) diff --git a/app/Presenters/SupplierPresenter.php b/app/Presenters/SupplierPresenter.php index a56fd4b635..1359b2da70 100644 --- a/app/Presenters/SupplierPresenter.php +++ b/app/Presenters/SupplierPresenter.php @@ -187,80 +187,14 @@ class SupplierPresenter extends Presenter return json_encode($layout); } - public static function assignedAccessoriesDataTableLayout() - { - $layout = [ - [ - 'field' => 'id', - 'searchable' => false, - 'sortable' => false, - 'switchable' => true, - 'title' => trans('general.id'), - 'visible' => false, - ], - [ - 'field' => 'accessory', - 'searchable' => false, - 'sortable' => false, - 'switchable' => true, - 'title' => trans('general.accessory'), - 'visible' => true, - 'formatter' => 'accessoriesLinkObjFormatter', - ], - [ - 'field' => 'image', - 'searchable' => false, - 'sortable' => false, - 'switchable' => true, - 'title' => trans('general.image'), - 'visible' => true, - 'formatter' => 'imageFormatter', - ], - [ - 'field' => 'note', - 'searchable' => false, - 'sortable' => false, - 'switchable' => true, - 'title' => trans('general.notes'), - 'visible' => true, - ], - [ - 'field' => 'created_at', - 'searchable' => false, - 'sortable' => false, - 'switchable' => true, - 'title' => trans('admin/hardware/table.checkout_date'), - 'visible' => true, - 'formatter' => 'dateDisplayFormatter', - ], - [ - 'field' => 'created_by', - 'searchable' => false, - 'sortable' => false, - 'title' => trans('general.created_by'), - 'visible' => false, - 'formatter' => 'usersLinkObjFormatter', - ], - [ - 'field' => 'available_actions', - 'searchable' => false, - 'sortable' => false, - 'switchable' => false, - 'title' => trans('table.actions'), - 'formatter' => 'accessoriesInOutFormatter', - ], - ]; - - return json_encode($layout); - } - + = /** * Link to this locations name * @return string */ public function nameUrl() { - return (string) link_to_route('locations.show', $this->name, $this->id); + return (string) link_to_route('suppliers.show', $this->name, $this->id); } /** @@ -278,12 +212,12 @@ class SupplierPresenter extends Presenter */ public function viewUrl() { - return route('locations.show', $this->id); + return route('suppliers.show', $this->id); } public function glyph() { - return ''; + return ''; } public function fullName() From 78d26fb7f6a41099918726662138876fed009609 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 May 2025 21:23:50 +0100 Subject: [PATCH 8/8] Removed stray character Typing is hard :( Signed-off-by: snipe --- app/Presenters/SupplierPresenter.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/Presenters/SupplierPresenter.php b/app/Presenters/SupplierPresenter.php index 1359b2da70..20957cc648 100644 --- a/app/Presenters/SupplierPresenter.php +++ b/app/Presenters/SupplierPresenter.php @@ -9,7 +9,6 @@ class SupplierPresenter extends Presenter { /** * Json Column Layout for bootstrap table - * @return string */ public static function dataTableLayout() { @@ -186,10 +185,10 @@ class SupplierPresenter extends Presenter return json_encode($layout); } + - = /** - * Link to this locations name + * Link to this supplier name * @return string */ public function nameUrl()