feat(event): add EventDateInfoFormatter to format event date messages and implement related tests

This commit is contained in:
2026-09-15 16:08:42 -03:00
parent dcf4383fbf
commit 51937ca93f
4 changed files with 108 additions and 5 deletions

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Domains\Event\Services;
use App\Domains\Event\Enums\EventDateChangeType;
use App\Domains\Event\Models\EventDate;
use App\Domains\Event\Models\EventDateChange;
use Illuminate\Support\Collection;
class EventDateInfoFormatter
{
/** @param Collection<int, EventDateChange> $changes */
public function format(EventDate $eventDate, Collection $changes): ?string
{
$messages = collect();
if ($eventDate->suspended_at !== null) {
$messages->push('Esta fecha fue cancelada.');
}
$sourceDates = $changes
->where('change_type', EventDateChangeType::Rescheduled)
->where('destination_event_date_id', $eventDate->getKey())
->pluck('previous_date')
->filter()
->map(fn ($date): string => $date->format('d/m/Y'))
->unique()
->values();
if ($sourceDates->isNotEmpty()) {
$verb = $sourceDates->count() === 1 ? 'se reprogramó' : 'se reprogramaron';
$messages->push("{$sourceDates->join(', ', ' y ')} {$verb} para este día.");
}
return $messages->isEmpty() ? null : $messages->join(' ');
}
}

View File

@@ -7,6 +7,7 @@ use App\Domains\Attachable\Models\AttachmentCrop;
use App\Domains\Catalog\Models\Category;
use App\Domains\Event\Models\EventDate;
use App\Domains\Event\Resources\EventDateChangeResource;
use App\Domains\Event\Services\EventDateInfoFormatter;
use App\Domains\Event\Services\EventDateNoticeFormatter;
use App\Domains\Menu\Models\Menu;
use App\Domains\Tenant\Models\Tenant;
@@ -25,6 +26,10 @@ class TenantResource extends JsonResource
*/
public function toArray(Request $request): array
{
$eventDateChanges = $this->relationLoaded('eventDateChanges')
? $this->eventDateChanges
: collect();
return [
'id' => $this->id,
'client_id' => $this->client_id,
@@ -54,14 +59,17 @@ class TenantResource extends JsonResource
'title' => $this->event_title,
'location' => $this->event_location,
'dates' => $this->eventDates
->filter(fn (EventDate $eventDate): bool => $eventDate->rescheduled_to_event_date_id === null
&& $eventDate->suspended_at === null
)
->filter(fn (EventDate $eventDate): bool => $eventDate->rescheduled_to_event_date_id === null)
->map(fn (EventDate $eventDate): array => [
'id' => $eventDate->id,
'date' => $eventDate->date->format('Y-m-d'),
'time_start' => $eventDate->time_start,
'time_end' => $eventDate->time_end,
'info_text' => app(EventDateInfoFormatter::class)->format(
$eventDate,
$eventDateChanges,
),
'isCanceled' => $eventDate->suspended_at !== null,
])->values(),
'date_changes' => $this->whenLoaded(
'eventDateChanges',

View File

@@ -326,6 +326,8 @@ class AdminAppEventControllerTest extends TestCase
->assertOk()
->assertJsonCount(1, 'data.event.dates')
->assertJsonPath('data.event.dates.0.id', $destination->id)
->assertJsonPath('data.event.dates.0.info_text', '09/10/2027 se reprogramó para este día.')
->assertJsonPath('data.event.dates.0.isCanceled', false)
->assertJsonCount(1, 'data.event.date_changes')
->assertJsonPath('data.event.date_changes.0.type', 'rescheduled')
->assertJsonPath('data.event.date_changes.0.source_event_date_id', $original->id)
@@ -483,8 +485,13 @@ class AdminAppEventControllerTest extends TestCase
$this->assertSame('10 de Octubre 2027', $tenant->fresh()->event_date_text);
$this->getJson('/api/tenants/bootstrap?dominio=acme.test&path=%2F')
->assertOk()
->assertJsonCount(1, 'data.event.dates')
->assertJsonPath('data.event.dates.0.id', $otherDate->id)
->assertJsonCount(2, 'data.event.dates')
->assertJsonPath('data.event.dates.0.id', $suspendedDate->id)
->assertJsonPath('data.event.dates.0.info_text', 'Esta fecha fue cancelada.')
->assertJsonPath('data.event.dates.0.isCanceled', true)
->assertJsonPath('data.event.dates.1.id', $otherDate->id)
->assertJsonPath('data.event.dates.1.info_text', null)
->assertJsonPath('data.event.dates.1.isCanceled', false)
->assertJsonCount(1, 'data.event.date_changes')
->assertJsonPath('data.event.date_changes.0.type', 'suspended')
->assertJsonPath('data.event.date_changes.0.source_event_date_id', $suspendedDate->id)

View File

@@ -0,0 +1,51 @@
<?php
namespace Tests\Unit\Event;
use App\Domains\Event\Enums\EventDateChangeType;
use App\Domains\Event\Models\EventDate;
use App\Domains\Event\Models\EventDateChange;
use App\Domains\Event\Services\EventDateInfoFormatter;
use Illuminate\Support\Carbon;
use Tests\TestCase;
class EventDateInfoFormatterTest extends TestCase
{
public function test_it_returns_null_for_a_date_without_changes(): void
{
$date = new EventDate;
$date->id = 10;
$this->assertNull((new EventDateInfoFormatter)->format($date, collect()));
}
public function test_it_formats_cancellation_and_source_dates_for_a_reschedule_destination(): void
{
$date = new EventDate;
$date->id = 20;
$date->suspended_at = Carbon::parse('2026-09-15');
$changes = collect([
$this->reschedule(1, 20, '2026-10-09'),
$this->reschedule(2, 20, '2026-10-10'),
]);
$this->assertSame(
'Esta fecha fue cancelada. 09/10/2026 y 10/10/2026 se reprogramaron para este día.',
(new EventDateInfoFormatter)->format($date, $changes),
);
}
private function reschedule(int $sourceId, int $destinationId, string $previousDate): EventDateChange
{
$change = new EventDateChange;
$change->setRawAttributes([
'change_type' => EventDateChangeType::Rescheduled->value,
'source_event_date_id' => $sourceId,
'destination_event_date_id' => $destinationId,
'previous_date' => $previousDate,
]);
return $change;
}
}