feat(ticket): implement ticket generation on purchase payment and add related tests
This commit is contained in:
@@ -7,9 +7,11 @@ use App\Domains\Attachable\Models\Attachment;
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Catalog\Enums\CatalogItemType;
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Purchase\Models\Purchase;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Domains\Ticket\Exceptions\TicketGenerationException;
|
||||
use App\Domains\Ticket\Services\TicketGeneratorService;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -121,6 +123,48 @@ class TicketGeneratorServiceTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function test_marking_a_purchase_as_paid_generates_its_tickets_once(): void
|
||||
{
|
||||
$item = $this->createTicketableItem('paid-ticket');
|
||||
$purchase = $this->createPurchase($item, 2);
|
||||
$purchase->setRelation('items', new EloquentCollection);
|
||||
|
||||
$purchase->markAsPaid();
|
||||
|
||||
$this->assertSame(Purchase::STATUS_PAID, $purchase->status);
|
||||
$this->assertDatabaseCount('tickets', 2);
|
||||
|
||||
$purchase->markAsPaid();
|
||||
|
||||
$this->assertDatabaseCount('tickets', 2);
|
||||
}
|
||||
|
||||
public function test_marking_a_purchase_as_paid_ignores_items_without_tickets(): void
|
||||
{
|
||||
$item = $this->createTicketableItem('regular-product');
|
||||
$item->update(['has_tickets' => false]);
|
||||
$purchase = $this->createPurchase($item->fresh(), 1);
|
||||
|
||||
$purchase->markAsPaid();
|
||||
|
||||
$this->assertSame(Purchase::STATUS_PAID, $purchase->status);
|
||||
$this->assertDatabaseCount('tickets', 0);
|
||||
}
|
||||
|
||||
public function test_paid_status_is_rolled_back_when_ticket_generation_fails(): 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);
|
||||
}
|
||||
}
|
||||
|
||||
private function createTicketableItem(
|
||||
string $slug,
|
||||
mixed $minimumUseDate = null,
|
||||
@@ -151,6 +195,35 @@ class TicketGeneratorServiceTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
private function createPurchase(CatalogItem $catalogItem, int $quantity): Purchase
|
||||
{
|
||||
$purchase = Purchase::query()->create([
|
||||
'tenant_codigo' => $this->tenant->codigo,
|
||||
'user_id' => $this->user->id,
|
||||
'status' => Purchase::STATUS_PENDING_PAYMENT,
|
||||
'payment_method' => 'transfer',
|
||||
'total' => 10 * $quantity,
|
||||
]);
|
||||
|
||||
$purchase->items()->create([
|
||||
'source_catalog_item_id' => $catalogItem->id,
|
||||
'source_variant_id' => null,
|
||||
'image_attachment_id' => null,
|
||||
'nombre' => $catalogItem->nombre,
|
||||
'descripcion' => $catalogItem->descripcion,
|
||||
'slug' => $catalogItem->slug,
|
||||
'item_nombre' => $catalogItem->nombre,
|
||||
'variant_attributes' => [],
|
||||
'cantidad' => $quantity,
|
||||
'precio_unitario' => 10,
|
||||
'discount_total' => null,
|
||||
'tax_total' => null,
|
||||
'total' => 10 * $quantity,
|
||||
]);
|
||||
|
||||
return $purchase;
|
||||
}
|
||||
|
||||
private function createTenant(): Tenant
|
||||
{
|
||||
$header = Attachment::query()->create([
|
||||
|
||||
Reference in New Issue
Block a user