Files
shopit-back/app/Domains/Event/Models/EventDate.php
ncoronel 5197862a62 feat(ticket): implement ticket generation policies and validity time management
- Added `ticket_generation_policy` column to `catalog_items` table to manage ticket generation strategies.
- Created `ticket_validity_times` table to allow multiple validity times per ticket.
- Introduced `validity_time_id` column in `event_dates` table to associate event dates with validity times.
- Established `ticket_validity_groups` and `ticket_validity_group_times` tables to group validity times for tickets.
- Updated seeder to set default ticket generation policy for specific tenant.
- Enhanced tests to cover new functionality, including ticket generation based on event dates and validity times.
- Refactored ticket validity checks to accommodate multiple validity times in a group.
2026-08-11 12:29:32 -03:00

142 lines
3.9 KiB
PHP

<?php
namespace App\Domains\Event\Models;
use App\Domains\Catalog\Models\Variant;
use App\Domains\Event\Services\EventDateTextFormatter;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Enums\ValidityTimeType;
use App\Domains\Ticket\Models\ValidityTime;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
#[Fillable([
'tenant_code',
'date',
'time_start',
'time_end',
])]
class EventDate extends Model
{
use HasFactory;
public $timestamps = false;
protected static function booted(): void
{
static::creating(fn (self $eventDate) => $eventDate->syncValidityTime());
static::created(fn (self $eventDate) => $eventDate->syncTenantDateText());
static::updated(function (self $eventDate): void {
if ($eventDate->wasChanged(['date', 'time_start', 'time_end'])) {
$eventDate->syncValidityTime();
}
$eventDate->syncTenantDateText();
});
static::deleted(function (self $eventDate): void {
$eventDate->syncTenantDateText();
ValidityTime::query()
->whereKey($eventDate->validity_time_id)
->whereDoesntHave('ticketValidityGroups')
->delete();
});
}
protected function casts(): array
{
return [
'date' => 'date:Y-m-d',
'validity_time_id' => 'integer',
];
}
/** @return BelongsTo<Tenant, $this> */
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo');
}
/** @return BelongsTo<ValidityTime, $this> */
public function validityTime(): BelongsTo
{
return $this->belongsTo(ValidityTime::class);
}
/** @return HasMany<Variant, $this> */
public function variants(): HasMany
{
return $this->hasMany(Variant::class);
}
/** @return BelongsToMany<Variant, $this> */
public function selectedByVariants(): BelongsToMany
{
return $this->belongsToMany(
Variant::class,
'variant_event_dates',
'event_date_id',
'variant_id',
);
}
public function startsAt(): CarbonInterface
{
return Carbon::parse($this->date->format('Y-m-d').' '.$this->time_start);
}
public function endsAt(): CarbonInterface
{
return Carbon::parse($this->date->format('Y-m-d').' '.$this->time_end);
}
private function syncTenantDateText(): void
{
$tenant = $this->tenant()->first();
if (! $tenant) {
return;
}
$tenant->update([
'event_date_text' => app(EventDateTextFormatter::class)->format(
$tenant->eventDates()->pluck('date')
),
]);
}
private function syncValidityTime(): void
{
$startsAt = $this->startsAt();
$expiresAt = $this->endsAt();
if ($expiresAt->lessThanOrEqualTo($startsAt)) {
$expiresAt = $expiresAt->addDay();
}
$attributes = [
'type' => ValidityTimeType::FixedWindow,
'start_time' => null,
'end_time' => null,
'fixed_starts_at' => $startsAt,
'fixed_expires_at' => $expiresAt,
];
if ($this->validity_time_id === null) {
$validityTime = ValidityTime::query()->create($attributes);
$this->validity_time_id = $validityTime->getKey();
$this->setRelation('validityTime', $validityTime);
return;
}
$this->validityTime()->update($attributes);
$this->unsetRelation('validityTime');
}
}