feat(tickets): refine FFI variant filters

This commit is contained in:
2026-09-01 14:29:26 -03:00
parent 6896646c54
commit 836aa1afd7
6 changed files with 300 additions and 74 deletions

View File

@@ -23,7 +23,7 @@ class TicketFilterFormService
if ($tenant->codigo === self::FIESTA_FUTBOL_INFANTIL) {
$fields = [
...$this->fiestaFutbolInfantilFields($tenant),
...$fields,
...$this->commonFields(includeDate: false),
];
}
@@ -55,20 +55,40 @@ class TicketFilterFormService
'value' => $category['value'],
'label' => $category['label'],
'children' => [
'field' => 'product',
'disabled' => $category['products'] === [],
'options' => array_map(
fn (array $product): array => [
'value' => $product['value'],
'label' => $product['label'],
'children' => [
'field' => 'type',
'disabled' => $product['types'] === [],
'options' => $product['types'],
[
'field' => 'product',
'disabled' => $category['products'] === [],
'options' => array_map(
fn (array $product): array => [
'value' => $product['value'],
'label' => $product['label'],
'children' => [
[
'field' => 'type',
'disabled' => $product['types'] === [],
'options' => array_map(
fn (array $type): array => [
'value' => $type['value'],
'label' => $type['label'],
'children' => [[
'field' => 'size',
'disabled' => ($type['sizes'] ?? []) === [],
'options' => $type['sizes'] ?? [],
]],
],
$product['types'],
),
],
],
],
],
$category['products'],
),
$category['products'],
),
],
[
'field' => 'date',
'disabled' => ! in_array($category['value'], ['comidas', 'comida'], true),
'options' => [],
],
],
],
$form['categories'],
@@ -76,21 +96,26 @@ class TicketFilterFormService
],
$this->dependentSelect('product', 'Producto', 'category'),
$this->dependentSelect('type', 'Tipo', 'product'),
$this->dependentSelect('size', 'Talle', 'type'),
[
...$this->dependentSelect('date', 'Fecha', 'category'),
'type' => 'date',
],
];
}
/** @return list<array<string, mixed>> */
private function commonFields(): array
private function commonFields(bool $includeDate = true): array
{
return [
[
...($includeDate ? [[
'name' => 'date',
'query_param' => 'date',
'label' => 'Fecha',
'type' => 'date',
'required' => false,
'default' => null,
],
]] : []),
[
'name' => 'status',
'query_param' => 'status',

View File

@@ -54,6 +54,18 @@ class TicketFormService
],
];
/**
* @var array<string, array{label: string|null, product: string, type: string|null, size: string|null, order: int}>
*/
private const FILTER_CATEGORY_PRESENTATIONS = [
'entradas' => ['label' => null, 'product' => self::PRODUCT, 'type' => null, 'size' => null, 'order' => 1],
'alojamientos' => ['label' => 'Camping', 'product' => 'tipo_alojamiento', 'type' => null, 'size' => null, 'order' => 2],
'camping' => ['label' => null, 'product' => 'tipo_alojamiento', 'type' => null, 'size' => null, 'order' => 2],
'comidas' => ['label' => 'Comida', 'product' => 'horario', 'type' => 'servicio', 'size' => null, 'order' => 3],
'comida' => ['label' => null, 'product' => 'horario', 'type' => 'servicio', 'size' => null, 'order' => 3],
'merchandising' => ['label' => null, 'product' => self::PRODUCT, 'type' => 'color', 'size' => 'talle', 'order' => 4],
];
/**
* @return array{
* statuses: list<array{value: string, label: string}>,
@@ -79,7 +91,7 @@ class TicketFormService
->orderBy('nombre')
->get();
return $this->build($items);
return $this->build($items, self::CATEGORY_PRESENTATIONS);
}
/**
@@ -154,7 +166,7 @@ class TicketFormService
->orderBy('nombre')
->get();
return $this->build($items);
return $this->build($items, self::FILTER_CATEGORY_PRESENTATIONS, includeSizes: true);
}
/**
@@ -172,17 +184,18 @@ class TicketFormService
* }>
* }
*/
private function build(Collection $items): array
private function build(Collection $items, array $presentations, bool $includeSizes = false): array
{
$categories = [];
foreach ($items as $item) {
$sourceCategory = trim((string) $item->category?->nombre);
$categoryValue = mb_strtolower($sourceCategory);
$presentation = self::CATEGORY_PRESENTATIONS[$categoryValue] ?? [
$presentation = $presentations[$categoryValue] ?? [
'label' => null,
'product' => self::PRODUCT,
'type' => null,
'size' => null,
'order' => PHP_INT_MAX,
];
@@ -193,18 +206,28 @@ class TicketFormService
'products' => [],
];
foreach ($this->products($item, $presentation['product'], $presentation['type']) as $product) {
foreach ($this->products(
$item,
$presentation['product'],
$presentation['type'],
$presentation['size'] ?? null,
) as $product) {
$productValue = $product['value'];
$existingProduct = $categories[$categoryValue]['products'][$productValue] ?? [
'value' => $productValue,
'label' => $product['label'],
'types' => [],
'sizes' => [],
];
foreach ($product['types'] as $type) {
$existingProduct['types'][$type['value']] = $type;
}
foreach ($product['sizes'] as $size) {
$existingProduct['sizes'][$size['value']] = $size;
}
$categories[$categoryValue]['products'][$productValue] = $existingProduct;
}
}
@@ -227,6 +250,7 @@ class TicketFormService
'value' => $product['value'],
'label' => $product['label'],
'types' => array_values($product['types']),
...($includeSizes ? ['sizes' => array_values($product['sizes'])] : []),
],
$category['products'],
)),
@@ -252,16 +276,18 @@ class TicketFormService
* @return list<array{
* value: string,
* label: string,
* types: list<array{value: string, label: string}>
* types: list<array{value: string, label: string}>,
* sizes: list<array{value: string, label: string}>
* }>
*/
private function products(CatalogItem $item, string $productCode, ?string $typeCode): array
private function products(CatalogItem $item, string $productCode, ?string $typeCode, ?string $sizeCode): array
{
if ($productCode === self::PRODUCT) {
return [[
'value' => $item->slug,
'label' => $item->nombre,
'types' => $this->types($item, $typeCode),
'types' => $this->types($item, $typeCode, $sizeCode),
'sizes' => $this->types($item, $sizeCode),
]];
}
@@ -274,10 +300,20 @@ class TicketFormService
'value' => $productValue,
'label' => $this->optionLabel($productOption['label'], $productCode),
'types' => [],
'sizes' => [],
];
foreach ($this->variantOptions($variant, $typeCode) as $typeOption) {
$products[$productValue]['types'][$typeOption['value']] = $typeOption;
$this->mergeTypeOption(
$products[$productValue]['types'],
$typeOption,
$variant,
$sizeCode,
);
}
foreach ($this->variantOptions($variant, $sizeCode) as $sizeOption) {
$products[$productValue]['sizes'][$sizeOption['value']] = $sizeOption;
}
}
}
@@ -287,23 +323,51 @@ class TicketFormService
'value' => $product['value'],
'label' => $product['label'],
'types' => array_values($product['types']),
'sizes' => array_values($product['sizes']),
],
$products,
));
}
/** @return list<array{value: string, label: string}> */
private function types(CatalogItem $item, ?string $typeCode): array
/** @return list<array<string, mixed>> */
private function types(CatalogItem $item, ?string $typeCode, ?string $sizeCode = null): array
{
$types = [];
foreach ($item->variants as $variant) {
foreach ($this->variantOptions($variant, $typeCode) as $typeOption) {
$types[$typeOption['value']] = $typeOption;
$this->mergeTypeOption($types, $typeOption, $variant, $sizeCode);
}
}
return array_values($types);
return array_values(array_map(function (array $type) use ($sizeCode): array {
if ($sizeCode !== null) {
$type['sizes'] = array_values($type['sizes']);
}
return $type;
}, $types));
}
/**
* @param array<string, array<string, mixed>> $types
* @param array{value: string, label: string} $typeOption
*/
private function mergeTypeOption(
array &$types,
array $typeOption,
Variant $variant,
?string $sizeCode,
): void {
$typeValue = $typeOption['value'];
$types[$typeValue] ??= [
...$typeOption,
...($sizeCode !== null ? ['sizes' => []] : []),
];
foreach ($this->variantOptions($variant, $sizeCode) as $sizeOption) {
$types[$typeValue]['sizes'][$sizeOption['value']] = $sizeOption;
}
}
/** @return list<array{value: string, label: string}> */