From 416b32cbc896a47f25979f35389bbcc68631e140 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 26 Nov 2025 12:36:44 +0000 Subject: [PATCH] Optimize queries for Components listing --- .../Controllers/Api/ComponentsController.php | 9 +++++---- app/Models/Component.php | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Api/ComponentsController.php b/app/Http/Controllers/Api/ComponentsController.php index 57bd6fe589..68695cf821 100644 --- a/app/Http/Controllers/Api/ComponentsController.php +++ b/app/Http/Controllers/Api/ComponentsController.php @@ -58,8 +58,8 @@ class ComponentsController extends Controller ]; $components = Component::select('components.*') - ->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser', 'manufacturer', 'uncontrainedAssets') - ->withSum('uncontrainedAssets', 'components_assets.assigned_qty'); + ->with('company', 'location', 'category', 'supplier', 'adminuser', 'manufacturer') + ->withSum('uncontrainedAssets as sum_unconstrained_assets', 'components_assets.assigned_qty'); $filter = []; @@ -112,7 +112,8 @@ class ComponentsController extends Controller } // Make sure the offset and limit are actually integers and do not exceed system limits - $offset = ($request->input('offset') > $components->count()) ? $components->count() : app('api_offset_value'); + $components_count = $components->count(); + $offset = ($request->input('offset') > $components_count) ? $components_count : app('api_offset_value'); $limit = app('api_limit_value'); $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; @@ -143,7 +144,7 @@ class ComponentsController extends Controller break; } - $total = $components->count(); + $total = $components_count; $components = $components->skip($offset)->take($limit)->get(); return (new ComponentsTransformer)->transformComponents($components, $total); diff --git a/app/Models/Component.php b/app/Models/Component.php index 14c4521fc4..7493d204c4 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -238,14 +238,26 @@ class Component extends SnipeModel * @since [v5.0] * @return int */ - public function numCheckedOut() + public function numCheckedOut(bool $recalculate = false) { - $checkedout = 0; + /** + * + * WARNING: This method caches the result, so if you're doing something + * that is going to change the number of checked-out items, make sure to pass + * 'true' as the first parameter to force this to recalculate the number of checked-out + * items!!!!! + * + */ // In case there are elements checked out to assets that belong to a different company // than this asset and full multiple company support is on we'll remove the global scope, // so they are included in the count. - return $this->uncontrainedAssets->sum('pivot.assigned_qty'); + if (is_null($this->sum_unconstrained_assets) || $recalculate) { + // This, in a components-listing context, is mostly important for when it sets a 'zero' which + // is *not* null - so we don't have to keep recalculating for un-checked-out components + $this->sum_unconstrained_assets = $this->uncontrainedAssets()->sum('assigned_qty') ?? 0; + } + return $this->sum_unconstrained_assets; }