# IMPACTO DE CAMBIOS EN BACKEND

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

---

## PROPOSITO

Documentar la cascada de cambios que ocurre cuando se modifica cualquier componente del Backend (Entity, DTO, Service, Controller) y su impacto en Frontend.

---

## 1. MATRIZ DE IMPACTO POR COMPONENTE

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                    CAMBIO EN BACKEND → IMPACTO EN CAPAS                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ENTITY         DTO            SERVICE        CONTROLLER      FRONTEND     │
│  ┌─────┐       ┌─────┐        ┌─────┐        ┌─────┐        ┌─────┐       │
│  │     │──────▶│     │───────▶│     │───────▶│     │───────▶│     │       │
│  └─────┘       └─────┘        └─────┘        └─────┘        └─────┘       │
│     │             │              │              │              │           │
│     ▼             ▼              ▼              ▼              ▼           │
│  Refleja       Valida         Logica        Endpoints      Types          │
│  DDL           Input          Negocio       REST           Zod            │
│                                                             Hooks         │
│                                                             Components    │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## 2. CAMBIOS EN ENTITY

### 2.1 Agregar Campo a Entity

```typescript
// CAMBIO: Agregar campo 'phone' a UserEntity
@Column({ type: 'varchar', length: 20, nullable: true })
phone: string | null;
```

**Cascada de Cambios:**

| Capa | Archivo | Accion | Obligatorio |
|------|---------|--------|-------------|
| DDL | `XX-users.sql` | Agregar columna (DDL-First) | SI - PRIMERO |
| Entity | `user.entity.ts` | Ya agregado | SI |
| CreateDto | `create-user.dto.ts` | Agregar campo + validacion | SI |
| UpdateDto | `update-user.dto.ts` | Hereda de CreateDto | AUTO |
| ResponseDto | `user-response.dto.ts` | Agregar campo | SI |
| Service | `user.service.ts` | Sin cambios (TypeORM maneja) | NO |
| Controller | `user.controller.ts` | Sin cambios | NO |
| **Frontend** | `user.types.ts` | Agregar campo a interface | SI |
| **Frontend** | `user.schema.ts` | Agregar a Zod schema | SI |
| **Frontend** | `UserForm.tsx` | Agregar input si editable | CONDICIONAL |

**Checklist:**

```
[ ] 1. DDL tiene la columna (DDL-First)
[ ] 2. Entity refleja DDL exactamente
[ ] 3. CreateDto tiene validacion apropiada
[ ] 4. ResponseDto incluye el campo
[ ] 5. Swagger muestra campo correctamente
[ ] 6. Frontend types actualizados
[ ] 7. Frontend Zod schema actualizado
[ ] 8. Componentes de formulario actualizados (si aplica)
[ ] 9. npm run build (backend)
[ ] 10. npm run build (frontend)
[ ] 11. npm run typecheck (frontend)
```

### 2.2 Eliminar Campo de Entity

```typescript
// CAMBIO: Eliminar campo 'legacyCode' de ProductEntity
// @Column() legacyCode: string;  // ELIMINADO
```

**Cascada de Cambios:**

| Capa | Archivo | Accion | Obligatorio |
|------|---------|--------|-------------|
| DDL | `XX-products.sql` | DROP COLUMN (con migracion) | SI - PRIMERO |
| Entity | `product.entity.ts` | Eliminar @Column | SI |
| CreateDto | `create-product.dto.ts` | Eliminar campo | SI |
| UpdateDto | `update-product.dto.ts` | Hereda cambio | AUTO |
| ResponseDto | `product-response.dto.ts` | Eliminar campo | SI |
| Service | `product.service.ts` | Eliminar referencias | VERIFICAR |
| Controller | `product.controller.ts` | Eliminar de queries | VERIFICAR |
| **Frontend** | `product.types.ts` | Eliminar de interface | SI |
| **Frontend** | `product.schema.ts` | Eliminar de Zod | SI |
| **Frontend** | Componentes | Eliminar referencias | SI |

**ADVERTENCIA:**

```
⚠️  ANTES DE ELIMINAR UN CAMPO:
1. Buscar TODAS las referencias en backend: grep -r "legacyCode" src/
2. Buscar TODAS las referencias en frontend: grep -r "legacyCode" apps/
3. Verificar que no hay datos importantes en la columna
4. Considerar soft-delete o campo deprecated primero
```

### 2.3 Cambiar Tipo de Campo

```typescript
// CAMBIO: price de number a Decimal
// ANTES
@Column({ type: 'integer' })
price: number;

// DESPUES
@Column({ type: 'decimal', precision: 10, scale: 2 })
price: string;  // String para precision decimal
```

**Cascada de Cambios:**

