- Create notifications schema - Add tables: notifications, notification_templates, notification_preferences, device_tokens - Add indexes for performance - Add default notification templates for orders, payments, alerts - Add updated_at triggers Sprint 3: MCH-017 Notificaciones Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
157 lines
6.9 KiB
PL/PgSQL
157 lines
6.9 KiB
PL/PgSQL
-- ============================================
|
|
-- Schema: notifications
|
|
-- Épica: MCH-017 - Notificaciones
|
|
-- Version: 1.0.0
|
|
-- ============================================
|
|
|
|
-- Create schema
|
|
CREATE SCHEMA IF NOT EXISTS notifications;
|
|
|
|
-- ============================================
|
|
-- Table: notifications
|
|
-- Stores all notification records
|
|
-- ============================================
|
|
CREATE TABLE notifications.notifications (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
user_id UUID,
|
|
customer_id UUID,
|
|
type VARCHAR(50) NOT NULL,
|
|
channel VARCHAR(20) NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
body TEXT NOT NULL,
|
|
data JSONB,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|
error_message TEXT,
|
|
retry_count INTEGER DEFAULT 0,
|
|
scheduled_at TIMESTAMPTZ,
|
|
sent_at TIMESTAMPTZ,
|
|
delivered_at TIMESTAMPTZ,
|
|
read_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_notifications_tenant_user_status
|
|
ON notifications.notifications(tenant_id, user_id, status);
|
|
CREATE INDEX idx_notifications_tenant_created
|
|
ON notifications.notifications(tenant_id, created_at);
|
|
CREATE INDEX idx_notifications_scheduled
|
|
ON notifications.notifications(scheduled_at)
|
|
WHERE scheduled_at IS NOT NULL AND status = 'pending';
|
|
|
|
-- ============================================
|
|
-- Table: notification_templates
|
|
-- Notification templates per type and channel
|
|
-- ============================================
|
|
CREATE TABLE notifications.notification_templates (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID, -- NULL = default template
|
|
type VARCHAR(50) NOT NULL,
|
|
channel VARCHAR(20) NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
body TEXT NOT NULL,
|
|
variables JSONB, -- List of required variables
|
|
active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE(tenant_id, type, channel)
|
|
);
|
|
|
|
-- ============================================
|
|
-- Table: notification_preferences
|
|
-- User preferences per channel
|
|
-- ============================================
|
|
CREATE TABLE notifications.notification_preferences (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL,
|
|
channel VARCHAR(20) NOT NULL,
|
|
enabled BOOLEAN DEFAULT true,
|
|
quiet_hours_enabled BOOLEAN DEFAULT false,
|
|
quiet_hours_start TIME,
|
|
quiet_hours_end TIME,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE(user_id, channel)
|
|
);
|
|
|
|
-- ============================================
|
|
-- Table: device_tokens
|
|
-- FCM/APNs tokens for push notifications
|
|
-- ============================================
|
|
CREATE TABLE notifications.device_tokens (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL,
|
|
platform VARCHAR(20) NOT NULL,
|
|
token TEXT NOT NULL UNIQUE,
|
|
device_name VARCHAR(100),
|
|
active BOOLEAN DEFAULT true,
|
|
last_used_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_device_tokens_user ON notifications.device_tokens(user_id);
|
|
|
|
-- ============================================
|
|
-- Default Templates (seed data)
|
|
-- ============================================
|
|
INSERT INTO notifications.notification_templates (tenant_id, type, channel, title, body, variables) VALUES
|
|
-- Order notifications
|
|
(NULL, 'new_order', 'push', '🛒 Nuevo Pedido #{{order_id}}', 'Pedido de {{customer_name}} por ${{total}}', '["order_id", "customer_name", "total"]'),
|
|
(NULL, 'new_order', 'whatsapp', '🛒 *Nuevo Pedido*', 'Pedido #{{order_id}}\nCliente: {{customer_name}}\nTotal: ${{total}}\n\nRevisa tu app para confirmar.', '["order_id", "customer_name", "total"]'),
|
|
|
|
(NULL, 'order_confirmed', 'whatsapp', '✅ *Pedido Confirmado*', '¡Tu pedido #{{order_id}} ha sido confirmado!\n\nEstamos preparándolo.\nTe avisamos cuando esté listo.', '["order_id"]'),
|
|
|
|
(NULL, 'order_ready', 'push', '📦 Pedido Listo', 'Tu pedido #{{order_id}} está listo para recoger', '["order_id"]'),
|
|
(NULL, 'order_ready', 'whatsapp', '📦 *Pedido Listo*', '¡Tu pedido #{{order_id}} está listo!\n\nPuedes pasar a recogerlo a:\n{{business_address}}', '["order_id", "business_address"]'),
|
|
|
|
(NULL, 'order_delivered', 'whatsapp', '🎉 *Pedido Entregado*', '¡Tu pedido #{{order_id}} ha sido entregado!\n\nTotal: ${{total}}\n\n¡Gracias por tu compra!', '["order_id", "total"]'),
|
|
|
|
(NULL, 'order_cancelled', 'whatsapp', '❌ *Pedido Cancelado*', 'Tu pedido #{{order_id}} ha sido cancelado.\n\nSi tienes dudas, contáctanos.', '["order_id"]'),
|
|
|
|
-- Payment notifications
|
|
(NULL, 'payment_received', 'push', '💰 Pago Recibido', 'Se recibió pago de ${{amount}} de {{customer_name}}', '["amount", "customer_name"]'),
|
|
|
|
-- Alert notifications
|
|
(NULL, 'low_stock', 'push', '⚠️ Stock Bajo', '{{product_name}}: quedan {{quantity}} unidades', '["product_name", "quantity"]'),
|
|
|
|
(NULL, 'fiado_reminder', 'whatsapp', '💳 *Recordatorio de Pago*', 'Hola {{customer_name}},\n\nTe recordamos que tienes un saldo pendiente de ${{balance}} en {{business_name}}.\n\n¿Cuándo podrías pasar a abonar?', '["customer_name", "balance", "business_name"]'),
|
|
|
|
-- Report notifications
|
|
(NULL, 'daily_summary', 'push', '📊 Resumen del Día', 'Ventas: ${{total_sales}} | Pedidos: {{orders_count}}', '["total_sales", "orders_count"]'),
|
|
|
|
(NULL, 'weekly_report', 'whatsapp', '📊 *Reporte Semanal*', '📈 Resumen de la semana:\n\n💰 Ventas: ${{total_sales}}\n📦 Pedidos: {{orders_count}}\n🎫 Ticket promedio: ${{avg_ticket}}\n\n¿Necesitas más detalles?', '["total_sales", "orders_count", "avg_ticket"]'),
|
|
|
|
-- System notifications
|
|
(NULL, 'welcome', 'whatsapp', '👋 *¡Bienvenido!*', '¡Hola {{name}}! Bienvenido a {{business_name}}.\n\nPuedes escribirme para:\n• Ver productos\n• Hacer pedidos\n• Consultar tu cuenta\n\n¿En qué te puedo ayudar?', '["name", "business_name"]');
|
|
|
|
-- ============================================
|
|
-- Updated_at trigger
|
|
-- ============================================
|
|
CREATE OR REPLACE FUNCTION notifications.update_updated_at()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_notifications_updated_at
|
|
BEFORE UPDATE ON notifications.notifications
|
|
FOR EACH ROW EXECUTE FUNCTION notifications.update_updated_at();
|
|
|
|
CREATE TRIGGER trg_templates_updated_at
|
|
BEFORE UPDATE ON notifications.notification_templates
|
|
FOR EACH ROW EXECUTE FUNCTION notifications.update_updated_at();
|
|
|
|
CREATE TRIGGER trg_preferences_updated_at
|
|
BEFORE UPDATE ON notifications.notification_preferences
|
|
FOR EACH ROW EXECUTE FUNCTION notifications.update_updated_at();
|
|
|
|
CREATE TRIGGER trg_device_tokens_updated_at
|
|
BEFORE UPDATE ON notifications.device_tokens
|
|
FOR EACH ROW EXECUTE FUNCTION notifications.update_updated_at();
|