Files
Gesti-n-Reservas-Naturcalab…/supabase/migrations/007_add_notification_events.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.';