diff --git a/app/Domains/Event/Services/EventDateInfoFormatter.php b/app/Domains/Event/Services/EventDateInfoFormatter.php new file mode 100644 index 0000000..28b3d2a --- /dev/null +++ b/app/Domains/Event/Services/EventDateInfoFormatter.php @@ -0,0 +1,37 @@ + $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(' '); + } +} diff --git a/app/Domains/Tenant/Resources/TenantResource.php b/app/Domains/Tenant/Resources/TenantResource.php index c15e28e..b68a8b2 100644 --- a/app/Domains/Tenant/Resources/TenantResource.php +++ b/app/Domains/Tenant/Resources/TenantResource.php @@ -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', diff --git a/tests/Feature/Event/AdminAppEventControllerTest.php b/tests/Feature/Event/AdminAppEventControllerTest.php index 32cad55..5ffa50d 100644 --- a/tests/Feature/Event/AdminAppEventControllerTest.php +++ b/tests/Feature/Event/AdminAppEventControllerTest.php @@ -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) diff --git a/tests/Unit/Event/EventDateInfoFormatterTest.php b/tests/Unit/Event/EventDateInfoFormatterTest.php new file mode 100644 index 0000000..40eb789 --- /dev/null +++ b/tests/Unit/Event/EventDateInfoFormatterTest.php @@ -0,0 +1,51 @@ +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; + } +}