workspace-v1/core/orchestration/impactos/IMPACTO-CAMBIOS-ENTITY.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

17 KiB

IMPACTO DE CAMBIOS EN ENTITY

Version: 1.0.0 Fecha: 2025-12-08 Prioridad: OBLIGATORIA - Consultar antes de modificar Entities Sistema: SIMCO + CAPVED


PROPOSITO

Documentar especificamente los impactos de modificar Entities de TypeORM, que son el puente entre la base de datos y la logica de negocio.


1. PRINCIPIO FUNDAMENTAL

╔══════════════════════════════════════════════════════════════════════╗
║  ENTITY ES REFLEJO DE DDL, NO AL REVES                               ║
║                                                                       ║
║  DDL (fuente) ──────▶ Entity (reflejo) ──────▶ DTO (contrato API)   ║
║                                                                       ║
║  ⚠️  NUNCA crear Entity sin DDL existente                            ║
║  ⚠️  NUNCA modificar Entity sin verificar DDL primero                ║
╚══════════════════════════════════════════════════════════════════════╝

2. TIPOS DE CAMBIOS EN ENTITY

2.1 Cambios de Columna

Tipo de Cambio Impacto DDL Impacto DTO Impacto Service Impacto Frontend
Agregar campo SI SI Posible SI
Eliminar campo SI SI Verificar SI
Renombrar campo SI SI SI SI
Cambiar tipo SI SI Posible SI
Cambiar nullable SI SI Posible SI
Agregar default SI Posible NO NO

2.2 Cambios de Relacion

Tipo de Cambio Impacto DDL Impacto DTO Impacto Service Impacto Frontend
Agregar ManyToOne SI (FK) SI SI SI
Agregar OneToMany NO SI SI SI
Agregar ManyToMany SI (junction) SI SI SI
Eliminar relacion SI SI SI SI
Cambiar cascade NO NO Verificar NO

2.3 Cambios de Indice/Constraint

Tipo de Cambio Impacto DDL Impacto DTO Impacto Service Impacto Frontend
Agregar indice SI NO NO NO
Agregar unique SI NO Manejar error Manejar error
Agregar check SI NO Manejar error Manejar error

3. AGREGAR CAMPO A ENTITY

Flujo Completo

┌─────────────────────────────────────────────────────────────────────┐
│ PASO 1: DDL (Database-Agent)                                        │
├─────────────────────────────────────────────────────────────────────┤
│ ALTER TABLE auth.users ADD COLUMN phone VARCHAR(20);                │
│                                                                      │
│ Validar: ./recreate-database.sh && psql -c "\d auth.users"         │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│ PASO 2: Entity (Backend-Agent)                                      │
├─────────────────────────────────────────────────────────────────────┤
│ @Column({ type: 'varchar', length: 20, nullable: true })           │
│ phone: string | null;                                               │
│                                                                      │
│ Validar: npm run build                                              │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│ PASO 3: DTOs (Backend-Agent)                                        │
├─────────────────────────────────────────────────────────────────────┤
│ CreateUserDto:                                                      │
│   @IsOptional()                                                     │
│   @IsString()                                                       │
│   @MaxLength(20)                                                    │
│   phone?: string;                                                   │
│                                                                      │
│ UserResponseDto:                                                    │
│   @ApiProperty({ required: false })                                 │
│   phone: string | null;                                             │
│                                                                      │
│ Validar: npm run build && npm run lint                              │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│ PASO 4: Frontend (Frontend-Agent)                                   │
├─────────────────────────────────────────────────────────────────────┤
│ user.types.ts:                                                      │
│   interface User {                                                  │
│     phone: string | null;                                           │
│   }                                                                 │
│                                                                      │
│ user.schema.ts:                                                     │
│   phone: z.string().max(20).optional()                              │
│                                                                      │
│ Validar: npm run build && npm run typecheck                         │
└─────────────────────────────────────────────────────────────────────┘

Checklist Agregar Campo

[ ] 1. DDL tiene la columna con tipo correcto
[ ] 2. Entity @Column refleja DDL (tipo, length, nullable)
[ ] 3. CreateDto tiene validaciones apropiadas
[ ] 4. UpdateDto hereda de CreateDto (automatico con PartialType)
[ ] 5. ResponseDto tiene el campo con ApiProperty
[ ] 6. Frontend interface tiene el campo
[ ] 7. Frontend Zod schema tiene validacion equivalente
[ ] 8. Swagger documenta correctamente
[ ] 9. Build pasa en backend
[ ] 10. Build y typecheck pasan en frontend

