From 0d3877c2aec1768109c9c4f5352460e35d2d661f Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 15 Oct 2026 19:05:14 +0800 Subject: [PATCH 1/2] feat(categories): include parent_uuid in internal category responses A console building a category tree from a flat list (Storefront's nested product categories) needs each category's parent without loading it. The internal Category resource now sends parent_uuid; public responses do not. --- RELEASE.md | 4 ++++ src/Http/Resources/Category.php | 2 ++ tests/Unit/Http/ResourceResponseContractsTest.php | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 5a041461..becabdd7 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,9 @@ # v1.6.71 — Keep live and test-mode API caches apart; driver-assigned events on driver channels +## Added + +- **Category `parent_uuid` on internal responses.** The internal Category resource now includes `parent_uuid`, so a console can build a category tree from a flat list (Storefront's nested product categories). (#PR) + ## Fixed - **A controller's filter is used for every query it serves.** `Find::httpFilterForModel()` cached its answer per model class for the life of the process, ignoring the filter a controller sets on its model (`$filter`) and whether the request was internal. Under Octane, the first controller to list a model decided the filter for every other: Fleet-Ops' order filter was applied to Storefront's order lists, so a network's orders page listed every order in the company. The cache is now keyed by the model's own filter, and a filter found by convention is picked per request audience. `Find::httpRequestForModel()` is keyed by the model's own request class too. (#315) diff --git a/src/Http/Resources/Category.php b/src/Http/Resources/Category.php index 5ade4f5c..d4c43cbb 100644 --- a/src/Http/Resources/Category.php +++ b/src/Http/Resources/Category.php @@ -34,6 +34,8 @@ public function toArray($request) 'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid), 'owner_uuid' => $this->when(Http::isInternalRequest(), $this->owner_uuid), 'owner_type' => $this->when(Http::isInternalRequest(), $this->owner_type), + // Lets a console build a category tree from a flat list without loading each parent. + 'parent_uuid' => $this->when(Http::isInternalRequest(), $this->parent_uuid), 'icon' => $this->icon, 'icon_url' => $this->icon_url, 'name' => $this->name, diff --git a/tests/Unit/Http/ResourceResponseContractsTest.php b/tests/Unit/Http/ResourceResponseContractsTest.php index d9ee4550..418d9264 100644 --- a/tests/Unit/Http/ResourceResponseContractsTest.php +++ b/tests/Unit/Http/ResourceResponseContractsTest.php @@ -258,7 +258,7 @@ function schedule_template_resource_model(array $attributes = []): ScheduleTempl ])); expect($payload['id'])->toBe('cat_1') - ->and($payload)->not->toHaveKeys(['uuid', 'company_uuid', 'owner_uuid', 'owner_type', 'public_id']) + ->and($payload)->not->toHaveKeys(['uuid', 'company_uuid', 'owner_uuid', 'owner_type', 'public_id', 'parent_uuid']) ->and($payload['name'])->toBe('Operations') ->and($payload['icon_url'])->toBe('https://flb-assets.s3.ap-southeast-1.amazonaws.com/images/fallback-placeholder-1.png') ->and($payload['tags'])->toBe(['ops', 'dispatch']) @@ -283,7 +283,7 @@ function schedule_template_resource_model(array $attributes = []): ScheduleTempl 'public_id' => 'cat_child', 'name' => 'Child Category', ]); - $category = category_resource_model([]); + $category = category_resource_model(['parent_uuid' => 'category-parent']); $category->setRelation('parentCategory', $parent); $category->setRelation('subCategories', collect([$child])); @@ -301,6 +301,8 @@ function schedule_template_resource_model(array $attributes = []): ScheduleTempl ->and($payload['company_uuid'])->toBe('company-1') ->and($payload['owner_uuid'])->toBe('owner-1') ->and($payload['owner_type'])->toBe('company') + // A console builds its tree from parent_uuid without loading each parent. + ->and($payload['parent_uuid'])->toBe('category-parent') ->and($payload)->not->toHaveKeys(['parent', 'subcategories']); $withParent = (new CategoryResource($category))->resolve(resource_contract_request('/int/v1/categories/category-1', [ From c31a3f0b6f7a8c8a68e3869eed92d56fc36ab2ac Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 15 Oct 2026 19:05:38 +0800 Subject: [PATCH 2/2] docs(release): link the category parent_uuid change --- RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index becabdd7..d018dfd2 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,7 +2,7 @@ ## Added -- **Category `parent_uuid` on internal responses.** The internal Category resource now includes `parent_uuid`, so a console can build a category tree from a flat list (Storefront's nested product categories). (#PR) +- **Category `parent_uuid` on internal responses.** The internal Category resource now includes `parent_uuid`, so a console can build a category tree from a flat list (Storefront's nested product categories). (#316) ## Fixed