| Capa | Archivo | Accion | Obligatorio |
|------|---------|--------|-------------|
| DDL | `XX-products.sql` | ALTER COLUMN type | SI - PRIMERO |
| Entity | `product.entity.ts` | Cambiar tipo TS | SI |
| CreateDto | `create-product.dto.ts` | Cambiar validador | SI |
| ResponseDto | `product-response.dto.ts` | Cambiar tipo | SI |
| Service | `product.service.ts` | Ajustar transformaciones | VERIFICAR |
| **Frontend** | `product.types.ts` | Cambiar tipo | SI |
| **Frontend** | `product.schema.ts` | Cambiar validador Zod | SI |
| **Frontend** | Componentes | Ajustar formateo/parsing | SI |

---

## 3. CAMBIOS EN DTO

### 3.1 Agregar Validacion a DTO

```typescript
// CAMBIO: Agregar validacion de formato a email
@IsEmail({}, { message: 'Email invalido' })
@MaxLength(255)
@Transform(({ value }) => value?.toLowerCase().trim())
email: string;
```

**Impacto:**

| Capa | Impacto | Accion Requerida |
|------|---------|------------------|
| Entity | Ninguno | - |
| Service | Ninguno | - |
| Controller | Ninguno (validacion automatica) | - |
| Swagger | Actualiza automaticamente | Verificar |
| **Frontend** | Debe sincronizar validacion | Actualizar Zod |

**Frontend debe reflejar:**

```typescript
// Zod schema debe coincidir con backend
const userSchema = z.object({
    email: z.string()
        .email('Email invalido')
        .max(255)
        .transform(v => v.toLowerCase().trim()),
});
```

### 3.2 Agregar Campo a ResponseDto

```typescript
// CAMBIO: Agregar campo calculado 'fullName'
@ApiProperty({ example: 'Juan Perez' })
fullName: string;
```

**Impacto:**

| Capa | Impacto | Accion Requerida |
|------|---------|------------------|
| Entity | Ninguno (campo calculado) | - |
| Service | Debe calcular el campo | Agregar logica |
| Controller | Ninguno | - |
| **Frontend** | Debe tipar el campo | Actualizar interface |

**Service debe mapear:**

```typescript
// En service
toResponseDto(entity: UserEntity): UserResponseDto {
    return {
        ...entity,
        fullName: `${entity.firstName} ${entity.lastName}`,
    };
}
```

---

## 4. CAMBIOS EN SERVICE

### 4.1 Agregar Metodo al Service

```typescript
// CAMBIO: Agregar metodo de busqueda avanzada
async searchByFilters(filters: SearchFiltersDto): Promise<UserEntity[]> {
    // ...
}
```

**Impacto:**

| Capa | Impacto | Accion Requerida |
|------|---------|------------------|
| Entity | Ninguno | - |
| DTO | Crear SearchFiltersDto | SI |
| Controller | Exponer endpoint | SI |
| **Frontend** | Crear servicio + hook | SI |

### 4.2 Modificar Logica de Negocio

```typescript
// CAMBIO: Agregar validacion de negocio en create
async create(dto: CreateOrderDto): Promise<OrderEntity> {
    // NUEVA: Validar stock antes de crear
    await this.validateStock(dto.items);
    // ... resto
}
```

**Impacto:**

| Capa | Impacto | Accion Requerida |
|------|---------|------------------|
| Entity | Ninguno | - |
| DTO | Posible nuevo error response | Documentar |
| Controller | Ninguno | - |
| Swagger | Documentar nuevo error | SI |
| **Frontend** | Manejar nuevo error | SI |

**Frontend debe manejar:**

```typescript
// Hook debe manejar error especifico
const { mutate } = useCreateOrder({
    onError: (error) => {
        if (error.message.includes('stock')) {
            toast.error('Stock insuficiente');
        }
    }
});
```

---

## 5. CAMBIOS EN CONTROLLER

### 5.1 Agregar Endpoint

```typescript
// CAMBIO: Agregar endpoint de exportacion
@Get('export')
@ApiOperation({ summary: 'Exportar usuarios a CSV' })
async exportToCsv(): Promise<StreamableFile> {
    // ...
}
```

**Impacto Frontend:**

| Componente | Accion Requerida |
|------------|------------------|
| `user.service.ts` | Agregar metodo `exportToCsv()` |
| `useExportUsers.ts` | Crear hook (si necesario) |
| Componente UI | Agregar boton de exportar |

### 5.2 Modificar Ruta de Endpoint

```typescript
// CAMBIO: Renombrar endpoint
// ANTES: @Get('by-email/:email')
// DESPUES: @Get('search/email/:email')
```

**ADVERTENCIA - BREAKING CHANGE:**

```
⚠️  CAMBIO DE RUTA ES BREAKING CHANGE

PROCESO OBLIGATORIO:
1. Verificar que frontend no usa la ruta antigua
2. Si usa: Actualizar frontend PRIMERO
3. Considerar: Mantener ruta antigua con @Deprecated
4. Documentar en CHANGELOG

BUSCAR EN FRONTEND:
grep -r "by-email" apps/
grep -r "users/by-email" apps/
```

### 5.3 Cambiar Metodo HTTP

```typescript
// CAMBIO: De POST a PUT para update
// ANTES: @Post(':id/update')
// DESPUES: @Put(':id')
```

