feat(ticket): implement DesfileEntryReservationController and related services for ticket reservations

This commit is contained in:
2026-10-02 11:50:47 -03:00
parent ab5bc43760
commit f10237eb1f
9 changed files with 365 additions and 264 deletions

View File

@@ -5,6 +5,7 @@ namespace Tests\Feature\Ticket;
use App\Domains\Commerce\Catalog\Models\Inventory;
use App\Domains\Core\Auth\Models\User;
use App\Domains\Ticketing\Ticket\Models\Ticket;
use App\Domains\Ticketing\Ticket\Services\EntryReservationPolicy;
use App\Domains\Ticketing\Ticket\Services\EntryReservationService;
use App\Domains\Ticketing\Ticket\Services\ResolvedTicketValidity;
use App\Domains\Ticketing\Ticket\Services\TicketGeneratorService;
@@ -224,6 +225,45 @@ class EntryReservationServiceTest extends TestCase
$service->reserve($user, (string) Str::uuid(), [$row]);
}
public function test_custom_policy_validates_resolved_selections_inside_the_transaction_before_stock_changes(): void
{
$policy = Mockery::mock(EntryReservationPolicy::class);
$policy->shouldReceive('validate')->once()->andReturnUsing(function (array $selections): void {
$this->assertGreaterThan(0, DB::transactionLevel());
$this->assertSame(1, $selections[0]['item']->id);
$this->assertSame(1, $selections[0]['variant']->id);
$this->assertSame(2, $selections[1]['item']->id);
$this->assertNull($selections[1]['variant']);
$this->assertSame(0, $selections[0]['inventory']->entry_reserved_stock);
throw ValidationException::withMessages(['rows.0.variant_id' => 'Custom selection rule.']);
});
try {
$this->service()->reserve(User::findOrFail(1), (string) Str::uuid(), $this->rows(), $policy);
$this->fail('Expected custom selection validation');
} catch (ValidationException $error) {
$this->assertSame(['rows.0.variant_id' => ['Custom selection rule.']], $error->errors());
}
$this->assertDatabaseCount('tickets', 0);
$this->assertDatabaseCount('reservation_batches', 0);
$this->assertSame(0, (int) Inventory::sum('entry_reserved_stock'));
}
public function test_idempotent_replays_do_not_validate_the_custom_policy_again(): void
{
$policy = Mockery::mock(EntryReservationPolicy::class);
$policy->shouldReceive('validate')->once();
$service = $this->service();
$user = User::findOrFail(1);
$key = (string) Str::uuid();
$result = $service->reserve($user, $key, $this->rows(), $policy);
$replay = $service->reserve($user, $key, array_reverse($this->rows()), $policy);
$this->assertSame($result->pluck('id')->all(), $replay->pluck('id')->all());
$this->assertDatabaseCount('tickets', 2);
$this->assertSame(1, Inventory::findOrFail(1)->entry_reserved_stock);
}
public function test_shared_inventory_is_checked_for_the_entire_batch(): void
{
DB::table('catalog_items')->where('id', 2)->update(['inventory_id' => 1]);