feat(desfile): refactor entry management to use row-based configuration and expand seat options
This commit is contained in:
@@ -39,7 +39,7 @@ class EntryControllerTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_it_returns_and_synchronizes_the_single_entry_product_variants(): void
|
||||
public function test_it_returns_row_configs_and_expands_them_into_seat_variants(): void
|
||||
{
|
||||
[$tenant, $entry] = $this->configuredEntry();
|
||||
$existing = $this->createVariant($entry, 'NORMAL', 'A', '1', '1', 100000);
|
||||
@@ -48,26 +48,25 @@ class EntryControllerTest extends TestCase
|
||||
$this->getJson('/api/v1/adminapp/tenant/desfile/entries')
|
||||
->assertOk()
|
||||
->assertJsonPath('data.id', $entry->id)
|
||||
->assertJsonPath('data.variants.0.id', $existing->id)
|
||||
->assertJsonPath('data.variants.0.type', 'NORMAL')
|
||||
->assertJsonPath('data.variants.0.seat', '1')
|
||||
->assertJsonPath('data.variants.0.price', '100000.00');
|
||||
->assertJsonPath('data.rows.0.type', 'NORMAL')
|
||||
->assertJsonPath('data.rows.0.row', '1')
|
||||
->assertJsonPath('data.rows.0.max_seat', 1)
|
||||
->assertJsonPath('data.rows.0.price', '100000.00');
|
||||
|
||||
$response = $this->putJson('/api/v1/adminapp/tenant/desfile/entries', [
|
||||
'variants' => [
|
||||
'rows' => [
|
||||
[
|
||||
'id' => $existing->id,
|
||||
'type' => 'NORMAL',
|
||||
'sector' => 'A',
|
||||
'row' => '1',
|
||||
'seat' => '1',
|
||||
'max_seat' => 2,
|
||||
'price' => 120000,
|
||||
],
|
||||
[
|
||||
'type' => 'VIP + LUNCH',
|
||||
'sector' => 'B',
|
||||
'row' => '2',
|
||||
'seat' => '3',
|
||||
'max_seat' => 3,
|
||||
'price' => 250000,
|
||||
],
|
||||
],
|
||||
@@ -75,21 +74,21 @@ class EntryControllerTest extends TestCase
|
||||
|
||||
$response
|
||||
->assertOk()
|
||||
->assertJsonCount(2, 'data.variants')
|
||||
->assertJsonPath('data.variants.0.price', '120000.00')
|
||||
->assertJsonPath('data.variants.1.type', 'VIP + LUNCH');
|
||||
->assertJsonCount(2, 'data.rows')
|
||||
->assertJsonPath('data.rows.0.max_seat', 2)
|
||||
->assertJsonPath('data.rows.0.price', '120000.00')
|
||||
->assertJsonPath('data.rows.1.max_seat', 3)
|
||||
->assertJsonPath('data.rows.1.type', 'VIP + LUNCH');
|
||||
|
||||
$this->assertDatabaseCount('variantes', 2);
|
||||
$this->assertDatabaseCount('variantes', 5);
|
||||
$this->assertDatabaseHas('catalog_items', [
|
||||
'id' => $entry->id,
|
||||
'precio' => 120000,
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $response->json('data.variants.1.id') === null
|
||||
? 0
|
||||
: Variant::query()->findOrFail($response->json('data.variants.1.id'))->inventory_id,
|
||||
'real_stock' => 1,
|
||||
]);
|
||||
$this->assertSame('120000.00', $existing->fresh()->precio);
|
||||
$this->assertSame(2, $entry->variants()->where('precio', 120000)->count());
|
||||
$this->assertSame(3, $entry->variants()->where('precio', 250000)->count());
|
||||
$this->assertSame(5, Inventory::query()->where('real_stock', 1)->count());
|
||||
}
|
||||
|
||||
public function test_it_replaces_and_toggles_the_entry_image(): void
|
||||
@@ -129,32 +128,52 @@ class EntryControllerTest extends TestCase
|
||||
$this->assertCount(1, $entry->fresh()->attachments);
|
||||
}
|
||||
|
||||
public function test_it_rejects_duplicate_seats_and_cross_tenant_access(): void
|
||||
public function test_it_rejects_duplicate_rows(): void
|
||||
{
|
||||
[, $entry] = $this->configuredEntry();
|
||||
$foreignVariant = $this->createVariant($entry, 'NORMAL', 'A', '1', '1', 100);
|
||||
[$otherTenant] = $this->configuredEntry('other-desfile');
|
||||
Sanctum::actingAs($this->createAdminAppUser($otherTenant));
|
||||
|
||||
$this->putJson('/api/v1/adminapp/tenant/desfile/entries', [
|
||||
'variants' => [[
|
||||
'id' => $foreignVariant->id,
|
||||
...$this->variantPayload('NORMAL', 'A', '1', '1', 100),
|
||||
]],
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('variants.0.id');
|
||||
[$tenant] = $this->configuredEntry();
|
||||
Sanctum::actingAs($this->createAdminAppUser($tenant));
|
||||
|
||||
$payload = [
|
||||
'variants' => [
|
||||
$this->variantPayload('NORMAL', 'A', '1', '1', 100),
|
||||
$this->variantPayload('normal', 'A', '1', '1', 200),
|
||||
'rows' => [
|
||||
$this->rowPayload('NORMAL', 'A', '1', 10, 100),
|
||||
$this->rowPayload('normal', 'A', '1', 20, 200),
|
||||
],
|
||||
];
|
||||
|
||||
$this->putJson('/api/v1/adminapp/tenant/desfile/entries', $payload)
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('variants.1');
|
||||
->assertJsonValidationErrors('rows.1');
|
||||
}
|
||||
|
||||
public function test_it_rejects_rows_and_seat_quantities_outside_the_configured_ranges(): void
|
||||
{
|
||||
[$tenant] = $this->configuredEntry();
|
||||
Sanctum::actingAs($this->createAdminAppUser($tenant));
|
||||
|
||||
$this->putJson('/api/v1/adminapp/tenant/desfile/entries', [
|
||||
'rows' => [
|
||||
$this->rowPayload('NORMAL', 'A', '6', 1, 100),
|
||||
$this->rowPayload('NORMAL', 'A', '1', 101, 100),
|
||||
],
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors(['rows.0.row', 'rows.1.max_seat']);
|
||||
}
|
||||
|
||||
public function test_it_cannot_reduce_the_maximum_below_a_reserved_seat(): void
|
||||
{
|
||||
[$tenant, $entry] = $this->configuredEntry();
|
||||
$reserved = $this->createVariant($entry, 'NORMAL', 'A', '1', '3', 100);
|
||||
$reserved->inventory()->update(['reserved_stock' => 1]);
|
||||
Sanctum::actingAs($this->createAdminAppUser($tenant));
|
||||
|
||||
$this->putJson('/api/v1/adminapp/tenant/desfile/entries', [
|
||||
'rows' => [$this->rowPayload('NORMAL', 'A', '1', 2, 100)],
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('rows');
|
||||
|
||||
$this->assertDatabaseHas('variantes', ['id' => $reserved->id, 'deleted_at' => null]);
|
||||
}
|
||||
|
||||
/** @return array{Tenant, CatalogItem} */
|
||||
@@ -184,8 +203,8 @@ class EntryControllerTest extends TestCase
|
||||
foreach ([
|
||||
'tipo' => ['VIP + LUNCH', 'NORMAL'],
|
||||
'sector' => ['A', 'B', 'C', 'D'],
|
||||
'fila' => ['1', '2'],
|
||||
'asiento' => ['1', '2', '3'],
|
||||
'fila' => array_map('strval', range(1, 5)),
|
||||
'asiento' => array_map('strval', range(1, 100)),
|
||||
] as $code => $options) {
|
||||
$attribute = Attribute::query()->create([
|
||||
'tenant_codigo' => $tenant->codigo,
|
||||
@@ -238,14 +257,17 @@ class EntryControllerTest extends TestCase
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function variantPayload(
|
||||
private function rowPayload(
|
||||
string $type,
|
||||
string $sector,
|
||||
string $row,
|
||||
string $seat,
|
||||
int $maxSeat,
|
||||
int $price,
|
||||
): array {
|
||||
return compact('type', 'sector', 'row', 'seat', 'price');
|
||||
return [
|
||||
...compact('type', 'sector', 'row', 'price'),
|
||||
'max_seat' => $maxSeat,
|
||||
];
|
||||
}
|
||||
|
||||
private function createAdminAppUser(Tenant $tenant): User
|
||||
|
||||
Reference in New Issue
Block a user