diff --git a/app/Domains/Catalog/Models/CatalogItem.php b/app/Domains/Catalog/Models/CatalogItem.php index 2828f65..2d31200 100644 --- a/app/Domains/Catalog/Models/CatalogItem.php +++ b/app/Domains/Catalog/Models/CatalogItem.php @@ -27,6 +27,7 @@ use Illuminate\Support\Collection; 'type', 'slug', 'nombre', + 'group_order', 'descripcion', 'precio', 'inventory_policy', @@ -47,6 +48,7 @@ class CatalogItem extends Model 'inventory_policy' => InventoryPolicy::Tracked->value, 'inventory_subject' => InventorySubject::Product->value, 'has_tickets' => false, + 'group_order' => 0, ]; protected function casts(): array @@ -56,6 +58,7 @@ class CatalogItem extends Model 'brand_id' => 'integer', 'inventory_id' => 'integer', 'type' => CatalogItemType::class, + 'group_order' => 'integer', 'precio' => 'decimal:2', 'inventory_policy' => InventoryPolicy::class, 'inventory_subject' => InventorySubject::class, diff --git a/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php b/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php index 9a39f5c..4827d96 100644 --- a/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php +++ b/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php @@ -51,6 +51,7 @@ class StoreCatalogItemRequest extends FormRequest ), ], 'nombre' => ['required', 'string', 'max:255'], + 'group_order' => ['sometimes', 'integer', 'min:0'], 'descripcion' => ['sometimes', 'nullable', 'string'], 'precio' => ['required', 'numeric', 'min:0'], 'inventory_policy' => [Rule::prohibitedIf($isBundle), 'sometimes', Rule::enum(InventoryPolicy::class)], diff --git a/app/Domains/Catalog/Services/FeaturedGroupService.php b/app/Domains/Catalog/Services/FeaturedGroupService.php index f01b679..6e807b5 100644 --- a/app/Domains/Catalog/Services/FeaturedGroupService.php +++ b/app/Domains/Catalog/Services/FeaturedGroupService.php @@ -72,7 +72,9 @@ class FeaturedGroupService FeaturedGroupSource::Category => $query ->where('catalog_items.category_id', $featuredGroup->category_id) ->orderBy('catalog_items.id'), - FeaturedGroupSource::All => $query->orderBy('catalog_items.id'), + FeaturedGroupSource::All => $query + ->orderBy('catalog_items.group_order') + ->orderBy('catalog_items.id'), }; } diff --git a/database/migrations/2026_08_25_000000_add_group_order_to_catalog_items.php b/database/migrations/2026_08_25_000000_add_group_order_to_catalog_items.php new file mode 100644 index 0000000..31ad1fa --- /dev/null +++ b/database/migrations/2026_08_25_000000_add_group_order_to_catalog_items.php @@ -0,0 +1,53 @@ +unsignedInteger('group_order')->default(0)->after('nombre'); + }); + + $footballOrder = [ + 1 => [ + 'slugs' => ['camiseta', 'camiseta-oficial-fnfi'], + 'names' => ['Camiseta', 'CAMISETA OFICIAL FNFI'], + ], + 2 => [ + 'slugs' => ['alojamiento', 'camping'], + 'names' => ['Alojamiento', 'CAMPING'], + ], + 3 => [ + 'slugs' => ['abono'], + 'names' => ['Abono', 'ABONO'], + ], + 4 => [ + 'slugs' => ['comida'], + 'names' => ['Comida', 'COMIDA'], + ], + ]; + + foreach ($footballOrder as $order => $identifiers) { + DB::table('catalog_items') + ->where('tenant_code', 'fiesta_futbol_infantil') + ->where(function ($query) use ($identifiers): void { + $query + ->whereIn('slug', $identifiers['slugs']) + ->orWhereIn('nombre', $identifiers['names']); + }) + ->update(['group_order' => $order]); + } + } + + public function down(): void + { + Schema::table('catalog_items', function (Blueprint $table): void { + $table->dropColumn('group_order'); + }); + } +}; diff --git a/database/seeders/FiestaFutbolInfantilProductSeeder.php b/database/seeders/FiestaFutbolInfantilProductSeeder.php index 5a65a8c..00bea4a 100644 --- a/database/seeders/FiestaFutbolInfantilProductSeeder.php +++ b/database/seeders/FiestaFutbolInfantilProductSeeder.php @@ -78,6 +78,7 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $this->createProduct($tenant, [ 'slug' => 'camiseta', 'nombre' => 'Camiseta', + 'group_order' => 1, 'category_id' => $categories['merchandising']->id, 'precio' => 18000, 'attribute_codes' => ['color', 'talle'], @@ -92,6 +93,7 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $this->createProduct($tenant, [ 'slug' => 'alojamiento', 'nombre' => 'Alojamiento', + 'group_order' => 2, 'category_id' => $categories['alojamientos']->id, 'precio' => 35000, 'attribute_codes' => ['tipo_alojamiento'], @@ -104,6 +106,7 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $this->createProduct($tenant, [ 'slug' => 'comida', 'nombre' => 'Comida', + 'group_order' => 4, 'category_id' => $categories['comidas']->id, 'precio' => 4000, 'attribute_codes' => ['event_date', 'horario', 'servicio'], @@ -126,6 +129,7 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $this->createProduct($tenant, [ 'slug' => 'abono', 'nombre' => 'Abono', + 'group_order' => 3, 'category_id' => $categories['entradas']->id, 'precio' => 40000, 'has_tickets' => true, diff --git a/tests/Feature/Catalog/CatalogControllerTest.php b/tests/Feature/Catalog/CatalogControllerTest.php index 63f1051..900dcf8 100644 --- a/tests/Feature/Catalog/CatalogControllerTest.php +++ b/tests/Feature/Catalog/CatalogControllerTest.php @@ -354,8 +354,10 @@ class CatalogControllerTest extends TestCase ]); $food = $this->createItem($tenant, 'Hamburger'); + $food->update(['group_order' => 2]); $food->category()->associate($category)->save(); - $this->createItem($tenant, 'Parking'); + $parking = $this->createItem($tenant, 'Parking'); + $parking->update(['group_order' => 1]); $this->getJson("/api/tenants/{$tenant->codigo}/catalog") ->assertOk() @@ -364,6 +366,9 @@ class CatalogControllerTest extends TestCase ->assertJsonPath('0.items.0.nombre', 'Hamburger') ->assertJsonPath('1.title', 'All products') ->assertJsonCount(2, '1.items.data') + ->assertJsonPath('1.items.data.0.nombre', 'Parking') + ->assertJsonPath('1.items.data.1.nombre', 'Hamburger') + ->assertJsonMissingPath('1.items.data.0.group_order') ->assertJsonPath('1.items.meta.total', 2); } diff --git a/tests/Feature/Catalog/CatalogItemControllerTest.php b/tests/Feature/Catalog/CatalogItemControllerTest.php index 4e2e359..c805fe5 100644 --- a/tests/Feature/Catalog/CatalogItemControllerTest.php +++ b/tests/Feature/Catalog/CatalogItemControllerTest.php @@ -31,6 +31,7 @@ class CatalogItemControllerTest extends TestCase $response = $this->postJson("/api/tenants/{$tenant->codigo}/catalog-items", [ 'slug' => 'shirt', 'nombre' => 'Shirt', + 'group_order' => 7, 'precio' => 100, 'max_units_per_user' => 4, 'attribute_codes' => [$attribute->codigo], @@ -47,6 +48,7 @@ class CatalogItemControllerTest extends TestCase $response ->assertCreated() ->assertJsonPath('data.nombre', 'Shirt') + ->assertJsonMissingPath('data.group_order') ->assertJsonPath('data.max_units_per_user', 4) ->assertJsonCount(2, 'data.images') ->assertJsonCount(1, 'data.variants') @@ -57,6 +59,7 @@ class CatalogItemControllerTest extends TestCase $this->assertSame([0, 1], $item->attachments()->get()->pluck('pivot.orden')->all()); $this->assertSame(4, $item->max_units_per_user); + $this->assertSame(7, $item->group_order); $this->assertSame([0], $variant->attachments()->get()->pluck('pivot.orden')->all()); $this->assertDatabaseHas('catalog_items_attachments', [ 'catalog_item_id' => $item->id, diff --git a/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php b/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php index 512cf9b..6fe8fdd 100644 --- a/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php +++ b/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php @@ -70,6 +70,14 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase ['abono', 'alojamiento', 'camiseta', 'comida'], CatalogItem::query()->where('tenant_code', $tenant->codigo)->orderBy('slug')->pluck('slug')->all(), ); + $this->assertSame( + ['camiseta', 'alojamiento', 'abono', 'comida'], + CatalogItem::query() + ->where('tenant_code', $tenant->codigo) + ->orderBy('group_order') + ->pluck('slug') + ->all(), + ); $this->assertTrue( CatalogItem::query() ->where('tenant_code', $tenant->codigo) diff --git a/tests/Unit/Catalog/CatalogModelsTest.php b/tests/Unit/Catalog/CatalogModelsTest.php index 1204a6f..84ef63d 100644 --- a/tests/Unit/Catalog/CatalogModelsTest.php +++ b/tests/Unit/Catalog/CatalogModelsTest.php @@ -83,11 +83,13 @@ class CatalogModelsTest extends TestCase public function test_catalog_item_is_the_catalog_root(): void { $item = new CatalogItem; + $this->assertSame(0, $item->group_order); $item->setRawAttributes([ 'category_id' => '10', 'brand_id' => '20', 'inventory_id' => '30', 'type' => CatalogItemType::Standard->value, + 'group_order' => '4', 'precio' => '12.50', 'inventory_policy' => InventoryPolicy::Tracked->value, 'inventory_subject' => InventorySubject::Seat->value, @@ -100,6 +102,7 @@ class CatalogModelsTest extends TestCase $this->assertSame(20, $item->brand_id); $this->assertSame(30, $item->inventory_id); $this->assertSame(CatalogItemType::Standard, $item->type); + $this->assertSame(4, $item->group_order); $this->assertSame('12.50', $item->precio); $this->assertSame(InventoryPolicy::Tracked, $item->inventory_policy); $this->assertSame(InventorySubject::Seat, $item->inventory_subject);