From df853de843ed648b89e4f3bdf88c278f6dd2d68c Mon Sep 17 00:00:00 2001 From: ncoronel Date: Fri, 28 Aug 2026 15:17:35 -0300 Subject: [PATCH] feat(tickets): implement AdminAppTicketResource and update ticket collection to use it --- .../AdminApp/AdminAppTicketCollection.php | 5 +- .../AdminApp/AdminAppTicketResource.php | 62 +++++++++++++++++++ .../Ticket/AdminAppTicketControllerTest.php | 59 +++++++++++++++++- 3 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 app/Domains/Ticket/Resources/AdminApp/AdminAppTicketResource.php diff --git a/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php b/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php index 4355ad6..3af312c 100644 --- a/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php +++ b/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php @@ -2,15 +2,14 @@ namespace App\Domains\Ticket\Resources\AdminApp; -use App\Domains\Ticket\Resources\TicketResource; use App\Domains\Ticket\Services\AdminAppTicketResult; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\ResourceCollection; class AdminAppTicketCollection extends ResourceCollection { - /** @var class-string */ - public $collects = TicketResource::class; + /** @var class-string */ + public $collects = AdminAppTicketResource::class; private readonly int $scannedTickets; diff --git a/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketResource.php b/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketResource.php new file mode 100644 index 0000000..8a7b9e2 --- /dev/null +++ b/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketResource.php @@ -0,0 +1,62 @@ + */ + public function toArray(Request $request): array + { + return [ + ...parent::toArray($request), + 'variant_properties' => $this->variantProperties(), + ]; + } + + /** + * @return list + * }> + */ + private function variantProperties(): array + { + $variant = $this->sourceVariant; + + if ($variant === null) { + return []; + } + + $itemAttributes = $variant->definitions + ->map(fn ($definition) => $definition->itemAttribute) + ->filter() + ->merge($variant->catalogItem?->itemAttributes ?? collect()) + ->unique('id') + ->values(); + + return $variant->selectionOptions($itemAttributes) + ->map(function (array $selection, string $attributeCode) use ($itemAttributes): array { + $itemAttribute = $itemAttributes->first( + fn (ItemAttribute $itemAttribute): bool => $itemAttribute->attribute?->codigo + === $attributeCode, + ); + $values = array_is_list($selection) ? $selection : [$selection]; + + return [ + 'code' => $attributeCode, + 'label' => $itemAttribute?->attribute?->nombre + ?? ($attributeCode === 'event_date' ? 'Fecha' : $attributeCode), + 'values' => array_values($values), + ]; + }) + ->values() + ->all(); + } +} diff --git a/tests/Feature/Ticket/AdminAppTicketControllerTest.php b/tests/Feature/Ticket/AdminAppTicketControllerTest.php index 9705e65..c8da04b 100644 --- a/tests/Feature/Ticket/AdminAppTicketControllerTest.php +++ b/tests/Feature/Ticket/AdminAppTicketControllerTest.php @@ -6,7 +6,12 @@ use App\Domains\Attachable\Enums\AttachmentType; use App\Domains\Attachable\Models\Attachment; use App\Domains\Auth\Models\User; use App\Domains\Authorization\Enums\RoleCode; +use App\Domains\Catalog\Models\Attribute; +use App\Domains\Catalog\Models\CatalogItem; +use App\Domains\Catalog\Models\Inventory; +use App\Domains\Catalog\Models\Variant; use App\Domains\Menu\Models\Menu; +use App\Domains\Shared\Enums\FieldType; use App\Domains\Tenant\Models\Tenant; use App\Domains\Tenant\Models\WebsiteType; use App\Domains\Ticket\Models\Ticket; @@ -107,6 +112,53 @@ class AdminAppTicketControllerTest extends TestCase ->assertJsonPath('total_tickets', 2); } + public function test_it_returns_structured_variant_properties(): void + { + $tenant = $this->createTenant('fiesta_futbol_infantil'); + $admin = $this->createAdminAppUser($tenant); + $this->grantTicketsMenu($tenant); + Sanctum::actingAs($admin); + + $item = CatalogItem::query()->create([ + 'tenant_code' => $tenant->codigo, + 'slug' => 'remera', + 'nombre' => 'Remera', + 'precio' => '8000.00', + 'has_tickets' => true, + ]); + $attribute = Attribute::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'codigo' => 'size', + 'nombre' => 'Talle', + 'type' => FieldType::Select, + ]); + $attribute->options()->create(['value' => 'xl', 'label' => 'XL']); + $itemAttribute = $item->itemAttributes()->create([ + 'attribute_id' => $attribute->id, + 'sort_order' => 1, + ]); + $variant = Variant::query()->create([ + 'catalog_item_id' => $item->id, + 'inventory_id' => Inventory::query()->create()->id, + ]); + $variant->definitions()->create([ + 'item_attribute_id' => $itemAttribute->id, + 'value' => 'xl', + ]); + $ticket = $this->createTicket($tenant, $admin, [ + 'source_catalog_item_id' => $item->id, + 'source_variant_id' => $variant->id, + ]); + + $this->getJson('/api/v1/adminapp/tenant/tickets') + ->assertOk() + ->assertJsonPath('data.0.id', $ticket->id) + ->assertJsonPath('data.0.variant_properties.0.code', 'size') + ->assertJsonPath('data.0.variant_properties.0.label', 'Talle') + ->assertJsonPath('data.0.variant_properties.0.values.0.value', 'xl') + ->assertJsonPath('data.0.variant_properties.0.values.0.label', 'XL'); + } + private function createTenant(string $code): Tenant { $headerLogo = $this->createAttachment("{$code}-header.png"); @@ -157,12 +209,13 @@ class AdminAppTicketControllerTest extends TestCase $tenant->menues()->attach($menu->code); } - private function createTicket(Tenant $tenant, User $user): Ticket + /** @param array $attributes */ + private function createTicket(Tenant $tenant, User $user, array $attributes = []): Ticket { - return Ticket::query()->create([ + return Ticket::query()->create(array_merge([ 'tenant_code' => $tenant->codigo, 'ticket' => (string) Str::uuid(), 'user_id' => $user->id, - ]); + ], $attributes)); } }