4. ELIMINAR CAMPO DE ENTITY

ADVERTENCIA

⚠️  ELIMINAR CAMPO ES OPERACION DESTRUCTIVA

ANTES DE ELIMINAR:
1. Verificar que no hay datos importantes
2. Buscar TODAS las referencias en codigo
3. Considerar deprecar primero (nullable + ignorar)
4. Planear migracion de datos si necesario

Flujo de Eliminacion

# PASO 0: Buscar todas las referencias
grep -rn "fieldName" src/
grep -rn "fieldName" apps/
grep -rn "field_name" db/  # snake_case en DDL

# PASO 1: Eliminar uso en Frontend primero (evita errores de tipo)
# PASO 2: Eliminar uso en Service/Controller
# PASO 3: Eliminar de DTOs
# PASO 4: Eliminar de Entity
# PASO 5: Eliminar de DDL (ultimo porque es irreversible)

Checklist Eliminar Campo

[ ] 1. Buscar referencias en backend: grep -rn "field" src/
[ ] 2. Buscar referencias en frontend: grep -rn "field" apps/
[ ] 3. Eliminar de componentes Frontend
[ ] 4. Eliminar de types/interfaces Frontend
[ ] 5. Eliminar de Zod schemas Frontend
[ ] 6. Eliminar de Service (si hay logica)
[ ] 7. Eliminar de ResponseDto
[ ] 8. Eliminar de CreateDto
[ ] 9. Eliminar de Entity
[ ] 10. Eliminar de DDL (con migracion)
[ ] 11. Build pasa en todos los proyectos

5. AGREGAR RELACION A ENTITY

5.1 ManyToOne (FK hacia otra tabla)

// Entity: Order tiene un User
@ManyToOne(() => UserEntity, { nullable: false })
@JoinColumn({ name: 'user_id' })
user: UserEntity;

// Columna FK explicita (opcional pero recomendado)
@Column({ type: 'uuid' })
userId: string;

Impacto:

Capa Archivo Cambio Requerido
DDL XX-orders.sql user_id UUID REFERENCES auth.users(id)
Entity order.entity.ts @ManyToOne + @JoinColumn
CreateDto create-order.dto.ts @IsUUID() userId: string;
ResponseDto order-response.dto.ts userId: string; o user: UserResponseDto;
Service order.service.ts Decidir: cargar relacion o no
Frontend order.types.ts userId: string; o user: User;

5.2 OneToMany (Coleccion inversa)

// Entity: User tiene muchos Orders
@OneToMany(() => OrderEntity, order => order.user)
orders: OrderEntity[];

Impacto:

Capa Archivo Cambio Requerido
DDL N/A Sin cambio (FK esta en orders)
Entity user.entity.ts @OneToMany
ResponseDto user-response.dto.ts Decidir: incluir o no
Service user.service.ts Decidir: cargar relacion o no
Frontend user.types.ts orders?: Order[];

5.3 ManyToMany (Tabla junction)

// Entity: User tiene muchos Roles
@ManyToMany(() => RoleEntity)
@JoinTable({
    name: 'user_roles',
    joinColumn: { name: 'user_id' },
    inverseJoinColumn: { name: 'role_id' },
})
roles: RoleEntity[];

Impacto:

Capa Archivo Cambio Requerido
DDL XX-user-roles.sql Crear tabla junction
Entity user.entity.ts @ManyToMany + @JoinTable
ResponseDto user-response.dto.ts roles: RoleResponseDto[];
Service user.service.ts Logica para asignar/remover roles
Controller user.controller.ts Endpoints para manejar roles
Frontend user.types.ts roles: Role[];
Frontend useUserRoles.ts Hook para manejar roles

Checklist Agregar Relacion

[ ] 1. DDL tiene FK o tabla junction
[ ] 2. Entity tiene decorador de relacion correcto
[ ] 3. Entity relacionada tiene relacion inversa (si necesario)
[ ] 4. CreateDto acepta ID de relacion
[ ] 5. ResponseDto decide: incluir objeto o solo ID
[ ] 6. Service decide: eager loading o lazy
[ ] 7. Frontend types reflejan estructura
[ ] 8. Frontend tiene logica para manejar relacion

