refactor(backend): reorganize domains into Core, Commerce, Ticketing and Shared
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Ticket\Services;
|
||||
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Resultado completo de resolver la vigencia de un ticket.
|
||||
*
|
||||
* Cada ResolvedValidityGroup contiene condiciones AND. Entre los grupos se
|
||||
* aplica OR, por lo que alcanza con que uno de ellos esté activo.
|
||||
*/
|
||||
final readonly class ResolvedTicketValidity
|
||||
{
|
||||
/** @param Collection<int, ResolvedValidityGroup> $groups */
|
||||
public function __construct(
|
||||
public Collection $groups,
|
||||
public bool $isResolvable = true,
|
||||
public bool $isUnrestricted = false,
|
||||
) {}
|
||||
|
||||
/** No existe ninguna restricción temporal configurada. */
|
||||
public static function unrestricted(): self
|
||||
{
|
||||
return new self(collect(), isUnrestricted: true);
|
||||
}
|
||||
|
||||
/** La configuración fuente está incompleta o es inconsistente. */
|
||||
public static function unresolvable(): self
|
||||
{
|
||||
return new self(collect(), isResolvable: false);
|
||||
}
|
||||
|
||||
/** Es válido cuando no tiene restricciones o algún grupo OR está activo. */
|
||||
public function isValid(?CarbonInterface $at = null): bool
|
||||
{
|
||||
if (! $this->isResolvable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isUnrestricted || $this->groups->contains(
|
||||
fn (ResolvedValidityGroup $group): bool => $group->isValid($at)
|
||||
);
|
||||
}
|
||||
|
||||
/** Sólo está vencido cuando todos los grupos OR ya vencieron. */
|
||||
public function isExpired(?CarbonInterface $at = null): bool
|
||||
{
|
||||
return $this->isResolvable
|
||||
&& ! $this->isUnrestricted
|
||||
&& $this->groups->isNotEmpty()
|
||||
&& $this->groups->every(
|
||||
fn (ResolvedValidityGroup $group): bool => $group->isExpired($at)
|
||||
);
|
||||
}
|
||||
|
||||
/** Inicio más temprano de todas las alternativas, usado como resumen. */
|
||||
public function effectiveStartsAt(?CarbonInterface $at = null): ?CarbonInterface
|
||||
{
|
||||
return $this->groups
|
||||
->map(fn (ResolvedValidityGroup $group): ?CarbonInterface => $group->effectiveStartsAt($at))
|
||||
->filter()
|
||||
->sortBy(fn (CarbonInterface $startsAt): int => $startsAt->getTimestamp())
|
||||
->first();
|
||||
}
|
||||
|
||||
/** Vencimiento más tardío de todas las alternativas, usado como resumen. */
|
||||
public function effectiveExpiresAt(?CarbonInterface $at = null): ?CarbonInterface
|
||||
{
|
||||
return $this->groups
|
||||
->map(fn (ResolvedValidityGroup $group): ?CarbonInterface => $group->effectiveExpiresAt($at))
|
||||
->filter()
|
||||
->sortByDesc(fn (CarbonInterface $expiresAt): int => $expiresAt->getTimestamp())
|
||||
->first();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user