template-saas-database-v2/ddl/schemas/goals/02-tables.sql
Adrian Flores Cortes 6e5244b612 [SAAS-022] feat: Add Goals module DDL
- 00-schema.sql: Schema creation with grants
- 01-enums.sql: 8 enums (goal_type, metric_type, period_type, etc.)
- 02-tables.sql: 4 tables (definitions, assignments, progress_log, milestone_notifications)
- 04-rls.sql: 16 RLS policies for tenant isolation
- 05-indexes.sql: Performance indexes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 06:29:04 -06:00

156 lines
5.8 KiB
SQL

-- ============================================
-- SAAS-022: Goals Tables
-- ============================================
-- ─────────────────────────────────────────────
-- Definiciones de metas
-- ─────────────────────────────────────────────
CREATE TABLE goals.definitions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
-- Info basica
name VARCHAR(200) NOT NULL,
description TEXT,
category VARCHAR(100),
-- Tipo de meta
type goals.goal_type NOT NULL DEFAULT 'target',
metric goals.metric_type NOT NULL DEFAULT 'number',
-- Objetivo
target_value DECIMAL(15,2) NOT NULL,
unit VARCHAR(50), -- 'USD', 'units', '%', etc.
-- Periodo
period goals.period_type NOT NULL DEFAULT 'monthly',
starts_at DATE NOT NULL,
ends_at DATE NOT NULL,
-- Fuente de datos (para tracking automatico)
source goals.data_source NOT NULL DEFAULT 'manual',
source_config JSONB DEFAULT '{}',
-- Ejemplo:
-- {
-- "module": "sales",
-- "entity": "opportunities",
-- "filter": { "status": "won" },
-- "aggregation": "sum",
-- "field": "amount"
-- }
-- Hitos para notificaciones
milestones JSONB DEFAULT '[]',
-- Ejemplo: [{ "percentage": 25, "notify": true }, { "percentage": 50, "notify": true }]
-- Estado
status goals.goal_status NOT NULL DEFAULT 'draft',
-- Metadata
tags JSONB DEFAULT '[]',
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES users.users(id),
-- Constraints
CONSTRAINT valid_date_range CHECK (ends_at >= starts_at),
CONSTRAINT positive_target CHECK (target_value > 0)
);
-- ─────────────────────────────────────────────
-- Asignaciones de metas
-- ─────────────────────────────────────────────
CREATE TABLE goals.assignments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
definition_id UUID NOT NULL REFERENCES goals.definitions(id) ON DELETE CASCADE,
-- Asignado a
assignee_type goals.assignee_type NOT NULL DEFAULT 'user',
user_id UUID REFERENCES users.users(id) ON DELETE CASCADE,
team_id UUID, -- Para uso futuro con modulo de equipos
-- Objetivo personalizado (override del definition)
custom_target DECIMAL(15,2),
-- Progreso
current_value DECIMAL(15,2) NOT NULL DEFAULT 0,
progress_percentage DECIMAL(5,2) NOT NULL DEFAULT 0,
last_updated_at TIMESTAMPTZ,
-- Estado
status goals.assignment_status NOT NULL DEFAULT 'active',
achieved_at TIMESTAMPTZ,
-- Metadata
notes TEXT,
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Constraints
CONSTRAINT valid_progress CHECK (progress_percentage >= 0 AND progress_percentage <= 100),
CONSTRAINT valid_assignee CHECK (
(assignee_type = 'user' AND user_id IS NOT NULL) OR
(assignee_type = 'team' AND team_id IS NOT NULL) OR
(assignee_type = 'tenant')
)
);
-- ─────────────────────────────────────────────
-- Historial de progreso
-- ─────────────────────────────────────────────
CREATE TABLE goals.progress_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
assignment_id UUID NOT NULL REFERENCES goals.assignments(id) ON DELETE CASCADE,
-- Valores
previous_value DECIMAL(15,2),
new_value DECIMAL(15,2) NOT NULL,
change_amount DECIMAL(15,2),
-- Fuente del cambio
source goals.progress_source NOT NULL DEFAULT 'manual',
source_reference VARCHAR(200), -- ID de la transaccion origen
notes TEXT,
-- Timestamps
logged_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
logged_by UUID REFERENCES users.users(id)
);
-- ─────────────────────────────────────────────
-- Notificaciones de hitos alcanzados
-- ─────────────────────────────────────────────
CREATE TABLE goals.milestone_notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
assignment_id UUID NOT NULL REFERENCES goals.assignments(id) ON DELETE CASCADE,
milestone_percentage INTEGER NOT NULL,
achieved_value DECIMAL(15,2) NOT NULL,
notified_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Evitar duplicados
CONSTRAINT unique_milestone_notification UNIQUE (assignment_id, milestone_percentage)
);
-- ─────────────────────────────────────────────
-- Triggers para updated_at
-- ─────────────────────────────────────────────
CREATE TRIGGER update_definitions_updated_at
BEFORE UPDATE ON goals.definitions
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_assignments_updated_at
BEFORE UPDATE ON goals.assignments
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();