refactor(ticket): implement fixed validity time generation for event date and time windows in TicketGeneratorService

This commit is contained in:
2026-08-07 10:43:05 -03:00
parent 717ee5d194
commit 91af233941
22 changed files with 665 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ namespace App\Domains\Ticket\Services;
use App\Domains\Auth\Models\User;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Variant;
use App\Domains\Ticket\Enums\ValidityTimeType;
use App\Domains\Ticket\Exceptions\TicketGenerationException;
use App\Domains\Ticket\Models\Ticket;
use App\Domains\Ticket\Models\ValidityTime;
@@ -34,14 +35,21 @@ class TicketGeneratorService
$quantity,
$sourceVariantId,
);
$fixedValidityTimes = [];
return $targets->map(function (array $target) use (
&$fixedValidityTimes,
$sourcePurchaseId,
$user,
): Ticket {
$item = $target['catalog_item'];
$variant = $target['variant'];
$validityTime = $this->resolveValidityTime($item, $variant);
$validityTime = $this->materializeEventDateValidityTime(
$variant,
$validityTime,
$fixedValidityTimes,
);
return Ticket::query()->create([
'tenant_code' => $item->tenant_code,
@@ -168,4 +176,56 @@ class TicketGeneratorService
return $validityTimes->first();
}
/**
* Convert a recurring time window into the fixed date and time purchased by
* the customer. Equal tickets generated together share the same snapshot.
*
* @param array<string, ValidityTime> $fixedValidityTimes
*/
private function materializeEventDateValidityTime(
?Variant $variant,
?ValidityTime $validityTime,
array &$fixedValidityTimes,
): ?ValidityTime {
if (
$variant === null
|| $validityTime === null
|| $validityTime->type !== ValidityTimeType::TimeWindow
) {
return $validityTime;
}
$variant->loadMissing('eventDate');
$eventDate = $variant->eventDate;
if ($eventDate === null) {
return $validityTime;
}
$cacheKey = $eventDate->getKey().':'.$validityTime->getKey();
if (isset($fixedValidityTimes[$cacheKey])) {
return $fixedValidityTimes[$cacheKey];
}
$startsAt = $validityTime->startsAt($eventDate->date);
$expiresAt = $validityTime->expiresAt($eventDate->date);
if (
$startsAt !== null
&& $expiresAt !== null
&& $expiresAt->lessThanOrEqualTo($startsAt)
) {
$expiresAt = $expiresAt->addDay();
}
return $fixedValidityTimes[$cacheKey] = ValidityTime::query()->create([
'type' => ValidityTimeType::FixedWindow,
'start_time' => null,
'end_time' => null,
'fixed_starts_at' => $startsAt,
'fixed_expires_at' => $expiresAt,
]);
}
}