workspace-v1/orchestration/directivas/simco/SIMCO-DDL.md
rckrdmrd 66161b1566 feat: Workspace-v1 complete migration with NEXUS v3.4
Sistema NEXUS v3.4 migrado con:

Estructura principal:
- core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles)
- core/catalog: Catalogo de funcionalidades reutilizables
- shared/knowledge-base: Base de conocimiento compartida
- devtools/scripts: Herramientas de desarrollo
- control-plane/registries: Control de servicios y CI/CD
- orchestration/: Configuracion de orquestacion de agentes

Proyectos incluidos (11):
- gamilit (submodule -> GitHub)
- trading-platform (OrbiquanTIA)
- erp-suite con 5 verticales:
  - erp-core, construccion, vidrio-templado
  - mecanicas-diesel, retail, clinicas
- betting-analytics
- inmobiliaria-analytics
- platform_marketing_content
- pos-micro, erp-basico

Configuracion:
- .gitignore completo para Node.js/Python/Docker
- gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git)
- Sistema de puertos estandarizado (3005-3199)

Generated with NEXUS v3.4 Migration System
EPIC-010: Configuracion Git y Repositorios
2026-01-04 03:37:42 -06:00

446 lines
14 KiB
Markdown

# SIMCO: OPERACIONES DDL (Database)
**Versión:** 1.0.0
**Fecha:** 2025-12-08
**Aplica a:** Todo agente que trabaje con base de datos PostgreSQL
**Prioridad:** OBLIGATORIA para operaciones de BD
---
## RESUMEN EJECUTIVO
> **DDL-First: Los archivos DDL son la fuente de verdad. La BD es el resultado de ejecutarlos.**
---
## PRINCIPIO FUNDAMENTAL
```
╔══════════════════════════════════════════════════════════════════════╗
║ POLÍTICA DE CARGA LIMPIA ║
║ ║
║ 1. TODO cambio de BD = modificar archivo DDL ║
║ 2. NUNCA ejecutar ALTER/CREATE directo en BD ║
║ 3. SIEMPRE validar con recreación completa ║
║ 4. La BD debe poder recrearse 100% desde DDL ║
╚══════════════════════════════════════════════════════════════════════╝
```
---
## FLUJO DDL-FIRST
```
1. CREAR/MODIFICAR ARCHIVO DDL
2. EJECUTAR CARGA LIMPIA COMPLETA
cd @DB_SCRIPTS && ./{RECREATE_CMD}
3. ¿PASA SIN ERRORES?
├── SÍ → Continuar a paso 4
└── NO → Volver a paso 1 (corregir DDL)
4. VALIDAR ESTRUCTURA
\dt, \di, \d tabla
5. COMMIT ARCHIVO DDL
```
---
## ESTRUCTURA DE ARCHIVOS DDL
```
{DB_DDL_PATH}/
├── 00-init.sql # Extensiones, tipos base
└── schemas/
├── {schema_1}/
│ ├── 00-schema.sql # CREATE SCHEMA
│ ├── tables/
│ │ ├── 01-{tabla}.sql # Tablas en orden de dependencia
│ │ └── 02-{tabla}.sql
│ ├── functions/
│ │ └── {funcion}.sql
│ └── triggers/
│ └── trg_{tabla}_{accion}.sql
└── {schema_2}/
└── ...
{DB_SEEDS_PATH}/
├── dev/ # Seeds para desarrollo
│ ├── 01-{nombre}.sql
│ └── 02-{nombre}.sql
└── prod/ # Seeds para producción
└── 01-{nombre}.sql
```
---
## CONVENCIONES DE NOMENCLATURA
### Schemas
```sql
-- snake_case
CREATE SCHEMA auth_management;
CREATE SCHEMA gamification_system;
CREATE SCHEMA project_management;
```
### Tablas
```sql
-- snake_case, plural
CREATE TABLE users;
CREATE TABLE student_progress;
CREATE TABLE badge_awards;
```
### Columnas
```sql
-- snake_case
user_id UUID
first_name VARCHAR(100)
created_at TIMESTAMP
is_active BOOLEAN
```
### Índices
```sql
-- idx_{tabla}_{columna(s)}
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status_created ON users(status, created_at);
CREATE UNIQUE INDEX idx_users_username ON users(username);
```
### Foreign Keys
```sql
-- fk_{tabla}_to_{tabla_referenciada}
CONSTRAINT fk_students_to_users
FOREIGN KEY (user_id)
REFERENCES auth_management.users(id)
```
### Check Constraints
```sql
-- chk_{tabla}_{columna}
CONSTRAINT chk_users_status
CHECK (status IN ('active', 'inactive', 'suspended'))
```
### Triggers
```sql
-- trg_{tabla}_{accion}
CREATE TRIGGER trg_users_updated
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
```
### Functions
```sql
-- snake_case con verbo
CREATE FUNCTION calculate_user_level()
CREATE FUNCTION award_badge_to_user()
CREATE FUNCTION update_updated_at_column()
```
---
## TEMPLATE DE ARCHIVO DDL
```sql
-- ============================================================================
-- Tabla: {nombre_tabla}
-- Schema: {schema}
-- Descripción: {descripción breve de la tabla y su propósito}
-- Autor: {Agente}
-- Fecha: {YYYY-MM-DD}
-- Dependencias: {lista de tablas de las que depende o "Ninguna"}
-- ============================================================================
-- Eliminar si existe (solo desarrollo)
DROP TABLE IF EXISTS {schema}.{tabla} CASCADE;
-- ============================================================================
-- CREAR TABLA
-- ============================================================================
CREATE TABLE {schema}.{tabla} (
-- ─────────────────────────────────────────────────────────────────────
-- Identificador
-- ─────────────────────────────────────────────────────────────────────
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- ─────────────────────────────────────────────────────────────────────
-- Campos de Negocio
-- ─────────────────────────────────────────────────────────────────────
{campo_1} {TIPO} {NOT NULL} {DEFAULT},
{campo_2} {TIPO} {NOT NULL} {DEFAULT},
-- ─────────────────────────────────────────────────────────────────────
-- Referencias (Foreign Keys inline o al final)
-- ─────────────────────────────────────────────────────────────────────
{fk_campo} UUID,
-- ─────────────────────────────────────────────────────────────────────
-- Auditoría
-- ─────────────────────────────────────────────────────────────────────
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by UUID,
-- ─────────────────────────────────────────────────────────────────────
-- Constraints
-- ─────────────────────────────────────────────────────────────────────
CONSTRAINT fk_{tabla}_to_{ref}
FOREIGN KEY ({fk_campo})
REFERENCES {schema_ref}.{tabla_ref}(id)
ON DELETE {CASCADE|SET NULL|RESTRICT},
CONSTRAINT chk_{tabla}_{campo}
CHECK ({condicion})
);
-- ============================================================================
-- COMENTARIOS
-- ============================================================================
COMMENT ON TABLE {schema}.{tabla} IS
'{Descripción de la tabla}';
COMMENT ON COLUMN {schema}.{tabla}.{campo_1} IS
'{Descripción del campo, valores válidos, restricciones}';
COMMENT ON COLUMN {schema}.{tabla}.{campo_2} IS
'{Descripción del campo}';
-- ============================================================================
-- ÍNDICES
-- ============================================================================
-- Índice para búsqueda por {criterio}
CREATE INDEX idx_{tabla}_{campo}
ON {schema}.{tabla}({campo});
-- Índice único para {criterio}
CREATE UNIQUE INDEX idx_{tabla}_{campo}_unique
ON {schema}.{tabla}({campo});
-- Índice compuesto para {criterio}
CREATE INDEX idx_{tabla}_{campo1}_{campo2}
ON {schema}.{tabla}({campo1}, {campo2});
-- ============================================================================
-- TRIGGER DE AUDITORÍA
-- ============================================================================
CREATE TRIGGER trg_{tabla}_updated
BEFORE UPDATE ON {schema}.{tabla}
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- ============================================================================
-- ROW LEVEL SECURITY (si aplica)
-- ============================================================================
ALTER TABLE {schema}.{tabla} ENABLE ROW LEVEL SECURITY;
CREATE POLICY {tabla}_select_policy
ON {schema}.{tabla}
FOR SELECT
USING ({condicion_rls});
CREATE POLICY {tabla}_insert_policy
ON {schema}.{tabla}
FOR INSERT
WITH CHECK ({condicion_rls});
-- ============================================================================
-- FIN DE ARCHIVO
-- ============================================================================
```
---
## COMANDOS DE VALIDACIÓN
### Carga Limpia (OBLIGATORIO)
```bash
cd @DB_SCRIPTS
./{RECREATE_CMD}
# DEBE completar sin errores
```
### Verificar Estructura
```bash
# Listar schemas
psql -d {DB_NAME} -c "\dn"
# Listar tablas de un schema
psql -d {DB_NAME} -c "\dt {schema}.*"
# Ver estructura de tabla
psql -d {DB_NAME} -c "\d {schema}.{tabla}"
# Ver índices
psql -d {DB_NAME} -c "\di {schema}.*"
# Ver constraints
psql -d {DB_NAME} -c "\d+ {schema}.{tabla}"
```
### Verificar Comentarios
```bash
# Ver comentario de tabla
psql -d {DB_NAME} -c "
SELECT obj_description('{schema}.{tabla}'::regclass);
"
# Ver comentarios de columnas
psql -d {DB_NAME} -c "
SELECT column_name, col_description('{schema}.{tabla}'::regclass, ordinal_position)
FROM information_schema.columns
WHERE table_schema = '{schema}' AND table_name = '{tabla}';
"
```
### Tests Básicos
```bash
# Insert de prueba
psql -d {DB_NAME} -c "
INSERT INTO {schema}.{tabla} ({columnas})
VALUES ({valores});
"
# Verificar constraint CHECK
psql -d {DB_NAME} -c "
INSERT INTO {schema}.{tabla} ({columna})
VALUES ('valor_invalido');
"
# Debe fallar con error de constraint
# Verificar FK
psql -d {DB_NAME} -c "
INSERT INTO {schema}.{tabla} ({fk_columna})
VALUES ('uuid-no-existente');
"
# Debe fallar con error de FK
```
---
## PROHIBICIONES
```
╔══════════════════════════════════════════════════════════════════════╗
║ ❌ PROHIBIDO ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ • Ejecutar ALTER TABLE directo en BD sin actualizar DDL ║
║ • Crear carpeta migrations/ ║
║ • Crear archivos fix-*.sql o patch-*.sql ║
║ • Crear archivos migration-*.sql ║
║ • Dejar BD y DDL desincronizados ║
║ • Ejecutar psql -c "CREATE/ALTER..." sin archivo DDL ║
║ • Marcar tarea completa sin carga limpia exitosa ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
```
---
## MODIFICAR TABLA EXISTENTE
### Proceso Correcto
```bash
# 1. Editar archivo DDL existente (NO crear migration)
vim @DDL/{schema}/tables/{NN}-{tabla}.sql
# 2. Agregar/modificar columna en CREATE TABLE
# (NO usar ALTER TABLE como cambio principal)
# 3. Ejecutar carga limpia completa
cd @DB_SCRIPTS
./{RECREATE_CMD}
# 4. Verificar cambios
psql -d {DB_NAME} -c "\d {schema}.{tabla}"
# 5. Commit cambios
git add @DDL/{schema}/tables/{NN}-{tabla}.sql
git commit -m "feat(db): add column to {tabla}"
```
### Proceso INCORRECTO
```bash
# ❌ NO hacer esto
psql -d {DB_NAME} -c "ALTER TABLE {schema}.{tabla} ADD COLUMN..."
# ❌ NO crear migration
echo "ALTER TABLE..." > migrations/002-add-column.sql
# ❌ NO crear fix temporal
echo "ALTER TABLE..." > fix-add-column.sql
```
---
## CHECKLIST DDL
```
ANTES DE CREAR
├── [ ] Verificar que tabla no existe (@INVENTORY, grep)
├── [ ] Verificar schema existe (00-schema.sql)
├── [ ] Identificar dependencias (FKs a otras tablas)
├── [ ] Determinar número de archivo (secuencial)
└── [ ] Leer tabla similar como referencia
DURANTE CREACIÓN
├── [ ] Encabezado completo (descripción, autor, fecha, deps)
├── [ ] Columnas con tipos correctos
├── [ ] Campos de auditoría (created_at, updated_at)
├── [ ] Constraints nombrados correctamente
├── [ ] Índices necesarios
├── [ ] COMMENT ON para tabla y columnas importantes
└── [ ] Trigger de updated_at (si aplica)
VALIDACIÓN
├── [ ] Carga limpia exitosa
├── [ ] Estructura verificada (\d tabla)
├── [ ] Índices verificados (\di)
├── [ ] Insert de prueba exitoso
├── [ ] Constraints funcionan (test de validación)
└── [ ] Comentarios presentes
DOCUMENTACIÓN
├── [ ] @INVENTORY actualizado
├── [ ] @TRAZA_DB actualizada
└── [ ] Entity correspondiente identificada para Backend
```
---
## ERRORES COMUNES
| Error | Causa | Solución |
|-------|-------|----------|
| FK falla | Tabla referenciada no existe | Verificar orden de creación |
| Tipo incorrecto | No alineado con diseño | Consultar especificación |
| Sin comentarios | Olvidó COMMENT ON | Template incluye comentarios |
| Sin índices | No pensó en queries | Agregar para columnas de búsqueda |
| Carga limpia falla | DDL con errores | Corregir DDL, no fix manual |
---
## REFERENCIAS
- **Crear archivos:** @CREAR (SIMCO-CREAR.md)
- **Validar:** @VALIDAR (SIMCO-VALIDAR.md)
- **Documentar:** @DOCUMENTAR (SIMCO-DOCUMENTAR.md)
- **Política carga limpia:** @DIRECTIVAS/DIRECTIVA-POLITICA-CARGA-LIMPIA.md
- **Diseño de BD:** @DIRECTIVAS/DIRECTIVA-DISENO-BASE-DATOS.md
- **Nomenclatura:** @DIRECTIVAS/ESTANDARES-NOMENCLATURA-BASE.md
---
**Versión:** 1.0.0 | **Sistema:** SIMCO | **Mantenido por:** Tech Lead