# Dominio Event ## Propósito Administra los eventos de un tenant, sus fechas y sus redes sociales. ## Modelo `Tenant` tiene muchos `Event`. Cada evento tiene título, subtítulo, descripción, ubicación, texto de fechas y `published_at`. Sus fechas se guardan en `event_dates` mediante `event_id`. El catálogo `social_media` define las plataformas; `event_social_media` guarda la URL y el orden de cada cuenta del evento. `exact_location` guarda opcionalmente un objeto JSON con `latitude` (-90 a 90) y `longitude` (-180 a 180). `location` sigue siendo la dirección legible. `events.address_id` es una referencia opcional a `addresses.id`: `Event::address()` obtiene su dirección y `Address::events()` permite reutilizar una dirección en varios eventos. Al borrar una dirección, el vínculo queda en `NULL` y se conserva el evento. La migración `2026_09_30_000200_add_address_id_to_events` agrega el vínculo. `2026_09_30_000300_copy_event_locations_to_addresses` copia `location` a `address_text` y las coordenadas de `exact_location` a `latitude` y `longitude`, con el label `Ubicación del evento`. Solo copia eventos sin `address_id` y con texto de ubicación; no modifica los campos ni los timestamps originales, ni vincula la dirección al tenant. Si faltan texto y coordenadas, el vínculo queda en `NULL`. Los datos inválidos, incluidas coordenadas sin texto de dirección, detienen la copia y revierten las inserciones para evitar una migración parcial. Las migraciones deben ejecutarse explícitamente por quien administra la base. Las respuestas públicas, administrativas y el evento del bootstrap incluyen `address` con `id`, `label`, `address_text`, `latitude` y `longitude`. Las coordenadas se serializan como números o `null`. Los campos anteriores de la respuesta conservan sus valores originales; el frontend lee la ubicación y coordenadas desde `address`. El guardado administrativo de `location` y `exact_location` también actualiza `addresses`; si una dirección está compartida con otro evento o con un tenant, se crea una copia para el evento editado. El tenant devuelve `addresses` con `is_main` y `main_address`. El storefront usa todas las direcciones en contacto, la principal en el footer y la propia del evento en sus tarjetas, cabecera y mapa. Solo se agregan al mapa las direcciones con ambas coordenadas. La migración `2026_09_18_000500_restore_events` crea un evento por cada tenant que tenía datos de evento o fechas, y migra las fechas y redes correspondientes. `2026_09_18_000600_associate_active_event_social_media` copia al evento activo las redes del tenant que falten, sin sobrescribir las URL propias del evento. El seeder de Fiesta Fútbol Infantil hace lo mismo cuando crea el evento en una base nueva. ## Storefront - `onticket` muestra el evento señalado por `tenants.active_event_id`. - `onticket_multi_event` permite varios eventos publicados y mantiene `tenants.active_event_id` en `NULL`. La presentación y gestión de esos eventos en el frontend quedan pendientes de diseño. `active_event_id` selecciona el evento del storefront de evento único; no indica si está publicado. La asignación de este campo y los cambios de tipo de storefront se administran directamente en la base de datos. La aplicación no valida ni automatiza esas operaciones. Cuando hay un evento activo, el campo `social_media` del bootstrap usa sus redes, igual que `event.social_media`. Las actualizaciones de redes de ese tenant también se guardan en el evento. Sin evento activo se conservan las redes propias del tenant. ## API Los endpoints de AdminApp usan `auth:sanctum` y `adminapp.tenant`: - `GET/PUT /v1/adminapp/tenant/event`: acceso al evento seleccionado para el storefront de evento único. - `POST /v1/adminapp/tenant/event-dates`: crea una fecha para ese evento. - `POST /v1/adminapp/tenant/event-dates/{eventDate}/reschedule` y `POST /v1/adminapp/tenant/event-dates/{eventDate}/suspend`: cambios de fecha. El bootstrap del tenant entrega `event` para el evento seleccionado. No entrega una lista de eventos ni existe todavía una pantalla para gestionarlos. ## Dependencias Las fechas se vinculan con variantes de `Catalog`, que a su vez pueden generar tickets. Los avisos por suspensión y reprogramación se construyen dinámicamente después de excluir los cambios que el usuario ya vio tres veces.