feat(variants): add filtering for inactive event dates in visibleVariants method

This commit is contained in:
2026-09-14 16:52:34 -03:00
parent c27d9628fd
commit 9fa4da7de2
3 changed files with 50 additions and 6 deletions

View File

@@ -221,11 +221,12 @@ class CatalogItem extends Model
public function visibleVariants(?int $includedVariantId = null): Collection
{
return $this->variants
->filter(fn (Variant $variant): bool => ($includedVariantId !== null && $variant->id === $includedVariantId)
|| ($variant->isSellable() && (
$this->inventory_policy === InventoryPolicy::Unlimited
|| ($variant->inventory?->availableStock() ?? 0) > 0
)))
->filter(fn (Variant $variant): bool => $variant->hasOnlyActiveEventDates()
&& (($includedVariantId !== null && $variant->id === $includedVariantId)
|| ($variant->isSellable() && (
$this->inventory_policy === InventoryPolicy::Unlimited
|| ($variant->inventory?->availableStock() ?? 0) > 0
))))
->values();
}

View File

@@ -95,7 +95,22 @@ class Variant extends Model
public function isSellable(): bool
{
return $this->sales_disabled_at === null
&& $this->replaced_by_variant_id === null;
&& $this->replaced_by_variant_id === null
&& $this->hasOnlyActiveEventDates();
}
public function hasOnlyActiveEventDates(): bool
{
if (! $this->exists
&& $this->event_date_id === null
&& ! $this->relationLoaded('eventDates')) {
return true;
}
return $this->selectedEventDates()->every(
fn (EventDate $eventDate): bool => $eventDate->rescheduled_to_event_date_id === null
&& $eventDate->suspended_at === null,
);
}
/** @return HasMany<VariantDefinition, $this> */

View File

@@ -346,6 +346,34 @@ class CatalogModelsTest extends TestCase
$this->assertSame([$unavailable, $available], $item->visibleVariants()->all());
}
public function test_catalog_item_never_exposes_variants_with_inactive_event_dates(): void
{
$activeDate = new EventDate(['date' => '2026-10-10']);
$rescheduledDate = new EventDate([
'date' => '2026-09-08',
'rescheduled_to_event_date_id' => 100,
]);
$suspendedDate = new EventDate([
'date' => '2026-10-08',
'suspended_at' => now(),
]);
$active = (new Variant)->setRelation('eventDates', new EloquentCollection([$activeDate]));
$rescheduled = (new Variant)->setRelation('eventDates', new EloquentCollection([$rescheduledDate]));
$suspended = (new Variant)->setRelation('eventDates', new EloquentCollection([$suspendedDate]));
$active->id = 10;
$rescheduled->id = 20;
$suspended->id = 30;
$item = new CatalogItem;
$item->inventory_policy = InventoryPolicy::Unlimited;
$item->setRelation('variants', new EloquentCollection([$active, $rescheduled, $suspended]));
$this->assertSame([$active], $item->visibleVariants()->all());
$this->assertSame([$active], $item->visibleVariants($rescheduled->id)->all());
$this->assertSame([$active], $item->visibleVariants($suspended->id)->all());
}
public function test_catalog_item_prioritizes_its_inventory_over_variants(): void
{
$item = new CatalogItem;