diff --git a/database/seeders/TestEventsSeeder.php b/database/seeders/TestEventsSeeder.php index 7de99e7..85fd98f 100644 --- a/database/seeders/TestEventsSeeder.php +++ b/database/seeders/TestEventsSeeder.php @@ -2,8 +2,15 @@ namespace Database\Seeders; +use App\Domains\Commerce\Catalog\Enums\InventoryPolicy; +use App\Domains\Commerce\Catalog\Models\Attribute; +use App\Domains\Commerce\Catalog\Models\CatalogItem; +use App\Domains\Commerce\Catalog\Models\Category; +use App\Domains\Commerce\Catalog\Services\CatalogService; use App\Domains\Core\Tenant\Models\Tenant; +use App\Domains\Ticketing\Event\Models\Event; use App\Shared\Attachable\Services\AttachmentService; +use App\Shared\Enums\FieldType; use Illuminate\Database\Seeder; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\DB; @@ -13,7 +20,10 @@ class TestEventsSeeder extends Seeder { private const IMAGE_DIRECTORY = 'images/tennants/onticket_otpimizado/test-events'; - public function __construct(private readonly AttachmentService $attachmentService) {} + public function __construct( + private readonly AttachmentService $attachmentService, + private readonly CatalogService $catalogService, + ) {} public function run(): void { @@ -22,6 +32,7 @@ class TestEventsSeeder extends Seeder $events = [ [ 'title' => '[Prueba] Noche de Música en Vivo', + 'slug' => 'prueba-noche-de-musica-en-vivo', 'category' => 'Música', 'subtitle' => 'Una noche para cantar y bailar', 'description' => 'Evento de prueba para explorar la cartelera de OnTicket.', @@ -30,9 +41,26 @@ class TestEventsSeeder extends Seeder 'weeks_from_now' => [2], 'time_start' => '21:00:00', 'time_end' => '23:30:00', + 'catalog_items' => [ + [ + 'slug' => 'prueba-noche-musica-entrada-general', + 'name' => 'Entrada general', + 'description' => 'Acceso general a la noche de música en vivo.', + 'price' => 18000, + 'stock' => 100, + ], + [ + 'slug' => 'prueba-noche-musica-entrada-vip', + 'name' => 'Entrada VIP', + 'description' => 'Acceso preferencial y ubicación VIP.', + 'price' => 32000, + 'stock' => 40, + ], + ], ], [ 'title' => '[Prueba] Festival de Sabores', + 'slug' => 'prueba-festival-de-sabores', 'category' => 'Otros', 'subtitle' => 'Gastronomía y música para toda la familia', 'description' => 'Evento de prueba con dos jornadas disponibles.', @@ -42,9 +70,26 @@ class TestEventsSeeder extends Seeder 'day_offsets' => [0, 1], 'time_start' => '12:00:00', 'time_end' => '20:00:00', + 'catalog_items' => [ + [ + 'slug' => 'prueba-festival-sabores-entrada-general', + 'name' => 'Entrada general', + 'description' => 'Acceso general para la jornada seleccionada.', + 'price' => 12000, + 'stock' => 150, + ], + [ + 'slug' => 'prueba-festival-sabores-pase-premium', + 'name' => 'Pase premium', + 'description' => 'Acceso premium para la jornada seleccionada.', + 'price' => 22000, + 'stock' => 50, + ], + ], ], [ 'title' => '[Prueba] Stand Up en el Centro', + 'slug' => 'prueba-stand-up-en-el-centro', 'category' => 'Teatro', 'subtitle' => 'Humor para compartir', 'description' => 'Evento de prueba para visualizar distintas propuestas.', @@ -53,14 +98,48 @@ class TestEventsSeeder extends Seeder 'weeks_from_now' => [4], 'time_start' => '20:30:00', 'time_end' => '22:00:00', + 'catalog_items' => [ + [ + 'slug' => 'prueba-stand-up-entrada-general', + 'name' => 'Entrada general', + 'description' => 'Acceso general al show de stand up.', + 'price' => 14000, + 'stock' => 120, + ], + [ + 'slug' => 'prueba-stand-up-primera-fila', + 'name' => 'Primera fila', + 'description' => 'Ubicación preferencial en primera fila.', + 'price' => 26000, + 'stock' => 30, + ], + ], ], ]; DB::transaction(function () use ($tenant, $events): void { + Attribute::query()->firstOrCreate( + [ + 'tenant_codigo' => $tenant->codigo, + 'codigo' => 'event_date', + ], + [ + 'nombre' => 'Fecha', + 'type' => FieldType::EventDate->value, + 'is_required' => true, + ], + ); + + $entryCategory = Category::query()->firstOrCreate([ + 'tenant_code' => $tenant->codigo, + 'nombre' => 'Entradas', + ]); + foreach ($events as $definition) { $event = $tenant->events()->firstOrCreate( ['title' => $definition['title']], [ + 'slug' => $definition['slug'], 'subtitle' => $definition['subtitle'], 'description' => $definition['description'], 'location' => $definition['location'], @@ -70,6 +149,10 @@ class TestEventsSeeder extends Seeder ], ); + if ($event->slug !== $definition['slug']) { + $event->update(['slug' => $definition['slug']]); + } + if ($event->event_category_id === null) { $event->update(['event_category_id' => $tenant->eventCategories() ->where('nombre', $definition['category'])->value('id')]); @@ -89,22 +172,65 @@ class TestEventsSeeder extends Seeder $event->update(['attachment_id' => $attachment->id]); } - if ($event->dates()->exists()) { - continue; + if (! $event->dates()->exists()) { + foreach ($definition['weeks_from_now'] as $index => $weeks) { + $date = now()->startOfDay()->addWeeks($weeks) + ->addDays($definition['day_offsets'][$index] ?? 0); + + $event->dates()->create([ + 'tenant_code' => $tenant->codigo, + 'date' => $date->toDateString(), + 'time_start' => $definition['time_start'], + 'time_end' => $definition['time_end'], + ]); + } } - foreach ($definition['weeks_from_now'] as $index => $weeks) { - $date = now()->startOfDay()->addWeeks($weeks) - ->addDays($definition['day_offsets'][$index] ?? 0); - - $event->dates()->create([ - 'tenant_code' => $tenant->codigo, - 'date' => $date->toDateString(), - 'time_start' => $definition['time_start'], - 'time_end' => $definition['time_end'], - ]); - } + $this->seedCatalogItems($tenant, $event, $entryCategory, $definition['catalog_items']); } }); } + + /** @param array> $definitions */ + private function seedCatalogItems( + Tenant $tenant, + Event $event, + Category $category, + array $definitions, + ): void { + $eventDateIds = $event->dates() + ->pluck('id') + ->map(fn ($id): int => (int) $id) + ->values(); + + foreach ($definitions as $order => $definition) { + $catalogItem = CatalogItem::query() + ->where('tenant_code', $tenant->codigo) + ->where('slug', $definition['slug']) + ->first(); + + if ($catalogItem === null) { + $catalogItem = $this->catalogService->create([ + 'tenant_code' => $tenant->codigo, + 'category_id' => $category->id, + 'slug' => $definition['slug'], + 'nombre' => $definition['name'], + 'descripcion' => $definition['description'], + 'precio' => $definition['price'], + 'group_order' => $order, + 'has_tickets' => true, + 'inventory_policy' => InventoryPolicy::Tracked->value, + 'attribute_codes' => ['event_date'], + 'hidden_attribute_codes' => ['event_date'], + 'images' => [$event->attachment->key], + 'variants' => $eventDateIds->map(fn (int $eventDateId): array => [ + 'real_stock' => $definition['stock'], + 'event_date_ids' => [$eventDateId], + ])->all(), + ]); + } + + $catalogItem->forceFill(['event_id' => $event->id])->save(); + } + } } diff --git a/tests/Feature/Seeders/TestEventsSeederTest.php b/tests/Feature/Seeders/TestEventsSeederTest.php index ef9b81d..7bb09e0 100644 --- a/tests/Feature/Seeders/TestEventsSeederTest.php +++ b/tests/Feature/Seeders/TestEventsSeederTest.php @@ -29,6 +29,12 @@ class TestEventsSeederTest extends TestCase $events = $tenant->events()->with('dates.validityTime')->get(); $this->assertCount(3, $events); $this->assertSame(4, $events->sum(fn ($event): int => $event->dates->count())); + $this->assertSame(6, $events->sum(fn ($event): int => $event->catalogItems()->count())); + $this->assertEqualsCanonicalizing([ + 'prueba-noche-de-musica-en-vivo', + 'prueba-festival-de-sabores', + 'prueba-stand-up-en-el-centro', + ], $events->pluck('slug')->all()); $this->assertEqualsCanonicalizing( ['live-music.avif', 'food-festival.avif', 'stand-up.avif'], $events->map(fn ($event): string => $event->attachment->filename)->all(), @@ -41,6 +47,19 @@ class TestEventsSeederTest extends TestCase $this->assertSame('image/avif', $event->attachment->mime_type); Storage::disk('s3')->assertExists($event->attachment->path); + $this->assertCount(2, $event->catalogItems); + + foreach ($event->catalogItems as $catalogItem) { + $this->assertTrue($catalogItem->has_tickets); + $this->assertSame('Entradas', $catalogItem->category->nombre); + $this->assertSame($event->id, $catalogItem->event_id); + $this->assertSame($event->dates->count(), $catalogItem->variants->count()); + $this->assertTrue($catalogItem->variants->every( + fn ($variant): bool => $variant->inventory->real_stock > 0 + && $variant->eventDates->count() === 1 + )); + } + foreach ($event->dates as $date) { $this->assertTrue($date->startsAt()->isFuture()); $this->assertNotNull($date->validityTime); @@ -51,6 +70,7 @@ class TestEventsSeederTest extends TestCase $this->assertCount(3, $tenant->events()->get()); $this->assertCount(4, $tenant->eventDates()->get()); + $this->assertCount(6, $tenant->catalogItems()->get()); $this->assertSame( $events->pluck('attachment_id')->all(), $tenant->events()->orderBy('id')->pluck('attachment_id')->all(),