# IMPACTO: CAMBIOS EN DDL (Base de Datos) **Versión:** 1.0.0 **Fecha:** 2025-12-08 **Prioridad:** CRÍTICA - Leer antes de modificar DDL **Sistema:** SIMCO + CAPVED --- ## PROPÓSITO Documentar el impacto cascada de cambios en DDL y las acciones requeridas en cada capa. --- ## PRINCIPIO FUNDAMENTAL ``` ╔══════════════════════════════════════════════════════════════════════╗ ║ CAMBIO EN DDL = CAMBIO EN CASCADA ║ ║ ║ ║ DDL → Entity → DTO → Service → Controller → Frontend ║ ║ ║ ║ ⚠️ NUNCA cambiar DDL sin actualizar las capas dependientes ║ ╚══════════════════════════════════════════════════════════════════════╝ ``` --- ## 1. AGREGAR COLUMNA ### Impacto por Capa | Capa | Archivo(s) Afectado(s) | Acción Requerida | |------|------------------------|------------------| | **DDL** | `schemas/{schema}/tables/{tabla}.sql` | Agregar columna | | **Entity** | `{nombre}.entity.ts` | Agregar @Column | | **DTO Create** | `create-{nombre}.dto.ts` | Agregar campo (si input) | | **DTO Update** | `update-{nombre}.dto.ts` | Heredado de Create | | **DTO Response** | `{nombre}-response.dto.ts` | Agregar campo (si output) | | **Service** | `{nombre}.service.ts` | Ajustar lógica si necesario | | **Controller** | `{nombre}.controller.ts` | Swagger actualizado automático | | **Frontend Types** | `{nombre}.types.ts` | Agregar campo | | **Frontend Forms** | `{Nombre}Form.tsx` | Agregar input (si editable) | | **Frontend Display** | `{Nombre}Card.tsx`, etc. | Mostrar campo (si visible) | | **Tests** | `*.spec.ts`, `*.test.tsx` | Actualizar fixtures | ### Checklist: Agregar Columna ``` DDL (Database-Agent): [ ] ALTER TABLE o modificar CREATE TABLE [ ] Definir tipo correcto (ver MAPEO-TIPOS.md) [ ] Definir NULL/NOT NULL [ ] Definir DEFAULT si aplica [ ] Crear índice si es buscable [ ] Ejecutar carga limpia exitosa [ ] Actualizar DATABASE_INVENTORY.yml Backend (Backend-Agent): [ ] Agregar @Column en Entity - type: coincide con DDL - nullable: coincide con DDL - default: coincide con DDL [ ] Agregar campo en CreateDto (si es input) - Validaciones apropiadas - @ApiProperty con ejemplo [ ] Agregar campo en ResponseDto (si es output) [ ] Ajustar Service si hay lógica nueva [ ] npm run build → pasa [ ] npm run lint → pasa [ ] Actualizar BACKEND_INVENTORY.yml Frontend (Frontend-Agent): [ ] Agregar campo en interface/type [ ] Actualizar Zod schema si hay form [ ] Agregar input en formulario (si editable) [ ] Mostrar en UI (si visible) [ ] npm run build → pasa [ ] npm run lint → pasa [ ] Actualizar FRONTEND_INVENTORY.yml Integración: [ ] Test e2e funciona [ ] Swagger muestra campo nuevo [ ] Frontend consume correctamente ``` ### Ejemplo Completo: Agregar Campo `phone` **1. DDL:** ```sql -- schemas/auth/tables/01-users.sql ALTER TABLE auth.users ADD COLUMN phone VARCHAR(20); ``` **2. Entity:** ```typescript // entities/user.entity.ts @Column({ type: 'varchar', length: 20, nullable: true }) phone: string; ``` **3. DTO Create:** ```typescript // dto/create-user.dto.ts @ApiPropertyOptional({ description: 'Teléfono', example: '+521234567890' }) @IsOptional() @IsPhoneNumber('MX') phone?: string; ``` **4. DTO Response:** ```typescript // dto/user-response.dto.ts @ApiPropertyOptional() phone?: string; ``` **5. Frontend Type:** ```typescript // types/user.types.ts interface User { id: string; email: string; name: string; phone?: string; // ← NUEVO } ``` **6. Frontend Form:** ```typescript // components/UserForm.tsx ``` --- ## 2. ELIMINAR COLUMNA ### Impacto por Capa | Capa | Acción | Riesgo | |------|--------|--------| | **DDL** | `ALTER TABLE DROP COLUMN` | ALTO - Datos perdidos | | **Entity** | Eliminar @Column | MEDIO | | **DTO** | Eliminar campo | MEDIO | | **Service** | Eliminar referencias | ALTO - Lógica rota | | **Frontend** | Eliminar campo y usos | ALTO - UI rota | | **Tests** | Actualizar fixtures | MEDIO | ### Checklist: Eliminar Columna ``` ⚠️ ANTES DE ELIMINAR: [ ] Confirmar que datos no son necesarios [ ] Verificar que no hay dependencias en código [ ] Grep en todo el proyecto: grep -rn "{columna}" apps/ [ ] Planificar migración de datos si necesario DDL: [ ] ALTER TABLE DROP COLUMN [ ] Verificar que no rompe constraints/FK [ ] Carga limpia exitosa Backend: [ ] Eliminar @Column de Entity [ ] Eliminar de DTOs [ ] Buscar y eliminar referencias en Services [ ] npm run build → sin errores de tipo [ ] npm run test → pasa Frontend: [ ] Eliminar de types/interfaces [ ] Eliminar de formularios [ ] Eliminar de displays [ ] npm run build → sin errores de tipo Post-eliminación: [ ] Verificar que aplicación funciona [ ] Verificar que no hay errores en consola [ ] Actualizar documentación ``` --- ## 3. MODIFICAR TIPO DE COLUMNA ### Impacto por Capa | Cambio | Backend | Frontend | Riesgo | |--------|---------|----------|--------| | `VARCHAR(50)` → `VARCHAR(100)` | Cambiar length | - | BAJO | | `VARCHAR` → `TEXT` | Cambiar type | - | BAJO | | `INTEGER` → `BIGINT` | `number` → `string` | Cambiar tipo | MEDIO | | `VARCHAR` → `ENUM` | Agregar enum | Agregar enum | MEDIO | | `TEXT` → `JSON` | Cambiar tipo, parsear | Cambiar tipo | ALTO | ### Checklist: Modificar Tipo ``` DDL: [ ] ALTER TABLE ALTER COLUMN TYPE [ ] Verificar que datos existentes son compatibles [ ] Carga limpia exitosa Backend: [ ] Actualizar @Column type [ ] Actualizar tipo TypeScript si cambió [ ] Actualizar validaciones en DTO [ ] npm run build → pasa Frontend: [ ] Actualizar tipo en interface [ ] Actualizar validación Zod [ ] Ajustar componentes si tipo cambió [ ] npm run build → pasa Datos: [ ] Migrar datos existentes si necesario [ ] Validar integridad post-migración ``` --- ## 4. AGREGAR/MODIFICAR FOREIGN KEY ### Impacto por Capa | Capa | Acción | |------|--------| | **DDL** | Agregar FK + índice | | **Entity** | Agregar @ManyToOne + @JoinColumn | | **Service** | Validar existencia antes de insertar | | **DTO** | Agregar campo ID de relación | | **Frontend** | Agregar selector/dropdown | ### Checklist: Agregar FK ``` DDL: [ ] Agregar columna FK (UUID) [ ] Agregar FOREIGN KEY constraint [ ] Definir ON DELETE (CASCADE/SET NULL/RESTRICT) [ ] Crear índice en FK [ ] Verificar que tabla referenciada existe Backend: [ ] Agregar columna en Entity: {relation}Id: string [ ] Agregar relación: @ManyToOne(() => RelatedEntity) [ ] Agregar @JoinColumn({ name: '{relation}_id' }) [ ] Validar existencia en Service antes de crear [ ] Agregar en DTO con @IsUUID Frontend: [ ] Agregar campo en type [ ] Crear selector si es editable [ ] Mostrar relación en UI ``` --- ## 5. AGREGAR/MODIFICAR ÍNDICE ### Impacto - **DDL**: Agregar `CREATE INDEX` - **Otras capas**: Sin impacto directo - **Performance**: Mejora en queries ### Checklist: Agregar Índice ``` [ ] Identificar columnas frecuentemente buscadas [ ] Agregar CREATE INDEX en DDL [ ] Para búsquedas compuestas: índice compuesto [ ] Ejecutar carga limpia [ ] Verificar plan de query (EXPLAIN) ``` --- ## 6. AGREGAR TABLA NUEVA ### Impacto Completo ``` NUEVA TABLA = Feature completa DDL: ├── CREATE TABLE con todas las columnas ├── PRIMARY KEY ├── FOREIGN KEYS ├── INDEXES ├── COMMENTS └── Actualizar DATABASE_INVENTORY.yml Backend: ├── {nombre}.entity.ts ├── create-{nombre}.dto.ts ├── update-{nombre}.dto.ts ├── {nombre}-response.dto.ts ├── {nombre}.service.ts ├── {nombre}.controller.ts ├── {nombre}.module.ts ├── Tests unitarios └── Actualizar BACKEND_INVENTORY.yml Frontend: ├── {nombre}.types.ts ├── {nombre}.service.ts (API calls) ├── use{Nombre}.ts (hook) ├── {Nombre}Form.tsx ├── {Nombre}List.tsx ├── {Nombre}Page.tsx ├── Tests de componentes └── Actualizar FRONTEND_INVENTORY.yml ``` --- ## 7. ELIMINAR TABLA ### Impacto CRÍTICO ``` ⚠️ ELIMINAR TABLA = DESTRUIR FEATURE ANTES de eliminar: [ ] Confirmar que feature ya no se usa [ ] Backup de datos si necesario [ ] Verificar que no hay FK apuntando a esta tabla [ ] Grep completo: grep -rn "{tabla}" apps/ Orden de eliminación (inverso a creación): 1. Frontend: Eliminar páginas, componentes, types 2. Backend: Eliminar controller, service, entity, DTOs, module 3. DDL: DROP TABLE 4. Actualizar todos los inventarios Post-eliminación: [ ] Build pasa en todas las capas [ ] Aplicación funciona sin errores [ ] Documentación actualizada ``` --- ## 8. MATRIZ DE PROPAGACIÓN RÁPIDA ``` ┌─────────────────┬─────────┬────────┬─────────┬──────────┬──────────┐ │ Cambio DDL │ Entity │ DTO │ Service │ Frontend │ Tests │ ├─────────────────┼─────────┼────────┼─────────┼──────────┼──────────┤ │ + Columna │ +Column │ +Field │ ?Lógica │ +Type │ +Fixture │ │ - Columna │ -Column │ -Field │ -Refs │ -Type │ -Fixture │ │ ~ Tipo │ ~Type │ ~Valid │ ?Parse │ ~Type │ ~Fixture │ │ + FK │ +Rel │ +UUID │ +Valid │ +Select │ +Test │ │ + Índice │ - │ - │ - │ - │ - │ │ + Tabla │ +Todo │ +Todo │ +Todo │ +Todo │ +Todo │ │ - Tabla │ -Todo │ -Todo │ -Todo │ -Todo │ -Todo │ └─────────────────┴─────────┴────────┴─────────┴──────────┴──────────┘ Leyenda: + = Agregar - = Eliminar ~ = Modificar ? = Posiblemente ``` --- ## 9. COMANDOS DE VERIFICACIÓN ```bash # Verificar que cambio DDL no rompe cd {DB_SCRIPTS_PATH} ./recreate-database.sh # Carga limpia completa # Verificar build backend cd {BACKEND_ROOT} npm run build && npm run lint # Verificar build frontend cd {FRONTEND_ROOT} npm run build && npm run lint && npm run typecheck # Buscar referencias a columna/tabla grep -rn "{nombre}" apps/ # Verificar alineación Entity-DDL # Comparar @Column en Entity vs columnas en DDL ``` --- ## 10. ANTI-PATRONES ``` ❌ NUNCA: Cambiar DDL sin actualizar Entity → Resultado: Runtime error al acceder columna ❌ NUNCA: Agregar columna NOT NULL sin DEFAULT → Resultado: INSERT falla en registros existentes ❌ NUNCA: Eliminar columna sin verificar uso → Resultado: Código roto en múltiples lugares ❌ NUNCA: Cambiar tipo sin migrar datos → Resultado: Datos corruptos o perdidos ❌ NUNCA: Modificar FK sin ajustar relaciones en Entity → Resultado: ORM genera queries incorrectas ✅ SIEMPRE: DDL primero → Entity segundo → DTO tercero → Frontend cuarto ✅ SIEMPRE: Verificar build en TODAS las capas después de cambio ✅ SIEMPRE: Actualizar inventarios y trazas ✅ SIEMPRE: Grep antes de eliminar para encontrar usos ``` --- **Versión:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Guía de Impacto