From 38f74739daec383b460853c84693d375ebdd7123 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Tue, 21 Jul 2026 12:27:26 -0300 Subject: [PATCH] feat(ticket): add source IDs to tickets and update related services and tests --- .../GenerateTicketsForPaidPurchase.php | 1 + app/Domains/Ticket/Models/Ticket.php | 4 +++ .../Services/TicketGeneratorService.php | 12 ++++++--- ...000300_add_source_ids_to_tickets_table.php | 23 +++++++++++++++++ .../Ticket/TicketGeneratorServiceTest.php | 25 ++++++++++++++++--- tests/Unit/Ticket/TicketTest.php | 4 +++ 6 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 database/migrations/2026_07_21_000300_add_source_ids_to_tickets_table.php diff --git a/app/Domains/Ticket/Listeners/GenerateTicketsForPaidPurchase.php b/app/Domains/Ticket/Listeners/GenerateTicketsForPaidPurchase.php index 990fc31..6d7fcb0 100644 --- a/app/Domains/Ticket/Listeners/GenerateTicketsForPaidPurchase.php +++ b/app/Domains/Ticket/Listeners/GenerateTicketsForPaidPurchase.php @@ -42,6 +42,7 @@ class GenerateTicketsForPaidPurchase $catalogItem, $user, $purchaseItem->cantidad, + $purchaseItem->source_variant_id, ); } } diff --git a/app/Domains/Ticket/Models/Ticket.php b/app/Domains/Ticket/Models/Ticket.php index 0b6d048..e0aaa74 100644 --- a/app/Domains/Ticket/Models/Ticket.php +++ b/app/Domains/Ticket/Models/Ticket.php @@ -14,6 +14,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; 'ticket', 'name', 'description', + 'source_catalog_item_id', + 'source_variant_id', 'starts_at', 'expires_at', 'used_at', @@ -34,6 +36,8 @@ class Ticket extends Model protected function casts(): array { return [ + 'source_catalog_item_id' => 'integer', + 'source_variant_id' => 'integer', 'starts_at' => 'datetime', 'expires_at' => 'datetime', 'used_at' => 'datetime', diff --git a/app/Domains/Ticket/Services/TicketGeneratorService.php b/app/Domains/Ticket/Services/TicketGeneratorService.php index 614850a..90f920b 100644 --- a/app/Domains/Ticket/Services/TicketGeneratorService.php +++ b/app/Domains/Ticket/Services/TicketGeneratorService.php @@ -16,15 +16,19 @@ class TicketGeneratorService /** * @return Collection */ - public function generate(CatalogItem $catalogItem, User $user, int $quantity = 1): Collection - { + public function generate( + CatalogItem $catalogItem, + User $user, + int $quantity = 1, + ?int $sourceVariantId = null, + ): Collection { if ($quantity < 1) { throw TicketGenerationException::invalidQuantity(); } $now = now(); - return DB::transaction(function () use ($catalogItem, $user, $quantity, $now): Collection { + return DB::transaction(function () use ($catalogItem, $user, $quantity, $sourceVariantId, $now): Collection { $catalogItems = $this->resolveCatalogItems($catalogItem, $quantity, $now); return $catalogItems->map(fn (CatalogItem $item): Ticket => Ticket::query()->create([ @@ -32,6 +36,8 @@ class TicketGeneratorService 'ticket' => (string) Str::uuid(), 'name' => $item->nombre, 'description' => (string) ($item->descripcion ?? ''), + 'source_catalog_item_id' => $catalogItem->getKey(), + 'source_variant_id' => $sourceVariantId, 'starts_at' => $item->minimum_use_date, 'expires_at' => $item->maximum_use_date, 'used_at' => null, diff --git a/database/migrations/2026_07_21_000300_add_source_ids_to_tickets_table.php b/database/migrations/2026_07_21_000300_add_source_ids_to_tickets_table.php new file mode 100644 index 0000000..6611bff --- /dev/null +++ b/database/migrations/2026_07_21_000300_add_source_ids_to_tickets_table.php @@ -0,0 +1,23 @@ +unsignedBigInteger('source_catalog_item_id')->nullable()->after('description'); + $table->unsignedBigInteger('source_variant_id')->nullable()->after('source_catalog_item_id'); + }); + } + + public function down(): void + { + Schema::table('tickets', function (Blueprint $table): void { + $table->dropColumn(['source_catalog_item_id', 'source_variant_id']); + }); + } +}; diff --git a/tests/Feature/Ticket/TicketGeneratorServiceTest.php b/tests/Feature/Ticket/TicketGeneratorServiceTest.php index 990cf18..2cfbdd2 100644 --- a/tests/Feature/Ticket/TicketGeneratorServiceTest.php +++ b/tests/Feature/Ticket/TicketGeneratorServiceTest.php @@ -61,6 +61,8 @@ class TicketGeneratorServiceTest extends TestCase $this->assertSame($this->user->id, $ticket->user_id); $this->assertSame($item->nombre, $ticket->name); $this->assertSame($item->descripcion, $ticket->description); + $this->assertSame($item->id, $ticket->source_catalog_item_id); + $this->assertNull($ticket->source_variant_id); $this->assertTrue($ticket->starts_at->equalTo($item->minimum_use_date)); $this->assertTrue($ticket->expires_at->equalTo($item->maximum_use_date)); } @@ -100,6 +102,7 @@ class TicketGeneratorServiceTest extends TestCase $tickets = $this->service->generate($bundle, $this->user, 2); $this->assertCount(6, $tickets); + $this->assertCount(6, $tickets->where('source_catalog_item_id', $bundle->id)); $this->assertCount(4, $tickets->where('name', $first->nombre)); $this->assertCount(2, $tickets->where('name', $second->nombre)); } @@ -139,6 +142,19 @@ class TicketGeneratorServiceTest extends TestCase $this->assertDatabaseCount('tickets', 2); } + public function test_a_ticket_generated_from_a_purchase_keeps_its_source_ids(): void + { + $item = $this->createTicketableItem('sourced-ticket'); + $purchase = $this->createPurchase($item, 1, 1234); + + $purchase->markAsPaid(); + + $this->assertDatabaseHas('tickets', [ + 'source_catalog_item_id' => $item->id, + 'source_variant_id' => 1234, + ]); + } + public function test_marking_a_purchase_as_paid_ignores_items_without_tickets(): void { $item = $this->createTicketableItem('regular-product'); @@ -195,8 +211,11 @@ class TicketGeneratorServiceTest extends TestCase ]); } - private function createPurchase(CatalogItem $catalogItem, int $quantity): Purchase - { + private function createPurchase( + CatalogItem $catalogItem, + int $quantity, + ?int $sourceVariantId = null, + ): Purchase { $purchase = Purchase::query()->create([ 'tenant_codigo' => $this->tenant->codigo, 'user_id' => $this->user->id, @@ -207,7 +226,7 @@ class TicketGeneratorServiceTest extends TestCase $purchase->items()->create([ 'source_catalog_item_id' => $catalogItem->id, - 'source_variant_id' => null, + 'source_variant_id' => $sourceVariantId, 'image_attachment_id' => null, 'nombre' => $catalogItem->nombre, 'descripcion' => $catalogItem->descripcion, diff --git a/tests/Unit/Ticket/TicketTest.php b/tests/Unit/Ticket/TicketTest.php index fdf4b2d..1f4f526 100644 --- a/tests/Unit/Ticket/TicketTest.php +++ b/tests/Unit/Ticket/TicketTest.php @@ -21,6 +21,8 @@ class TicketTest extends TestCase { $ticket = new Ticket; $ticket->setRawAttributes([ + 'source_catalog_item_id' => '20', + 'source_variant_id' => '30', 'starts_at' => '2026-07-21 10:00:00', 'expires_at' => '2026-07-22 10:00:00', 'used_at' => null, @@ -29,6 +31,8 @@ class TicketTest extends TestCase $this->assertSame('tickets', $ticket->getTable()); $this->assertFalse($ticket->usesTimestamps()); + $this->assertSame(20, $ticket->source_catalog_item_id); + $this->assertSame(30, $ticket->source_variant_id); $this->assertInstanceOf(Carbon::class, $ticket->starts_at); $this->assertInstanceOf(Carbon::class, $ticket->expires_at); $this->assertNull($ticket->used_at);