DDL-SPEC-{schema_name}: Especificacion de Schema
INSTRUCCIONES: Copiar este template para cada schema nuevo.
Eliminar esta seccion antes de guardar.
Metadatos
| Campo |
Valor |
| Schema |
{schema_name} |
| Modulo |
{MGN-NNN / MAI-NNN} |
| Estado |
{Borrador / Aprobado / Implementado} |
| Version |
1.0.0 |
| Autor |
{nombre} |
| Fecha |
{YYYY-MM-DD} |
Resumen
| Metrica |
Cantidad |
| Tablas |
{N} |
| Vistas |
{N} |
| Funciones |
{N} |
| Triggers |
{N} |
| Indices |
{N} |
| RLS Policies |
{N} |
Diagrama ER
erDiagram
%% Ejemplo - reemplazar con diagrama real
TABLA_PRINCIPAL ||--o{ TABLA_DETALLE : tiene
TABLA_PRINCIPAL ||--|| TABLA_CONFIG : configura
TABLA_PRINCIPAL {
uuid id PK
uuid tenant_id FK
varchar nombre
timestamp created_at
timestamp updated_at
}
TABLA_DETALLE {
uuid id PK
uuid principal_id FK
varchar descripcion
decimal cantidad
}
Tablas
{nombre_tabla_1}
Proposito: {Descripcion breve del proposito de la tabla}
DDL Path: database/ddl/schemas/{schema}/tables/{NN}-{nombre}.sql
Columnas
| Columna |
Tipo |
Nullable |
Default |
Descripcion |
id |
UUID |
NOT NULL |
gen_random_uuid() |
Primary Key |
tenant_id |
UUID |
NOT NULL |
- |
FK a tenants (multi-tenant) |
{columna} |
{tipo} |
{NULL/NOT NULL} |
{default} |
{descripcion} |
created_at |
TIMESTAMPTZ |
NOT NULL |
NOW() |
Fecha creacion |
updated_at |
TIMESTAMPTZ |
NOT NULL |
NOW() |
Fecha actualizacion |
created_by |
UUID |
NULL |
- |
Usuario que creo |
updated_by |
UUID |
NULL |
- |
Usuario que actualizo |
is_active |
BOOLEAN |
NOT NULL |
TRUE |
Soft delete |
Constraints
| Tipo |
Nombre |
Definicion |
| PK |
pk_{tabla} |
PRIMARY KEY (id) |
| FK |
fk_{tabla}_tenant |
FOREIGN KEY (tenant_id) REFERENCES core_system.tenants(id) |
| FK |
fk_{tabla}_{ref} |
FOREIGN KEY ({col}) REFERENCES {schema}.{tabla}(id) |
| UQ |
uq_{tabla}_{cols} |
UNIQUE (tenant_id, {columna}) |
| CHK |
chk_{tabla}_{regla} |
CHECK ({condicion}) |
Indices
| Nombre |
Columnas |
Tipo |
Proposito |
idx_{tabla}_tenant |
(tenant_id) |
BTREE |
Filtro multi-tenant |
idx_{tabla}_{col} |
({columna}) |
BTREE |
Busqueda por {col} |
idx_{tabla}_search |
({cols}) |
GIN/GIST |
Busqueda full-text |
Triggers
| Nombre |
Evento |
Funcion |
Proposito |
trg_{tabla}_updated_at |
BEFORE UPDATE |
core_system.update_timestamp() |
Actualizar updated_at |
trg_{tabla}_audit |
AFTER INSERT/UPDATE/DELETE |
audit_logging.log_change() |
Auditoria |
RLS Policies
| Nombre |
Operacion |
Definicion |
tenant_isolation_{tabla} |
ALL |
tenant_id = current_setting('app.tenant_id')::uuid |
{policy_name} |
{SELECT/INSERT/UPDATE/DELETE} |
{condicion} |
SQL de Creacion
-- Schema: {schema_name}
-- Tabla: {nombre_tabla}
-- Modulo: {MGN-NNN}
CREATE TABLE {schema_name}.{nombre_tabla} (
-- Primary Key
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Multi-tenant (OBLIGATORIO)
tenant_id UUID NOT NULL REFERENCES core_system.tenants(id),
-- Columnas de negocio
{columna} {TIPO} {NOT NULL} {DEFAULT},
-- Auditoria (OBLIGATORIO)
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES core_auth.users(id),
updated_by UUID REFERENCES core_auth.users(id),
is_active BOOLEAN NOT NULL DEFAULT TRUE
);
-- Comentarios
COMMENT ON TABLE {schema_name}.{nombre_tabla} IS '{Descripcion de la tabla}';
COMMENT ON COLUMN {schema_name}.{nombre_tabla}.{columna} IS '{Descripcion columna}';
-- Indices
CREATE INDEX idx_{tabla}_tenant ON {schema_name}.{nombre_tabla}(tenant_id);
CREATE INDEX idx_{tabla}_{col} ON {schema_name}.{nombre_tabla}({columna});
-- Unique constraints
ALTER TABLE {schema_name}.{nombre_tabla}
ADD CONSTRAINT uq_{tabla}_{cols} UNIQUE (tenant_id, {columna});
-- Trigger updated_at
CREATE TRIGGER trg_{tabla}_updated_at
BEFORE UPDATE ON {schema_name}.{nombre_tabla}
FOR EACH ROW
EXECUTE FUNCTION core_system.update_timestamp();
-- RLS
ALTER TABLE {schema_name}.{nombre_tabla} ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_{tabla} ON {schema_name}.{nombre_tabla}
USING (tenant_id = current_setting('app.tenant_id')::uuid);
{nombre_tabla_2}
Repetir la estructura anterior para cada tabla
Vistas
v_{nombre_vista}
Proposito: {Descripcion}
CREATE OR REPLACE VIEW {schema_name}.v_{nombre} AS
SELECT
t1.id,
t1.nombre,
t2.descripcion
FROM {schema_name}.{tabla1} t1
JOIN {schema_name}.{tabla2} t2 ON t1.id = t2.{fk}
WHERE t1.is_active = TRUE;
Funciones
{nombre_funcion}
Proposito: {Descripcion}
Parametros:
| Nombre |
Tipo |
Descripcion |
p_{param} |
{tipo} |
{descripcion} |
Retorna: {tipo}
CREATE OR REPLACE FUNCTION {schema_name}.{nombre_funcion}(
p_param1 UUID,
p_param2 VARCHAR
) RETURNS {tipo} AS $$
DECLARE
v_result {tipo};
BEGIN
-- Logica
RETURN v_result;
END;
$$ LANGUAGE plpgsql;
Datos Iniciales (Seeds)
Catalogos Base
-- Seeds para {schema_name}
-- Ejecutar despues de crear tablas
INSERT INTO {schema_name}.{tabla} (id, tenant_id, {columnas})
VALUES
('uuid-fijo-1', 'tenant-default', {valores}),
('uuid-fijo-2', 'tenant-default', {valores});
Nota: Usar UUIDs fijos para datos de referencia (catalogos)
Dependencias
Schemas Requeridos
| Schema |
Proposito |
core_system |
Tenants, sequences |
core_auth |
Users (para FK created_by/updated_by) |
Funciones Requeridas
| Funcion |
Schema |
Proposito |
update_timestamp() |
core_system |
Trigger updated_at |
log_change() |
audit_logging |
Auditoria |
Orden de Ejecucion
00-schema.sql - Crear schema
01-{tabla_principal}.sql - Tabla sin FK a otras del schema
02-{tabla_dependiente}.sql - Tablas con FK
10-functions.sql - Funciones
20-views.sql - Vistas
30-triggers.sql - Triggers adicionales
90-seeds.sql - Datos iniciales
Validaciones Pre-Implementacion
Referencias
| Documento |
Path |
| Directiva BD |
core/orchestration/directivas/DIRECTIVA-DISENO-BASE-DATOS.md |
| Patrones Odoo |
erp-core/orchestration/directivas/DIRECTIVA-PATRONES-ODOO.md |
| Requerimiento |
docs/01-requerimientos/RF-{modulo}/ |
Historial
| Version |
Fecha |
Autor |
Cambios |
| 1.0 |
{YYYY-MM-DD} |
{nombre} |
Creacion inicial |
Template version 1.0 - ERP Suite