template-saas-database-v2/ddl/schemas/notifications/tables/01-notifications.sql
rckrdmrd 3ce06fbce4 Initial commit - Database de template-saas migrado desde monorepo
Migración desde workspace-v2/projects/template-saas/apps/database
Este repositorio es parte del estándar multi-repo v2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:07:11 -06:00

161 lines
5.2 KiB
PL/PgSQL

-- ============================================
-- TEMPLATE-SAAS: Notifications
-- Schema: notifications
-- Version: 1.0.0
-- ============================================
-- Notification templates
CREATE TABLE notifications.templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Template identification
code VARCHAR(100) UNIQUE NOT NULL, -- e.g., 'welcome_email', 'invoice_paid'
name VARCHAR(200) NOT NULL,
description TEXT,
category VARCHAR(100), -- 'transactional', 'marketing', 'system'
-- Channel
channel notifications.channel NOT NULL,
-- Content
subject VARCHAR(500), -- For email
body TEXT NOT NULL,
body_html TEXT, -- For email HTML version
-- Variables (for template rendering)
variables JSONB DEFAULT '[]'::jsonb,
-- Example: [{"name": "user_name", "required": true}, {"name": "company", "default": "SaaS"}]
-- Status
is_active BOOLEAN DEFAULT TRUE,
-- Audit
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);
-- Notifications (instances)
CREATE TABLE notifications.notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
user_id UUID REFERENCES users.users(id) ON DELETE SET NULL,
-- Template
template_id UUID REFERENCES notifications.templates(id),
template_code VARCHAR(100),
-- Channel
channel notifications.channel NOT NULL,
-- Content
subject VARCHAR(500),
body TEXT NOT NULL,
body_html TEXT,
-- Recipient
recipient_email VARCHAR(255),
recipient_phone VARCHAR(50),
recipient_device_token VARCHAR(500),
-- Status
status notifications.notification_status DEFAULT 'pending' NOT NULL,
priority notifications.priority DEFAULT 'normal',
-- Delivery info
sent_at TIMESTAMPTZ,
delivered_at TIMESTAMPTZ,
is_read BOOLEAN DEFAULT FALSE NOT NULL,
read_at TIMESTAMPTZ,
failed_at TIMESTAMPTZ,
failure_reason TEXT,
-- Retry
retry_count INT DEFAULT 0,
next_retry_at TIMESTAMPTZ,
-- Metadata
metadata JSONB DEFAULT '{}'::jsonb,
-- Audit
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);
-- User preferences
CREATE TABLE notifications.user_preferences (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users.users(id) ON DELETE CASCADE,
-- Channel preferences
email_enabled BOOLEAN DEFAULT TRUE,
push_enabled BOOLEAN DEFAULT TRUE,
sms_enabled BOOLEAN DEFAULT FALSE,
in_app_enabled BOOLEAN DEFAULT TRUE,
-- Category preferences (JSONB)
category_preferences JSONB DEFAULT '{}'::jsonb,
-- Example: { "marketing": false, "transactional": true }
-- Quiet hours
quiet_hours_enabled BOOLEAN DEFAULT FALSE,
quiet_hours_start TIME,
quiet_hours_end TIME,
quiet_hours_timezone VARCHAR(50),
-- Digest
digest_enabled BOOLEAN DEFAULT FALSE,
digest_frequency VARCHAR(20), -- 'daily', 'weekly'
-- Audit
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
-- Constraints
CONSTRAINT unique_user_preferences UNIQUE (user_id)
);
-- Indexes
CREATE INDEX idx_templates_code ON notifications.templates(code) WHERE is_active = TRUE;
CREATE INDEX idx_templates_channel ON notifications.templates(channel) WHERE is_active = TRUE;
CREATE INDEX idx_notifications_tenant ON notifications.notifications(tenant_id, created_at DESC);
CREATE INDEX idx_notifications_user ON notifications.notifications(user_id, created_at DESC);
CREATE INDEX idx_notifications_status ON notifications.notifications(status) WHERE status IN ('pending', 'sent');
CREATE INDEX idx_notifications_retry ON notifications.notifications(next_retry_at) WHERE status = 'pending' AND next_retry_at IS NOT NULL;
CREATE INDEX idx_user_preferences_user ON notifications.user_preferences(user_id);
-- RLS
ALTER TABLE notifications.notifications ENABLE ROW LEVEL SECURITY;
ALTER TABLE notifications.user_preferences ENABLE ROW LEVEL SECURITY;
CREATE POLICY notifications_tenant_isolation ON notifications.notifications
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY user_preferences_tenant_isolation ON notifications.user_preferences
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
-- 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_templates_updated_at
BEFORE UPDATE ON notifications.templates
FOR EACH ROW
EXECUTE FUNCTION notifications.update_updated_at();
CREATE TRIGGER trg_user_preferences_updated_at
BEFORE UPDATE ON notifications.user_preferences
FOR EACH ROW
EXECUTE FUNCTION notifications.update_updated_at();
-- Comments
COMMENT ON TABLE notifications.templates IS 'Notification templates with variables';
COMMENT ON TABLE notifications.notifications IS 'Notification instances and delivery status';
COMMENT ON TABLE notifications.user_preferences IS 'User notification preferences';