50 lines
2.2 KiB
SQL
50 lines
2.2 KiB
SQL
-- Migración 007: Tabla de eventos de notificación
|
|
-- Fuente de verdad para el sistema de jobs. Garantiza idempotencia mediante UNIQUE constraint.
|
|
--
|
|
-- Tipos de evento soportados:
|
|
-- reservation.created — Teneriffa CRUD
|
|
-- reservation.updated — Teneriffa CRUD
|
|
-- reservation.cancelled — Teneriffa CRUD
|
|
-- reservation.reminder_24h — 24h antes check-in (Teneriffa + Los Dragos)
|
|
-- reservation.invoice_second_notice — 10 días antes check-in (Natur, ambas casas)
|
|
-- reservation.pool_heating_notice — 48h antes check-in (si has_pool_heating = true)
|
|
|
|
CREATE TABLE public.notification_events (
|
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
reservation_id UUID REFERENCES public.reservations(id) ON DELETE CASCADE,
|
|
event_type TEXT NOT NULL,
|
|
scheduled_for TIMESTAMPTZ NOT NULL,
|
|
sent_at TIMESTAMPTZ,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
-- 'pending': esperando ejecución
|
|
-- 'processing': siendo procesado por el runner (previene duplicados)
|
|
-- 'sent': enviado correctamente
|
|
-- 'failed': fallido después de max_retries intentos
|
|
attempts INTEGER DEFAULT 0 NOT NULL,
|
|
last_error TEXT,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
|
|
|
-- CONSTRAINT DE IDEMPOTENCIA:
|
|
-- Un mismo evento (mismo tipo + misma fecha programada) para una reserva
|
|
-- solo puede existir una vez. ON CONFLICT DO NOTHING previene duplicados.
|
|
CONSTRAINT uq_notification_event
|
|
UNIQUE(reservation_id, event_type, scheduled_for)
|
|
);
|
|
|
|
CREATE INDEX idx_notification_events_pending
|
|
ON public.notification_events(scheduled_for)
|
|
WHERE status = 'pending';
|
|
|
|
ALTER TABLE public.notification_events ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Solo admin puede ver eventos de notificación (se refina en migración 009)
|
|
CREATE POLICY "Temp: authenticated can read notifications"
|
|
ON public.notification_events FOR SELECT TO authenticated
|
|
USING (true);
|
|
|
|
COMMENT ON TABLE public.notification_events IS
|
|
'Eventos de notificación programados. El runner en apps/api los procesa periódicamente.';
|
|
COMMENT ON COLUMN public.notification_events.status IS
|
|
'pending → processing → sent | failed. El estado "processing" previene que múltiples instancias procesen el mismo evento.';
|