From 5107d858ccf04dbee143aef56403291a42d53d05 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Mon, 27 Jul 2026 17:01:08 -0300 Subject: [PATCH] fix(ticket): temporarily disable maximum use date validation in ticket generation --- .../Services/TicketGeneratorService.php | 26 ++++------ .../Integration/TelepagosWebhookTest.php | 50 +++++++++++++++++++ .../Ticket/TicketGeneratorServiceTest.php | 24 ++++----- 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/app/Domains/Ticket/Services/TicketGeneratorService.php b/app/Domains/Ticket/Services/TicketGeneratorService.php index 4af0808..7c8d770 100644 --- a/app/Domains/Ticket/Services/TicketGeneratorService.php +++ b/app/Domains/Ticket/Services/TicketGeneratorService.php @@ -7,7 +7,6 @@ use App\Domains\Catalog\Models\CatalogItem; use App\Domains\Catalog\Models\Variant; use App\Domains\Ticket\Exceptions\TicketGenerationException; use App\Domains\Ticket\Models\Ticket; -use Carbon\CarbonInterface; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; @@ -27,14 +26,11 @@ class TicketGeneratorService throw TicketGenerationException::invalidQuantity(); } - $now = now(); - - return DB::transaction(function () use ($catalogItem, $user, $quantity, $sourceVariantId, $now): Collection { + return DB::transaction(function () use ($catalogItem, $user, $quantity, $sourceVariantId): Collection { $targets = $this->resolveTargets( $catalogItem, $quantity, $sourceVariantId, - $now, ); return $targets->map(function (array $target) use ( @@ -68,11 +64,10 @@ class TicketGeneratorService CatalogItem $catalogItem, int $quantity, ?int $sourceVariantId, - CarbonInterface $now, ): Collection { if (! $catalogItem->isBundle()) { $variant = $this->resolveVariant($catalogItem, $sourceVariantId); - $this->validateTarget($catalogItem, $variant, $now); + $this->validateTarget($catalogItem, $variant); return Collection::times($quantity, fn (): array => [ 'catalog_item' => $catalogItem, @@ -90,10 +85,10 @@ class TicketGeneratorService } return $catalogItem->bundleComponents - ->flatMap(function ($component) use ($quantity, $now): Collection { + ->flatMap(function ($component) use ($quantity): Collection { $componentItem = $component->catalogItem; $variant = $component->variant; - $this->validateTarget($componentItem, $variant, $now); + $this->validateTarget($componentItem, $variant); return Collection::times( $quantity * $component->quantity, @@ -133,16 +128,17 @@ class TicketGeneratorService private function validateTarget( CatalogItem $catalogItem, ?Variant $variant, - CarbonInterface $now, ): void { if (! $catalogItem->has_tickets) { throw TicketGenerationException::ticketsDisabled($catalogItem); } - $selectedItem = $variant ?? $catalogItem; - - if ($selectedItem->getMaximumUseDate()?->lessThanOrEqualTo($now)) { - throw TicketGenerationException::maximumUseDateReached($catalogItem); - } + // TODO: Reactivar esta validación cuando los pagos con productos vencidos + // deban rechazarse nuevamente. Se deja deshabilitada temporalmente. + // $selectedItem = $variant ?? $catalogItem; + // + // if ($selectedItem->getMaximumUseDate()?->lessThanOrEqualTo(now())) { + // throw TicketGenerationException::maximumUseDateReached($catalogItem); + // } } } diff --git a/tests/Feature/Integration/TelepagosWebhookTest.php b/tests/Feature/Integration/TelepagosWebhookTest.php index 0749066..ba3bcb5 100644 --- a/tests/Feature/Integration/TelepagosWebhookTest.php +++ b/tests/Feature/Integration/TelepagosWebhookTest.php @@ -259,6 +259,56 @@ class TelepagosWebhookTest extends TestCase ]); } + public function test_webhook_confirms_a_purchase_when_its_ticket_use_date_has_ended(): void + { + $tenant = $this->createTenant('expired-ticket', 'Expired Ticket', 'expired-ticket.com.ar'); + $this->configureTelepagosIntegration($tenant); + $user = User::factory()->create(); + $variant = $this->createVariantForTenant('expired-ticket', 1, '50.00'); + $variant->catalogItem->update([ + 'has_tickets' => true, + 'maximum_use_date' => now()->subMinute(), + ]); + $purchase = $this->createPendingTransferPurchase( + $tenant, + $user->id, + $variant->id, + 1, + '87654321', + ); + + Http::fake([ + 'https://api.telepagos.com.ar/v2/auth/token' => Http::response([ + 'status' => 'ok', + 'token' => 'test-token', + 'expires_at' => now()->addHour()->toIso8601String(), + ]), + 'https://api.telepagos.com.ar/v2/payment/cashin/7001' => Http::response([ + 'status' => 'ok', + 'data' => [ + 'amount' => 50, + 'operation_id' => 1, + 'transaction_id' => 'tx-expired-ticket', + 'buyer' => ['cuit' => '20876543219'], + ], + ]), + ]); + + $this->postJson('/api/webhooks/telepagos/expired-ticket', ['id' => '7001']) + ->assertOk() + ->assertJsonPath('status', 'success'); + + $this->assertDatabaseHas('compras', [ + 'id' => $purchase->id, + 'status' => Purchase::STATUS_PAID, + ]); + $this->assertDatabaseHas('tickets', [ + 'source_catalog_item_id' => $variant->catalog_item_id, + 'source_variant_id' => $variant->id, + 'user_id' => $user->id, + ]); + } + private function createPendingTransferPurchase( Tenant $tenant, int $userId, diff --git a/tests/Feature/Ticket/TicketGeneratorServiceTest.php b/tests/Feature/Ticket/TicketGeneratorServiceTest.php index f8636ec..e0912ff 100644 --- a/tests/Feature/Ticket/TicketGeneratorServiceTest.php +++ b/tests/Feature/Ticket/TicketGeneratorServiceTest.php @@ -84,14 +84,14 @@ class TicketGeneratorServiceTest extends TestCase $this->service->generate($item->fresh(), $this->user); } - public function test_it_rejects_an_item_when_its_maximum_use_date_was_reached(): void + public function test_it_generates_a_ticket_when_its_maximum_use_date_was_reached(): void { $item = $this->createTicketableItem('expired', maximumUseDate: now()); - $this->expectException(TicketGenerationException::class); - $this->expectExceptionMessage('alcanzó su fecha máxima de uso'); + $tickets = $this->service->generate($item, $this->user); - $this->service->generate($item, $this->user); + $this->assertCount(1, $tickets); + $this->assertTrue($tickets->first()->expires_at->equalTo($item->maximum_use_date)); } public function test_variant_dates_override_and_inherit_catalog_item_dates(): void @@ -228,18 +228,18 @@ class TicketGeneratorServiceTest extends TestCase Event::assertNotDispatched(TicketsAvailable::class); } - public function test_paid_status_is_rolled_back_when_ticket_generation_fails(): void + public function test_paid_status_is_confirmed_when_ticket_maximum_use_date_was_reached(): void { $item = $this->createTicketableItem('expired-paid-ticket', maximumUseDate: now()); $purchase = $this->createPurchase($item, 1); - try { - $purchase->markAsPaid(); - $this->fail('La generación debería haber fallado.'); - } catch (TicketGenerationException) { - $this->assertSame(Purchase::STATUS_PENDING_PAYMENT, $purchase->fresh()->status); - $this->assertDatabaseCount('tickets', 0); - } + $purchase->markAsPaid(); + + $this->assertSame(Purchase::STATUS_PAID, $purchase->fresh()->status); + $this->assertDatabaseHas('tickets', [ + 'source_catalog_item_id' => $item->id, + 'user_id' => $purchase->user_id, + ]); } private function createTicketableItem(