6. CAMBIAR TIPO DE CAMPO

Mapeo de Cambios Comunes

Cambio DDL Entity DTO Frontend
INTBIGINT ALTER TYPE number (sin cambio) Sin cambio Sin cambio
VARCHARTEXT ALTER TYPE Sin cambio Ajustar MaxLength Ajustar max
INTEGERDECIMAL ALTER TYPE numberstring Ajustar validador Ajustar tipo
BOOLEANENUM ALTER TYPE booleanenum Cambiar validador Cambiar tipo
VARCHARUUID ALTER TYPE + datos string (sin cambio) Agregar @IsUUID Agregar validacion

Ejemplo: INTEGER a DECIMAL

-- DDL
ALTER TABLE products ALTER COLUMN price TYPE DECIMAL(10,2);
// Entity ANTES
@Column({ type: 'integer' })
price: number;

// Entity DESPUES
@Column({ type: 'decimal', precision: 10, scale: 2 })
price: string;  // String para precision
// CreateDto ANTES
@IsNumber()
price: number;

// CreateDto DESPUES
@IsNumberString()
@Matches(/^\d+(\.\d{1,2})?$/)
price: string;
// Frontend ANTES
interface Product {
    price: number;
}

// Frontend DESPUES
interface Product {
    price: string;
}

// Uso en componente
const displayPrice = parseFloat(product.price).toFixed(2);

7. PATRON DE MIGRACION SEGURA

Para cambios que pueden romper

FASE 1: Agregar nuevo (sin eliminar viejo)
═══════════════════════════════════════════════════════════════
1. Agregar nuevo campo/columna junto al existente
2. Actualizar codigo para escribir en ambos
3. Deploy backend

FASE 2: Migrar datos
═══════════════════════════════════════════════════════════════
1. Script para copiar datos de viejo a nuevo
2. Verificar integridad

FASE 3: Cambiar lecturas
═══════════════════════════════════════════════════════════════
1. Actualizar codigo para leer de nuevo
2. Deploy backend + frontend

FASE 4: Eliminar viejo
═══════════════════════════════════════════════════════════════
1. Eliminar campo viejo de codigo
2. Eliminar columna de DDL
3. Deploy final

8. DECORADORES ENTITY Y SU IMPACTO

@Column Options

Option Impacto si cambia Requiere DDL
type Tipo TS, validacion DTO SI
length Validacion DTO SI
nullable Tipo TS (null), validacion SI
default Posible logica Service SI
unique Manejo error Service SI
name Ninguno (mapeo interno) SI
precision/scale Tipo TS, formateo FE SI

@Index

Cambio Impacto
Agregar Solo performance, DDL
Eliminar Solo performance, DDL
Cambiar columnas Solo performance, DDL

Relation Options

Option Impacto si cambia
eager: true Queries cargan automatico
cascade: true Operaciones se propagan
onDelete Comportamiento al eliminar padre
nullable Validacion, tipo TS

9. COMANDOS DE VERIFICACION

# Ver diferencias entre DDL y Entity
# (manual: comparar columnas)
psql -d mydb -c "\d schema.table"
cat src/modules/x/entities/x.entity.ts

# Verificar que Entity compila
npm run build

# Verificar que no hay referencias rotas
npm run lint

# Verificar sincronizacion con frontend
npm run typecheck --prefix apps/web

# Buscar uso de campo especifico
grep -rn "fieldName" src/ apps/

10. MATRIZ DE DECISION

¿Que tipo de cambio en Entity?

┌─────────────────────┐
│ Agregar campo       │──▶ DDL primero → Entity → DTO → Frontend
└─────────────────────┘

┌─────────────────────┐
│ Eliminar campo      │──▶ Frontend primero → Service → DTO → Entity → DDL
└─────────────────────┘

┌─────────────────────┐
│ Cambiar tipo        │──▶ DDL primero → Entity → DTO → Frontend
└─────────────────────┘

┌─────────────────────┐
│ Agregar relacion    │──▶ DDL (FK) → Entity → DTO → Service → Frontend
└─────────────────────┘

┌─────────────────────┐
│ Renombrar campo     │──▶ Migracion segura (agregar nuevo → migrar → eliminar viejo)
└─────────────────────┘

Version: 1.0.0 | Sistema: SIMCO | Tipo: Guia de Impacto