feat(ticket): add refund calculation functionality and corresponding tests

This commit is contained in:
2026-09-11 10:43:03 -03:00
parent 6384c0046d
commit 4abb6c67fd
5 changed files with 231 additions and 3 deletions

View File

@@ -235,6 +235,101 @@ class AdminAppTicketControllerTest extends TestCase
->assertJsonValidationErrors('refund_type');
}
public function test_it_calculates_total_and_partial_refund_for_a_ticket(): void
{
$tenant = $this->createTenant('ticket-calc-both');
$tenant->update([
'allow_ticket_total_refund' => true,
'allow_ticket_partial_refund' => true,
'ticket_partial_refund_percentage' => 30.00,
]);
$admin = $this->createAdminAppUser($tenant);
$this->grantTicketsMenu($tenant);
Sanctum::actingAs($admin);
[$ticket, $purchaseItem] = $this->createRefundableTicket($tenant, $admin, '100.00');
$this->getJson("/api/v1/adminapp/tenant/tickets/{$ticket->id}/refund")
->assertOk()
->assertJsonPath('data.total', '100.00')
->assertJsonPath('data.partial', '30.00');
}
public function test_it_calculates_only_total_when_partial_is_disabled(): void
{
$tenant = $this->createTenant('ticket-calc-total');
$tenant->update([
'allow_ticket_total_refund' => true,
'allow_ticket_partial_refund' => false,
]);
$admin = $this->createAdminAppUser($tenant);
$this->grantTicketsMenu($tenant);
Sanctum::actingAs($admin);
[$ticket] = $this->createRefundableTicket($tenant, $admin, '150.00');
$this->getJson("/api/v1/adminapp/tenant/tickets/{$ticket->id}/refund")
->assertOk()
->assertJsonPath('data.total', '150.00')
->assertJsonPath('data.partial', null);
}
public function test_it_returns_null_when_remaining_item_balance_is_insufficient(): void
{
$tenant = $this->createTenant('ticket-calc-insufficient');
$tenant->update([
'allow_ticket_total_refund' => true,
'allow_ticket_partial_refund' => true,
'ticket_partial_refund_percentage' => 50.00,
]);
$admin = $this->createAdminAppUser($tenant);
$this->grantTicketsMenu($tenant);
Sanctum::actingAs($admin);
[$ticket, $purchaseItem] = $this->createRefundableTicket($tenant, $admin, '100.00');
// Simulate 70 already refunded out of 100 on the item (remaining is 30)
$purchaseItem->update(['refunded_amount' => '70.00']);
$this->getJson("/api/v1/adminapp/tenant/tickets/{$ticket->id}/refund")
->assertOk()
// Total is 100, which exceeds remaining 30 -> total is null
->assertJsonPath('data.total', null)
// Partial is 50, which exceeds remaining 30 -> partial is null
->assertJsonPath('data.partial', null);
}
public function test_it_fails_calculating_refund_if_ticket_is_not_active(): void
{
$tenant = $this->createTenant('ticket-calc-inactive');
$tenant->update(['allow_ticket_total_refund' => true]);
$admin = $this->createAdminAppUser($tenant);
$this->grantTicketsMenu($tenant);
Sanctum::actingAs($admin);
[$ticket] = $this->createRefundableTicket($tenant, $admin, '100.00');
$ticket->update(['cancelled_at' => now()]);
$this->getJson("/api/v1/adminapp/tenant/tickets/{$ticket->id}/refund")
->assertUnprocessable()
->assertJsonValidationErrors('refund');
}
public function test_it_cannot_calculate_refund_for_another_tenants_ticket(): void
{
$tenantA = $this->createTenant('ticket-calc-a');
$tenantB = $this->createTenant('ticket-calc-b');
$tenantA->update(['allow_ticket_total_refund' => true]);
$tenantB->update(['allow_ticket_total_refund' => true]);
$adminA = $this->createAdminAppUser($tenantA);
$adminB = $this->createAdminAppUser($tenantB);
$this->grantTicketsMenu($tenantA);
[$ticketB] = $this->createRefundableTicket($tenantB, $adminB, '100.00');
Sanctum::actingAs($adminA);
$this->getJson("/api/v1/adminapp/tenant/tickets/{$ticketB->id}/refund")
->assertNotFound();
}
public function test_it_searches_by_id_and_does_not_search_by_uuid(): void
{
$tenant = $this->createTenant('fiesta_futbol_infantil');
@@ -410,6 +505,9 @@ class AdminAppTicketControllerTest extends TestCase
$this->createTicket($tenant, $admin)->update(['used_at' => now()]);
$this->createTicket($tenant, $admin);
$this->createTicket($tenant, $admin)->update(['cancelled_at' => now()]);
$this->createTicket($tenant, $admin)->update(['refunded_at' => now()]);
$this->createTicket($tenant, $admin)->update(['disabled_at' => now()]);
$this->createTicket($otherTenant, $otherUser)->update(['used_at' => now()]);
$this->getJson('/api/v1/adminapp/tenant/tickets?q=does-not-match')
@@ -420,6 +518,7 @@ class AdminAppTicketControllerTest extends TestCase
$this->getJson('/api/v1/adminapp/tenant/tickets')
->assertOk()
->assertJsonCount(5, 'data')
->assertJsonPath('scanned_tickets', 1)
->assertJsonPath('total_tickets', 2);
}