feat: Introduce source type for featured groups; add category association and implement FeaturedGroupService for item sourcing

This commit is contained in:
2026-08-04 13:17:00 -03:00
parent 8aa3a26ee7
commit 84e45bb964
13 changed files with 260 additions and 136 deletions

View File

@@ -0,0 +1,31 @@
<?php
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('featured_groups', function (Blueprint $table): void {
$table->enum('source_type', FeaturedGroupSource::values())
->default(FeaturedGroupSource::Manual->value)
->after('tenant_code');
$table->foreignId('category_id')
->nullable()
->after('source_type')
->constrained('categorias')
->nullOnDelete();
});
}
public function down(): void
{
Schema::table('featured_groups', function (Blueprint $table): void {
$table->dropConstrainedForeignId('category_id');
$table->dropColumn('source_type');
});
}
};

View File

@@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Domains\Catalog\Enums\CatalogItemType;
use App\Domains\Catalog\Enums\EventProductType;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\InventoryPolicy;
use App\Domains\Catalog\Enums\ProductLayout;
@@ -61,6 +62,18 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
'nombre' => 'Gastronomía',
'tenant_code' => $tenant->codigo,
]);
$mealCategory = Category::query()->updateOrCreate([
'nombre' => 'Comidas',
'tenant_code' => $tenant->codigo,
], [
'categoria_id' => $foodCategory->id,
]);
$drinkCategory = Category::query()->updateOrCreate([
'nombre' => 'Bebidas',
'tenant_code' => $tenant->codigo,
], [
'categoria_id' => $foodCategory->id,
]);
$parkingCategory = Category::query()->firstOrCreate([
'nombre' => 'Estacionamiento',
'tenant_code' => $tenant->codigo,
@@ -93,10 +106,10 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
]);
$items = [
['slug' => 'hamburguesa-papa-frita', 'nombre' => 'Hamburguesa con papa frita', 'precio' => 8000, 'category_id' => $foodCategory->id],
['slug' => 'pancho', 'nombre' => 'Pancho', 'precio' => 4000, 'category_id' => $foodCategory->id],
['slug' => 'coca-cola-500ml', 'nombre' => 'Coca Cola 500ml', 'precio' => 3000, 'category_id' => $foodCategory->id],
['slug' => 'agua-mineral-1l', 'nombre' => 'Agua Mineral 1L', 'precio' => 2500, 'category_id' => $foodCategory->id],
['slug' => 'hamburguesa-papa-frita', 'nombre' => 'Hamburguesa con papa frita', 'precio' => 8000, 'category_id' => $mealCategory->id],
['slug' => 'pancho', 'nombre' => 'Pancho', 'precio' => 4000, 'category_id' => $mealCategory->id],
['slug' => 'coca-cola-500ml', 'nombre' => 'Coca Cola 500ml', 'precio' => 3000, 'category_id' => $drinkCategory->id],
['slug' => 'agua-mineral-1l', 'nombre' => 'Agua Mineral 1L', 'precio' => 2500, 'category_id' => $drinkCategory->id],
['slug' => 'estacionamiento-auto', 'nombre' => 'Estacionamiento Auto', 'precio' => 5000, 'category_id' => $parkingCategory->id],
['slug' => 'estacionamiento-moto', 'nombre' => 'Estacionamiento Moto', 'precio' => 2000, 'category_id' => $parkingCategory->id],
];
@@ -144,7 +157,7 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
'nombre' => 'Combo 2 Panchos + 2 Hamburguesas',
'descripcion' => 'Incluye 2 panchos y 2 hamburguesas con papa frita.',
'precio' => 24000,
'category_id' => $foodCategory->id,
'category_id' => $mealCategory->id,
'components' => [
[
'catalog_item_id' => $createdItems['pancho']->id,
@@ -157,7 +170,12 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
],
]);
$this->seedFeaturedGroups($tenant);
$this->seedFeaturedGroups($tenant, [
'Entradas' => $ticketCategory,
'Estacionamiento' => $parkingCategory,
'Comidas' => $mealCategory,
'Bebidas' => $drinkCategory,
]);
}
private function deleteExistingCatalog(Tenant $tenant): void
@@ -173,7 +191,8 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
->each(fn (CatalogItem $item) => $this->catalogService->delete($item));
}
private function seedFeaturedGroups(Tenant $tenant): void
/** @param array<string, Category> $categories */
private function seedFeaturedGroups(Tenant $tenant, array $categories): void
{
FeaturedGroup::query()->where('tenant_code', $tenant->codigo)->delete();
@@ -181,62 +200,33 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
'Entradas' => [
'product_layout' => ProductLayout::Row,
'group_layout' => GroupLayout::SimpleVertical,
'slugs' => [
'entrada-general',
'entrada-general-todos-los-dias',
],
],
'Estacionamiento' => [
'product_layout' => ProductLayout::ColumnWithCart,
'group_layout' => GroupLayout::Simple,
'slugs' => [
'estacionamiento-auto',
'estacionamiento-moto',
],
],
'Comidas' => [
'product_layout' => ProductLayout::ColumnWithCart,
'group_layout' => GroupLayout::Simple,
'slugs' => [
'hamburguesa-papa-frita',
'pancho',
'combo-2-panchos-2-hamburguesas',
],
],
'Bebidas' => [
'product_layout' => ProductLayout::ColumnWithCart,
'group_layout' => GroupLayout::Simple,
'slugs' => [
'coca-cola-500ml',
'agua-mineral-1l',
],
],
];
$catalogItems = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->whereIn('slug', collect($groups)->pluck('slugs')->flatten()->all())
->get()
->keyBy('slug');
$groupOrder = 0;
foreach ($groups as $groupName => $config) {
$featuredGroup = FeaturedGroup::query()->create([
FeaturedGroup::query()->create([
'tenant_code' => $tenant->codigo,
'source_type' => FeaturedGroupSource::Category,
'category_id' => $categories[$groupName]->id,
'product_layout' => $config['product_layout'],
'group_layout' => $config['group_layout'],
'group_name' => $groupName,
'group_order' => $groupOrder++,
]);
$featuredGroup->featuredItems()->createMany(
collect($config['slugs'])->values()->map(
fn (string $slug, int $order): array => [
'catalog_item_id' => $catalogItems->get($slug)->id,
'order' => $order,
]
)->all()
);
}
}
}

View File

@@ -2,6 +2,7 @@
namespace Database\Seeders;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\InventoryPolicy;
use App\Domains\Catalog\Enums\ProductLayout;
@@ -168,30 +169,18 @@ class ProductCatalogFromImagesSeeder extends Seeder
{
FeaturedGroup::query()->where('tenant_code', $tenant->codigo)->delete();
$paginatedGroup = FeaturedGroup::query()->create([
FeaturedGroup::query()->create([
'tenant_code' => $tenant->codigo,
'source_type' => FeaturedGroupSource::All,
'product_layout' => ProductLayout::ColumnWithImage,
'group_layout' => GroupLayout::Paginated,
'group_name' => 'Productos',
'group_order' => 2,
]);
$items = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->orderBy('id')
->get('id');
$paginatedGroup->featuredItems()->createMany(
$items->values()->map(
fn (CatalogItem $item, int $order): array => [
'catalog_item_id' => $item->id,
'order' => $order,
]
)->all()
);
$carouselGroup = FeaturedGroup::query()->create([
'tenant_code' => $tenant->codigo,
'source_type' => FeaturedGroupSource::Manual,
'product_layout' => ProductLayout::ColumnWithImage,
'group_layout' => GroupLayout::Carousel,
'group_name' => 'Productos destacados',