diff --git a/RELEASE.md b/RELEASE.md index 5a041461..d018dfd2 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). (#316) + ## 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', [