feat(notification): email event date changes

This commit is contained in:
2026-09-14 08:53:51 -03:00
parent 205d77bc0b
commit 756f4dad0a
10 changed files with 601 additions and 0 deletions

View File

@@ -270,6 +270,131 @@ class NotificationMailServiceTest extends TestCase
});
}
public function test_it_sends_one_rescheduling_email_per_purchase_and_does_not_duplicate_it(): void
{
$purchase = Purchase::query()->create([
'tenant_codigo' => $this->tenant->codigo,
'user_id' => $this->user->id,
'status' => Purchase::STATUS_PAID,
'payment_method' => 'transfer',
'total' => 25,
'email' => 'checkout@example.com',
]);
$purchaseItem = $purchase->items()->create([
'source_catalog_item_id' => $this->catalogItem()->id,
'nombre' => 'Entrada',
'item_nombre' => 'Entrada general',
'variant_attributes' => [],
'cantidad' => 2,
'precio_unitario' => 25,
'total' => 25,
]);
$firstTicket = $this->ticketFor($purchaseItem->id);
$secondTicket = $this->ticketFor($purchaseItem->id);
$purchaseTickets = [[
'purchase_id' => $purchase->id,
'ticket_ids' => [$firstTicket->id, $secondTicket->id],
]];
app(NotificationMailService::class)->sendEventDateRescheduled(
$this->tenant->codigo,
10,
20,
'09/10/2027',
'20/10/2027',
$purchaseTickets,
);
app(NotificationMailService::class)->sendEventDateRescheduled(
$this->tenant->codigo,
10,
20,
'09/10/2027',
'20/10/2027',
$purchaseTickets,
);
Mail::assertSent(Mailable::class, 1);
Mail::assertSent(Mailable::class, function (Mailable $mail) use ($purchase, $firstTicket, $secondTicket): bool {
$mail->assertTo('checkout@example.com');
return $mail->subject === "Tu evento fue reprogramado - Compra #{$purchase->id}"
&& str_contains($mail->render(), '09/10/2027')
&& str_contains($mail->render(), '20/10/2027')
&& str_contains($mail->render(), '#'.$firstTicket->id)
&& str_contains($mail->render(), '#'.$secondTicket->id);
});
$this->assertDatabaseHas('event_date_notification_deliveries', [
'notification_key' => "event-date-rescheduled:10:20:{$purchase->id}",
'purchase_id' => $purchase->id,
]);
}
public function test_suspension_email_uses_the_account_email_and_separates_disabled_tickets(): void
{
$purchase = Purchase::query()->create([
'tenant_codigo' => $this->tenant->codigo,
'user_id' => $this->user->id,
'status' => Purchase::STATUS_PAID,
'payment_method' => 'transfer',
'total' => 25,
'email' => null,
]);
$purchaseItem = $purchase->items()->create([
'source_catalog_item_id' => $this->catalogItem()->id,
'nombre' => 'Entrada',
'item_nombre' => 'Entrada general',
'variant_attributes' => [],
'cantidad' => 2,
'precio_unitario' => 25,
'total' => 25,
]);
$disabledTicket = $this->ticketFor($purchaseItem->id);
$disabledTicket->markAsDisabled();
$disabledTicket->save();
$activeTicket = $this->ticketFor($purchaseItem->id);
app(NotificationMailService::class)->sendEventDateSuspended(
$this->tenant->codigo,
10,
'09/10/2027',
[[
'purchase_id' => $purchase->id,
'ticket_ids' => [$disabledTicket->id, $activeTicket->id],
]],
);
Mail::assertSent(Mailable::class, function (Mailable $mail) use ($disabledTicket, $activeTicket): bool {
$mail->assertTo('ada@example.com');
return str_contains($mail->render(), 'quedaron inhabilitados')
&& str_contains($mail->render(), 'conservan otras fechas disponibles')
&& str_contains($mail->render(), '#'.$disabledTicket->id)
&& str_contains($mail->render(), '#'.$activeTicket->id);
});
}
private function ticketFor(int $purchaseItemId): Ticket
{
return Ticket::query()->create([
'tenant_code' => $this->tenant->codigo,
'ticket' => fake()->uuid(),
'source_purchase_item_id' => $purchaseItemId,
'user_id' => $this->user->id,
]);
}
private function catalogItem(): CatalogItem
{
return CatalogItem::query()->create([
'tenant_code' => $this->tenant->codigo,
'slug' => fake()->unique()->slug(),
'nombre' => 'Entrada',
'descripcion' => 'Entrada general',
'precio' => 25,
'has_tickets' => true,
]);
}
private function useWebsiteTypeBranding(): void
{
$websiteType = WebsiteType::query()->create([

View File

@@ -2,6 +2,10 @@
namespace Tests\Feature\Notification;
use App\Domains\Event\Events\EventDateRescheduled;
use App\Domains\Event\Events\EventDateSuspended;
use App\Domains\Notification\Listeners\SendEventDateRescheduledEmails;
use App\Domains\Notification\Listeners\SendEventDateSuspendedEmails;
use App\Domains\Notification\Listeners\SendPurchaseConfirmedEmail;
use App\Domains\Notification\Services\NotificationMailService;
use App\Domains\Purchase\Events\PurchasePaid;
@@ -27,4 +31,42 @@ class QueuedNotificationListenerTest extends TestCase
$this->assertSame(123, $purchasePaid->purchaseId);
}
public function test_rescheduled_date_email_listener_delegates_the_captured_purchase_tickets(): void
{
$mailService = Mockery::mock(NotificationMailService::class);
$mailService->shouldReceive('sendEventDateRescheduled')
->once()
->with('acme', 10, 20, '2027-10-09', '2027-10-20', [[
'purchase_id' => 123,
'ticket_ids' => [456, 789],
]]);
$this->app->instance(NotificationMailService::class, $mailService);
(new SendEventDateRescheduledEmails)->handle(new EventDateRescheduled(
'acme', 10, 20, '2027-10-09', '2027-10-20', [[
'purchase_id' => 123,
'ticket_ids' => [456, 789],
]]
));
}
public function test_suspended_date_email_listener_delegates_the_captured_purchase_tickets(): void
{
$mailService = Mockery::mock(NotificationMailService::class);
$mailService->shouldReceive('sendEventDateSuspended')
->once()
->with('acme', 10, '2027-10-09', [[
'purchase_id' => 123,
'ticket_ids' => [456],
]]);
$this->app->instance(NotificationMailService::class, $mailService);
(new SendEventDateSuspendedEmails)->handle(new EventDateSuspended(
'acme', 10, '2027-10-09', [[
'purchase_id' => 123,
'ticket_ids' => [456],
]]
));
}
}