From 36eb41a18ab7468fc928292376a5582252ab41b7 Mon Sep 17 00:00:00 2001 From: nahu Date: Sat, 22 Aug 2026 14:16:57 +0000 Subject: [PATCH] feat(invitation): update seat allocation structure and enhance provisioning logic --- .../InvitationPurchaseProvisioner.php | 20 +++++++++------ ...22_000000_add_desfile_invitation_seats.php | 25 +++++++++++++++++++ .../DesfilePuraTendenciaSeederTest.php | 23 ++++++++++++++--- 3 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 database/migrations/2026_08_22_000000_add_desfile_invitation_seats.php diff --git a/app/Domains/Desfile/Services/InvitationPurchaseProvisioner.php b/app/Domains/Desfile/Services/InvitationPurchaseProvisioner.php index 0275cd5..6e76244 100644 --- a/app/Domains/Desfile/Services/InvitationPurchaseProvisioner.php +++ b/app/Domains/Desfile/Services/InvitationPurchaseProvisioner.php @@ -17,21 +17,25 @@ class InvitationPurchaseProvisioner private const PAYMENT_METHOD = 'invitation'; /** - * @var list + * @var list */ private const ALLOCATIONS = [ - ['sector' => 'A', 'row' => 1, 'seats' => 16, 'type' => 'NORMAL'], - ['sector' => 'A', 'row' => 3, 'seats' => 14, 'type' => 'NORMAL'], - ['sector' => 'C', 'row' => 1, 'seats' => 16, 'type' => 'VIP + LUNCH'], + ['sector' => 'A', 'row' => 1, 'first_seat' => 1, 'last_seat' => 16, 'type' => 'NORMAL'], + ['sector' => 'A', 'row' => 3, 'first_seat' => 1, 'last_seat' => 14, 'type' => 'NORMAL'], + ['sector' => 'C', 'row' => 1, 'first_seat' => 1, 'last_seat' => 16, 'type' => 'VIP + LUNCH'], + ['sector' => 'C', 'row' => 3, 'first_seat' => 6, 'last_seat' => 7, 'type' => 'NORMAL'], ]; - public function provision(): void + /** + * @param list|null $allocations + */ + public function provision(?array $allocations = null): void { if (! $this->prerequisitesExist()) { return; } - DB::transaction(function (): void { + DB::transaction(function () use ($allocations): void { $now = now(); $userId = $this->userId($now); $purchaseId = $this->purchaseId($userId, $now); @@ -44,8 +48,8 @@ class InvitationPurchaseProvisioner throw new RuntimeException('No se encontró el catálogo de entradas del desfile.'); } - foreach (self::ALLOCATIONS as $allocation) { - foreach (range(1, $allocation['seats']) as $seat) { + foreach ($allocations ?? self::ALLOCATIONS as $allocation) { + foreach (range($allocation['first_seat'], $allocation['last_seat']) as $seat) { $variant = $this->variant( (int) $catalogItem->id, $allocation['sector'], diff --git a/database/migrations/2026_08_22_000000_add_desfile_invitation_seats.php b/database/migrations/2026_08_22_000000_add_desfile_invitation_seats.php new file mode 100644 index 0000000..7af359f --- /dev/null +++ b/database/migrations/2026_08_22_000000_add_desfile_invitation_seats.php @@ -0,0 +1,25 @@ +provision([ + [ + 'sector' => 'C', + 'row' => 3, + 'first_seat' => 6, + 'last_seat' => 7, + 'type' => 'NORMAL', + ], + ]); + } + + public function down(): void + { + // Intentionally irreversible: issued invitation tickets may already be used. + } +}; diff --git a/tests/Feature/Seeders/DesfilePuraTendenciaSeederTest.php b/tests/Feature/Seeders/DesfilePuraTendenciaSeederTest.php index cdfa29a..16deae3 100644 --- a/tests/Feature/Seeders/DesfilePuraTendenciaSeederTest.php +++ b/tests/Feature/Seeders/DesfilePuraTendenciaSeederTest.php @@ -288,19 +288,19 @@ class DesfilePuraTendenciaSeederTest extends TestCase $items = DB::table('compra_items')->where('compra_id', $purchase->id); - $this->assertSame(46, (clone $items)->count()); - $this->assertSame(46, (clone $items) + $this->assertSame(48, (clone $items)->count()); + $this->assertSame(48, (clone $items) ->where('precio_unitario', 0) ->where('discount_total', 0) ->where('tax_total', 0) ->where('total', 0) ->count()); - $this->assertSame(46, DB::table('tickets') + $this->assertSame(48, DB::table('tickets') ->where('source_purchase_id', $purchase->id) ->where('user_id', $user->id) ->where('source_catalog_item_id', $catalogItemId) ->count()); - $this->assertSame(46, DB::table('stock_reservations') + $this->assertSame(48, DB::table('stock_reservations') ->where('purchase_id', $purchase->id) ->where('status', 'committed') ->count()); @@ -309,6 +309,7 @@ class DesfilePuraTendenciaSeederTest extends TestCase ['sector' => 'A', 'fila' => '1', 'tipo' => 'NORMAL', 'count' => 16], ['sector' => 'A', 'fila' => '3', 'tipo' => 'NORMAL', 'count' => 14], ['sector' => 'C', 'fila' => '1', 'tipo' => 'VIP + LUNCH', 'count' => 16], + ['sector' => 'C', 'fila' => '3', 'tipo' => 'NORMAL', 'count' => 2, 'seats' => ['6', '7']], ] as $allocation) { $allocatedVariants = DB::table('variantes') ->where('catalog_item_id', $catalogItemId) @@ -326,6 +327,20 @@ class DesfilePuraTendenciaSeederTest extends TestCase } $this->assertSame($allocation['count'], $allocatedVariants->count()); + + if (isset($allocation['seats'])) { + $seatValues = DB::table('variant_values') + ->join('item_attributes', 'item_attributes.id', '=', 'variant_values.item_attribute_id') + ->join('attribute', 'attribute.id', '=', 'item_attributes.attribute_id') + ->whereIn('variant_values.variant_id', (clone $allocatedVariants)->pluck('id')) + ->where('attribute.codigo', 'asiento') + ->pluck('variant_values.value') + ->sort() + ->values() + ->all(); + + $this->assertSame($allocation['seats'], $seatValues); + } } }