**Impacto Frontend:**

```typescript
// ANTES
await api.post(`/users/${id}/update`, data);

// DESPUES
await api.put(`/users/${id}`, data);
```

---

## 6. SINCRONIZACION BACKEND-FRONTEND

### 6.1 Mapeo de Tipos

| Backend (NestJS) | Frontend (TypeScript) | Notas |
|------------------|----------------------|-------|
| `string` | `string` | Directo |
| `number` | `number` | Directo |
| `boolean` | `boolean` | Directo |
| `Date` | `string` | ISO string en JSON |
| `Decimal` (string) | `string` o `number` | Parsear si necesario |
| `UUID` | `string` | Directo |
| `enum Status` | `type Status = ...` | Replicar valores |
| `T[]` | `T[]` | Directo |
| `T \| null` | `T \| null` | Directo |

### 6.2 Patron de Sincronizacion

```typescript
// BACKEND: ResponseDto define contrato
export class UserResponseDto {
    @ApiProperty()
    id: string;

    @ApiProperty()
    email: string;

    @ApiProperty({ enum: UserStatus })
    status: UserStatus;

    @ApiProperty()
    createdAt: Date;  // Se serializa como ISO string
}

// FRONTEND: Interface refleja ResponseDto
export interface User {
    id: string;
    email: string;
    status: UserStatus;
    createdAt: string;  // String porque viene de JSON
}

// FRONTEND: Enum replicado
export enum UserStatus {
    ACTIVE = 'active',
    INACTIVE = 'inactive',
}

// FRONTEND: Zod refleja CreateDto
export const createUserSchema = z.object({
    email: z.string().email(),
    // ... campos de CreateUserDto
});
```

### 6.3 Checklist de Sincronizacion

```
Cuando cambias Backend, verificar en Frontend:

[ ] 1. Interfaces actualizadas (types/*.ts)
[ ] 2. Enums sincronizados
[ ] 3. Zod schemas actualizados
[ ] 4. Services API actualizados
[ ] 5. Hooks actualizados (si cambia endpoint)
[ ] 6. Componentes manejan nuevos campos
[ ] 7. Componentes manejan campos eliminados
[ ] 8. Manejo de errores actualizado
[ ] 9. npm run typecheck pasa
[ ] 10. npm run build pasa
```

---

## 7. COMANDOS DE VERIFICACION

```bash
# Buscar referencias a campo en backend
grep -rn "fieldName" src/

# Buscar referencias a campo en frontend
grep -rn "fieldName" apps/ shared/

# Verificar tipos TypeScript
npm run typecheck

# Verificar que Swagger refleja cambios
curl http://localhost:3000/api-json | jq '.paths["/users"]'

# Comparar DTO con Interface
diff <(grep -A 50 "class UserResponseDto" src/modules/user/dto/user-response.dto.ts) \
     <(grep -A 50 "interface User" apps/web/types/user.types.ts)
```

---

## 8. ANTI-PATRONES

### Anti-Patron 1: Cambiar Backend sin Frontend

```
❌ INCORRECTO:
1. Backend-Agent agrega campo a ResponseDto
2. Se hace deploy
3. Frontend falla porque no espera el campo (usualmente OK)
4. O peor: Frontend espera campo que ya no existe (ROMPE)

✅ CORRECTO:
1. Backend-Agent agrega campo
2. Frontend-Agent actualiza types ANTES de deploy
3. Deploy coordinado
```

### Anti-Patron 2: Tipos Diferentes

```
❌ INCORRECTO:
// Backend
@Column({ type: 'decimal' })
price: string;  // String para precision

// Frontend
interface Product {
    price: number;  // ← INCORRECTO: tipo diferente
}

✅ CORRECTO:
// Frontend
interface Product {
    price: string;  // String como backend
}

// O usar transformacion explicita
const displayPrice = parseFloat(product.price).toFixed(2);
```

### Anti-Patron 3: Validaciones Desincronizadas

```
❌ INCORRECTO:
// Backend: max 100 caracteres
@MaxLength(100)
name: string;

// Frontend: max 50 caracteres
const schema = z.object({
    name: z.string().max(50)  // ← INCORRECTO: limite diferente
});

✅ CORRECTO:
// Mismos limites en ambos lados
// Backend: @MaxLength(100)
// Frontend: z.string().max(100)
```

---

## 9. MATRIZ RESUMEN

| Si Cambias... | Actualiza en Backend | Actualiza en Frontend |
|---------------|---------------------|----------------------|
| Entity campo | DTO, posible Service | Types, Schema, Components |
| Entity relacion | DTO, Service | Types, Hooks |
| CreateDto campo | - | Schema (Zod) |
| CreateDto validacion | - | Schema (Zod) |
| ResponseDto campo | Service (si calculado) | Types, Components |
| Service metodo | Controller (si expuesto) | Service, Hook |
| Service logica | - | Manejo errores |
| Controller endpoint | Swagger | Service, Hook |
| Controller ruta | Swagger | Service (URL) |

---

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