diff --git a/app/Domains/Tenant/Controllers/BootstrapTenantController.php b/app/Domains/Tenant/Controllers/BootstrapTenantController.php index e8d899c..ed1d97e 100644 --- a/app/Domains/Tenant/Controllers/BootstrapTenantController.php +++ b/app/Domains/Tenant/Controllers/BootstrapTenantController.php @@ -16,7 +16,14 @@ class BootstrapTenantController extends Controller return TenantResource::make( Tenant::query() - ->with(['headerLogo', 'footerLogo', 'mainCarouselImages', 'menues', 'socialMedia']) + ->with([ + 'headerLogo', + 'footerLogo', + 'mainCarouselImages', + 'menues', + 'socialMedia', + 'categories' => fn ($query) => $query->orderBy('nombre'), + ]) ->where('dominio', $dominio) ->firstOrFail() ); diff --git a/app/Domains/Tenant/Models/Tenant.php b/app/Domains/Tenant/Models/Tenant.php index f1e5f07..0b183ba 100644 --- a/app/Domains/Tenant/Models/Tenant.php +++ b/app/Domains/Tenant/Models/Tenant.php @@ -6,6 +6,7 @@ use App\Domains\Attachable\Models\Attachment; use App\Domains\Catalog\Enums\GroupLayout; use App\Domains\Catalog\Enums\ProductLayout; use App\Domains\Catalog\Models\CatalogItem; +use App\Domains\Catalog\Models\Category; use App\Domains\Menu\Models\Menu; use App\Domains\Menu\Models\TenantMenu; use Illuminate\Database\Eloquent\Attributes\Fillable; @@ -109,6 +110,14 @@ class Tenant extends Model return $this->hasMany(CatalogItem::class, 'tenant_code', 'codigo'); } + /** + * @return HasMany + */ + public function categories(): HasMany + { + return $this->hasMany(Category::class, 'tenant_code', 'codigo'); + } + /** * @return BelongsToMany */ diff --git a/app/Domains/Tenant/Resources/TenantResource.php b/app/Domains/Tenant/Resources/TenantResource.php index 7592b37..989d169 100644 --- a/app/Domains/Tenant/Resources/TenantResource.php +++ b/app/Domains/Tenant/Resources/TenantResource.php @@ -2,6 +2,7 @@ namespace App\Domains\Tenant\Resources; +use App\Domains\Catalog\Models\Category; use App\Domains\Menu\Models\Menu; use App\Domains\Tenant\Models\Tenant; use Illuminate\Http\Request; @@ -64,9 +65,43 @@ class TenantResource extends JsonResource 'menues', fn () => $this->menuTree($this->menues) ), + 'categories' => $this->whenLoaded( + 'categories', + fn () => $this->categoryTree($this->categories) + ), ]; } + /** + * @param Collection $categories + * @return Collection> + */ + private function categoryTree(Collection $categories): Collection + { + $categoryIds = $categories->pluck('id')->flip(); + $childrenByParent = $categories + ->filter(fn (Category $category) => $category->categoria_id !== null + && $categoryIds->has($category->categoria_id)) + ->groupBy('categoria_id'); + + $formatCategory = function (Category $category) use (&$formatCategory, $childrenByParent): array { + return [ + 'id' => $category->id, + 'nombre' => $category->nombre, + 'subcategories' => $childrenByParent + ->get($category->id, collect()) + ->map($formatCategory) + ->values(), + ]; + }; + + return $categories + ->filter(fn (Category $category) => $category->categoria_id === null + || ! $categoryIds->has($category->categoria_id)) + ->map($formatCategory) + ->values(); + } + /** * @param Collection $menus * @return Collection> diff --git a/tests/Feature/Tenant/BootstrapTenantControllerTest.php b/tests/Feature/Tenant/BootstrapTenantControllerTest.php index b6ec956..8e74b82 100644 --- a/tests/Feature/Tenant/BootstrapTenantControllerTest.php +++ b/tests/Feature/Tenant/BootstrapTenantControllerTest.php @@ -4,6 +4,7 @@ namespace Tests\Feature\Tenant; use App\Domains\Attachable\Enums\AttachmentType; use App\Domains\Attachable\Models\Attachment; +use App\Domains\Catalog\Models\Category; use App\Domains\Menu\Models\Menu; use App\Domains\Tenant\Models\Tenant; use Illuminate\Foundation\Testing\RefreshDatabase; @@ -95,6 +96,45 @@ class BootstrapTenantControllerTest extends TestCase ->assertJsonPath('data.dominio', 'acme.com'); } + public function test_it_returns_only_the_tenant_categories_in_the_bootstrap(): void + { + $tenant = $this->createTenant(); + $otherTenant = $this->createTenant([ + 'codigo' => 'globex', + 'nombre' => 'Globex', + 'dominio' => 'globex.com', + ]); + + $parent = Category::query()->create([ + 'tenant_code' => $tenant->codigo, + 'nombre' => 'Remeras', + ]); + Category::query()->create([ + 'tenant_code' => $tenant->codigo, + 'categoria_id' => $parent->id, + 'nombre' => 'Manga corta', + ]); + Category::query()->create([ + 'tenant_code' => $otherTenant->codigo, + 'nombre' => 'Otra categoría', + ]); + Category::query()->create([ + 'tenant_code' => null, + 'nombre' => 'Global', + ]); + + $this->getJson('/api/tenants/bootstrap/acme.com') + ->assertOk() + ->assertJsonCount(1, 'data.categories') + ->assertJsonPath('data.categories.0.nombre', 'Remeras') + ->assertJsonCount(1, 'data.categories.0.subcategories') + ->assertJsonPath('data.categories.0.subcategories.0.nombre', 'Manga corta') + ->assertJsonPath('data.categories.0.subcategories.0.subcategories', []) + ->assertJsonMissingPath('data.categories.0.categoria_id') + ->assertJsonMissing(['nombre' => 'Otra categoría']) + ->assertJsonMissing(['nombre' => 'Global']); + } + public function test_it_returns_not_found_when_the_domain_does_not_exist(): void { $response = $this->getJson('/api/tenants/bootstrap/missing.example');