- Introduced new routes for entry reservations in admin app, including form, index, store, and download functionalities. - Created a migration to add the "Reserva de Tickets" menu item to the admin app. - Updated MenuSeeder to include the new menu item for ticket reservations. - Developed a PDF view for entry reservations. - Implemented tests for the EntryReservationController and EntryReservationService to ensure proper functionality and access control. - Refactored test setup to use a dedicated schema creation trait for better isolation and maintainability.
66 lines
3.3 KiB
PHP
66 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Ticketing\Ticket\Services;
|
|
|
|
use App\Domains\Commerce\Catalog\Enums\InventoryPolicy;
|
|
use App\Domains\Commerce\Catalog\Models\CatalogItem;
|
|
use App\Domains\Commerce\Catalog\Models\Variant;
|
|
use App\Domains\Core\Tenant\Models\Tenant;
|
|
use App\Domains\Ticketing\Ticket\Enums\EntryReservationPaymentType;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
|
|
class EntryReservationFormService
|
|
{
|
|
public function get(Tenant $tenant, ?int $eventId = null): array
|
|
{
|
|
$items = CatalogItem::query()->where('tenant_code', $tenant->codigo)->where('has_tickets', true)
|
|
->when($eventId !== null, fn (Builder $query) => $query->where('event_id', $eventId))
|
|
->with([
|
|
'inventory', 'itemAttributes.attribute.options',
|
|
'variants' => fn ($query) => $query->orderBy('id'),
|
|
'variants.inventory', 'variants.definitions.itemAttribute.attribute.options',
|
|
'variants.eventDates', 'variants.eventDate',
|
|
])->orderBy('nombre')->orderBy('id')->get();
|
|
|
|
$filterItems = $items->map(fn (CatalogItem $item): array => [
|
|
'id' => $item->id, 'name' => $item->nombre,
|
|
'variants' => $item->variants->map(function (Variant $variant) use ($item): array {
|
|
$variant->setRelation('catalogItem', $item);
|
|
|
|
return ['id' => $variant->id, 'label' => $variant->getSelectionLabel()];
|
|
})->values()->all(),
|
|
])->values()->all();
|
|
|
|
$reservationEventId = $eventId ?? $tenant->active_event_id;
|
|
$available = $items->filter(fn (CatalogItem $item): bool => ! $item->isBundle()
|
|
&& $item->isSaleOpen()
|
|
&& ($reservationEventId === null || $item->event_id === $reservationEventId))
|
|
->map(function (CatalogItem $item): ?array {
|
|
$tracked = $item->inventory_policy !== InventoryPolicy::Unlimited;
|
|
$requiresVariant = $item->variants->isNotEmpty();
|
|
$variants = $item->variants->filter(function (Variant $variant) use ($item, $tracked): bool {
|
|
$variant->setRelation('catalogItem', $item);
|
|
|
|
return $variant->isSellable()
|
|
&& (! $tracked || ($variant->inventory?->availableStock() ?? 0) > 0);
|
|
})->map(fn (Variant $variant): array => [
|
|
'id' => $variant->id, 'label' => $variant->getSelectionLabel(),
|
|
'price' => $variant->getPrice(),
|
|
'available_stock' => $tracked ? $variant->inventory->availableStock() : null,
|
|
])->values()->all();
|
|
if (($requiresVariant && $variants === [])
|
|
|| (! $requiresVariant && $tracked && ($item->inventory?->availableStock() ?? 0) <= 0)) {
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'id' => $item->id, 'name' => $item->nombre, 'price' => $item->getPrice(),
|
|
'requires_variant' => $requiresVariant, 'variants' => $variants,
|
|
'available_stock' => $tracked ? $item->inventory?->availableStock() : null,
|
|
];
|
|
})->filter()->values()->all();
|
|
|
|
return ['payment_types' => EntryReservationPaymentType::options(), 'items' => $available, 'filter_items' => $filterItems];
|
|
}
|
|
}
|