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]; } }