diff --git a/core/orchestration/directivas/simco/_INDEX.md b/core/orchestration/directivas/simco/_INDEX.md index 4287568..d9c4e58 100644 --- a/core/orchestration/directivas/simco/_INDEX.md +++ b/core/orchestration/directivas/simco/_INDEX.md @@ -74,6 +74,29 @@ core/ β”‚ β”œβ”€β”€ CONTEXTO-NIVEL-SUITE-CORE.md # πŸ†• Template para core de suite β”‚ └── CONTEXTO-NIVEL-VERTICAL.md # πŸ†• Template para verticales β”‚ + β”œβ”€β”€ patrones/ # PATRONES DE CΓ“DIGO + β”‚ β”œβ”€β”€ MAPEO-TIPOS-DDL-TYPESCRIPT.md # Mapeo PostgreSQL ↔ TypeScript + β”‚ β”œβ”€β”€ PATRON-VALIDACION.md # ValidaciΓ³n con class-validator/Zod + β”‚ β”œβ”€β”€ PATRON-EXCEPTION-HANDLING.md # Manejo de errores y excepciones + β”‚ β”œβ”€β”€ PATRON-TESTING.md # Patrones de testing + β”‚ β”œβ”€β”€ PATRON-LOGGING.md # Logging estructurado + β”‚ β”œβ”€β”€ PATRON-CONFIGURACION.md # Variables de entorno y config + β”‚ β”œβ”€β”€ PATRON-SEGURIDAD.md # Seguridad y OWASP + β”‚ β”œβ”€β”€ PATRON-PERFORMANCE.md # OptimizaciΓ³n y caching + β”‚ β”œβ”€β”€ PATRON-TRANSACCIONES.md # Transacciones de BD + β”‚ β”œβ”€β”€ ANTIPATRONES.md # Lo que NUNCA hacer + β”‚ └── NOMENCLATURA-UNIFICADA.md # Convenciones de nombres + β”‚ + β”œβ”€β”€ impactos/ # IMPACTO DE CAMBIOS + β”‚ β”œβ”€β”€ IMPACTO-CAMBIOS-DDL.md # Cascada de cambios en BD + β”‚ β”œβ”€β”€ IMPACTO-CAMBIOS-BACKEND.md # SincronizaciΓ³n Backend↔Frontend + β”‚ β”œβ”€β”€ IMPACTO-CAMBIOS-ENTITY.md # Cambios en Entities TypeORM + β”‚ β”œβ”€β”€ IMPACTO-CAMBIOS-API.md # Cambios en endpoints REST + β”‚ └── MATRIZ-DEPENDENCIAS.md # Matriz completa de dependencias + β”‚ + β”œβ”€β”€ procesos/ # PROCESOS DE TRABAJO + β”‚ └── ORDEN-IMPLEMENTACION.md # DDL-First, orden de capas + β”‚ β”œβ”€β”€ _historico/ β”‚ └── MAPA-CONTEXTO-AGENTE.md # Trazabilidad (histΓ³rico) β”‚ diff --git a/core/orchestration/impactos/IMPACTO-CAMBIOS-API.md b/core/orchestration/impactos/IMPACTO-CAMBIOS-API.md new file mode 100644 index 0000000..a80b116 --- /dev/null +++ b/core/orchestration/impactos/IMPACTO-CAMBIOS-API.md @@ -0,0 +1,669 @@ +# IMPACTO DE CAMBIOS EN API + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - Consultar antes de modificar endpoints +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Documentar el impacto de modificar endpoints REST (Controllers), rutas, metodos HTTP, y contratos de API en el sistema. + +--- + +## 1. CLASIFICACION DE CAMBIOS API + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ TIPOS DE CAMBIOS EN API β•‘ +╠══════════════════════════════════════════════════════════════════════╣ +β•‘ β•‘ +β•‘ BREAKING CHANGES (⚠️ ROMPEN CLIENTES): β•‘ +β•‘ β€’ Eliminar endpoint β•‘ +β•‘ β€’ Cambiar ruta de endpoint β•‘ +β•‘ β€’ Cambiar metodo HTTP β•‘ +β•‘ β€’ Eliminar campo de response β•‘ +β•‘ β€’ Cambiar tipo de campo en response β•‘ +β•‘ β€’ Agregar campo requerido a request β•‘ +β•‘ β€’ Cambiar formato de error β•‘ +β•‘ β•‘ +β•‘ NON-BREAKING CHANGES (βœ… COMPATIBLES): β•‘ +β•‘ β€’ Agregar endpoint nuevo β•‘ +β•‘ β€’ Agregar campo opcional a request β•‘ +β•‘ β€’ Agregar campo a response β•‘ +β•‘ β€’ Agregar nuevo codigo de error β•‘ +β•‘ β€’ Mejorar mensaje de error β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 2. CAMBIOS EN RUTAS (BREAKING) + +### 2.1 Cambiar Ruta de Endpoint + +```typescript +// ANTES +@Get('users/by-email/:email') + +// DESPUES +@Get('users/search/email/:email') +``` + +**Impacto:** + +| Componente | Impacto | Accion Requerida | +|------------|---------|------------------| +| Frontend Service | ROMPE | Actualizar URL | +| Frontend Hooks | ROMPE | Actualizar llamadas | +| Documentacion | Desactualizada | Actualizar | +| Clientes externos | ROMPE | Notificar + migrar | +| Tests e2e | ROMPE | Actualizar URLs | + +**Proceso de Migracion:** + +``` +OPCION A: Migracion Inmediata (proyectos internos) +═══════════════════════════════════════════════════════════════ +1. Actualizar Frontend primero (cambiar URL) +2. Actualizar Backend (cambiar ruta) +3. Deploy coordinado + +OPCION B: Deprecacion Gradual (APIs publicas) +═══════════════════════════════════════════════════════════════ +1. Agregar nueva ruta (mantener vieja) +2. Marcar vieja como @Deprecated +3. Notificar clientes +4. Periodo de gracia (30-90 dias) +5. Eliminar ruta vieja +``` + +**Implementacion Deprecacion:** + +```typescript +// Mantener ambas rutas temporalmente +@Get('users/by-email/:email') +@ApiOperation({ + summary: 'Buscar por email (DEPRECATED)', + deprecated: true, + description: 'Use GET /users/search/email/:email instead' +}) +async findByEmailDeprecated(@Param('email') email: string) { + return this.findByEmail(email); +} + +@Get('users/search/email/:email') +@ApiOperation({ summary: 'Buscar usuario por email' }) +async findByEmail(@Param('email') email: string) { + return this.userService.findByEmail(email); +} +``` + +### 2.2 Cambiar Prefijo de Controller + +```typescript +// ANTES +@Controller('products') + +// DESPUES +@Controller('catalog/products') +``` + +**Impacto:** TODOS los endpoints del controller cambian de ruta. + +``` +ANTES: +GET /api/products +POST /api/products +GET /api/products/:id + +DESPUES: +GET /api/catalog/products +POST /api/catalog/products +GET /api/catalog/products/:id +``` + +**Checklist:** + +``` +[ ] 1. Buscar en frontend: grep -rn "/products" apps/ +[ ] 2. Actualizar TODOS los services que usan estos endpoints +[ ] 3. Actualizar tests e2e +[ ] 4. Actualizar documentacion +[ ] 5. Verificar Swagger refleja cambios +``` + +--- + +## 3. CAMBIOS EN METODO HTTP (BREAKING) + +### Cambiar Metodo + +```typescript +// ANTES: Actualizar con POST +@Post(':id/update') +async update() {} + +// DESPUES: Actualizar con PUT (RESTful correcto) +@Put(':id') +async update() {} +``` + +**Impacto Frontend:** + +```typescript +// ANTES +const response = await api.post(`/users/${id}/update`, data); + +// DESPUES +const response = await api.put(`/users/${id}`, data); +``` + +**Checklist:** + +``` +[ ] 1. Identificar todos los lugares que llaman al endpoint +[ ] 2. Actualizar metodo HTTP en frontend service +[ ] 3. Actualizar tests +[ ] 4. Si API publica: periodo de deprecacion +``` + +--- + +## 4. CAMBIOS EN REQUEST DTO + +### 4.1 Agregar Campo Requerido (BREAKING) + +```typescript +// ANTES +export class CreateOrderDto { + productId: string; + quantity: number; +} + +// DESPUES - Nuevo campo requerido +export class CreateOrderDto { + productId: string; + quantity: number; + @IsNotEmpty() + deliveryAddress: string; // ← BREAKING: requerido +} +``` + +**Impacto:** + +| Componente | Impacto | Accion | +|------------|---------|--------| +| Frontend Form | ROMPE | Agregar campo | +| Frontend Zod | ROMPE | Agregar validacion | +| Clientes existentes | ROMPE | Falla validacion | +| Tests | ROMPE | Actualizar fixtures | + +**Mitigacion:** + +```typescript +// OPCION 1: Hacer opcional con default +@IsOptional() +@IsString() +deliveryAddress?: string = 'Por definir'; + +// OPCION 2: Migrar en fases +// Fase 1: Agregar como opcional +// Fase 2: Poblar datos existentes +// Fase 3: Hacer requerido +``` + +### 4.2 Agregar Campo Opcional (NON-BREAKING) + +```typescript +// Agregar campo opcional - NO rompe +export class CreateOrderDto { + productId: string; + quantity: number; + + @IsOptional() + @IsString() + notes?: string; // ← NON-BREAKING: opcional +} +``` + +**Impacto:** + +| Componente | Impacto | Accion | +|------------|---------|--------| +| Frontend | Ninguno inmediato | Agregar si se quiere usar | +| Clientes existentes | Ninguno | Siguen funcionando | +| Tests | Ninguno | Siguen pasando | + +### 4.3 Eliminar Campo de Request (BREAKING si requerido) + +```typescript +// ANTES +export class CreateUserDto { + email: string; + password: string; + legacyCode: string; // ← Se va a eliminar +} + +// DESPUES +export class CreateUserDto { + email: string; + password: string; + // legacyCode eliminado +} +``` + +**Proceso:** + +``` +1. Hacer campo opcional primero (si era requerido) +2. Marcar como @Deprecated en Swagger +3. Ignorar en backend (no procesar) +4. Notificar clientes +5. Eliminar despues de periodo de gracia +``` + +### 4.4 Cambiar Validacion (Puede ser BREAKING) + +```typescript +// ANTES: email cualquier formato +@IsString() +email: string; + +// DESPUES: email debe ser valido +@IsEmail() +email: string; +``` + +**Impacto:** Requests que antes pasaban ahora fallan. + +**Mitigacion:** + +```typescript +// Agregar transformacion para casos edge +@IsEmail() +@Transform(({ value }) => value?.toLowerCase().trim()) +email: string; +``` + +--- + +## 5. CAMBIOS EN RESPONSE DTO + +### 5.1 Eliminar Campo de Response (BREAKING) + +```typescript +// ANTES +export class UserResponseDto { + id: string; + email: string; + legacyCode: string; // ← Se elimina +} + +// DESPUES +export class UserResponseDto { + id: string; + email: string; + // legacyCode eliminado +} +``` + +**Impacto Frontend:** + +```typescript +// Si frontend usa el campo, ROMPE +const UserCard = ({ user }) => { + return
{user.legacyCode}
; // ← TypeError: undefined +}; +``` + +**Proceso Seguro:** + +``` +1. Buscar uso en frontend: grep -rn "legacyCode" apps/ +2. Eliminar uso en frontend primero +3. Luego eliminar de ResponseDto +4. Deploy coordinado +``` + +### 5.2 Agregar Campo a Response (NON-BREAKING) + +```typescript +// Agregar campo - NO rompe +export class UserResponseDto { + id: string; + email: string; + createdAt: Date; // ← Nuevo campo +} +``` + +**Impacto:** + +- Frontend puede ignorar campos nuevos +- TypeScript mostrara warning si interface no coincide +- Actualizar interface en frontend eventualmente + +### 5.3 Cambiar Tipo de Campo (BREAKING) + +```typescript +// ANTES +export class ProductResponseDto { + price: number; // 99 +} + +// DESPUES +export class ProductResponseDto { + price: string; // "99.00" +} +``` + +**Impacto Frontend:** + +```typescript +// ANTES funcionaba +const total = product.price * quantity; + +// DESPUES rompe (string * number = NaN) +const total = product.price * quantity; // NaN! + +// Debe cambiar a +const total = parseFloat(product.price) * quantity; +``` + +### 5.4 Cambiar Estructura de Response (BREAKING) + +```typescript +// ANTES: Array directo +@Get() +async findAll(): Promise { + return this.users; +} +// Response: [{ id: 1 }, { id: 2 }] + +// DESPUES: Objeto paginado +@Get() +async findAll(): Promise> { + return { data: this.users, total: 100, page: 1 }; +} +// Response: { data: [...], total: 100, page: 1 } +``` + +**Impacto Frontend:** + +```typescript +// ANTES +const users = await api.get('/users'); +users.map(u => ...); + +// DESPUES +const response = await api.get('/users'); +response.data.map(u => ...); // Acceder a .data +``` + +--- + +## 6. CAMBIOS EN CODIGOS DE ERROR + +### 6.1 Agregar Nuevo Codigo (NON-BREAKING) + +```typescript +// Agregar nueva excepcion - generalmente no rompe +throw new ConflictException('Email already registered'); +// HTTP 409 - nuevo codigo +``` + +**Impacto:** Frontend deberia manejar, pero no rompe si no lo hace. + +### 6.2 Cambiar Codigo Existente (BREAKING) + +```typescript +// ANTES: 400 para duplicado +throw new BadRequestException('Email exists'); + +// DESPUES: 409 para duplicado (correcto) +throw new ConflictException('Email exists'); +``` + +**Impacto:** Frontend que verifica status code especifico rompe. + +```typescript +// Frontend que rompe +if (error.status === 400 && error.message.includes('Email')) { + // Ya no entra aqui +} + +// Frontend robusto +if (error.status === 409 || error.message.includes('Email')) { + // Maneja ambos casos +} +``` + +### 6.3 Cambiar Formato de Error (BREAKING) + +```typescript +// ANTES +{ + "statusCode": 400, + "message": "Validation failed" +} + +// DESPUES +{ + "error": { + "code": "VALIDATION_ERROR", + "message": "Validation failed", + "details": [...] + } +} +``` + +**Impacto:** TODO el manejo de errores en frontend debe cambiar. + +--- + +## 7. VERSIONADO DE API + +### Cuando Usar Versionado + +``` +USA VERSIONADO CUANDO: +β€’ API es consumida por clientes externos +β€’ Cambios breaking frecuentes +β€’ Necesitas mantener compatibilidad largo plazo + +NO NECESITAS VERSIONADO CUANDO: +β€’ Solo frontend interno consume la API +β€’ Puedes coordinar deploys +β€’ Equipo pequeno con comunicacion directa +``` + +### Implementacion de Versiones + +```typescript +// Opcion 1: En URL +@Controller('v1/users') +export class UsersV1Controller {} + +@Controller('v2/users') +export class UsersV2Controller {} + +// Opcion 2: En Header +@Controller('users') +@ApiHeader({ name: 'Api-Version', enum: ['1', '2'] }) +export class UsersController { + @Get() + findAll(@Headers('Api-Version') version: string) { + if (version === '2') { + return this.findAllV2(); + } + return this.findAllV1(); + } +} +``` + +--- + +## 8. CHECKLIST POR TIPO DE CAMBIO + +### Agregar Endpoint Nuevo + +``` +[ ] 1. Crear metodo en Controller +[ ] 2. Agregar decoradores Swagger (@ApiOperation, @ApiResponse) +[ ] 3. Crear/actualizar DTOs si necesario +[ ] 4. Implementar en Service +[ ] 5. Agregar tests +[ ] 6. Actualizar Frontend service +[ ] 7. Crear Frontend hook si necesario +[ ] 8. Verificar Swagger +``` + +### Modificar Endpoint Existente (NON-BREAKING) + +``` +[ ] 1. Verificar que cambio es non-breaking +[ ] 2. Actualizar Controller +[ ] 3. Actualizar DTOs si necesario +[ ] 4. Actualizar Swagger decoradores +[ ] 5. Actualizar tests +[ ] 6. Actualizar Frontend si aprovecha nuevas features +``` + +### Modificar Endpoint Existente (BREAKING) + +``` +[ ] 1. Evaluar: ΒΏse puede hacer non-breaking? +[ ] 2. Buscar todos los consumidores: grep -rn "endpoint" apps/ +[ ] 3. Planear estrategia de migracion +[ ] 4. Si API publica: crear version nueva, deprecar vieja +[ ] 5. Si API interna: coordinar con frontend +[ ] 6. Actualizar Frontend PRIMERO (apuntar a nuevo) +[ ] 7. Actualizar Backend +[ ] 8. Actualizar tests +[ ] 9. Deploy coordinado +[ ] 10. Eliminar codigo deprecated despues de periodo +``` + +### Eliminar Endpoint + +``` +[ ] 1. Buscar todos los usos: grep -rn "endpoint" apps/ tests/ +[ ] 2. Eliminar uso en Frontend +[ ] 3. Eliminar tests del endpoint +[ ] 4. Marcar como @Deprecated (si API publica) +[ ] 5. Periodo de gracia +[ ] 6. Eliminar de Controller +[ ] 7. Limpiar Service si metodos quedan sin usar +``` + +--- + +## 9. FRONTEND: ADAPTARSE A CAMBIOS API + +### Service Layer Pattern + +```typescript +// Encapsular llamadas API en service +// Facilita cambiar cuando API cambia + +// user.service.ts +export const userService = { + // Si cambia la ruta, solo cambiar aqui + getAll: () => api.get('/users'), + + // Si cambia estructura response + getAllPaginated: async (page: number) => { + const response = await api.get>('/users', { params: { page } }); + return response.data; // Extraer data aqui + }, + + // Si cambia metodo HTTP + update: (id: string, data: UpdateUserDto) => + api.put(`/users/${id}`, data), // Cambiar postβ†’put aqui +}; +``` + +### Type Guards para Cambios de Estructura + +```typescript +// Manejar diferentes versiones de response +interface UserV1 { + name: string; +} + +interface UserV2 { + firstName: string; + lastName: string; +} + +function isUserV2(user: UserV1 | UserV2): user is UserV2 { + return 'firstName' in user; +} + +function getDisplayName(user: UserV1 | UserV2): string { + if (isUserV2(user)) { + return `${user.firstName} ${user.lastName}`; + } + return user.name; +} +``` + +--- + +## 10. MATRIZ DE DECISION + +``` +ΒΏEs BREAKING CHANGE? + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ ΒΏCambio de │───NO───▢ Implementar directamente + β”‚ ruta? β”‚ Actualizar Swagger + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Actualizar Frontend (opcional) + β”‚ + YES + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ ΒΏAPI │───NO───▢ Actualizar Frontend PRIMERO + β”‚ publica? β”‚ Luego actualizar Backend + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Deploy coordinado + β”‚ + YES + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ 1. Crear endpoint nuevo β”‚ + β”‚ 2. Deprecar endpoint viejo β”‚ + β”‚ 3. Notificar clientes β”‚ + β”‚ 4. Periodo de gracia (30-90 dias) β”‚ + β”‚ 5. Eliminar endpoint viejo β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 11. COMANDOS UTILES + +```bash +# Ver todos los endpoints actuales +curl http://localhost:3000/api-json | jq '.paths | keys' + +# Ver detalle de un endpoint +curl http://localhost:3000/api-json | jq '.paths["/users/{id}"]' + +# Buscar uso de endpoint en frontend +grep -rn "users" apps/*/services/ +grep -rn "/api/users" apps/ + +# Comparar Swagger entre versiones +diff <(curl -s http://localhost:3000/api-json | jq -S) \ + <(curl -s http://production/api-json | jq -S) +``` + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Guia de Impacto diff --git a/core/orchestration/impactos/IMPACTO-CAMBIOS-BACKEND.md b/core/orchestration/impactos/IMPACTO-CAMBIOS-BACKEND.md new file mode 100644 index 0000000..77d8063 --- /dev/null +++ b/core/orchestration/impactos/IMPACTO-CAMBIOS-BACKEND.md @@ -0,0 +1,498 @@ +# 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 { + // ... +} +``` + +**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 { + // 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 { + // ... +} +``` + +**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 diff --git a/core/orchestration/impactos/IMPACTO-CAMBIOS-DDL.md b/core/orchestration/impactos/IMPACTO-CAMBIOS-DDL.md new file mode 100644 index 0000000..14b425b --- /dev/null +++ b/core/orchestration/impactos/IMPACTO-CAMBIOS-DDL.md @@ -0,0 +1,428 @@ +# 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 diff --git a/core/orchestration/impactos/IMPACTO-CAMBIOS-ENTITY.md b/core/orchestration/impactos/IMPACTO-CAMBIOS-ENTITY.md new file mode 100644 index 0000000..7c7974a --- /dev/null +++ b/core/orchestration/impactos/IMPACTO-CAMBIOS-ENTITY.md @@ -0,0 +1,439 @@ +# 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 + +```bash +# 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) + +```typescript +// 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) + +```typescript +// 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) + +```typescript +// 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 | +|--------|-----|--------|-----|----------| +| `INT` β†’ `BIGINT` | ALTER TYPE | `number` (sin cambio) | Sin cambio | Sin cambio | +| `VARCHAR` β†’ `TEXT` | ALTER TYPE | Sin cambio | Ajustar MaxLength | Ajustar max | +| `INTEGER` β†’ `DECIMAL` | ALTER TYPE | `number` β†’ `string` | Ajustar validador | Ajustar tipo | +| `BOOLEAN` β†’ `ENUM` | ALTER TYPE | `boolean` β†’ `enum` | Cambiar validador | Cambiar tipo | +| `VARCHAR` β†’ `UUID` | ALTER TYPE + datos | `string` (sin cambio) | Agregar @IsUUID | Agregar validacion | + +### Ejemplo: INTEGER a DECIMAL + +```sql +-- DDL +ALTER TABLE products ALTER COLUMN price TYPE DECIMAL(10,2); +``` + +```typescript +// Entity ANTES +@Column({ type: 'integer' }) +price: number; + +// Entity DESPUES +@Column({ type: 'decimal', precision: 10, scale: 2 }) +price: string; // String para precision +``` + +```typescript +// CreateDto ANTES +@IsNumber() +price: number; + +// CreateDto DESPUES +@IsNumberString() +@Matches(/^\d+(\.\d{1,2})?$/) +price: string; +``` + +```typescript +// 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 + +```bash +# 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 diff --git a/core/orchestration/impactos/MATRIZ-DEPENDENCIAS.md b/core/orchestration/impactos/MATRIZ-DEPENDENCIAS.md new file mode 100644 index 0000000..4b3830f --- /dev/null +++ b/core/orchestration/impactos/MATRIZ-DEPENDENCIAS.md @@ -0,0 +1,445 @@ +# MATRIZ DE DEPENDENCIAS ENTRE CAPAS + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** REFERENCIA - Consultar para entender impactos +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Proporcionar una matriz completa de dependencias entre todos los componentes del sistema para que los agentes puedan identificar rapidamente que se debe actualizar cuando se modifica algo. + +--- + +## 1. VISION GENERAL DE DEPENDENCIAS + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FLUJO DE DEPENDENCIAS β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ DDL │────▢│ Entity │────▢│ DTO │────▢│ Service β”‚ β”‚ +β”‚ β”‚ (SQL) β”‚ β”‚(TypeORM)β”‚ β”‚ (class) β”‚ β”‚ (logic) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ +β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚Controllerβ”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ (REST) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ +β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ SWAGGER β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ (API Contract) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β–Ό β–Ό β”‚ +β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ FRONTEND β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ Typesβ”‚Schemaβ”‚Hooksβ”‚UI β”‚ β”‚ +β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ INVENTARIOS β”‚ β”‚ +β”‚ β”‚ DBβ”‚BEβ”‚FEβ”‚MASTER β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 2. MATRIZ DE DEPENDENCIA: DDL + +### Cuando se modifica DDL (tablas, columnas) + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Entity** | SI | 1 - Inmediato | Debe reflejar estructura DDL | +| **CreateDto** | SI | 2 | Campos nuevos/eliminados | +| **UpdateDto** | AUTO | 2 | Hereda de CreateDto | +| **ResponseDto** | SI | 2 | Campos en response | +| **Service** | POSIBLE | 3 | Si hay logica de campo | +| **Controller** | NO | - | Usa DTOs | +| **Frontend Types** | SI | 4 | Reflejar ResponseDto | +| **Frontend Schema** | SI | 4 | Reflejar CreateDto | +| **Frontend Components** | POSIBLE | 5 | Si muestran campo | +| **Swagger** | AUTO | - | Generado de DTOs | +| **DATABASE_INVENTORY** | SI | 6 | Registrar cambio | +| **Tests** | POSIBLE | 5 | Si prueban campo | + +### Diagrama de Propagacion DDL + +``` +DDL Change + β”‚ + β”œβ”€β”€β–Ά Entity (obligatorio) + β”‚ β”‚ + β”‚ β”œβ”€β”€β–Ά CreateDto (obligatorio) + β”‚ β”‚ β”‚ + β”‚ β”‚ └──▢ Frontend Schema (obligatorio) + β”‚ β”‚ + β”‚ β”œβ”€β”€β–Ά ResponseDto (obligatorio) + β”‚ β”‚ β”‚ + β”‚ β”‚ └──▢ Frontend Types (obligatorio) + β”‚ β”‚ β”‚ + β”‚ β”‚ └──▢ Frontend Components (si usa campo) + β”‚ β”‚ + β”‚ └──▢ Service (si logica de campo) + β”‚ + └──▢ DATABASE_INVENTORY (obligatorio) +``` + +--- + +## 3. MATRIZ DE DEPENDENCIA: ENTITY + +### Cuando se modifica Entity + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **DDL** | VERIFICAR | 0 | DDL debe existir primero | +| **CreateDto** | SI | 1 | Reflejar campos | +| **UpdateDto** | AUTO | 1 | Hereda de CreateDto | +| **ResponseDto** | SI | 1 | Reflejar campos | +| **Service** | POSIBLE | 2 | Si usa campo directamente | +| **Controller** | NO | - | Usa DTOs | +| **Frontend Types** | SI | 3 | Reflejar ResponseDto | +| **Frontend Schema** | SI | 3 | Reflejar CreateDto | +| **Frontend Components** | POSIBLE | 4 | Si muestran campo | +| **BACKEND_INVENTORY** | SI | 5 | Registrar cambio | +| **Unit Tests** | SI | 4 | Actualizar mocks | + +### Por Tipo de Cambio en Entity + +| Cambio | DTOs | Service | Frontend | Tests | +|--------|------|---------|----------|-------| +| Agregar @Column | SI | NO | SI | SI | +| Eliminar @Column | SI | Verificar | SI | SI | +| Cambiar tipo @Column | SI | Posible | SI | SI | +| Agregar @ManyToOne | SI | SI | SI | SI | +| Agregar @OneToMany | SI | Posible | SI | Posible | +| Cambiar @Index | NO | NO | NO | NO | +| Cambiar nullable | SI | NO | SI | Posible | + +--- + +## 4. MATRIZ DE DEPENDENCIA: DTO + +### Cuando se modifica CreateDto + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **UpdateDto** | AUTO | 1 | Si usa PartialType | +| **Service** | NO | - | Recibe DTO | +| **Controller** | NO | - | Usa DTO | +| **Swagger** | AUTO | - | Generado | +| **Frontend Schema (Zod)** | SI | 2 | Mismas validaciones | +| **Frontend Forms** | POSIBLE | 3 | Si campos cambian | +| **Integration Tests** | SI | 3 | Fixtures | + +### Cuando se modifica ResponseDto + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Service** | SI | 1 | Si mapea a ResponseDto | +| **Controller** | NO | - | Retorna Service result | +| **Swagger** | AUTO | - | Generado | +| **Frontend Types** | SI | 2 | Interface debe coincidir | +| **Frontend Components** | POSIBLE | 3 | Si muestran campo | +| **Frontend Hooks** | NO | - | Usan Types | + +--- + +## 5. MATRIZ DE DEPENDENCIA: SERVICE + +### Cuando se modifica Service + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Controller** | POSIBLE | 1 | Si cambia firma metodo | +| **Swagger** | POSIBLE | 2 | Si cambia response/errors | +| **Frontend** | POSIBLE | 2 | Si cambia contrato API | +| **Unit Tests** | SI | 1 | Tests del service | +| **Integration Tests** | POSIBLE | 2 | Si cambia comportamiento | + +### Por Tipo de Cambio en Service + +| Cambio | Controller | Frontend | Tests | +|--------|------------|----------|-------| +| Agregar metodo | SI (nuevo endpoint) | SI | SI | +| Eliminar metodo | SI | SI | SI | +| Cambiar firma | SI | SI | SI | +| Cambiar logica interna | NO | NO | SI | +| Agregar validacion | NO | Manejar error | SI | +| Cambiar error thrown | NO | Manejar error | SI | + +--- + +## 6. MATRIZ DE DEPENDENCIA: CONTROLLER + +### Cuando se modifica Controller + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Service** | NO | - | Controller consume Service | +| **Swagger** | AUTO | - | Generado de decoradores | +| **Frontend Service** | SI | 1 | Si cambia ruta/metodo | +| **Frontend Hooks** | POSIBLE | 2 | Si cambia endpoint | +| **E2E Tests** | SI | 2 | Tests de endpoint | + +### Por Tipo de Cambio en Controller + +| Cambio | Frontend Service | Frontend Hooks | Tests | +|--------|------------------|----------------|-------| +| Agregar endpoint | SI (nuevo metodo) | SI (nuevo hook) | SI | +| Eliminar endpoint | SI | SI | SI | +| Cambiar ruta | SI | NO | SI | +| Cambiar metodo HTTP | SI | NO | SI | +| Cambiar decoradores Swagger | NO | NO | NO | +| Agregar guard | NO | Manejar 401/403 | SI | + +--- + +## 7. MATRIZ DE DEPENDENCIA: FRONTEND + +### Cuando se modifica Frontend Types + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Zod Schema** | VERIFICAR | 1 | Debe ser consistente | +| **Hooks** | NO | - | Usan Types | +| **Components** | VERIFICAR | 2 | Si usan tipo | +| **Services** | NO | - | Usan Types | + +### Cuando se modifica Frontend Schema (Zod) + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Forms** | VERIFICAR | 1 | Si usan schema | +| **Types** | VERIFICAR | 1 | Deben coincidir | + +### Cuando se modifica Frontend Hook + +| Componente Dependiente | Requiere Actualizacion | Prioridad | Detalle | +|------------------------|------------------------|-----------|---------| +| **Components** | VERIFICAR | 1 | Si usan hook | +| **Pages** | VERIFICAR | 1 | Si usan hook | + +--- + +## 8. MATRIZ RAPIDA DE REFERENCIA + +### "Si cambio X, que debo actualizar?" + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ SI CAMBIO... β”‚ DDL β”‚ Entity β”‚DTO-Crea β”‚DTO-Resp β”‚Service β”‚ Controller β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ DDL columna β”‚ ── β”‚ SI β”‚ SI β”‚ SI β”‚ Posib β”‚ NO β”‚ +β”‚ DDL FK β”‚ ── β”‚ SI β”‚ SI β”‚ SI β”‚ SI β”‚ Posible β”‚ +β”‚ DDL indice β”‚ ── β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Entity columna β”‚ Ver β”‚ ── β”‚ SI β”‚ SI β”‚ Posib β”‚ NO β”‚ +β”‚ Entity relacion β”‚ Ver β”‚ ── β”‚ SI β”‚ SI β”‚ SI β”‚ Posible β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ CreateDto campo β”‚ NO β”‚ NO β”‚ ── β”‚ NO β”‚ NO β”‚ NO β”‚ +β”‚ CreateDto valid β”‚ NO β”‚ NO β”‚ ── β”‚ NO β”‚ NO β”‚ NO β”‚ +β”‚ ResponseDto β”‚ NO β”‚ NO β”‚ NO β”‚ ── β”‚ Ver β”‚ NO β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Service metodo β”‚ NO β”‚ NO β”‚ NO β”‚ Posib β”‚ ── β”‚ SI β”‚ +β”‚ Service logica β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ ── β”‚ NO β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Controller ruta β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ ── β”‚ +β”‚ Controller meth β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ ── β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +Continuacion β†’ Frontend + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ SI CAMBIO... β”‚ Types β”‚ Schema β”‚ Hooks β”‚Components β”‚ Inventory β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ DDL columna β”‚ SI β”‚ SI β”‚ NO β”‚ Posible β”‚ DB+MAST β”‚ +β”‚ DDL FK β”‚ SI β”‚ SI β”‚ SI β”‚ Posible β”‚ DB+MAST β”‚ +β”‚ DDL indice β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ DB β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Entity columna β”‚ SI β”‚ SI β”‚ NO β”‚ Posible β”‚ BE+MAST β”‚ +β”‚ Entity relacion β”‚ SI β”‚ SI β”‚ SI β”‚ Posible β”‚ BE+MAST β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ CreateDto campo β”‚ NO β”‚ SI β”‚ NO β”‚ Posible β”‚ BE β”‚ +β”‚ CreateDto valid β”‚ NO β”‚ SI β”‚ NO β”‚ NO β”‚ NO β”‚ +β”‚ ResponseDto β”‚ SI β”‚ NO β”‚ NO β”‚ Posible β”‚ BE β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Service metodo β”‚ Posib β”‚ Posib β”‚ SI β”‚ Posible β”‚ BE β”‚ +β”‚ Service logica β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ NO β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Controller ruta β”‚ NO β”‚ NO β”‚ SI β”‚ NO β”‚ BE β”‚ +β”‚ Controller meth β”‚ NO β”‚ NO β”‚ SI β”‚ NO β”‚ NO β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Frontend Types β”‚ ── β”‚ Ver β”‚ NO β”‚ Ver β”‚ FE β”‚ +β”‚ Frontend Schema β”‚ Ver β”‚ ── β”‚ NO β”‚ Ver β”‚ FE β”‚ +β”‚ Frontend Hook β”‚ NO β”‚ NO β”‚ ── β”‚ Ver β”‚ FE β”‚ +β”‚ Frontend Comp β”‚ NO β”‚ NO β”‚ NO β”‚ ── β”‚ FE β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +Leyenda: +SI = Siempre actualizar +NO = No requiere actualizacion +Ver = Verificar DDL primero +Posib = Posiblemente, depende del caso +── = No aplica (mismo componente) +``` + +--- + +## 9. DEPENDENCIAS POR MODULO + +### Modulo Tipico NestJS + +``` +modules/user/ +β”œβ”€β”€ entities/ +β”‚ └── user.entity.ts ← Depende de: DDL +β”‚ Impacta: DTOs, Service +β”œβ”€β”€ dto/ +β”‚ β”œβ”€β”€ create-user.dto.ts ← Depende de: Entity +β”‚ β”‚ Impacta: Frontend Schema +β”‚ β”œβ”€β”€ update-user.dto.ts ← Depende de: CreateDto +β”‚ β”‚ Impacta: Frontend Schema +β”‚ └── user-response.dto.ts ← Depende de: Entity +β”‚ Impacta: Frontend Types +β”œβ”€β”€ services/ +β”‚ └── user.service.ts ← Depende de: Entity, DTOs +β”‚ Impacta: Controller +β”œβ”€β”€ controllers/ +β”‚ └── user.controller.ts ← Depende de: Service, DTOs +β”‚ Impacta: Frontend Hooks +└── user.module.ts ← Depende de: Todo lo anterior +``` + +### Modulo Tipico Frontend + +``` +shared/ +β”œβ”€β”€ types/ +β”‚ └── user.types.ts ← Depende de: ResponseDto +β”‚ Impacta: Hooks, Components +β”œβ”€β”€ schemas/ +β”‚ └── user.schema.ts ← Depende de: CreateDto +β”‚ Impacta: Forms +└── services/ + └── user.service.ts ← Depende de: Controller routes + Impacta: Hooks + +apps/web/ +β”œβ”€β”€ hooks/ +β”‚ └── useUsers.ts ← Depende de: Service, Types +β”‚ Impacta: Pages, Components +β”œβ”€β”€ components/ +β”‚ └── UserCard.tsx ← Depende de: Types, Hooks +β”‚ Impacta: Pages +└── pages/ + └── UsersPage.tsx ← Depende de: Hooks, Components +``` + +--- + +## 10. COMANDOS DE VERIFICACION DE DEPENDENCIAS + +```bash +# Ver todas las importaciones de un archivo +grep -n "import" src/modules/user/user.service.ts + +# Ver quien importa un archivo +grep -rn "from.*user.entity" src/ + +# Ver dependencias de modulo +grep -rn "UserModule" src/ + +# Ver uso de tipo en frontend +grep -rn "User" apps/web/ + +# Arbol de dependencias (si usa herramientas) +npx madge --image graph.svg src/modules/user/ + +# TypeScript: ver errores de tipo despues de cambio +npm run typecheck 2>&1 | head -50 +``` + +--- + +## 11. ESCENARIOS COMUNES + +### Escenario 1: Agregar campo a tabla existente + +``` +1. DDL: ALTER TABLE ADD COLUMN +2. Entity: Agregar @Column +3. CreateDto: Agregar campo + validacion +4. ResponseDto: Agregar campo +5. Service: Solo si hay logica especial +6. Frontend Types: Agregar a interface +7. Frontend Schema: Agregar validacion Zod +8. Frontend Components: Agregar UI si necesario +9. Inventarios: DB, BE, FE, MASTER +``` + +### Escenario 2: Crear nuevo modulo/feature + +``` +1. DDL: CREATE TABLE +2. Entity: Crear archivo +3. DTOs: Crear Create, Update, Response +4. Service: Crear con CRUD basico +5. Controller: Crear con endpoints REST +6. Module: Crear y registrar en AppModule +7. Frontend Types: Crear interface +8. Frontend Schema: Crear Zod schema +9. Frontend Service: Crear API service +10. Frontend Hook: Crear useQuery/useMutation +11. Frontend Components: Crear UI +12. Inventarios: TODOS +``` + +### Escenario 3: Refactorizar nombre de campo + +``` +1. EVALUAR: ΒΏEs breaking change? +2. OPCION A (breaking): Cambiar en cadena DDLβ†’Entityβ†’DTOβ†’FE +3. OPCION B (seguro): + a. Agregar nuevo campo + b. Migrar datos + c. Actualizar codigo para usar nuevo + d. Eliminar campo viejo +``` + +--- + +## 12. ANTI-PATRON: DEPENDENCIAS CIRCULARES + +``` +❌ INCORRECTO: Dependencia circular entre Services +UserService ──▢ OrderService + β–² β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +βœ… CORRECTO: Extraer a servicio compartido +UserService ──▢ SharedService ◀── OrderService +``` + +``` +❌ INCORRECTO: Frontend importa de Backend +apps/web/types/user.ts +import { UserEntity } from '@backend/modules/user'; + +βœ… CORRECTO: Frontend tiene sus propios tipos +apps/web/types/user.ts +export interface User { ... } // Definido independiente +``` + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Matriz de Referencia diff --git a/core/orchestration/patrones/ANTIPATRONES.md b/core/orchestration/patrones/ANTIPATRONES.md new file mode 100644 index 0000000..686630b --- /dev/null +++ b/core/orchestration/patrones/ANTIPATRONES.md @@ -0,0 +1,714 @@ +# ANTIPATRONES: Lo que NUNCA Hacer + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - Consultar antes de implementar +**Sistema:** SIMCO + CAPVED + +--- + +## PROPΓ“SITO + +Documentar antipatrones comunes para que agentes y subagentes los eviten. Cada antipatrΓ³n incluye el problema, por quΓ© es malo, y la soluciΓ³n correcta. + +--- + +## 1. ANTIPATRONES DE DATABASE + +### DB-001: Crear tabla sin schema + +```sql +-- ❌ INCORRECTO +CREATE TABLE users ( + id UUID PRIMARY KEY +); + +-- βœ… CORRECTO +CREATE TABLE auth.users ( + id UUID PRIMARY KEY +); +``` + +**Por quΓ© es malo:** Sin schema, la tabla va a `public`, mezclando dominios y dificultando permisos. + +--- + +### DB-002: Columna NOT NULL sin DEFAULT en tabla existente + +```sql +-- ❌ INCORRECTO (en tabla con datos) +ALTER TABLE users ADD COLUMN status VARCHAR(20) NOT NULL; + +-- βœ… CORRECTO +ALTER TABLE users ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'active'; +``` + +**Por quΓ© es malo:** Falla en INSERT para registros existentes que no tienen valor. + +--- + +### DB-003: Foreign Key sin ON DELETE + +```sql +-- ❌ INCORRECTO +CREATE TABLE orders ( + user_id UUID REFERENCES users(id) +); + +-- βœ… CORRECTO +CREATE TABLE orders ( + user_id UUID REFERENCES users(id) ON DELETE CASCADE + -- o ON DELETE SET NULL, ON DELETE RESTRICT segΓΊn el caso +); +``` + +**Por quΓ© es malo:** Al eliminar usuario, los orders quedan huΓ©rfanos o el DELETE falla sin explicaciΓ³n clara. + +--- + +### DB-004: Usar TEXT cuando deberΓ­a ser ENUM + +```sql +-- ❌ INCORRECTO +CREATE TABLE users ( + status TEXT -- Permite cualquier valor +); + +-- βœ… CORRECTO +CREATE TYPE user_status AS ENUM ('active', 'inactive', 'suspended'); +CREATE TABLE users ( + status user_status DEFAULT 'active' +); + +-- O con CHECK constraint +CREATE TABLE users ( + status VARCHAR(20) CHECK (status IN ('active', 'inactive', 'suspended')) +); +``` + +**Por quΓ© es malo:** TEXT permite valores invΓ‘lidos, causando bugs silenciosos. + +--- + +### DB-005: Índice faltante en columna de bΓΊsqueda frecuente + +```sql +-- ❌ INCORRECTO +CREATE TABLE products ( + sku VARCHAR(50) UNIQUE -- Sin Γ­ndice adicional para bΓΊsquedas +); + +-- βœ… CORRECTO +CREATE TABLE products ( + sku VARCHAR(50) UNIQUE +); +CREATE INDEX idx_products_sku ON products(sku); +-- UNIQUE ya crea Γ­ndice, pero para bΓΊsquedas parciales: +CREATE INDEX idx_products_sku_pattern ON products(sku varchar_pattern_ops); +``` + +**Por quΓ© es malo:** Queries lentas en tablas grandes (full table scan). + +--- + +### DB-006: Guardar contraseΓ±as en texto plano + +```sql +-- ❌ INCORRECTO +CREATE TABLE users ( + password VARCHAR(100) -- Almacena "mipassword123" +); + +-- βœ… CORRECTO +CREATE TABLE users ( + password_hash VARCHAR(255) -- Almacena hash bcrypt +); +-- Hashing se hace en backend, no en SQL +``` + +**Por quΓ© es malo:** Vulnerabilidad de seguridad crΓ­tica. + +--- + +## 2. ANTIPATRONES DE BACKEND + +### BE-001: LΓ³gica de negocio en Controller + +```typescript +// ❌ INCORRECTO +@Controller('orders') +export class OrderController { + @Post() + async create(@Body() dto: CreateOrderDto) { + // LΓ³gica de negocio en controller + const total = dto.items.reduce((sum, item) => sum + item.price * item.qty, 0); + const tax = total * 0.16; + const discount = dto.couponCode ? await this.calculateDiscount() : 0; + // ... mΓ‘s lΓ³gica + } +} + +// βœ… CORRECTO +@Controller('orders') +export class OrderController { + @Post() + async create(@Body() dto: CreateOrderDto) { + return this.orderService.create(dto); // Delega a service + } +} + +@Injectable() +export class OrderService { + async create(dto: CreateOrderDto) { + const total = this.calculateTotal(dto.items); + const tax = this.calculateTax(total); + // LΓ³gica de negocio en service + } +} +``` + +**Por quΓ© es malo:** Controller difΓ­cil de testear, lΓ³gica no reutilizable, violaciΓ³n de SRP. + +--- + +### BE-002: Query directo en Service sin Repository + +```typescript +// ❌ INCORRECTO +@Injectable() +export class UserService { + async findActive() { + // Query directo con QueryBuilder + return this.connection.query(` + SELECT * FROM users WHERE status = 'active' + `); + } +} + +// βœ… CORRECTO +@Injectable() +export class UserService { + constructor( + @InjectRepository(UserEntity) + private readonly repository: Repository, + ) {} + + async findActive() { + return this.repository.find({ + where: { status: UserStatus.ACTIVE }, + }); + } +} +``` + +**Por quΓ© es malo:** No tipado, vulnerable a SQL injection, difΓ­cil de mantener. + +--- + +### BE-003: ValidaciΓ³n en Service en lugar de DTO + +```typescript +// ❌ INCORRECTO +@Injectable() +export class UserService { + async create(dto: any) { + if (!dto.email) throw new BadRequestException('Email required'); + if (!dto.email.includes('@')) throw new BadRequestException('Invalid email'); + if (dto.name.length < 2) throw new BadRequestException('Name too short'); + // ... mΓ‘s validaciones manuales + } +} + +// βœ… CORRECTO +export class CreateUserDto { + @IsEmail() + @IsNotEmpty() + email: string; + + @IsString() + @MinLength(2) + name: string; +} + +// Service recibe DTO ya validado +``` + +**Por quΓ© es malo:** ValidaciΓ³n duplicada, inconsistente, no documentada en Swagger. + +--- + +### BE-004: Catch vacΓ­o o silencioso + +```typescript +// ❌ INCORRECTO +async processPayment() { + try { + await this.paymentGateway.charge(); + } catch (e) { + // Silencioso - error perdido + } +} + +// ❌ TAMBIΓ‰N INCORRECTO +async processPayment() { + try { + await this.paymentGateway.charge(); + } catch (e) { + console.log(e); // Solo log, sin manejar + } +} + +// βœ… CORRECTO +async processPayment() { + try { + await this.paymentGateway.charge(); + } catch (error) { + this.logger.error('Payment failed', { error, context: 'payment' }); + throw new InternalServerErrorException('Error procesando pago'); + } +} +``` + +**Por quΓ© es malo:** Errores silenciosos causan bugs imposibles de debuggear. + +--- + +### BE-005: Entity no alineada con DDL + +```typescript +// DDL tiene: +// status VARCHAR(20) CHECK (status IN ('active', 'inactive')) + +// ❌ INCORRECTO +@Column() +status: string; // No valida valores + +// βœ… CORRECTO +enum UserStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', +} + +@Column({ type: 'varchar', length: 20 }) +status: UserStatus; +``` + +**Por quΓ© es malo:** Entity permite valores que BD rechaza, errores en runtime. + +--- + +### BE-006: Hardcodear configuraciΓ³n + +```typescript +// ❌ INCORRECTO +const API_URL = 'https://api.stripe.com/v1'; +const DB_HOST = '192.168.1.100'; + +// βœ… CORRECTO +const API_URL = this.configService.get('STRIPE_API_URL'); +const DB_HOST = this.configService.get('DB_HOST'); + +// O usar decorador +@Injectable() +export class PaymentService { + constructor( + @Inject('STRIPE_CONFIG') + private readonly config: StripeConfig, + ) {} +} +``` + +**Por quΓ© es malo:** DifΓ­cil cambiar entre ambientes, secretos expuestos en cΓ³digo. + +--- + +### BE-007: N+1 Query Problem + +```typescript +// ❌ INCORRECTO +async getOrdersWithItems() { + const orders = await this.orderRepository.find(); + for (const order of orders) { + order.items = await this.itemRepository.find({ + where: { orderId: order.id } + }); + } + return orders; +} +// Resultado: 1 query para orders + N queries para items + +// βœ… CORRECTO +async getOrdersWithItems() { + return this.orderRepository.find({ + relations: ['items'], // JOIN en una query + }); +} +// Resultado: 1 query con JOIN +``` + +**Por quΓ© es malo:** Performance terrible en listas grandes (100 orders = 101 queries). + +--- + +## 3. ANTIPATRONES DE FRONTEND + +### FE-001: Fetch directo en componente + +```typescript +// ❌ INCORRECTO +const UserProfile = () => { + const [user, setUser] = useState(null); + + useEffect(() => { + fetch('/api/users/me') + .then(res => res.json()) + .then(setUser); + }, []); + + return
{user?.name}
; +}; + +// βœ… CORRECTO +// hooks/useUser.ts +const useUser = () => { + return useQuery({ + queryKey: ['user', 'me'], + queryFn: () => userService.getMe(), + }); +}; + +// components/UserProfile.tsx +const UserProfile = () => { + const { data: user, isLoading, error } = useUser(); + + if (isLoading) return ; + if (error) return ; + + return
{user.name}
; +}; +``` + +**Por quΓ© es malo:** No cachea, no maneja loading/error, lΓ³gica no reutilizable. + +--- + +### FE-002: Hardcodear URLs de API + +```typescript +// ❌ INCORRECTO +const response = await fetch('http://localhost:3000/api/users'); + +// βœ… CORRECTO +// config.ts +export const API_URL = import.meta.env.VITE_API_URL; + +// services/api.ts +const api = axios.create({ + baseURL: API_URL, +}); +``` + +**Por quΓ© es malo:** Rompe en producciΓ³n, difΓ­cil cambiar backend. + +--- + +### FE-003: Estado global para todo + +```typescript +// ❌ INCORRECTO - Redux/Zustand para estado de formulario +const formStore = create((set) => ({ + name: '', + email: '', + setName: (name) => set({ name }), + setEmail: (email) => set({ email }), +})); + +// βœ… CORRECTO - Estado local para formularios +const UserForm = () => { + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + // O usar react-hook-form +}; + +// Store global SOLO para: +// - Auth state (usuario logueado) +// - UI state (tema, sidebar abierto) +// - Cache de server state (mejor usar React Query) +``` + +**Por quΓ© es malo:** Complejidad innecesaria, renders innecesarios, difΓ­cil de seguir. + +--- + +### FE-004: Props drilling excesivo + +```typescript +// ❌ INCORRECTO + + + + + // Finalmente se usa + + + + + +// βœ… CORRECTO - Context para datos compartidos +const UserContext = createContext(null); +const useUser = () => useContext(UserContext); + + + + + + + // Usa useUser() internamente + + + + + +``` + +**Por quΓ© es malo:** Componentes intermedios reciben props que no usan, refactoring doloroso. + +--- + +### FE-005: useEffect para todo + +```typescript +// ❌ INCORRECTO +const ProductList = ({ categoryId }) => { + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + setLoading(true); + fetch(`/api/products?category=${categoryId}`) + .then(res => res.json()) + .then(data => { + setProducts(data); + setLoading(false); + }); + }, [categoryId]); + // Race conditions, no cleanup, no error handling +}; + +// βœ… CORRECTO - React Query +const ProductList = ({ categoryId }) => { + const { data: products, isLoading } = useQuery({ + queryKey: ['products', categoryId], + queryFn: () => productService.getByCategory(categoryId), + }); + // Maneja cache, loading, error, race conditions automΓ‘ticamente +}; +``` + +**Por quΓ© es malo:** Race conditions, memory leaks, re-inventar la rueda. + +--- + +### FE-006: Tipos no sincronizados con backend + +```typescript +// Backend DTO (actualizado) +class UserDto { + id: string; + email: string; + name: string; + phone: string; // ← NUEVO CAMPO +} + +// ❌ INCORRECTO - Frontend desactualizado +interface User { + id: string; + email: string; + name: string; + // Falta phone β†’ undefined en runtime +} + +// βœ… CORRECTO - Mantener sincronizado +interface User { + id: string; + email: string; + name: string; + phone?: string; // Sincronizado con backend +} +``` + +**Por quΓ© es malo:** Bugs silenciosos en runtime cuando backend cambia. + +--- + +## 4. ANTIPATRONES DE ARQUITECTURA + +### ARCH-001: Importar de capa incorrecta + +```typescript +// ❌ INCORRECTO - Controller importa de otro mΓ³dulo directamente +import { ProductEntity } from '../products/entities/product.entity'; + +// βœ… CORRECTO - Usar exports del mΓ³dulo +import { ProductService } from '../products/product.module'; + +// O mejor: dependency injection +@Module({ + imports: [ProductModule], +}) +export class OrderModule {} +``` + +**Por quΓ© es malo:** Acopla mΓ³dulos, rompe encapsulamiento, dependencias circulares. + +--- + +### ARCH-002: Duplicar cΓ³digo entre mΓ³dulos + +```typescript +// ❌ INCORRECTO - Misma funciΓ³n en dos mΓ³dulos +// users/utils.ts +function formatDate(date: Date) { ... } + +// orders/utils.ts +function formatDate(date: Date) { ... } // Duplicado + +// βœ… CORRECTO - Shared utils +// shared/utils/date.utils.ts +export function formatDate(date: Date) { ... } +``` + +**Por quΓ© es malo:** Cambios deben hacerse en mΓΊltiples lugares, inconsistencias. + +--- + +### ARCH-003: Circular dependencies + +```typescript +// ❌ INCORRECTO +// user.service.ts +import { OrderService } from '../orders/order.service'; + +// order.service.ts +import { UserService } from '../users/user.service'; + +// βœ… CORRECTO - Usar forwardRef o reestructurar +@Injectable() +export class UserService { + constructor( + @Inject(forwardRef(() => OrderService)) + private orderService: OrderService, + ) {} +} + +// O mejor: Extraer lΓ³gica compartida a un tercer servicio +``` + +**Por quΓ© es malo:** Errores en runtime, cΓ³digo difΓ­cil de entender. + +--- + +## 5. ANTIPATRONES DE TESTING + +### TEST-001: Tests que dependen de orden + +```typescript +// ❌ INCORRECTO +describe('UserService', () => { + it('should create user', () => { + const user = service.create({ email: 'test@test.com' }); + // Asume que este test corre primero + }); + + it('should find user', () => { + const user = service.findByEmail('test@test.com'); + // Depende del test anterior + }); +}); + +// βœ… CORRECTO - Tests independientes +describe('UserService', () => { + beforeEach(async () => { + // Setup limpio para cada test + await repository.clear(); + }); + + it('should create user', () => { ... }); + + it('should find user', async () => { + // Crear datos necesarios en el test + await repository.save({ email: 'test@test.com' }); + const user = await service.findByEmail('test@test.com'); + }); +}); +``` + +--- + +### TEST-002: Mock incorrecto + +```typescript +// ❌ INCORRECTO - Mock parcial/inconsistente +jest.mock('./user.service', () => ({ + findOne: jest.fn().mockResolvedValue({ id: '1' }), + // Otros mΓ©todos no mockeados β†’ undefined +})); + +// βœ… CORRECTO - Mock completo +const mockUserService = { + findOne: jest.fn(), + findAll: jest.fn(), + create: jest.fn(), + update: jest.fn(), + delete: jest.fn(), +}; + +beforeEach(() => { + jest.clearAllMocks(); +}); +``` + +--- + +## 6. CHECKLIST DE REVISIΓ“N + +Antes de hacer commit, verificar que NO estΓ‘s haciendo: + +``` +Database: +[ ] Tabla sin schema +[ ] NOT NULL sin DEFAULT en tabla existente +[ ] FK sin ON DELETE +[ ] TEXT donde deberΓ­a ser ENUM +[ ] Índices faltantes + +Backend: +[ ] LΓ³gica en Controller +[ ] Queries directas sin Repository +[ ] ValidaciΓ³n en Service +[ ] Catch vacΓ­o +[ ] Entity desalineada con DDL +[ ] Config hardcodeada +[ ] N+1 queries + +Frontend: +[ ] Fetch en componente +[ ] URLs hardcodeadas +[ ] Store global para estado local +[ ] Props drilling excesivo +[ ] useEffect innecesario +[ ] Tipos desactualizados + +Arquitectura: +[ ] Import de capa incorrecta +[ ] CΓ³digo duplicado +[ ] Dependencias circulares + +Testing: +[ ] Tests dependientes +[ ] Mocks incompletos +``` + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** GuΓ­a de Antipatrones diff --git a/core/orchestration/patrones/MAPEO-TIPOS-DDL-TYPESCRIPT.md b/core/orchestration/patrones/MAPEO-TIPOS-DDL-TYPESCRIPT.md new file mode 100644 index 0000000..209be33 --- /dev/null +++ b/core/orchestration/patrones/MAPEO-TIPOS-DDL-TYPESCRIPT.md @@ -0,0 +1,499 @@ +# MAPEO DE TIPOS: PostgreSQL DDL β†’ TypeScript/TypeORM + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - Consultar antes de crear Entity +**Sistema:** SIMCO + CAPVED + +--- + +## PROPΓ“SITO + +Este documento define el mapeo EXACTO entre tipos de PostgreSQL y TypeScript/TypeORM para garantizar alineaciΓ³n 100% entre DDL y Entities. + +--- + +## REGLA FUNDAMENTAL + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ DDL ES LA FUENTE DE VERDAD (DDL-First) β•‘ +β•‘ β•‘ +β•‘ 1. DDL define el tipo β†’ Entity lo REFLEJA β•‘ +β•‘ 2. NUNCA crear Entity sin DDL existente β•‘ +β•‘ 3. Si DDL cambia β†’ Entity DEBE cambiar β•‘ +β•‘ 4. Si Entity no coincide β†’ ERROR (corregir Entity, no DDL) β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## TABLA DE MAPEO COMPLETA + +### Tipos NumΓ©ricos + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `SMALLINT` | `number` | `@Column({ type: 'smallint' })` | -32,768 a 32,767 | +| `INTEGER` | `number` | `@Column({ type: 'integer' })` | -2B a 2B | +| `BIGINT` | `string` | `@Column({ type: 'bigint' })` | Usar string para precisiΓ³n | +| `DECIMAL(p,s)` | `string` | `@Column({ type: 'decimal', precision: p, scale: s })` | Usar string para dinero | +| `NUMERIC(p,s)` | `string` | `@Column({ type: 'numeric', precision: p, scale: s })` | Igual que DECIMAL | +| `REAL` | `number` | `@Column({ type: 'real' })` | Punto flotante 4 bytes | +| `DOUBLE PRECISION` | `number` | `@Column({ type: 'double precision' })` | Punto flotante 8 bytes | +| `SERIAL` | `number` | `@PrimaryGeneratedColumn()` | Auto-increment | +| `BIGSERIAL` | `string` | `@PrimaryGeneratedColumn('increment')` | Auto-increment grande | + +**Ejemplo NumΓ©ricos:** +```sql +-- DDL +CREATE TABLE products ( + id SERIAL PRIMARY KEY, + price DECIMAL(10,2) NOT NULL, + quantity INTEGER DEFAULT 0, + rating REAL +); +``` + +```typescript +// Entity +@Entity({ schema: 'inventory', name: 'products' }) +export class ProductEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ type: 'decimal', precision: 10, scale: 2 }) + price: string; // String para precisiΓ³n decimal + + @Column({ type: 'integer', default: 0 }) + quantity: number; + + @Column({ type: 'real', nullable: true }) + rating: number; +} +``` + +--- + +### Tipos de Texto + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `CHAR(n)` | `string` | `@Column({ type: 'char', length: n })` | Longitud fija | +| `VARCHAR(n)` | `string` | `@Column({ type: 'varchar', length: n })` | Longitud variable | +| `TEXT` | `string` | `@Column({ type: 'text' })` | Sin lΓ­mite | + +**Ejemplo Texto:** +```sql +-- DDL +CREATE TABLE users ( + code CHAR(10) NOT NULL, + email VARCHAR(255) UNIQUE NOT NULL, + bio TEXT +); +``` + +```typescript +// Entity +@Column({ type: 'char', length: 10 }) +code: string; + +@Column({ type: 'varchar', length: 255, unique: true }) +email: string; + +@Column({ type: 'text', nullable: true }) +bio: string; +``` + +--- + +### Tipos de Fecha y Hora + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `DATE` | `Date` | `@Column({ type: 'date' })` | Solo fecha | +| `TIME` | `string` | `@Column({ type: 'time' })` | Solo hora | +| `TIMESTAMP` | `Date` | `@Column({ type: 'timestamp' })` | Fecha + hora sin TZ | +| `TIMESTAMPTZ` | `Date` | `@Column({ type: 'timestamptz' })` | Fecha + hora con TZ | +| `INTERVAL` | `string` | `@Column({ type: 'interval' })` | Intervalo de tiempo | + +**Ejemplo Fechas:** +```sql +-- DDL +CREATE TABLE events ( + event_date DATE NOT NULL, + start_time TIME, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW(), + duration INTERVAL +); +``` + +```typescript +// Entity +@Column({ type: 'date' }) +eventDate: Date; + +@Column({ type: 'time', nullable: true }) +startTime: string; + +@CreateDateColumn({ type: 'timestamp' }) +createdAt: Date; + +@UpdateDateColumn({ type: 'timestamptz' }) +updatedAt: Date; + +@Column({ type: 'interval', nullable: true }) +duration: string; +``` + +--- + +### Tipos Booleanos + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `BOOLEAN` | `boolean` | `@Column({ type: 'boolean' })` | true/false | + +**Ejemplo Boolean:** +```sql +-- DDL +CREATE TABLE users ( + is_active BOOLEAN DEFAULT TRUE, + is_verified BOOLEAN DEFAULT FALSE +); +``` + +```typescript +// Entity +@Column({ type: 'boolean', default: true }) +isActive: boolean; + +@Column({ type: 'boolean', default: false }) +isVerified: boolean; +``` + +--- + +### Tipos UUID + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `UUID` | `string` | `@Column({ type: 'uuid' })` | Usar con gen_random_uuid() | + +**Ejemplo UUID:** +```sql +-- DDL +CREATE TABLE users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES tenants(id) +); +``` + +```typescript +// Entity +@PrimaryGeneratedColumn('uuid') +id: string; + +@Column({ type: 'uuid' }) +tenantId: string; + +@ManyToOne(() => TenantEntity) +@JoinColumn({ name: 'tenant_id' }) +tenant: TenantEntity; +``` + +--- + +### Tipos JSON + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `JSON` | `object \| any` | `@Column({ type: 'json' })` | Sin indexaciΓ³n | +| `JSONB` | `object \| any` | `@Column({ type: 'jsonb' })` | Con indexaciΓ³n | + +**Ejemplo JSON:** +```sql +-- DDL +CREATE TABLE users ( + preferences JSONB DEFAULT '{}', + metadata JSON +); +``` + +```typescript +// Entity - OpciΓ³n 1: any +@Column({ type: 'jsonb', default: {} }) +preferences: any; + +// Entity - OpciΓ³n 2: Interface tipada (RECOMENDADO) +interface UserPreferences { + theme: 'light' | 'dark'; + notifications: boolean; + language: string; +} + +@Column({ type: 'jsonb', default: {} }) +preferences: UserPreferences; + +@Column({ type: 'json', nullable: true }) +metadata: Record; +``` + +--- + +### Tipos ENUM + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `CREATE TYPE ... AS ENUM` | `enum` | `@Column({ type: 'enum', enum: X })` | Definir enum TS | +| `VARCHAR CHECK (IN ...)` | `enum \| string` | `@Column()` + validator | Alternativa sin tipo | + +**Ejemplo ENUM (Recomendado):** +```sql +-- DDL +CREATE TYPE user_status AS ENUM ('active', 'inactive', 'suspended', 'deleted'); + +CREATE TABLE users ( + status user_status DEFAULT 'active' +); +``` + +```typescript +// Entity +export enum UserStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', + SUSPENDED = 'suspended', + DELETED = 'deleted', +} + +@Column({ + type: 'enum', + enum: UserStatus, + default: UserStatus.ACTIVE, +}) +status: UserStatus; +``` + +**Ejemplo VARCHAR con CHECK (Alternativa):** +```sql +-- DDL +CREATE TABLE orders ( + status VARCHAR(20) CHECK (status IN ('pending', 'processing', 'completed', 'cancelled')) +); +``` + +```typescript +// Entity - Usar tipo union + validaciΓ³n en DTO +type OrderStatus = 'pending' | 'processing' | 'completed' | 'cancelled'; + +@Column({ type: 'varchar', length: 20 }) +status: OrderStatus; + +// DTO - ValidaciΓ³n obligatoria +@IsIn(['pending', 'processing', 'completed', 'cancelled']) +status: string; +``` + +--- + +### Tipos Array + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `INTEGER[]` | `number[]` | `@Column({ type: 'integer', array: true })` | Array de enteros | +| `VARCHAR[]` | `string[]` | `@Column({ type: 'varchar', array: true })` | Array de strings | +| `UUID[]` | `string[]` | `@Column({ type: 'uuid', array: true })` | Array de UUIDs | + +**Ejemplo Arrays:** +```sql +-- DDL +CREATE TABLE posts ( + tags VARCHAR(50)[], + category_ids UUID[] +); +``` + +```typescript +// Entity +@Column({ type: 'varchar', array: true, nullable: true }) +tags: string[]; + +@Column({ type: 'uuid', array: true, nullable: true }) +categoryIds: string[]; +``` + +--- + +### Tipos Especiales + +| PostgreSQL | TypeScript | TypeORM Column | Notas | +|------------|------------|----------------|-------| +| `BYTEA` | `Buffer` | `@Column({ type: 'bytea' })` | Datos binarios | +| `INET` | `string` | `@Column({ type: 'inet' })` | DirecciΓ³n IP | +| `CIDR` | `string` | `@Column({ type: 'cidr' })` | Red IP | +| `MACADDR` | `string` | `@Column({ type: 'macaddr' })` | DirecciΓ³n MAC | + +--- + +## MAPEO DE CONSTRAINTS + +### NOT NULL + +```sql +-- DDL +email VARCHAR(255) NOT NULL +``` + +```typescript +// Entity +@Column({ type: 'varchar', length: 255, nullable: false }) +email: string; // Sin ? = no nullable +``` + +### DEFAULT + +```sql +-- DDL +created_at TIMESTAMP DEFAULT NOW() +status VARCHAR(20) DEFAULT 'active' +``` + +```typescript +// Entity +@CreateDateColumn({ type: 'timestamp' }) +createdAt: Date; + +@Column({ type: 'varchar', length: 20, default: 'active' }) +status: string; +``` + +### UNIQUE + +```sql +-- DDL +email VARCHAR(255) UNIQUE +``` + +```typescript +// Entity +@Column({ type: 'varchar', length: 255, unique: true }) +email: string; +``` + +### CHECK (No soportado directamente en TypeORM) + +```sql +-- DDL +age INTEGER CHECK (age >= 0 AND age <= 150) +``` + +```typescript +// Entity - Sin validaciΓ³n en Entity +@Column({ type: 'integer' }) +age: number; + +// DTO - OBLIGATORIO validar aquΓ­ +@IsInt() +@Min(0) +@Max(150) +age: number; +``` + +--- + +## MAPEO DE RELACIONES + +### ONE-TO-MANY / MANY-TO-ONE + +```sql +-- DDL +CREATE TABLE orders ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE +); +``` + +```typescript +// Entity Order +@ManyToOne(() => UserEntity, user => user.orders, { onDelete: 'CASCADE' }) +@JoinColumn({ name: 'user_id' }) +user: UserEntity; + +@Column({ type: 'uuid' }) +userId: string; + +// Entity User +@OneToMany(() => OrderEntity, order => order.user) +orders: OrderEntity[]; +``` + +### MANY-TO-MANY + +```sql +-- DDL +CREATE TABLE user_roles ( + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, + role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, + PRIMARY KEY (user_id, role_id) +); +``` + +```typescript +// Entity User +@ManyToMany(() => RoleEntity, role => role.users) +@JoinTable({ + name: 'user_roles', + joinColumn: { name: 'user_id', referencedColumnName: 'id' }, + inverseJoinColumn: { name: 'role_id', referencedColumnName: 'id' }, +}) +roles: RoleEntity[]; + +// Entity Role +@ManyToMany(() => UserEntity, user => user.roles) +users: UserEntity[]; +``` + +--- + +## CHECKLIST DE ALINEACIΓ“N + +Antes de completar Entity, verificar: + +``` +[ ] Cada columna DDL tiene @Column en Entity +[ ] Tipos PostgreSQL mapeados correctamente (ver tabla) +[ ] nullable: false para NOT NULL +[ ] default: X para DEFAULT X +[ ] unique: true para UNIQUE +[ ] Relaciones (@ManyToOne, etc.) coinciden con FOREIGN KEY +[ ] onDelete coincide con ON DELETE +[ ] Nombre de tabla correcto en @Entity({ name: 'x' }) +[ ] Schema correcto en @Entity({ schema: 'x' }) +[ ] PK coincide (@PrimaryGeneratedColumn vs @PrimaryColumn) +``` + +--- + +## ERRORES COMUNES + +| Error | Causa | SoluciΓ³n | +|-------|-------|----------| +| `bigint` retorna string inesperado | BIGINT se mapea a string | Usar `string` en TypeScript | +| Decimales pierden precisiΓ³n | DECIMAL mapeado a number | Usar `string` para dinero | +| Enum no reconocido | Tipo no creado en BD | Crear TYPE primero en DDL | +| Array vacΓ­o falla | Array sin default | Agregar `default: []` | +| Fecha invΓ‘lida | TIMESTAMP vs TIMESTAMPTZ | Usar TIMESTAMPTZ para TZ | + +--- + +## REFERENCIAS + +- SIMCO-DDL.md - Crear tablas +- SIMCO-BACKEND.md - Crear entities +- PRINCIPIO-VALIDACION-OBLIGATORIA.md - Validar alineaciΓ³n + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** PatrΓ³n de Mapeo diff --git a/core/orchestration/patrones/NOMENCLATURA-UNIFICADA.md b/core/orchestration/patrones/NOMENCLATURA-UNIFICADA.md new file mode 100644 index 0000000..e3c552f --- /dev/null +++ b/core/orchestration/patrones/NOMENCLATURA-UNIFICADA.md @@ -0,0 +1,539 @@ +# NOMENCLATURA UNIFICADA + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - Seguir en todo el cΓ³digo +**Sistema:** SIMCO + CAPVED + +--- + +## PROPΓ“SITO + +Definir convenciones de nomenclatura consistentes para todas las capas del sistema. + +--- + +## 1. DIRECTORIOS + +### Regla General + +``` +lowercase-kebab-case +``` + +### Ejemplos + +``` +βœ… CORRECTO ❌ INCORRECTO +─────────────────────────────────────── +user-management/ UserManagement/ +auth-module/ AuthModule/ +shared-utils/ sharedUtils/ +api-v1/ API_V1/ +``` + +### Estructura por Capa + +``` +DATABASE: +db/ +β”œβ”€β”€ schemas/ +β”‚ β”œβ”€β”€ auth/ +β”‚ β”‚ └── tables/ +β”‚ β”œβ”€β”€ core/ +β”‚ └── {domain}/ +β”œβ”€β”€ seeds/ +β”‚ β”œβ”€β”€ dev/ +β”‚ └── prod/ +└── scripts/ + +BACKEND (NestJS): +src/ +β”œβ”€β”€ modules/ +β”‚ └── {module-name}/ +β”‚ β”œβ”€β”€ entities/ +β”‚ β”œβ”€β”€ dto/ +β”‚ β”œβ”€β”€ services/ +β”‚ β”œβ”€β”€ controllers/ +β”‚ └── tests/ +β”œβ”€β”€ shared/ +β”‚ β”œβ”€β”€ config/ +β”‚ β”œβ”€β”€ guards/ +β”‚ β”œβ”€β”€ decorators/ +β”‚ β”œβ”€β”€ filters/ +β”‚ β”œβ”€β”€ interceptors/ +β”‚ └── utils/ +└── main.ts + +FRONTEND (React): +src/ +β”œβ”€β”€ apps/ +β”‚ └── {app-name}/ +β”‚ β”œβ”€β”€ components/ +β”‚ β”œβ”€β”€ pages/ +β”‚ └── hooks/ +β”œβ”€β”€ shared/ +β”‚ β”œβ”€β”€ components/ +β”‚ β”‚ β”œβ”€β”€ ui/ # Componentes base +β”‚ β”‚ └── common/ # Componentes compartidos +β”‚ β”œβ”€β”€ hooks/ +β”‚ β”œβ”€β”€ stores/ +β”‚ β”œβ”€β”€ services/ +β”‚ β”œβ”€β”€ types/ +β”‚ └── utils/ +└── main.tsx +``` + +--- + +## 2. ARCHIVOS + +### Por Capa + +| Capa | PatrΓ³n | Ejemplo | +|------|--------|---------| +| **DDL** | `{NN}-{nombre}.sql` | `01-users.sql`, `02-products.sql` | +| **Seed** | `{NN}-{nombre}.sql` | `01-admin-user.sql` | +| **Entity** | `{nombre}.entity.ts` | `user.entity.ts` | +| **DTO Create** | `create-{nombre}.dto.ts` | `create-user.dto.ts` | +| **DTO Update** | `update-{nombre}.dto.ts` | `update-user.dto.ts` | +| **DTO Response** | `{nombre}-response.dto.ts` | `user-response.dto.ts` | +| **DTO Query** | `{nombre}-query.dto.ts` | `user-query.dto.ts` | +| **Service** | `{nombre}.service.ts` | `user.service.ts` | +| **Controller** | `{nombre}.controller.ts` | `user.controller.ts` | +| **Module** | `{nombre}.module.ts` | `user.module.ts` | +| **Guard** | `{nombre}.guard.ts` | `jwt-auth.guard.ts` | +| **Strategy** | `{nombre}.strategy.ts` | `jwt.strategy.ts` | +| **Filter** | `{nombre}.filter.ts` | `http-exception.filter.ts` | +| **Interceptor** | `{nombre}.interceptor.ts` | `logging.interceptor.ts` | +| **Decorator** | `{nombre}.decorator.ts` | `current-user.decorator.ts` | +| **Component** | `{Nombre}.tsx` | `UserCard.tsx` | +| **Page** | `{Nombre}Page.tsx` | `UserProfilePage.tsx` | +| **Hook** | `use{Nombre}.ts` | `useUser.ts`, `useAuth.ts` | +| **Store** | `{nombre}.store.ts` | `auth.store.ts` | +| **Service (FE)** | `{nombre}.service.ts` | `user.service.ts` | +| **Types** | `{nombre}.types.ts` | `user.types.ts` | +| **Test Unit** | `{nombre}.spec.ts` | `user.service.spec.ts` | +| **Test E2E** | `{nombre}.e2e-spec.ts` | `user.e2e-spec.ts` | +| **Test Component** | `{Nombre}.test.tsx` | `UserCard.test.tsx` | + +### DDL - Orden de Archivos + +```sql +-- Usar prefijo numΓ©rico para orden de ejecuciΓ³n +01-users.sql -- Tablas base primero +02-roles.sql -- Tablas relacionadas +03-user-roles.sql -- Junction tables despuΓ©s +04-permissions.sql +10-products.sql -- Otro dominio, nuevo rango +11-categories.sql +12-product-categories.sql +``` + +--- + +## 3. CLASES Y TIPOS + +### TypeScript/NestJS + +| Tipo | PatrΓ³n | Ejemplo | +|------|--------|---------| +| **Entity** | `{Nombre}Entity` | `UserEntity` | +| **DTO** | `{Accion}{Nombre}Dto` | `CreateUserDto` | +| **Service** | `{Nombre}Service` | `UserService` | +| **Controller** | `{Nombre}Controller` | `UserController` | +| **Module** | `{Nombre}Module` | `UserModule` | +| **Guard** | `{Nombre}Guard` | `JwtAuthGuard` | +| **Strategy** | `{Nombre}Strategy` | `JwtStrategy` | +| **Filter** | `{Nombre}Filter` | `HttpExceptionFilter` | +| **Interceptor** | `{Nombre}Interceptor` | `LoggingInterceptor` | +| **Enum** | `{Nombre}` | `UserStatus`, `OrderState` | +| **Interface** | `{Nombre}` o `I{Nombre}` | `User`, `IUserService` | +| **Type** | `{Nombre}` | `UserWithRoles`, `OrderSummary` | + +### Ejemplos Completos + +```typescript +// Entity +@Entity({ schema: 'auth', name: 'users' }) +export class UserEntity { ... } + +// DTOs +export class CreateUserDto { ... } +export class UpdateUserDto extends PartialType(CreateUserDto) { ... } +export class UserResponseDto { ... } +export class UserQueryDto { ... } + +// Service +@Injectable() +export class UserService { ... } + +// Controller +@Controller('users') +export class UserController { ... } + +// Module +@Module({}) +export class UserModule { ... } + +// Enum +export enum UserStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', +} + +// Interface +export interface User { + id: string; + email: string; +} + +// Type +export type UserWithRoles = User & { roles: Role[] }; +``` + +--- + +## 4. FUNCIONES Y MΓ‰TODOS + +### Verbos EstΓ‘ndar + +| OperaciΓ³n | Verbo | Ejemplo | +|-----------|-------|---------| +| Obtener uno | `find`, `get` | `findById()`, `getUser()` | +| Obtener muchos | `findAll`, `list` | `findAll()`, `listUsers()` | +| Crear | `create` | `create()`, `createUser()` | +| Actualizar | `update` | `update()`, `updateUser()` | +| Eliminar | `remove`, `delete` | `remove()`, `deleteUser()` | +| Buscar | `search` | `search()`, `searchUsers()` | +| Verificar | `is`, `has`, `can` | `isActive()`, `hasPermission()` | +| Contar | `count` | `count()`, `countActive()` | +| Validar | `validate` | `validateEmail()` | +| Formatear | `format` | `formatDate()`, `formatPrice()` | +| Parsear | `parse` | `parseJson()`, `parseDate()` | +| Convertir | `to`, `from` | `toDto()`, `fromEntity()` | + +### Ejemplos por Capa + +```typescript +// Service - CRUD estΓ‘ndar +class UserService { + async create(dto: CreateUserDto): Promise { ... } + async findAll(query: UserQueryDto): Promise { ... } + async findById(id: string): Promise { ... } + async findByEmail(email: string): Promise { ... } + async update(id: string, dto: UpdateUserDto): Promise { ... } + async remove(id: string): Promise { ... } + + // MΓ©todos adicionales + async activate(id: string): Promise { ... } + async deactivate(id: string): Promise { ... } + async assignRole(userId: string, roleId: string): Promise { ... } + async hasPermission(userId: string, permission: string): Promise { ... } +} + +// Controller - Endpoints REST +class UserController { + @Get() + async findAll(@Query() query: UserQueryDto) { ... } + + @Get(':id') + async findOne(@Param('id') id: string) { ... } + + @Post() + async create(@Body() dto: CreateUserDto) { ... } + + @Put(':id') + async update(@Param('id') id: string, @Body() dto: UpdateUserDto) { ... } + + @Delete(':id') + async remove(@Param('id') id: string) { ... } +} + +// Hook (Frontend) +function useUsers() { + return useQuery({ ... }); +} + +function useUser(id: string) { + return useQuery({ ... }); +} + +function useCreateUser() { + return useMutation({ ... }); +} + +function useUpdateUser() { + return useMutation({ ... }); +} + +function useDeleteUser() { + return useMutation({ ... }); +} +``` + +--- + +## 5. VARIABLES Y CONSTANTES + +### Variables + +```typescript +// camelCase +const userId = '123'; +const isActive = true; +const userCount = 10; +const createdAt = new Date(); + +// Arrays en plural +const users = []; +const activeUsers = []; +const userIds = ['1', '2', '3']; + +// Maps/Records con sufijo +const userMap = new Map(); +const roleById = {}; // Record +``` + +### Constantes + +```typescript +// UPPER_SNAKE_CASE para constantes +const MAX_LOGIN_ATTEMPTS = 5; +const DEFAULT_PAGE_SIZE = 20; +const API_VERSION = 'v1'; +const JWT_EXPIRATION = '1d'; + +// Constantes de configuraciΓ³n +const CONFIG = { + MAX_FILE_SIZE: 10 * 1024 * 1024, // 10MB + ALLOWED_EXTENSIONS: ['.jpg', '.png', '.pdf'], + RATE_LIMIT: 100, +}; + +// Rutas/Paths +const ROUTES = { + HOME: '/', + LOGIN: '/auth/login', + DASHBOARD: '/dashboard', + USER_PROFILE: '/users/:id', +}; +``` + +--- + +## 6. ENUMS + +### DefiniciΓ³n + +```typescript +// PascalCase para nombre +// Valores en minΓΊsculas (para BD) o UPPER_CASE (para constantes) + +// OpciΓ³n 1: Valores string (recomendado para BD) +export enum UserStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', + SUSPENDED = 'suspended', + DELETED = 'deleted', +} + +// OpciΓ³n 2: Valores UPPER_CASE (para constantes internas) +export enum HttpMethod { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +// OpciΓ³n 3: NumΓ©ricos (solo si necesario) +export enum Priority { + LOW = 1, + MEDIUM = 2, + HIGH = 3, + CRITICAL = 4, +} +``` + +### Uso + +```typescript +// Entity +@Column({ type: 'enum', enum: UserStatus, default: UserStatus.ACTIVE }) +status: UserStatus; + +// ValidaciΓ³n DTO +@IsEnum(UserStatus) +status: UserStatus; + +// Frontend +const statusLabel = { + [UserStatus.ACTIVE]: 'Activo', + [UserStatus.INACTIVE]: 'Inactivo', + [UserStatus.SUSPENDED]: 'Suspendido', +}; +``` + +--- + +## 7. DATABASE (SQL) + +### Tablas y Columnas + +```sql +-- Tablas: snake_case, plural +CREATE TABLE users ( ... ); +CREATE TABLE product_categories ( ... ); +CREATE TABLE user_login_attempts ( ... ); + +-- Columnas: snake_case +CREATE TABLE users ( + id UUID PRIMARY KEY, + first_name VARCHAR(100), + last_name VARCHAR(100), + email VARCHAR(255), + is_active BOOLEAN, + created_at TIMESTAMP, + updated_at TIMESTAMP, + deleted_at TIMESTAMP +); + +-- Foreign Keys: {tabla_singular}_id +CREATE TABLE orders ( + user_id UUID REFERENCES users(id), + product_id UUID REFERENCES products(id) +); + +-- Junction Tables: {tabla1}_{tabla2} (orden alfabΓ©tico) +CREATE TABLE role_users ( ... ); -- ❌ +CREATE TABLE user_roles ( ... ); -- βœ… (u antes de r) +``` + +### Índices y Constraints + +```sql +-- Índices: idx_{tabla}_{columnas} +CREATE INDEX idx_users_email ON users(email); +CREATE INDEX idx_orders_user_created ON orders(user_id, created_at); + +-- Unique: uq_{tabla}_{columnas} +ALTER TABLE users ADD CONSTRAINT uq_users_email UNIQUE (email); + +-- Foreign Key: fk_{tabla}_{referencia} +ALTER TABLE orders ADD CONSTRAINT fk_orders_user + FOREIGN KEY (user_id) REFERENCES users(id); + +-- Check: chk_{tabla}_{descripcion} +ALTER TABLE users ADD CONSTRAINT chk_users_status + CHECK (status IN ('active', 'inactive')); +``` + +--- + +## 8. API ENDPOINTS + +### Convenciones REST + +``` +GET /api/v1/users # Listar +GET /api/v1/users/:id # Obtener uno +POST /api/v1/users # Crear +PUT /api/v1/users/:id # Actualizar completo +PATCH /api/v1/users/:id # Actualizar parcial +DELETE /api/v1/users/:id # Eliminar + +# Recursos anidados +GET /api/v1/users/:id/orders # Γ“rdenes del usuario +POST /api/v1/users/:id/orders # Crear orden para usuario + +# Acciones especiales +POST /api/v1/users/:id/activate # AcciΓ³n +POST /api/v1/users/:id/deactivate # AcciΓ³n +POST /api/v1/auth/login # Auth +POST /api/v1/auth/logout # Auth +POST /api/v1/auth/refresh # Auth +``` + +### URL Patterns + +``` +βœ… CORRECTO ❌ INCORRECTO +────────────────────────────────────────── +/users /user # Plural +/users/:id /users/get/:id # Verbo innecesario +/users/:id/orders /getUserOrders # Snake case, verbo +/auth/login /doLogin # Verbo innecesario +``` + +--- + +## 9. COMPONENTES REACT + +### Nombres + +```typescript +// PascalCase para componentes +const UserCard = () => { ... }; +const ProductList = () => { ... }; +const LoginForm = () => { ... }; + +// Sufijos descriptivos +const UserProfilePage = () => { ... }; // PΓ‘gina completa +const UserEditModal = () => { ... }; // Modal +const UserDeleteDialog = () => { ... }; // Dialog de confirmaciΓ³n +const UserAvatarSkeleton = () => { ... }; // Loading skeleton +``` + +### Props + +```typescript +// Interface con Props suffix +interface UserCardProps { + user: User; + onEdit?: (user: User) => void; + onDelete?: (id: string) => void; + isLoading?: boolean; +} + +const UserCard: React.FC = ({ + user, + onEdit, + onDelete, + isLoading = false, +}) => { ... }; +``` + +--- + +## 10. CHECKLIST DE NOMENCLATURA + +``` +Antes de crear archivo: +[ ] Nombre en formato correcto para su tipo +[ ] Directorio correcto segΓΊn capa +[ ] Sin duplicados en nombre + +Antes de crear clase/tipo: +[ ] PascalCase +[ ] Sufijo correcto (Entity, Dto, Service, etc.) +[ ] Nombre descriptivo + +Antes de crear funciΓ³n: +[ ] camelCase +[ ] Verbo al inicio +[ ] Nombre describe quΓ© hace + +Antes de crear variable: +[ ] camelCase +[ ] Nombre descriptivo +[ ] Plural para arrays + +Antes de crear endpoint: +[ ] Recurso en plural +[ ] Sin verbos en URL +[ ] Estructura RESTful +``` + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** GuΓ­a de Nomenclatura diff --git a/core/orchestration/patrones/PATRON-CONFIGURACION.md b/core/orchestration/patrones/PATRON-CONFIGURACION.md new file mode 100644 index 0000000..63ad0fe --- /dev/null +++ b/core/orchestration/patrones/PATRON-CONFIGURACION.md @@ -0,0 +1,745 @@ +# PATRON DE CONFIGURACION + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** RECOMENDADA - Seguir para consistencia +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Definir patrones estandarizados para manejo de configuracion en todas las capas, incluyendo variables de entorno, archivos de configuracion, y validacion de settings. + +--- + +## 1. PRINCIPIOS FUNDAMENTALES + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ PRINCIPIOS DE CONFIGURACION β•‘ +╠══════════════════════════════════════════════════════════════════════╣ +β•‘ β•‘ +β•‘ 1. NUNCA hardcodear valores sensibles β•‘ +β•‘ 2. SIEMPRE validar configuracion al iniciar β•‘ +β•‘ 3. FALLAR RAPIDO si configuracion es invalida β•‘ +β•‘ 4. SEPARAR configuracion por ambiente β•‘ +β•‘ 5. CENTRALIZAR acceso a configuracion β•‘ +β•‘ 6. DOCUMENTAR cada variable requerida β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 2. ESTRUCTURA DE ARCHIVOS + +### Estructura Recomendada + +``` +project/ +β”œβ”€β”€ .env.example # Template con TODAS las variables (sin valores reales) +β”œβ”€β”€ .env # Valores locales (NUNCA en git) +β”œβ”€β”€ .env.development # Override para desarrollo +β”œβ”€β”€ .env.staging # Override para staging +β”œβ”€β”€ .env.production # Override para produccion (solo en servidor) +β”‚ +β”œβ”€β”€ apps/backend/ +β”‚ └── src/ +β”‚ └── shared/ +β”‚ └── config/ +β”‚ β”œβ”€β”€ configuration.ts # Configuracion principal +β”‚ β”œβ”€β”€ config.validation.ts # Schema de validacion +β”‚ β”œβ”€β”€ database.config.ts # Config de BD +β”‚ β”œβ”€β”€ jwt.config.ts # Config de JWT +β”‚ └── index.ts # Export centralizado +β”‚ +└── apps/frontend/ + └── src/ + └── shared/ + └── config/ + β”œβ”€β”€ env.ts # Variables de entorno + └── constants.ts # Constantes de app +``` + +### .env.example (Template) + +```bash +# ═══════════════════════════════════════════════════════════════════ +# CONFIGURACION DE BASE DE DATOS +# ═══════════════════════════════════════════════════════════════════ +DB_HOST=localhost +DB_PORT=5432 +DB_NAME=myapp_development +DB_USER=postgres +DB_PASSWORD= # REQUERIDO: Password de BD +DB_SSL=false + +# ═══════════════════════════════════════════════════════════════════ +# CONFIGURACION DE JWT/AUTH +# ═══════════════════════════════════════════════════════════════════ +JWT_SECRET= # REQUERIDO: Minimo 32 caracteres +JWT_EXPIRATION=1d +JWT_REFRESH_EXPIRATION=7d + +# ═══════════════════════════════════════════════════════════════════ +# CONFIGURACION DE SERVIDOR +# ═══════════════════════════════════════════════════════════════════ +NODE_ENV=development +PORT=3000 +API_PREFIX=api +CORS_ORIGINS=http://localhost:5173 + +# ═══════════════════════════════════════════════════════════════════ +# CONFIGURACION DE SERVICIOS EXTERNOS +# ═══════════════════════════════════════════════════════════════════ +REDIS_URL=redis://localhost:6379 +SMTP_HOST= +SMTP_PORT=587 +SMTP_USER= +SMTP_PASSWORD= + +# ═══════════════════════════════════════════════════════════════════ +# CONFIGURACION DE LOGGING +# ═══════════════════════════════════════════════════════════════════ +LOG_LEVEL=debug # trace|debug|info|warn|error +LOG_FORMAT=pretty # pretty|json +``` + +--- + +## 3. BACKEND (NestJS) + +### Schema de Validacion con Joi + +```typescript +// src/shared/config/config.validation.ts +import * as Joi from 'joi'; + +export const configValidationSchema = Joi.object({ + // Database + DB_HOST: Joi.string().required(), + DB_PORT: Joi.number().default(5432), + DB_NAME: Joi.string().required(), + DB_USER: Joi.string().required(), + DB_PASSWORD: Joi.string().required(), + DB_SSL: Joi.boolean().default(false), + + // JWT + JWT_SECRET: Joi.string().min(32).required(), + JWT_EXPIRATION: Joi.string().default('1d'), + JWT_REFRESH_EXPIRATION: Joi.string().default('7d'), + + // Server + NODE_ENV: Joi.string() + .valid('development', 'staging', 'production', 'test') + .default('development'), + PORT: Joi.number().default(3000), + API_PREFIX: Joi.string().default('api'), + CORS_ORIGINS: Joi.string().default('*'), + + // Redis (opcional) + REDIS_URL: Joi.string().uri().optional(), + + // SMTP (opcional) + SMTP_HOST: Joi.string().optional(), + SMTP_PORT: Joi.number().optional(), + SMTP_USER: Joi.string().optional(), + SMTP_PASSWORD: Joi.string().optional(), + + // Logging + LOG_LEVEL: Joi.string() + .valid('trace', 'debug', 'info', 'warn', 'error') + .default('info'), + LOG_FORMAT: Joi.string().valid('pretty', 'json').default('json'), +}); +``` + +### Configuracion Tipada + +```typescript +// src/shared/config/configuration.ts +export interface DatabaseConfig { + host: string; + port: number; + name: string; + user: string; + password: string; + ssl: boolean; +} + +export interface JwtConfig { + secret: string; + expiration: string; + refreshExpiration: string; +} + +export interface ServerConfig { + nodeEnv: string; + port: number; + apiPrefix: string; + corsOrigins: string[]; +} + +export interface AppConfig { + database: DatabaseConfig; + jwt: JwtConfig; + server: ServerConfig; + redis?: { + url: string; + }; + smtp?: { + host: string; + port: number; + user: string; + password: string; + }; + logging: { + level: string; + format: string; + }; +} + +export default (): AppConfig => ({ + database: { + host: process.env.DB_HOST, + port: parseInt(process.env.DB_PORT, 10), + name: process.env.DB_NAME, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + ssl: process.env.DB_SSL === 'true', + }, + jwt: { + secret: process.env.JWT_SECRET, + expiration: process.env.JWT_EXPIRATION, + refreshExpiration: process.env.JWT_REFRESH_EXPIRATION, + }, + server: { + nodeEnv: process.env.NODE_ENV, + port: parseInt(process.env.PORT, 10), + apiPrefix: process.env.API_PREFIX, + corsOrigins: process.env.CORS_ORIGINS?.split(',') || ['*'], + }, + redis: process.env.REDIS_URL + ? { url: process.env.REDIS_URL } + : undefined, + smtp: process.env.SMTP_HOST + ? { + host: process.env.SMTP_HOST, + port: parseInt(process.env.SMTP_PORT, 10), + user: process.env.SMTP_USER, + password: process.env.SMTP_PASSWORD, + } + : undefined, + logging: { + level: process.env.LOG_LEVEL, + format: process.env.LOG_FORMAT, + }, +}); +``` + +### Registro en AppModule + +```typescript +// src/app.module.ts +import { Module } from '@nestjs/common'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import configuration from './shared/config/configuration'; +import { configValidationSchema } from './shared/config/config.validation'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [configuration], + validationSchema: configValidationSchema, + validationOptions: { + abortEarly: true, // Fallar en primer error + }, + expandVariables: true, // Permitir ${VAR} en valores + }), + // ... otros modulos + ], +}) +export class AppModule {} +``` + +### Uso en Services + +```typescript +// src/modules/auth/services/auth.service.ts +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { JwtConfig } from '@/shared/config/configuration'; + +@Injectable() +export class AuthService { + private readonly jwtConfig: JwtConfig; + + constructor(private readonly configService: ConfigService) { + // Acceso tipado a configuracion + this.jwtConfig = this.configService.get('jwt'); + } + + async generateToken(userId: string): Promise { + return this.jwtService.sign( + { sub: userId }, + { + secret: this.jwtConfig.secret, + expiresIn: this.jwtConfig.expiration, + }, + ); + } +} +``` + +### Configuraciones Especificas + +```typescript +// src/shared/config/database.config.ts +import { registerAs } from '@nestjs/config'; +import { TypeOrmModuleOptions } from '@nestjs/typeorm'; + +export default registerAs('database', (): TypeOrmModuleOptions => ({ + type: 'postgres', + host: process.env.DB_HOST, + port: parseInt(process.env.DB_PORT, 10), + username: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + ssl: process.env.DB_SSL === 'true' + ? { rejectUnauthorized: false } + : false, + autoLoadEntities: true, + synchronize: false, // NUNCA true en produccion + logging: process.env.NODE_ENV === 'development', +})); +``` + +```typescript +// src/shared/config/jwt.config.ts +import { registerAs } from '@nestjs/config'; +import { JwtModuleOptions } from '@nestjs/jwt'; + +export default registerAs('jwt', (): JwtModuleOptions => ({ + secret: process.env.JWT_SECRET, + signOptions: { + expiresIn: process.env.JWT_EXPIRATION || '1d', + }, +})); +``` + +--- + +## 4. FRONTEND (React/Vite) + +### Variables de Entorno + +```typescript +// src/shared/config/env.ts + +// Vite expone variables con prefijo VITE_ +interface EnvConfig { + apiUrl: string; + apiTimeout: number; + environment: 'development' | 'staging' | 'production'; + enableMockApi: boolean; + sentryDsn?: string; + gaTrackingId?: string; +} + +function validateEnv(): EnvConfig { + const apiUrl = import.meta.env.VITE_API_URL; + const environment = import.meta.env.VITE_ENVIRONMENT || 'development'; + + // Validar variables requeridas + if (!apiUrl) { + throw new Error('VITE_API_URL is required'); + } + + return { + apiUrl, + apiTimeout: parseInt(import.meta.env.VITE_API_TIMEOUT || '30000', 10), + environment: environment as EnvConfig['environment'], + enableMockApi: import.meta.env.VITE_ENABLE_MOCK_API === 'true', + sentryDsn: import.meta.env.VITE_SENTRY_DSN, + gaTrackingId: import.meta.env.VITE_GA_TRACKING_ID, + }; +} + +export const env = validateEnv(); + +// Helpers +export const isDev = env.environment === 'development'; +export const isProd = env.environment === 'production'; +export const isStaging = env.environment === 'staging'; +``` + +### Constantes de Aplicacion + +```typescript +// src/shared/config/constants.ts +import { env } from './env'; + +export const APP_CONFIG = { + // API + API_URL: env.apiUrl, + API_TIMEOUT: env.apiTimeout, + + // Paginacion + DEFAULT_PAGE_SIZE: 20, + MAX_PAGE_SIZE: 100, + + // UI + TOAST_DURATION: 5000, + DEBOUNCE_DELAY: 300, + + // Storage keys + STORAGE_KEYS: { + AUTH_TOKEN: 'auth_token', + REFRESH_TOKEN: 'refresh_token', + USER_PREFERENCES: 'user_preferences', + THEME: 'theme', + }, + + // Feature flags (pueden venir de API) + FEATURES: { + DARK_MODE: true, + NOTIFICATIONS: true, + BETA_FEATURES: env.environment !== 'production', + }, +} as const; + +// Rutas +export const ROUTES = { + HOME: '/', + LOGIN: '/auth/login', + REGISTER: '/auth/register', + DASHBOARD: '/dashboard', + PROFILE: '/profile', + SETTINGS: '/settings', + USERS: '/users', + USER_DETAIL: '/users/:id', +} as const; + +// API Endpoints +export const API_ENDPOINTS = { + AUTH: { + LOGIN: '/auth/login', + REGISTER: '/auth/register', + REFRESH: '/auth/refresh', + LOGOUT: '/auth/logout', + }, + USERS: { + BASE: '/users', + BY_ID: (id: string) => `/users/${id}`, + ME: '/users/me', + }, + // ... otros endpoints +} as const; +``` + +### Uso en Componentes + +```typescript +// src/apps/web/hooks/useAuth.ts +import { APP_CONFIG } from '@/shared/config/constants'; + +export const useAuth = () => { + const login = async (credentials: LoginCredentials) => { + const response = await api.post(API_ENDPOINTS.AUTH.LOGIN, credentials); + + // Guardar token usando key centralizada + localStorage.setItem( + APP_CONFIG.STORAGE_KEYS.AUTH_TOKEN, + response.data.accessToken, + ); + }; + + return { login, /* ... */ }; +}; +``` + +--- + +## 5. DATABASE + +### Configuracion de Conexion + +```typescript +// src/shared/config/typeorm.config.ts +import { DataSource, DataSourceOptions } from 'typeorm'; +import * as dotenv from 'dotenv'; + +dotenv.config(); + +export const dataSourceOptions: DataSourceOptions = { + type: 'postgres', + host: process.env.DB_HOST, + port: parseInt(process.env.DB_PORT, 10), + username: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + ssl: process.env.DB_SSL === 'true' + ? { rejectUnauthorized: false } + : false, + + // Entities + entities: ['dist/**/*.entity.js'], + + // Migrations + migrations: ['dist/migrations/*.js'], + migrationsTableName: 'migrations', + + // Logging + logging: process.env.DB_LOGGING === 'true', + maxQueryExecutionTime: 1000, // Log queries > 1s + + // Pool + extra: { + max: parseInt(process.env.DB_POOL_SIZE || '10', 10), + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 10000, + }, +}; + +// Para CLI de TypeORM +export default new DataSource(dataSourceOptions); +``` + +--- + +## 6. PATRON POR AMBIENTE + +### Configuracion Condicional + +```typescript +// src/shared/config/by-environment.ts +type Environment = 'development' | 'staging' | 'production' | 'test'; + +interface EnvironmentConfig { + api: { + rateLimit: number; + timeout: number; + }; + cache: { + ttl: number; + enabled: boolean; + }; + features: { + debugMode: boolean; + mockExternalApis: boolean; + }; +} + +const configs: Record = { + development: { + api: { + rateLimit: 1000, // Muy alto para desarrollo + timeout: 60000, + }, + cache: { + ttl: 60, + enabled: false, // Deshabilitado para desarrollo + }, + features: { + debugMode: true, + mockExternalApis: true, + }, + }, + staging: { + api: { + rateLimit: 100, + timeout: 30000, + }, + cache: { + ttl: 300, + enabled: true, + }, + features: { + debugMode: true, + mockExternalApis: false, + }, + }, + production: { + api: { + rateLimit: 60, + timeout: 15000, + }, + cache: { + ttl: 3600, + enabled: true, + }, + features: { + debugMode: false, + mockExternalApis: false, + }, + }, + test: { + api: { + rateLimit: 10000, + timeout: 5000, + }, + cache: { + ttl: 0, + enabled: false, + }, + features: { + debugMode: true, + mockExternalApis: true, + }, + }, +}; + +export function getEnvironmentConfig(): EnvironmentConfig { + const env = (process.env.NODE_ENV || 'development') as Environment; + return configs[env]; +} +``` + +--- + +## 7. SECRETOS Y SEGURIDAD + +### Nunca en Codigo + +```typescript +// ❌ INCORRECTO: Secretos hardcodeados +const JWT_SECRET = 'my-super-secret-key-12345'; +const DB_PASSWORD = 'password123'; + +// βœ… CORRECTO: Desde variables de entorno +const JWT_SECRET = process.env.JWT_SECRET; +const DB_PASSWORD = process.env.DB_PASSWORD; +``` + +### Validar Secretos Requeridos + +```typescript +// src/shared/config/secrets.validation.ts +const REQUIRED_SECRETS = [ + 'JWT_SECRET', + 'DB_PASSWORD', +]; + +const OPTIONAL_SECRETS = [ + 'SMTP_PASSWORD', + 'STRIPE_SECRET_KEY', +]; + +export function validateSecrets(): void { + const missing: string[] = []; + + for (const secret of REQUIRED_SECRETS) { + if (!process.env[secret]) { + missing.push(secret); + } + } + + if (missing.length > 0) { + throw new Error( + `Missing required secrets: ${missing.join(', ')}\n` + + 'Please check your .env file or environment variables.', + ); + } + + // Validar formato de secretos + if (process.env.JWT_SECRET && process.env.JWT_SECRET.length < 32) { + throw new Error('JWT_SECRET must be at least 32 characters'); + } +} +``` + +### Rotacion de Secretos + +```typescript +// Soportar multiples secretos para rotacion +const JWT_SECRETS = (process.env.JWT_SECRETS || process.env.JWT_SECRET).split(','); + +// Verificar token con cualquier secreto valido +async function verifyToken(token: string): Promise { + for (const secret of JWT_SECRETS) { + try { + return jwt.verify(token, secret.trim()) as TokenPayload; + } catch { + continue; // Probar siguiente secreto + } + } + throw new UnauthorizedException('Invalid token'); +} + +// Firmar siempre con el primer secreto (mas reciente) +function signToken(payload: TokenPayload): string { + return jwt.sign(payload, JWT_SECRETS[0].trim()); +} +``` + +--- + +## 8. CHECKLIST DE CONFIGURACION + +``` +Setup inicial: +[ ] .env.example creado con TODAS las variables +[ ] .env en .gitignore +[ ] Schema de validacion implementado +[ ] App falla si configuracion invalida +[ ] Tipos definidos para configuracion + +Seguridad: +[ ] Ningun secreto en codigo fuente +[ ] Ningun secreto en logs +[ ] Secretos rotables (multiples valores soportados) +[ ] Variables sensibles marcadas en documentacion + +Por ambiente: +[ ] Configuracion diferenciada por ambiente +[ ] Defaults seguros para produccion +[ ] Modo debug deshabilitado en produccion +[ ] Rate limiting apropiado por ambiente + +Documentacion: +[ ] Cada variable documentada en .env.example +[ ] README explica como configurar +[ ] Variables opcionales vs requeridas claras +``` + +--- + +## 9. ANTI-PATRONES + +```typescript +// ❌ ANTI-PATRON 1: Configuracion dispersa +// archivo1.ts +const API_URL = 'http://api.com'; +// archivo2.ts +const apiUrl = process.env.API_URL || 'http://api.com'; + +// βœ… CORRECTO: Centralizado +// config/constants.ts +export const API_URL = process.env.API_URL; +``` + +```typescript +// ❌ ANTI-PATRON 2: No validar +const port = process.env.PORT; // Puede ser undefined o string invalido +server.listen(port); // Error en runtime + +// βœ… CORRECTO: Validar y convertir +const port = parseInt(process.env.PORT, 10); +if (isNaN(port)) { + throw new Error('PORT must be a valid number'); +} +``` + +```typescript +// ❌ ANTI-PATRON 3: Defaults inseguros +const DEBUG = process.env.DEBUG || true; // Debug activo por default + +// βœ… CORRECTO: Defaults seguros +const DEBUG = process.env.DEBUG === 'true'; // False por default +``` + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Patron de Codigo diff --git a/core/orchestration/patrones/PATRON-EXCEPTION-HANDLING.md b/core/orchestration/patrones/PATRON-EXCEPTION-HANDLING.md new file mode 100644 index 0000000..9ed9cee --- /dev/null +++ b/core/orchestration/patrones/PATRON-EXCEPTION-HANDLING.md @@ -0,0 +1,534 @@ +# PATRΓ“N: MANEJO DE EXCEPCIONES + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Aplica a:** Backend (NestJS/Express) +**Prioridad:** OBLIGATORIA + +--- + +## PROPΓ“SITO + +Definir patrones estΓ‘ndar de manejo de errores para garantizar respuestas consistentes y debugging efectivo. + +--- + +## PRINCIPIO FUNDAMENTAL + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ EXCEPCIONES CLARAS Y CONSISTENTES β•‘ +β•‘ β•‘ +β•‘ 1. Usar HttpException estΓ‘ndar de NestJS β•‘ +β•‘ 2. Mensajes claros para el usuario β•‘ +β•‘ 3. Detalles tΓ©cnicos en logs (no en response) β•‘ +β•‘ 4. CΓ³digos HTTP semΓ‘nticos β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 1. EXCEPCIONES HTTP ESTÁNDAR + +### Matriz de DecisiΓ³n + +| SituaciΓ³n | Exception | HTTP Code | CuΓ‘ndo Usar | +|-----------|-----------|-----------|-------------| +| Recurso no existe | `NotFoundException` | 404 | `findOne` retorna null | +| Ya existe (duplicado) | `ConflictException` | 409 | ViolaciΓ³n de unique | +| Datos invΓ‘lidos | `BadRequestException` | 400 | ValidaciΓ³n de negocio falla | +| Sin autenticaciΓ³n | `UnauthorizedException` | 401 | Token falta o invΓ‘lido | +| Sin permiso | `ForbiddenException` | 403 | Autenticado pero sin permiso | +| MΓ©todo no permitido | `MethodNotAllowedException` | 405 | HTTP method incorrecto | +| Payload muy grande | `PayloadTooLargeException` | 413 | Archivo/body excede lΓ­mite | +| Rate limit | `TooManyRequestsException` | 429 | Muchas peticiones | +| Error interno | `InternalServerErrorException` | 500 | Error inesperado | +| Servicio no disponible | `ServiceUnavailableException` | 503 | DB/API externa caΓ­da | + +--- + +## 2. PATRONES POR CASO + +### Not Found (404) + +```typescript +// PATRΓ“N: Recurso no encontrado +async findOne(id: string): Promise { + const user = await this.repository.findOne({ where: { id } }); + + if (!user) { + throw new NotFoundException(`Usuario con ID ${id} no encontrado`); + } + + return user; +} + +// PATRΓ“N: Recurso relacionado no encontrado +async assignRole(userId: string, roleId: string): Promise { + const user = await this.userRepository.findOne({ where: { id: userId } }); + if (!user) { + throw new NotFoundException(`Usuario ${userId} no encontrado`); + } + + const role = await this.roleRepository.findOne({ where: { id: roleId } }); + if (!role) { + throw new NotFoundException(`Rol ${roleId} no encontrado`); + } + + // Proceder... +} +``` + +### Conflict (409) + +```typescript +// PATRΓ“N: Duplicado por campo ΓΊnico +async create(dto: CreateUserDto): Promise { + const existing = await this.repository.findOne({ + where: { email: dto.email }, + }); + + if (existing) { + throw new ConflictException('El email ya estΓ‘ registrado'); + } + + return this.repository.save(this.repository.create(dto)); +} + +// PATRΓ“N: Duplicado con mΓΊltiples campos +async createProduct(dto: CreateProductDto): Promise { + const existing = await this.repository.findOne({ + where: { + sku: dto.sku, + tenantId: dto.tenantId, + }, + }); + + if (existing) { + throw new ConflictException( + `Ya existe un producto con SKU ${dto.sku} en este tenant` + ); + } + + return this.repository.save(this.repository.create(dto)); +} +``` + +### Bad Request (400) + +```typescript +// PATRΓ“N: ValidaciΓ³n de negocio +async transfer(dto: TransferDto): Promise { + if (dto.fromAccountId === dto.toAccountId) { + throw new BadRequestException( + 'La cuenta origen y destino no pueden ser iguales' + ); + } + + const fromAccount = await this.findAccount(dto.fromAccountId); + + if (fromAccount.balance < dto.amount) { + throw new BadRequestException('Saldo insuficiente para la transferencia'); + } + + // Proceder... +} + +// PATRΓ“N: Estado invΓ‘lido para operaciΓ³n +async cancelOrder(orderId: string): Promise { + const order = await this.findOne(orderId); + + if (order.status === 'delivered') { + throw new BadRequestException( + 'No se puede cancelar un pedido ya entregado' + ); + } + + if (order.status === 'cancelled') { + throw new BadRequestException('El pedido ya estΓ‘ cancelado'); + } + + // Proceder... +} +``` + +### Forbidden (403) + +```typescript +// PATRΓ“N: Sin permiso sobre recurso +async update(userId: string, dto: UpdateUserDto, currentUser: User): Promise { + const user = await this.findOne(userId); + + // Solo el usuario mismo o admin puede editar + if (user.id !== currentUser.id && !currentUser.roles.includes('admin')) { + throw new ForbiddenException('No tienes permiso para editar este usuario'); + } + + return this.repository.save({ ...user, ...dto }); +} + +// PATRΓ“N: LΓ­mite de plan/tenant +async createProject(dto: CreateProjectDto, tenant: Tenant): Promise { + const projectCount = await this.repository.count({ + where: { tenantId: tenant.id }, + }); + + if (projectCount >= tenant.plan.maxProjects) { + throw new ForbiddenException( + `Tu plan permite mΓ‘ximo ${tenant.plan.maxProjects} proyectos. ` + + 'Actualiza tu plan para crear mΓ‘s.' + ); + } + + // Proceder... +} +``` + +### Unauthorized (401) + +```typescript +// PATRΓ“N: Token invΓ‘lido (en Guard) +@Injectable() +export class JwtAuthGuard extends AuthGuard('jwt') { + handleRequest(err: any, user: any, info: any) { + if (err || !user) { + if (info?.name === 'TokenExpiredError') { + throw new UnauthorizedException('Tu sesiΓ³n ha expirado'); + } + if (info?.name === 'JsonWebTokenError') { + throw new UnauthorizedException('Token invΓ‘lido'); + } + throw new UnauthorizedException('No autenticado'); + } + return user; + } +} + +// PATRΓ“N: Credenciales incorrectas +async login(dto: LoginDto): Promise { + const user = await this.userRepository.findOne({ + where: { email: dto.email }, + }); + + if (!user || !(await bcrypt.compare(dto.password, user.password))) { + throw new UnauthorizedException('Credenciales incorrectas'); + } + + // Generar token... +} +``` + +### Internal Server Error (500) + +```typescript +// PATRΓ“N: Error inesperado con logging +async processPayment(dto: PaymentDto): Promise { + try { + const result = await this.paymentGateway.charge(dto); + return result; + } catch (error) { + // Log detallado para debugging + this.logger.error('Error procesando pago', { + dto, + error: error.message, + stack: error.stack, + gatewayResponse: error.response?.data, + }); + + // Respuesta genΓ©rica al usuario + throw new InternalServerErrorException( + 'Error procesando el pago. Por favor intenta de nuevo.' + ); + } +} +``` + +--- + +## 3. ESTRUCTURA DE RESPUESTA DE ERROR + +### Formato EstΓ‘ndar + +```typescript +// Respuesta de error estΓ‘ndar +interface ErrorResponse { + statusCode: number; + message: string | string[]; + error: string; + timestamp: string; + path: string; +} + +// Ejemplo de respuesta +{ + "statusCode": 404, + "message": "Usuario con ID abc-123 no encontrado", + "error": "Not Found", + "timestamp": "2024-01-15T10:30:00.000Z", + "path": "/api/v1/users/abc-123" +} +``` + +### Exception Filter Global + +```typescript +// filters/http-exception.filter.ts +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpException, + HttpStatus, + Logger, +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +@Catch() +export class GlobalExceptionFilter implements ExceptionFilter { + private readonly logger = new Logger(GlobalExceptionFilter.name); + + catch(exception: unknown, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + + let status = HttpStatus.INTERNAL_SERVER_ERROR; + let message: string | string[] = 'Error interno del servidor'; + let error = 'Internal Server Error'; + + if (exception instanceof HttpException) { + status = exception.getStatus(); + const exceptionResponse = exception.getResponse(); + + if (typeof exceptionResponse === 'object') { + message = (exceptionResponse as any).message || exception.message; + error = (exceptionResponse as any).error || exception.name; + } else { + message = exceptionResponse; + } + } else if (exception instanceof Error) { + // Log error interno completo + this.logger.error('Unhandled exception', { + message: exception.message, + stack: exception.stack, + path: request.url, + method: request.method, + body: request.body, + user: (request as any).user?.id, + }); + } + + response.status(status).json({ + statusCode: status, + message, + error, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} +``` + +--- + +## 4. EXCEPCIONES PERSONALIZADAS + +### CuΓ‘ndo Crear ExcepciΓ³n Custom + +```typescript +// CREAR excepciΓ³n custom cuando: +// 1. Necesitas informaciΓ³n adicional estructurada +// 2. El error es especΓ­fico del dominio +// 3. Quieres diferenciar en handling + +// NO crear custom para errores HTTP estΓ‘ndar +// ❌ class UserNotFoundException extends HttpException {} // Usar NotFoundException +``` + +### Ejemplo ExcepciΓ³n Custom + +```typescript +// exceptions/business.exception.ts +export class InsufficientBalanceException extends BadRequestException { + constructor( + public readonly currentBalance: number, + public readonly requiredAmount: number, + ) { + super({ + message: `Saldo insuficiente. Tienes $${currentBalance}, necesitas $${requiredAmount}`, + error: 'Insufficient Balance', + currentBalance, + requiredAmount, + deficit: requiredAmount - currentBalance, + }); + } +} + +// Uso +if (account.balance < amount) { + throw new InsufficientBalanceException(account.balance, amount); +} +``` + +### ExcepciΓ³n para Errores de IntegraciΓ³n + +```typescript +// exceptions/integration.exception.ts +export class PaymentGatewayException extends ServiceUnavailableException { + constructor( + public readonly gateway: string, + public readonly originalError: string, + ) { + super({ + message: 'Error de conexiΓ³n con el servicio de pagos', + error: 'Payment Gateway Error', + gateway, + }); + } +} + +// Uso +try { + await stripe.charges.create(params); +} catch (error) { + throw new PaymentGatewayException('Stripe', error.message); +} +``` + +--- + +## 5. LOGGING DE ERRORES + +### Niveles de Log + +```typescript +// logger.service.ts +@Injectable() +export class AppLogger { + private readonly logger = new Logger(); + + // ERROR: Errores que requieren atenciΓ³n + error(message: string, context: object) { + this.logger.error(message, { ...context, timestamp: new Date() }); + } + + // WARN: Situaciones anΓ³malas pero manejadas + warn(message: string, context: object) { + this.logger.warn(message, { ...context, timestamp: new Date() }); + } + + // INFO: Eventos importantes del negocio + info(message: string, context: object) { + this.logger.log(message, { ...context, timestamp: new Date() }); + } + + // DEBUG: InformaciΓ³n para desarrollo + debug(message: string, context: object) { + this.logger.debug(message, { ...context, timestamp: new Date() }); + } +} +``` + +### QuΓ© Loggear + +```typescript +// SIEMPRE loggear en ERROR: +{ + message: 'DescripciΓ³n del error', + stack: error.stack, // Stack trace + userId: currentUser?.id, // QuiΓ©n causΓ³ el error + tenantId: currentUser?.tenant, // Contexto de tenant + requestId: request.id, // Para tracing + path: request.url, // Endpoint + method: request.method, // HTTP method + body: sanitize(request.body), // Body (sin passwords) + query: request.query, // Query params + timestamp: new Date(), // CuΓ‘ndo +} + +// NUNCA loggear: +// - Passwords +// - Tokens +// - Tarjetas de crΓ©dito +// - Datos sensibles (CURP, RFC, etc.) +``` + +--- + +## 6. DOCUMENTACIΓ“N SWAGGER + +```typescript +// Documentar posibles errores en controller +@Post() +@ApiOperation({ summary: 'Crear usuario' }) +@ApiResponse({ status: 201, description: 'Usuario creado', type: UserEntity }) +@ApiResponse({ status: 400, description: 'Datos invΓ‘lidos' }) +@ApiResponse({ status: 409, description: 'Email ya registrado' }) +@ApiResponse({ status: 401, description: 'No autenticado' }) +@ApiResponse({ status: 403, description: 'Sin permisos' }) +async create(@Body() dto: CreateUserDto): Promise { + return this.service.create(dto); +} +``` + +--- + +## 7. CHECKLIST DE MANEJO DE ERRORES + +``` +Service: +[ ] Cada mΓ©todo que busca por ID usa NotFoundException si no existe +[ ] Operaciones de creaciΓ³n verifican duplicados β†’ ConflictException +[ ] Validaciones de negocio usan BadRequestException +[ ] Verificaciones de permisos usan ForbiddenException +[ ] Errores de integraciones externas tienen try/catch +[ ] Errores inesperados se loggean con contexto completo +[ ] Mensajes de error son claros para el usuario + +Controller: +[ ] Swagger documenta posibles errores +[ ] @ApiResponse para cada cΓ³digo de error posible + +Global: +[ ] GlobalExceptionFilter configurado +[ ] Logger configurado para errores +[ ] Errores no exponen detalles tΓ©cnicos en producciΓ³n +``` + +--- + +## ANTI-PATRONES + +```typescript +// ❌ NUNCA: Mensaje genΓ©rico sin contexto +throw new BadRequestException('Error'); + +// βœ… SIEMPRE: Mensaje descriptivo +throw new BadRequestException('El email ya estΓ‘ registrado'); + +// ❌ NUNCA: Exponer stack trace en response +throw new Error(error.stack); + +// βœ… SIEMPRE: Log interno, mensaje limpio al usuario +this.logger.error('Error detallado', { stack: error.stack }); +throw new InternalServerErrorException('Error procesando solicitud'); + +// ❌ NUNCA: Catch vacΓ­o +try { ... } catch (e) { } + +// βœ… SIEMPRE: Manejar o re-lanzar +try { ... } catch (e) { + this.logger.error('Context', { error: e }); + throw new InternalServerErrorException('Mensaje usuario'); +} + +// ❌ NUNCA: 500 para errores de validaciΓ³n +throw new InternalServerErrorException('Email invΓ‘lido'); + +// βœ… SIEMPRE: CΓ³digo HTTP semΓ‘ntico +throw new BadRequestException('Email invΓ‘lido'); +``` + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** PatrΓ³n de Excepciones diff --git a/core/orchestration/patrones/PATRON-LOGGING.md b/core/orchestration/patrones/PATRON-LOGGING.md new file mode 100644 index 0000000..d5fc9c5 --- /dev/null +++ b/core/orchestration/patrones/PATRON-LOGGING.md @@ -0,0 +1,663 @@ +# PATRON DE LOGGING + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** RECOMENDADA - Seguir para consistencia +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Definir patrones estandarizados de logging para todas las capas del sistema, asegurando trazabilidad, debugging efectivo y monitoreo en produccion. + +--- + +## 1. NIVELES DE LOG + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ NIVELES DE LOG (de menor a mayor severidad) β•‘ +╠══════════════════════════════════════════════════════════════════════╣ +β•‘ β•‘ +β•‘ TRACE β†’ Detalle extremo (solo desarrollo) β•‘ +β•‘ DEBUG β†’ Informacion de debugging β•‘ +β•‘ INFO β†’ Eventos normales del sistema β•‘ +β•‘ WARN β†’ Situaciones anormales pero manejables β•‘ +β•‘ ERROR β†’ Errores que afectan funcionalidad β•‘ +β•‘ FATAL β†’ Errores criticos que detienen el sistema β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +### Cuando Usar Cada Nivel + +| Nivel | Uso | Ejemplo | +|-------|-----|---------| +| **TRACE** | Flujo detallado de ejecucion | `Entering method findById with id=123` | +| **DEBUG** | Variables, estados internos | `User cache hit: userId=123` | +| **INFO** | Eventos de negocio normales | `Order created: orderId=456` | +| **WARN** | Situaciones inesperadas no criticas | `Retry attempt 2/3 for external API` | +| **ERROR** | Errores que necesitan atencion | `Failed to process payment: timeout` | +| **FATAL** | Sistema no puede continuar | `Database connection lost` | + +--- + +## 2. ESTRUCTURA DE LOG + +### Formato Estandar + +```typescript +{ + timestamp: "2025-12-08T10:30:45.123Z", // ISO 8601 + level: "INFO", // Nivel + context: "UserService", // Clase/modulo origen + message: "User created successfully", // Mensaje descriptivo + correlationId: "req-abc123", // ID de request/transaccion + userId: "user-456", // Usuario (si aplica) + data: { // Datos adicionales + email: "user@example.com", + action: "create" + }, + duration: 45 // Duracion en ms (si aplica) +} +``` + +### Campos Obligatorios + +| Campo | Descripcion | Siempre | +|-------|-------------|---------| +| `timestamp` | Fecha/hora ISO 8601 | SI | +| `level` | Nivel del log | SI | +| `context` | Origen del log | SI | +| `message` | Descripcion del evento | SI | +| `correlationId` | ID para trazar request | EN PRODUCCION | + +### Campos Opcionales Recomendados + +| Campo | Cuando Usar | +|-------|-------------| +| `userId` | Cuando hay usuario autenticado | +| `data` | Datos relevantes al evento | +| `duration` | Para operaciones medibles | +| `error` | Cuando es log de error | +| `stack` | Stack trace en errores | + +--- + +## 3. BACKEND (NestJS) + +### Configuracion del Logger + +```typescript +// src/shared/logger/logger.service.ts +import { Injectable, LoggerService, Scope } from '@nestjs/common'; +import { Logger } from 'winston'; + +@Injectable({ scope: Scope.TRANSIENT }) +export class AppLogger implements LoggerService { + private context: string; + private correlationId: string; + + constructor(private readonly logger: Logger) {} + + setContext(context: string) { + this.context = context; + } + + setCorrelationId(correlationId: string) { + this.correlationId = correlationId; + } + + log(message: string, data?: Record) { + this.logger.info(message, { + context: this.context, + correlationId: this.correlationId, + ...data, + }); + } + + error(message: string, trace?: string, data?: Record) { + this.logger.error(message, { + context: this.context, + correlationId: this.correlationId, + stack: trace, + ...data, + }); + } + + warn(message: string, data?: Record) { + this.logger.warn(message, { + context: this.context, + correlationId: this.correlationId, + ...data, + }); + } + + debug(message: string, data?: Record) { + this.logger.debug(message, { + context: this.context, + correlationId: this.correlationId, + ...data, + }); + } +} +``` + +### Configuracion Winston + +```typescript +// src/shared/logger/winston.config.ts +import * as winston from 'winston'; + +const { combine, timestamp, json, printf, colorize } = winston.format; + +// Formato para desarrollo +const devFormat = combine( + colorize(), + timestamp(), + printf(({ timestamp, level, message, context, ...meta }) => { + return `${timestamp} [${context}] ${level}: ${message} ${ + Object.keys(meta).length ? JSON.stringify(meta) : '' + }`; + }), +); + +// Formato para produccion (JSON estructurado) +const prodFormat = combine( + timestamp(), + json(), +); + +export const winstonConfig: winston.LoggerOptions = { + level: process.env.LOG_LEVEL || 'info', + format: process.env.NODE_ENV === 'production' ? prodFormat : devFormat, + transports: [ + new winston.transports.Console(), + // En produccion: agregar transports adicionales + // new winston.transports.File({ filename: 'error.log', level: 'error' }), + ], +}; +``` + +### Uso en Service + +```typescript +// src/modules/user/services/user.service.ts +@Injectable() +export class UserService { + constructor( + private readonly logger: AppLogger, + private readonly repository: Repository, + ) { + this.logger.setContext(UserService.name); + } + + async create(dto: CreateUserDto): Promise { + this.logger.log('Creating new user', { email: dto.email }); + + try { + const user = await this.repository.save(dto); + + this.logger.log('User created successfully', { + userId: user.id, + email: user.email, + }); + + return user; + } catch (error) { + this.logger.error('Failed to create user', error.stack, { + email: dto.email, + errorCode: error.code, + }); + throw error; + } + } + + async findById(id: string): Promise { + this.logger.debug('Finding user by ID', { userId: id }); + + const startTime = Date.now(); + const user = await this.repository.findOne({ where: { id } }); + const duration = Date.now() - startTime; + + if (!user) { + this.logger.warn('User not found', { userId: id, duration }); + throw new NotFoundException(`User ${id} not found`); + } + + this.logger.debug('User found', { userId: id, duration }); + return user; + } +} +``` + +### Interceptor para Correlation ID + +```typescript +// src/shared/interceptors/correlation.interceptor.ts +import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { v4 as uuidv4 } from 'uuid'; + +@Injectable() +export class CorrelationInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + const request = context.switchToHttp().getRequest(); + + // Usar header existente o generar nuevo + const correlationId = request.headers['x-correlation-id'] || uuidv4(); + + // Guardar en request para uso posterior + request.correlationId = correlationId; + + // Agregar a response headers + const response = context.switchToHttp().getResponse(); + response.setHeader('x-correlation-id', correlationId); + + return next.handle(); + } +} +``` + +### Interceptor de Logging de Requests + +```typescript +// src/shared/interceptors/logging.interceptor.ts +import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Injectable() +export class LoggingInterceptor implements NestInterceptor { + constructor(private readonly logger: AppLogger) { + this.logger.setContext('HTTP'); + } + + intercept(context: ExecutionContext, next: CallHandler): Observable { + const request = context.switchToHttp().getRequest(); + const { method, url, correlationId, user } = request; + const startTime = Date.now(); + + this.logger.log('Incoming request', { + method, + url, + correlationId, + userId: user?.id, + }); + + return next.handle().pipe( + tap({ + next: () => { + const duration = Date.now() - startTime; + this.logger.log('Request completed', { + method, + url, + correlationId, + duration, + statusCode: context.switchToHttp().getResponse().statusCode, + }); + }, + error: (error) => { + const duration = Date.now() - startTime; + this.logger.error('Request failed', error.stack, { + method, + url, + correlationId, + duration, + errorMessage: error.message, + }); + }, + }), + ); + } +} +``` + +--- + +## 4. FRONTEND (React) + +### Logger Service + +```typescript +// src/shared/services/logger.service.ts +type LogLevel = 'debug' | 'info' | 'warn' | 'error'; + +interface LogEntry { + timestamp: string; + level: LogLevel; + message: string; + context?: string; + data?: Record; + userId?: string; +} + +class LoggerService { + private isDev = process.env.NODE_ENV === 'development'; + private userId: string | null = null; + + setUserId(userId: string | null) { + this.userId = userId; + } + + private log(level: LogLevel, message: string, context?: string, data?: Record) { + const entry: LogEntry = { + timestamp: new Date().toISOString(), + level, + message, + context, + data, + userId: this.userId || undefined, + }; + + // En desarrollo: console + if (this.isDev) { + const consoleMethod = level === 'error' ? console.error : + level === 'warn' ? console.warn : + level === 'debug' ? console.debug : console.log; + consoleMethod(`[${entry.context}] ${message}`, data || ''); + } + + // En produccion: enviar a servicio de logging + if (!this.isDev && (level === 'error' || level === 'warn')) { + this.sendToServer(entry); + } + } + + private async sendToServer(entry: LogEntry) { + try { + await fetch('/api/logs', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(entry), + }); + } catch { + // Silently fail - don't cause more errors + } + } + + debug(message: string, context?: string, data?: Record) { + this.log('debug', message, context, data); + } + + info(message: string, context?: string, data?: Record) { + this.log('info', message, context, data); + } + + warn(message: string, context?: string, data?: Record) { + this.log('warn', message, context, data); + } + + error(message: string, context?: string, data?: Record) { + this.log('error', message, context, data); + } +} + +export const logger = new LoggerService(); +``` + +### Uso en Componentes + +```typescript +// src/apps/web/pages/UsersPage.tsx +import { logger } from '@/shared/services/logger.service'; + +export const UsersPage = () => { + const { data, error, isLoading } = useUsers(); + + useEffect(() => { + logger.info('Users page mounted', 'UsersPage'); + }, []); + + useEffect(() => { + if (error) { + logger.error('Failed to load users', 'UsersPage', { + errorMessage: error.message, + }); + } + }, [error]); + + const handleDelete = async (userId: string) => { + logger.info('Deleting user', 'UsersPage', { userId }); + + try { + await deleteUser(userId); + logger.info('User deleted successfully', 'UsersPage', { userId }); + } catch (err) { + logger.error('Failed to delete user', 'UsersPage', { + userId, + error: err.message, + }); + } + }; + + return (/* ... */); +}; +``` + +### Error Boundary con Logging + +```typescript +// src/shared/components/ErrorBoundary.tsx +import { Component, ErrorInfo, ReactNode } from 'react'; +import { logger } from '@/shared/services/logger.service'; + +interface Props { + children: ReactNode; + fallback?: ReactNode; +} + +interface State { + hasError: boolean; +} + +export class ErrorBoundary extends Component { + state = { hasError: false }; + + static getDerivedStateFromError(): State { + return { hasError: true }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo) { + logger.error('React error boundary caught error', 'ErrorBoundary', { + error: error.message, + stack: error.stack, + componentStack: errorInfo.componentStack, + }); + } + + render() { + if (this.state.hasError) { + return this.props.fallback ||
Something went wrong
; + } + return this.props.children; + } +} +``` + +--- + +## 5. DATABASE + +### Logging de Queries (TypeORM) + +```typescript +// src/shared/config/typeorm.config.ts +import { TypeOrmModuleOptions } from '@nestjs/typeorm'; + +export const typeOrmConfig: TypeOrmModuleOptions = { + // ... otras opciones + logging: process.env.NODE_ENV === 'development' + ? ['query', 'error', 'warn'] + : ['error'], + logger: 'advanced-console', // o custom logger + maxQueryExecutionTime: 1000, // Log queries > 1s +}; +``` + +### Custom Query Logger + +```typescript +// src/shared/logger/typeorm.logger.ts +import { Logger as TypeOrmLogger } from 'typeorm'; +import { AppLogger } from './logger.service'; + +export class CustomTypeOrmLogger implements TypeOrmLogger { + constructor(private readonly logger: AppLogger) { + this.logger.setContext('TypeORM'); + } + + logQuery(query: string, parameters?: any[]) { + this.logger.debug('Query executed', { + query: query.substring(0, 500), // Truncar queries largas + parameters, + }); + } + + logQueryError(error: string, query: string, parameters?: any[]) { + this.logger.error('Query failed', undefined, { + error, + query: query.substring(0, 500), + parameters, + }); + } + + logQuerySlow(time: number, query: string, parameters?: any[]) { + this.logger.warn('Slow query detected', { + duration: time, + query: query.substring(0, 500), + parameters, + }); + } + + logSchemaBuild(message: string) { + this.logger.info(message); + } + + logMigration(message: string) { + this.logger.info(message); + } + + log(level: 'log' | 'info' | 'warn', message: any) { + if (level === 'warn') { + this.logger.warn(message); + } else { + this.logger.log(message); + } + } +} +``` + +--- + +## 6. QUE LOGUEAR Y QUE NO + +### SI Loguear + +``` +βœ… Inicio/fin de operaciones importantes +βœ… Errores y excepciones (con contexto) +βœ… Eventos de autenticacion (login, logout, failed attempts) +βœ… Operaciones de negocio criticas (pagos, cambios de estado) +βœ… Llamadas a APIs externas (request/response resumido) +βœ… Queries lentas (>1s) +βœ… Warnings de recursos (memoria, conexiones) +βœ… Cambios de configuracion en runtime +``` + +### NO Loguear + +``` +❌ Datos sensibles (passwords, tokens, tarjetas) +❌ PII sin necesidad (emails completos, nombres) +❌ Cada iteracion de loops +❌ Contenido completo de requests/responses grandes +❌ Logs de debug en produccion +❌ Informacion redundante +❌ Stack traces en logs INFO/DEBUG +``` + +### Sanitizacion de Datos Sensibles + +```typescript +// src/shared/utils/log-sanitizer.ts +const SENSITIVE_FIELDS = ['password', 'token', 'secret', 'authorization', 'credit_card']; + +export function sanitizeForLogging(data: Record): Record { + const sanitized = { ...data }; + + for (const key of Object.keys(sanitized)) { + if (SENSITIVE_FIELDS.some(field => key.toLowerCase().includes(field))) { + sanitized[key] = '[REDACTED]'; + } else if (typeof sanitized[key] === 'object' && sanitized[key] !== null) { + sanitized[key] = sanitizeForLogging(sanitized[key]); + } + } + + return sanitized; +} + +// Uso +this.logger.log('User login attempt', sanitizeForLogging({ + email: dto.email, + password: dto.password, // Se convierte en [REDACTED] +})); +``` + +--- + +## 7. CONFIGURACION POR AMBIENTE + +```typescript +// src/shared/config/logger.config.ts +export const loggerConfig = { + development: { + level: 'debug', + format: 'pretty', + includeTimestamp: true, + colorize: true, + }, + staging: { + level: 'info', + format: 'json', + includeTimestamp: true, + colorize: false, + }, + production: { + level: 'warn', + format: 'json', + includeTimestamp: true, + colorize: false, + // Enviar a servicio externo + externalService: { + enabled: true, + endpoint: process.env.LOG_ENDPOINT, + }, + }, +}; +``` + +--- + +## 8. CHECKLIST DE LOGGING + +``` +Antes de hacer deploy: +[ ] Logs no contienen datos sensibles +[ ] Nivel de log apropiado para ambiente +[ ] Errores tienen contexto suficiente para debug +[ ] Correlation ID implementado +[ ] Queries lentas se detectan +[ ] Error boundary implementado en frontend + +En cada Service nuevo: +[ ] Logger inyectado y contexto configurado +[ ] Operaciones principales logueadas +[ ] Errores logueados con stack trace +[ ] Tiempos de operaciones criticas medidos +``` + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Patron de Codigo diff --git a/core/orchestration/patrones/PATRON-PERFORMANCE.md b/core/orchestration/patrones/PATRON-PERFORMANCE.md new file mode 100644 index 0000000..4ed84f4 --- /dev/null +++ b/core/orchestration/patrones/PATRON-PERFORMANCE.md @@ -0,0 +1,657 @@ +# PATRON DE PERFORMANCE + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** RECOMENDADA - Seguir para optimizacion +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Definir patrones de optimizacion de rendimiento para todas las capas del sistema, asegurando tiempos de respuesta aceptables y uso eficiente de recursos. + +--- + +## 1. METRICAS OBJETIVO + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ OBJETIVOS DE PERFORMANCE β•‘ +╠══════════════════════════════════════════════════════════════════════╣ +β•‘ β•‘ +β•‘ API Response Time: β•‘ +β•‘ β€’ P50: < 100ms β•‘ +β•‘ β€’ P95: < 500ms β•‘ +β•‘ β€’ P99: < 1000ms β•‘ +β•‘ β•‘ +β•‘ Database Queries: β•‘ +β•‘ β€’ Simple query: < 10ms β•‘ +β•‘ β€’ Complex query: < 100ms β•‘ +β•‘ β€’ Report query: < 1000ms β•‘ +β•‘ β•‘ +β•‘ Frontend: β•‘ +β•‘ β€’ First Contentful Paint: < 1.5s β•‘ +β•‘ β€’ Time to Interactive: < 3s β•‘ +β•‘ β€’ Largest Contentful Paint: < 2.5s β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 2. DATABASE PERFORMANCE + +### 2.1 Indices Efectivos + +```sql +-- Indices para columnas frecuentemente filtradas +CREATE INDEX idx_users_email ON auth.users(email); +CREATE INDEX idx_users_status ON auth.users(status); + +-- Indice compuesto para queries frecuentes +CREATE INDEX idx_orders_user_created +ON core.orders(user_id, created_at DESC); + +-- Indice parcial para datos activos +CREATE INDEX idx_users_active +ON auth.users(email) +WHERE status = 'active'; + +-- Indice para busqueda de texto +CREATE INDEX idx_products_name_gin +ON core.products USING gin(to_tsvector('spanish', name)); +``` + +### 2.2 Analisis de Queries + +```sql +-- Ver plan de ejecucion +EXPLAIN ANALYZE +SELECT * FROM orders +WHERE user_id = 'uuid-123' + AND created_at > NOW() - INTERVAL '30 days'; + +-- Identificar queries lentas +SELECT query, calls, mean_time, total_time +FROM pg_stat_statements +ORDER BY mean_time DESC +LIMIT 10; +``` + +### 2.3 Evitar N+1 Queries + +```typescript +// ❌ INCORRECTO: N+1 queries +async findAllWithOrders(): Promise { + const users = await this.userRepository.find(); + // N queries adicionales para cargar orders + for (const user of users) { + user.orders = await this.orderRepository.find({ + where: { userId: user.id } + }); + } + return users; +} + +// βœ… CORRECTO: Join en una query +async findAllWithOrders(): Promise { + return this.userRepository.find({ + relations: ['orders'], // TypeORM hace JOIN + }); +} + +// βœ… CORRECTO: QueryBuilder con control +async findAllWithOrders(): Promise { + return this.userRepository + .createQueryBuilder('user') + .leftJoinAndSelect('user.orders', 'order') + .where('user.status = :status', { status: 'active' }) + .orderBy('user.createdAt', 'DESC') + .getMany(); +} +``` + +### 2.4 Paginacion Eficiente + +```typescript +// ❌ INCORRECTO: OFFSET para paginas grandes +async findPaginated(page: number, limit: number) { + return this.repository.find({ + skip: (page - 1) * limit, // Lento en paginas grandes + take: limit, + }); +} + +// βœ… CORRECTO: Cursor-based pagination +async findPaginatedByCursor(cursor?: string, limit: number = 20) { + const qb = this.repository + .createQueryBuilder('item') + .orderBy('item.createdAt', 'DESC') + .take(limit + 1); // +1 para saber si hay mas + + if (cursor) { + const decodedCursor = this.decodeCursor(cursor); + qb.where('item.createdAt < :cursor', { cursor: decodedCursor }); + } + + const items = await qb.getMany(); + const hasMore = items.length > limit; + + if (hasMore) { + items.pop(); // Remover el extra + } + + return { + data: items, + nextCursor: hasMore ? this.encodeCursor(items[items.length - 1]) : null, + hasMore, + }; +} +``` + +### 2.5 Select Solo Campos Necesarios + +```typescript +// ❌ INCORRECTO: Traer toda la entidad +const users = await this.userRepository.find(); + +// βœ… CORRECTO: Solo campos necesarios +const users = await this.userRepository.find({ + select: ['id', 'email', 'firstName'], +}); + +// βœ… CORRECTO: Con QueryBuilder +const users = await this.userRepository + .createQueryBuilder('user') + .select(['user.id', 'user.email', 'user.firstName']) + .getMany(); +``` + +--- + +## 3. BACKEND PERFORMANCE + +### 3.1 Caching con Redis + +```typescript +// src/shared/cache/cache.service.ts +import { Injectable, Inject } from '@nestjs/common'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Cache } from 'cache-manager'; + +@Injectable() +export class CacheService { + constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} + + async get(key: string): Promise { + return this.cacheManager.get(key); + } + + async set(key: string, value: T, ttlSeconds: number): Promise { + await this.cacheManager.set(key, value, ttlSeconds * 1000); + } + + async del(key: string): Promise { + await this.cacheManager.del(key); + } + + async delByPattern(pattern: string): Promise { + const keys = await this.cacheManager.store.keys(pattern); + await Promise.all(keys.map(key => this.cacheManager.del(key))); + } +} +``` + +### 3.2 Cache Decorator + +```typescript +// src/shared/decorators/cached.decorator.ts +import { SetMetadata } from '@nestjs/common'; + +export const CACHE_KEY = 'cache_key'; +export const CACHE_TTL = 'cache_ttl'; + +export const Cached = (key: string, ttlSeconds: number = 300) => { + return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => { + SetMetadata(CACHE_KEY, key)(target, propertyKey, descriptor); + SetMetadata(CACHE_TTL, ttlSeconds)(target, propertyKey, descriptor); + }; +}; + +// Interceptor que implementa el caching +@Injectable() +export class CacheInterceptor implements NestInterceptor { + constructor( + private readonly cacheService: CacheService, + private readonly reflector: Reflector, + ) {} + + async intercept(context: ExecutionContext, next: CallHandler): Promise> { + const cacheKey = this.reflector.get(CACHE_KEY, context.getHandler()); + if (!cacheKey) { + return next.handle(); + } + + const cacheTtl = this.reflector.get(CACHE_TTL, context.getHandler()) || 300; + const request = context.switchToHttp().getRequest(); + const fullKey = `${cacheKey}:${JSON.stringify(request.query)}`; + + const cached = await this.cacheService.get(fullKey); + if (cached) { + return of(cached); + } + + return next.handle().pipe( + tap(async (data) => { + await this.cacheService.set(fullKey, data, cacheTtl); + }), + ); + } +} +``` + +### 3.3 Uso de Cache en Service + +```typescript +// src/modules/product/services/product.service.ts +@Injectable() +export class ProductService { + constructor( + private readonly repository: Repository, + private readonly cacheService: CacheService, + ) {} + + async findAll(query: ProductQueryDto): Promise { + const cacheKey = `products:list:${JSON.stringify(query)}`; + + // Intentar obtener de cache + const cached = await this.cacheService.get(cacheKey); + if (cached) { + return cached; + } + + // Query a BD + const products = await this.repository.find({ + where: this.buildWhereClause(query), + take: query.limit, + }); + + // Guardar en cache (5 minutos) + await this.cacheService.set(cacheKey, products, 300); + + return products; + } + + async update(id: string, dto: UpdateProductDto): Promise { + const product = await this.repository.save({ id, ...dto }); + + // Invalidar cache relacionado + await this.cacheService.delByPattern('products:*'); + + return product; + } +} +``` + +### 3.4 Compresion de Responses + +```typescript +// src/main.ts +import * as compression from 'compression'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + + // Comprimir responses > 1kb + app.use(compression({ + threshold: 1024, + level: 6, // Balance entre compresion y CPU + })); + + await app.listen(3000); +} +``` + +### 3.5 Lazy Loading de Modulos + +```typescript +// Cargar modulo pesado solo cuando se necesita +@Module({ + imports: [ + // Modulo de reportes cargado lazy + RouterModule.register([ + { + path: 'reports', + module: ReportsModule, + }, + ]), + ], +}) +export class AppModule {} +``` + +--- + +## 4. FRONTEND PERFORMANCE + +### 4.1 Code Splitting + +```typescript +// ❌ INCORRECTO: Importar todo +import { HeavyComponent } from './HeavyComponent'; + +// βœ… CORRECTO: Lazy loading +const HeavyComponent = lazy(() => import('./HeavyComponent')); + +// Uso con Suspense +}> + + +``` + +### 4.2 Memoizacion + +```typescript +// React.memo para componentes puros +const UserCard = memo(({ user }: { user: User }) => { + return ( +
+

{user.name}

+

{user.email}

+
+ ); +}); + +// useMemo para calculos costosos +const ExpensiveList = ({ items, filter }: Props) => { + const filteredItems = useMemo( + () => items.filter(item => complexFilter(item, filter)), + [items, filter], // Solo recalcular si cambian + ); + + return
    {filteredItems.map(/* ... */)}
; +}; + +// useCallback para funciones estables +const ParentComponent = () => { + const [count, setCount] = useState(0); + + const handleClick = useCallback(() => { + console.log('clicked'); + }, []); // Funcion estable + + return ; +}; +``` + +### 4.3 Virtualizacion de Listas + +```typescript +// Para listas largas, usar virtualizacion +import { useVirtualizer } from '@tanstack/react-virtual'; + +const VirtualList = ({ items }: { items: Item[] }) => { + const parentRef = useRef(null); + + const virtualizer = useVirtualizer({ + count: items.length, + getScrollElement: () => parentRef.current, + estimateSize: () => 50, // Altura estimada de cada item + }); + + return ( +
+
+ {virtualizer.getVirtualItems().map(virtualItem => ( +
+ +
+ ))} +
+
+ ); +}; +``` + +### 4.4 Optimizacion de Imagenes + +```typescript +// Componente de imagen optimizada +const OptimizedImage = ({ + src, + alt, + width, + height, +}: ImageProps) => { + return ( + {alt} + ); +}; + +// Con srcset para responsive +const ResponsiveImage = ({ src, alt }: Props) => { + return ( + {alt} + ); +}; +``` + +### 4.5 Debounce y Throttle + +```typescript +// src/shared/hooks/useDebounce.ts +import { useState, useEffect } from 'react'; + +export function useDebounce(value: T, delay: number): T { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const timer = setTimeout(() => setDebouncedValue(value), delay); + return () => clearTimeout(timer); + }, [value, delay]); + + return debouncedValue; +} + +// Uso en busqueda +const SearchInput = () => { + const [search, setSearch] = useState(''); + const debouncedSearch = useDebounce(search, 300); + + // Query solo se ejecuta cuando debouncedSearch cambia + const { data } = useQuery({ + queryKey: ['search', debouncedSearch], + queryFn: () => api.search(debouncedSearch), + enabled: debouncedSearch.length > 2, + }); + + return setSearch(e.target.value)} />; +}; +``` + +### 4.6 React Query - Cache y Stale Time + +```typescript +// src/shared/hooks/useProducts.ts +export const useProducts = (filters: ProductFilters) => { + return useQuery({ + queryKey: ['products', filters], + queryFn: () => productService.getAll(filters), + staleTime: 5 * 60 * 1000, // 5 minutos antes de refetch + gcTime: 30 * 60 * 1000, // 30 minutos en cache + placeholderData: keepPreviousData, // Mostrar datos anteriores mientras carga + }); +}; + +// Prefetch para navegacion anticipada +const ProductList = () => { + const queryClient = useQueryClient(); + + const handleMouseEnter = (productId: string) => { + // Prefetch detalle del producto + queryClient.prefetchQuery({ + queryKey: ['product', productId], + queryFn: () => productService.getById(productId), + }); + }; + + return (/* ... */); +}; +``` + +--- + +## 5. API DESIGN PARA PERFORMANCE + +### 5.1 Campos Seleccionables + +```typescript +// Permitir al cliente elegir campos +@Get() +async findAll( + @Query('fields') fields?: string, // ?fields=id,name,price +): Promise[]> { + const select = fields?.split(',') || undefined; + return this.productService.findAll({ select }); +} +``` + +### 5.2 Expansion de Relaciones + +```typescript +// Permitir expansion opcional de relaciones +@Get(':id') +async findOne( + @Param('id') id: string, + @Query('expand') expand?: string, // ?expand=category,reviews +): Promise { + const relations = expand?.split(',') || []; + return this.productService.findOne(id, { relations }); +} +``` + +### 5.3 Batch Endpoints + +```typescript +// Endpoint para multiples operaciones +@Post('batch') +async batchCreate(@Body() dtos: CreateProductDto[]): Promise { + // Una transaccion en lugar de N requests + return this.productService.createMany(dtos); +} + +// Endpoint para multiples IDs +@Get('batch') +async batchGet(@Query('ids') ids: string): Promise { + const idArray = ids.split(','); + return this.productService.findByIds(idArray); +} +``` + +--- + +## 6. MONITORING Y PROFILING + +### 6.1 Metricas de API + +```typescript +// src/shared/interceptors/metrics.interceptor.ts +@Injectable() +export class MetricsInterceptor implements NestInterceptor { + constructor(private readonly metricsService: MetricsService) {} + + intercept(context: ExecutionContext, next: CallHandler): Observable { + const request = context.switchToHttp().getRequest(); + const { method, url } = request; + const startTime = Date.now(); + + return next.handle().pipe( + tap({ + next: () => { + const duration = Date.now() - startTime; + this.metricsService.recordRequest(method, url, 200, duration); + }, + error: (error) => { + const duration = Date.now() - startTime; + this.metricsService.recordRequest(method, url, error.status || 500, duration); + }, + }), + ); + } +} +``` + +### 6.2 Query Logging Condicional + +```typescript +// Solo loguear queries lentas en produccion +const typeOrmConfig: TypeOrmModuleOptions = { + logging: process.env.NODE_ENV === 'production' ? ['error', 'warn'] : true, + maxQueryExecutionTime: 1000, // Loguear queries > 1s +}; +``` + +--- + +## 7. CHECKLIST DE PERFORMANCE + +``` +Database: +[ ] Indices en columnas de WHERE frecuentes +[ ] Indices compuestos para queries comunes +[ ] No N+1 queries (usar JOIN/relations) +[ ] Paginacion cursor-based para datasets grandes +[ ] SELECT solo campos necesarios +[ ] EXPLAIN ANALYZE en queries criticas + +Backend: +[ ] Cache implementado para datos frecuentes +[ ] Invalidacion de cache correcta +[ ] Compresion habilitada +[ ] Connection pooling configurado +[ ] Timeouts apropiados + +Frontend: +[ ] Code splitting / lazy loading +[ ] Memoizacion donde corresponde +[ ] Virtualizacion para listas largas +[ ] Imagenes optimizadas y lazy loaded +[ ] Debounce en inputs de busqueda +[ ] React Query con staleTime apropiado + +API: +[ ] Paginacion en endpoints de listas +[ ] Campos seleccionables (opcional) +[ ] Batch endpoints para operaciones multiples +[ ] Rate limiting para proteger recursos +``` + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Patron de Performance diff --git a/core/orchestration/patrones/PATRON-SEGURIDAD.md b/core/orchestration/patrones/PATRON-SEGURIDAD.md new file mode 100644 index 0000000..e7d99be --- /dev/null +++ b/core/orchestration/patrones/PATRON-SEGURIDAD.md @@ -0,0 +1,778 @@ +# PATRON DE SEGURIDAD + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - Seguir en todo el codigo +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Definir patrones de seguridad obligatorios para prevenir vulnerabilidades comunes (OWASP Top 10) y proteger datos sensibles. + +--- + +## 1. OWASP TOP 10 - RESUMEN + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ OWASP TOP 10 - 2021 β•‘ +╠══════════════════════════════════════════════════════════════════════╣ +β•‘ β•‘ +β•‘ A01 - Broken Access Control β•‘ +β•‘ A02 - Cryptographic Failures β•‘ +β•‘ A03 - Injection β•‘ +β•‘ A04 - Insecure Design β•‘ +β•‘ A05 - Security Misconfiguration β•‘ +β•‘ A06 - Vulnerable Components β•‘ +β•‘ A07 - Authentication Failures β•‘ +β•‘ A08 - Software Integrity Failures β•‘ +β•‘ A09 - Logging & Monitoring Failures β•‘ +β•‘ A10 - Server-Side Request Forgery (SSRF) β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 2. SANITIZACION DE INPUT + +### Backend - Validacion con class-validator + +```typescript +// src/modules/user/dto/create-user.dto.ts +import { + IsEmail, + IsString, + MinLength, + MaxLength, + Matches, + IsNotEmpty, +} from 'class-validator'; +import { Transform } from 'class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateUserDto { + @ApiProperty({ example: 'user@example.com' }) + @IsEmail({}, { message: 'Email invalido' }) + @MaxLength(255) + @Transform(({ value }) => value?.toLowerCase().trim()) // Sanitizar + email: string; + + @ApiProperty({ example: 'John' }) + @IsString() + @IsNotEmpty() + @MinLength(2) + @MaxLength(100) + @Matches(/^[a-zA-ZΓ€-ΓΏ\s'-]+$/, { + message: 'Nombre solo puede contener letras', + }) + @Transform(({ value }) => value?.trim()) // Sanitizar espacios + firstName: string; + + @ApiProperty() + @IsString() + @MinLength(8) + @MaxLength(128) + @Matches( + /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/, + { message: 'Password debe tener mayuscula, minuscula, numero y simbolo' }, + ) + password: string; +} +``` + +### Sanitizacion de HTML (Prevenir XSS) + +```typescript +// src/shared/utils/sanitizer.ts +import DOMPurify from 'isomorphic-dompurify'; + +export function sanitizeHtml(dirty: string): string { + return DOMPurify.sanitize(dirty, { + ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br'], + ALLOWED_ATTR: [], + }); +} + +export function stripHtml(dirty: string): string { + return DOMPurify.sanitize(dirty, { + ALLOWED_TAGS: [], + ALLOWED_ATTR: [], + }); +} + +// Uso en DTO +@Transform(({ value }) => stripHtml(value)) +@IsString() +comment: string; +``` + +### Prevenir SQL Injection + +```typescript +// ❌ INCORRECTO: SQL Injection vulnerable +async findByName(name: string) { + return this.repository.query( + `SELECT * FROM users WHERE name = '${name}'` // VULNERABLE + ); +} + +// βœ… CORRECTO: Usar parametros +async findByName(name: string) { + return this.repository.query( + 'SELECT * FROM users WHERE name = $1', + [name], // Parametrizado + ); +} + +// βœ… MEJOR: Usar QueryBuilder de TypeORM +async findByName(name: string) { + return this.repository + .createQueryBuilder('user') + .where('user.name = :name', { name }) // Automaticamente seguro + .getMany(); +} +``` + +--- + +## 3. AUTENTICACION + +### Password Hashing + +```typescript +// src/shared/utils/password.util.ts +import * as bcrypt from 'bcrypt'; + +const SALT_ROUNDS = 12; // Minimo 10 para produccion + +export async function hashPassword(password: string): Promise { + return bcrypt.hash(password, SALT_ROUNDS); +} + +export async function verifyPassword( + password: string, + hash: string, +): Promise { + return bcrypt.compare(password, hash); +} +``` + +### JWT con Refresh Tokens + +```typescript +// src/modules/auth/services/auth.service.ts +@Injectable() +export class AuthService { + constructor( + private readonly jwtService: JwtService, + private readonly configService: ConfigService, + private readonly userService: UserService, + private readonly tokenService: RefreshTokenService, + ) {} + + async login(dto: LoginDto): Promise { + const user = await this.validateUser(dto.email, dto.password); + if (!user) { + // Mensaje generico para no revelar si email existe + throw new UnauthorizedException('Credenciales invalidas'); + } + + const tokens = await this.generateTokens(user); + + // Guardar refresh token hasheado en BD + await this.tokenService.saveRefreshToken( + user.id, + await hashPassword(tokens.refreshToken), + ); + + return tokens; + } + + private async generateTokens(user: UserEntity): Promise { + const payload: JwtPayload = { + sub: user.id, + email: user.email, + roles: user.roles.map(r => r.name), + }; + + const [accessToken, refreshToken] = await Promise.all([ + this.jwtService.signAsync(payload, { + secret: this.configService.get('JWT_SECRET'), + expiresIn: '15m', // Corta duracion + }), + this.jwtService.signAsync( + { sub: user.id, type: 'refresh' }, + { + secret: this.configService.get('JWT_REFRESH_SECRET'), + expiresIn: '7d', + }, + ), + ]); + + return { accessToken, refreshToken }; + } + + async refresh(refreshToken: string): Promise { + try { + const payload = await this.jwtService.verifyAsync(refreshToken, { + secret: this.configService.get('JWT_REFRESH_SECRET'), + }); + + // Verificar que token existe en BD y no fue revocado + const storedToken = await this.tokenService.findByUserId(payload.sub); + if (!storedToken || !await verifyPassword(refreshToken, storedToken.hash)) { + throw new UnauthorizedException('Token invalido'); + } + + const user = await this.userService.findById(payload.sub); + return this.generateTokens(user); + } catch { + throw new UnauthorizedException('Token invalido o expirado'); + } + } + + async logout(userId: string): Promise { + // Revocar todos los refresh tokens del usuario + await this.tokenService.revokeAllUserTokens(userId); + } +} +``` + +### Guard de Autenticacion + +```typescript +// src/shared/guards/jwt-auth.guard.ts +import { Injectable, ExecutionContext, UnauthorizedException } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { Reflector } from '@nestjs/core'; +import { IS_PUBLIC_KEY } from '../decorators/public.decorator'; + +@Injectable() +export class JwtAuthGuard extends AuthGuard('jwt') { + constructor(private reflector: Reflector) { + super(); + } + + canActivate(context: ExecutionContext) { + // Verificar si es ruta publica + const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ + context.getHandler(), + context.getClass(), + ]); + + if (isPublic) { + return true; + } + + return super.canActivate(context); + } + + handleRequest(err: any, user: any, info: any) { + if (err || !user) { + throw err || new UnauthorizedException('No autorizado'); + } + return user; + } +} +``` + +--- + +## 4. AUTORIZACION (RBAC) + +### Roles y Permisos + +```typescript +// src/shared/enums/roles.enum.ts +export enum Role { + SUPER_ADMIN = 'super_admin', + ADMIN = 'admin', + MANAGER = 'manager', + USER = 'user', + GUEST = 'guest', +} + +export enum Permission { + // Users + USER_CREATE = 'user:create', + USER_READ = 'user:read', + USER_UPDATE = 'user:update', + USER_DELETE = 'user:delete', + + // Products + PRODUCT_CREATE = 'product:create', + PRODUCT_READ = 'product:read', + PRODUCT_UPDATE = 'product:update', + PRODUCT_DELETE = 'product:delete', +} + +// Mapeo de roles a permisos +export const ROLE_PERMISSIONS: Record = { + [Role.SUPER_ADMIN]: Object.values(Permission), + [Role.ADMIN]: [ + Permission.USER_CREATE, + Permission.USER_READ, + Permission.USER_UPDATE, + Permission.PRODUCT_CREATE, + Permission.PRODUCT_READ, + Permission.PRODUCT_UPDATE, + Permission.PRODUCT_DELETE, + ], + [Role.MANAGER]: [ + Permission.USER_READ, + Permission.PRODUCT_CREATE, + Permission.PRODUCT_READ, + Permission.PRODUCT_UPDATE, + ], + [Role.USER]: [ + Permission.PRODUCT_READ, + ], + [Role.GUEST]: [], +}; +``` + +### Guard de Roles + +```typescript +// src/shared/guards/roles.guard.ts +import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; +import { Role, Permission, ROLE_PERMISSIONS } from '../enums/roles.enum'; + +@Injectable() +export class RolesGuard implements CanActivate { + constructor(private reflector: Reflector) {} + + canActivate(context: ExecutionContext): boolean { + const requiredRoles = this.reflector.getAllAndOverride('roles', [ + context.getHandler(), + context.getClass(), + ]); + + const requiredPermissions = this.reflector.getAllAndOverride( + 'permissions', + [context.getHandler(), context.getClass()], + ); + + if (!requiredRoles && !requiredPermissions) { + return true; // Sin restricciones + } + + const { user } = context.switchToHttp().getRequest(); + + if (!user) { + throw new ForbiddenException('Usuario no autenticado'); + } + + // Verificar roles + if (requiredRoles?.length > 0) { + const hasRole = requiredRoles.some(role => user.roles?.includes(role)); + if (!hasRole) { + throw new ForbiddenException('Rol insuficiente'); + } + } + + // Verificar permisos + if (requiredPermissions?.length > 0) { + const userPermissions = this.getUserPermissions(user.roles); + const hasPermission = requiredPermissions.every( + permission => userPermissions.includes(permission), + ); + if (!hasPermission) { + throw new ForbiddenException('Permiso insuficiente'); + } + } + + return true; + } + + private getUserPermissions(roles: Role[]): Permission[] { + const permissions = new Set(); + for (const role of roles) { + for (const permission of ROLE_PERMISSIONS[role] || []) { + permissions.add(permission); + } + } + return Array.from(permissions); + } +} +``` + +### Decoradores + +```typescript +// src/shared/decorators/roles.decorator.ts +import { SetMetadata } from '@nestjs/common'; +import { Role, Permission } from '../enums/roles.enum'; + +export const Roles = (...roles: Role[]) => SetMetadata('roles', roles); +export const Permissions = (...permissions: Permission[]) => + SetMetadata('permissions', permissions); +``` + +### Uso en Controller + +```typescript +// src/modules/user/controllers/user.controller.ts +@Controller('users') +@UseGuards(JwtAuthGuard, RolesGuard) +export class UserController { + @Get() + @Roles(Role.ADMIN, Role.MANAGER) + findAll() { + return this.userService.findAll(); + } + + @Post() + @Permissions(Permission.USER_CREATE) + create(@Body() dto: CreateUserDto) { + return this.userService.create(dto); + } + + @Delete(':id') + @Roles(Role.SUPER_ADMIN) // Solo super admin puede eliminar + remove(@Param('id') id: string) { + return this.userService.remove(id); + } +} +``` + +--- + +## 5. PROTECCION DE DATOS + +### Encriptacion de Datos Sensibles + +```typescript +// src/shared/utils/encryption.util.ts +import * as crypto from 'crypto'; + +const ALGORITHM = 'aes-256-gcm'; +const IV_LENGTH = 16; +const AUTH_TAG_LENGTH = 16; + +export function encrypt(text: string, key: string): string { + const iv = crypto.randomBytes(IV_LENGTH); + const cipher = crypto.createCipheriv( + ALGORITHM, + Buffer.from(key, 'hex'), + iv, + ); + + let encrypted = cipher.update(text, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + + const authTag = cipher.getAuthTag(); + + // IV + AuthTag + Encrypted + return iv.toString('hex') + authTag.toString('hex') + encrypted; +} + +export function decrypt(encryptedText: string, key: string): string { + const iv = Buffer.from(encryptedText.slice(0, IV_LENGTH * 2), 'hex'); + const authTag = Buffer.from( + encryptedText.slice(IV_LENGTH * 2, (IV_LENGTH + AUTH_TAG_LENGTH) * 2), + 'hex', + ); + const encrypted = encryptedText.slice((IV_LENGTH + AUTH_TAG_LENGTH) * 2); + + const decipher = crypto.createDecipheriv( + ALGORITHM, + Buffer.from(key, 'hex'), + iv, + ); + decipher.setAuthTag(authTag); + + let decrypted = decipher.update(encrypted, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + + return decrypted; +} +``` + +### Columnas Encriptadas en Entity + +```typescript +// src/shared/transformers/encrypted.transformer.ts +import { ValueTransformer } from 'typeorm'; +import { encrypt, decrypt } from '../utils/encryption.util'; + +export class EncryptedTransformer implements ValueTransformer { + constructor(private readonly key: string) {} + + to(value: string | null): string | null { + if (!value) return null; + return encrypt(value, this.key); + } + + from(value: string | null): string | null { + if (!value) return null; + return decrypt(value, this.key); + } +} + +// Uso en Entity +@Column({ + type: 'text', + transformer: new EncryptedTransformer(process.env.ENCRYPTION_KEY), +}) +ssn: string; // Se guarda encriptado en BD +``` + +### Nunca Exponer Datos Sensibles + +```typescript +// ❌ INCORRECTO: Exponer password en response +@Get(':id') +async findOne(@Param('id') id: string) { + return this.userRepository.findOne({ where: { id } }); + // Retorna { id, email, password, ... } - PASSWORD EXPUESTO! +} + +// βœ… CORRECTO: Usar ResponseDto que excluye campos sensibles +@Get(':id') +async findOne(@Param('id') id: string): Promise { + const user = await this.userService.findOne(id); + return plainToClass(UserResponseDto, user, { + excludeExtraneousValues: true, + }); +} + +// ResponseDto solo expone campos seguros +export class UserResponseDto { + @Expose() id: string; + @Expose() email: string; + @Expose() firstName: string; + // password NO esta expuesto +} +``` + +--- + +## 6. RATE LIMITING + +### Implementacion con Throttler + +```typescript +// src/app.module.ts +import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler'; + +@Module({ + imports: [ + ThrottlerModule.forRoot([ + { + name: 'short', + ttl: 1000, // 1 segundo + limit: 3, // 3 requests por segundo + }, + { + name: 'medium', + ttl: 10000, // 10 segundos + limit: 20, // 20 requests por 10 segundos + }, + { + name: 'long', + ttl: 60000, // 1 minuto + limit: 100, // 100 requests por minuto + }, + ]), + ], + providers: [ + { + provide: APP_GUARD, + useClass: ThrottlerGuard, + }, + ], +}) +export class AppModule {} +``` + +### Rate Limiting por Endpoint + +```typescript +// Rate limit especifico para login (prevenir brute force) +@Post('login') +@Throttle({ default: { limit: 5, ttl: 60000 } }) // 5 intentos por minuto +async login(@Body() dto: LoginDto) { + return this.authService.login(dto); +} + +// Endpoint sin rate limit +@Get('health') +@SkipThrottle() +healthCheck() { + return { status: 'ok' }; +} +``` + +--- + +## 7. HEADERS DE SEGURIDAD + +### Helmet Middleware + +```typescript +// src/main.ts +import helmet from 'helmet'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + + // Headers de seguridad + app.use(helmet({ + contentSecurityPolicy: { + directives: { + defaultSrc: ["'self'"], + styleSrc: ["'self'", "'unsafe-inline'"], + scriptSrc: ["'self'"], + imgSrc: ["'self'", 'data:', 'https:'], + }, + }, + hsts: { + maxAge: 31536000, // 1 aΓ±o + includeSubDomains: true, + }, + })); + + // CORS configurado + app.enableCors({ + origin: process.env.CORS_ORIGINS?.split(',') || false, + methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], + credentials: true, + }); + + await app.listen(3000); +} +``` + +--- + +## 8. FRONTEND - SEGURIDAD + +### Almacenamiento de Tokens + +```typescript +// ❌ INCORRECTO: Token en localStorage (vulnerable a XSS) +localStorage.setItem('token', accessToken); + +// βœ… MEJOR: HttpOnly cookies (configurado desde backend) +// El token se maneja automaticamente por el navegador + +// βœ… ALTERNATIVA: Si debe estar en JS, usar memoria +class TokenStore { + private accessToken: string | null = null; + + setToken(token: string) { + this.accessToken = token; + } + + getToken(): string | null { + return this.accessToken; + } + + clearToken() { + this.accessToken = null; + } +} + +export const tokenStore = new TokenStore(); +``` + +### Prevenir XSS en React + +```typescript +// ❌ INCORRECTO: dangerouslySetInnerHTML sin sanitizar +
+ +// βœ… CORRECTO: Sanitizar primero +import DOMPurify from 'dompurify'; + +
+ +// βœ… MEJOR: Evitar dangerouslySetInnerHTML cuando sea posible +
{userInput}
// React escapa automaticamente +``` + +### Validacion en Frontend (Defense in Depth) + +```typescript +// src/shared/schemas/user.schema.ts +import { z } from 'zod'; + +export const createUserSchema = z.object({ + email: z.string() + .email('Email invalido') + .max(255) + .transform(v => v.toLowerCase().trim()), + + firstName: z.string() + .min(2, 'Minimo 2 caracteres') + .max(100) + .regex(/^[a-zA-ZΓ€-ΓΏ\s'-]+$/, 'Solo letras permitidas') + .transform(v => v.trim()), + + password: z.string() + .min(8, 'Minimo 8 caracteres') + .max(128) + .regex( + /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])/, + 'Debe incluir mayuscula, minuscula, numero y simbolo', + ), +}); +``` + +--- + +## 9. CHECKLIST DE SEGURIDAD + +``` +Input/Output: +[ ] Todos los inputs validados con class-validator +[ ] HTML sanitizado antes de renderizar +[ ] SQL usa queries parametrizadas +[ ] Datos sensibles nunca en logs +[ ] ResponseDto excluye campos sensibles + +Autenticacion: +[ ] Passwords hasheados con bcrypt (rounds >= 10) +[ ] JWT con expiracion corta (< 15min) +[ ] Refresh tokens almacenados hasheados +[ ] Logout revoca tokens +[ ] Mensajes de error genericos (no revelar info) + +Autorizacion: +[ ] Guards en todos los endpoints protegidos +[ ] Verificacion de ownership en recursos +[ ] Roles y permisos implementados +[ ] Principio de minimo privilegio + +Infraestructura: +[ ] HTTPS obligatorio +[ ] Headers de seguridad (Helmet) +[ ] CORS configurado correctamente +[ ] Rate limiting implementado +[ ] Secrets en variables de entorno + +Frontend: +[ ] No localStorage para tokens sensibles +[ ] CSP configurado +[ ] Validacion client-side (defense in depth) +[ ] No exponer errores detallados a usuarios +``` + +--- + +## 10. RECURSOS ADICIONALES + +- OWASP Cheat Sheets: https://cheatsheetseries.owasp.org/ +- NestJS Security: https://docs.nestjs.com/security/helmet +- React Security: https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Patron de Seguridad diff --git a/core/orchestration/patrones/PATRON-TESTING.md b/core/orchestration/patrones/PATRON-TESTING.md new file mode 100644 index 0000000..84812a6 --- /dev/null +++ b/core/orchestration/patrones/PATRON-TESTING.md @@ -0,0 +1,727 @@ +# PATRΓ“N: TESTING + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Aplica a:** Backend (NestJS), Frontend (React) +**Prioridad:** RECOMENDADA + +--- + +## PROPΓ“SITO + +Definir patrones estΓ‘ndar de testing para garantizar cΓ³digo de calidad. + +--- + +## 1. TIPOS DE TESTS + +| Tipo | QuΓ© Testea | Herramienta | Cobertura Objetivo | +|------|------------|-------------|-------------------| +| **Unit** | Funciones/Clases aisladas | Jest | 70%+ | +| **Integration** | MΓ³dulos integrados | Jest + Supertest | 50%+ | +| **E2E** | Flujos completos | Jest + Supertest | CrΓ­ticos | +| **Component** | Componentes React | React Testing Library | 60%+ | + +--- + +## 2. BACKEND: TEST DE SERVICE + +### Template + +```typescript +// user.service.spec.ts +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { UserService } from './user.service'; +import { UserEntity } from '../entities/user.entity'; +import { CreateUserDto } from '../dto/create-user.dto'; +import { NotFoundException, ConflictException } from '@nestjs/common'; + +describe('UserService', () => { + let service: UserService; + let repository: jest.Mocked>; + + // Mock del repositorio + const mockRepository = { + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + remove: jest.fn(), + count: jest.fn(), + }; + + // Fixtures + const mockUser: UserEntity = { + id: '550e8400-e29b-41d4-a716-446655440000', + email: 'test@example.com', + name: 'Test User', + status: 'active', + createdAt: new Date(), + updatedAt: new Date(), + }; + + const createUserDto: CreateUserDto = { + email: 'new@example.com', + name: 'New User', + password: 'SecurePass123!', + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + UserService, + { + provide: getRepositoryToken(UserEntity), + useValue: mockRepository, + }, + ], + }).compile(); + + service = module.get(UserService); + repository = module.get(getRepositoryToken(UserEntity)); + + // Reset mocks + jest.clearAllMocks(); + }); + + describe('findOne', () => { + it('should return user when found', async () => { + // Arrange + mockRepository.findOne.mockResolvedValue(mockUser); + + // Act + const result = await service.findOne(mockUser.id); + + // Assert + expect(result).toEqual(mockUser); + expect(mockRepository.findOne).toHaveBeenCalledWith({ + where: { id: mockUser.id }, + }); + }); + + it('should throw NotFoundException when user not found', async () => { + // Arrange + mockRepository.findOne.mockResolvedValue(null); + + // Act & Assert + await expect(service.findOne('non-existent-id')) + .rejects + .toThrow(NotFoundException); + }); + }); + + describe('create', () => { + it('should create user successfully', async () => { + // Arrange + mockRepository.findOne.mockResolvedValue(null); // No existe + mockRepository.create.mockReturnValue(mockUser); + mockRepository.save.mockResolvedValue(mockUser); + + // Act + const result = await service.create(createUserDto); + + // Assert + expect(result).toEqual(mockUser); + expect(mockRepository.findOne).toHaveBeenCalled(); + expect(mockRepository.create).toHaveBeenCalledWith( + expect.objectContaining({ + email: createUserDto.email, + name: createUserDto.name, + }) + ); + expect(mockRepository.save).toHaveBeenCalled(); + }); + + it('should throw ConflictException when email exists', async () => { + // Arrange + mockRepository.findOne.mockResolvedValue(mockUser); // Ya existe + + // Act & Assert + await expect(service.create(createUserDto)) + .rejects + .toThrow(ConflictException); + + expect(mockRepository.save).not.toHaveBeenCalled(); + }); + }); + + describe('findAll', () => { + it('should return array of users', async () => { + // Arrange + const users = [mockUser, { ...mockUser, id: '2' }]; + mockRepository.find.mockResolvedValue(users); + + // Act + const result = await service.findAll(); + + // Assert + expect(result).toHaveLength(2); + expect(mockRepository.find).toHaveBeenCalled(); + }); + + it('should return empty array when no users', async () => { + // Arrange + mockRepository.find.mockResolvedValue([]); + + // Act + const result = await service.findAll(); + + // Assert + expect(result).toHaveLength(0); + }); + }); + + describe('update', () => { + it('should update user successfully', async () => { + // Arrange + const updateDto = { name: 'Updated Name' }; + const updatedUser = { ...mockUser, ...updateDto }; + + mockRepository.findOne.mockResolvedValue(mockUser); + mockRepository.save.mockResolvedValue(updatedUser); + + // Act + const result = await service.update(mockUser.id, updateDto); + + // Assert + expect(result.name).toBe('Updated Name'); + expect(mockRepository.save).toHaveBeenCalled(); + }); + + it('should throw NotFoundException when user not found', async () => { + // Arrange + mockRepository.findOne.mockResolvedValue(null); + + // Act & Assert + await expect(service.update('non-existent', { name: 'Test' })) + .rejects + .toThrow(NotFoundException); + }); + }); + + describe('remove', () => { + it('should remove user successfully', async () => { + // Arrange + mockRepository.findOne.mockResolvedValue(mockUser); + mockRepository.remove.mockResolvedValue(mockUser); + + // Act + await service.remove(mockUser.id); + + // Assert + expect(mockRepository.remove).toHaveBeenCalledWith(mockUser); + }); + }); +}); +``` + +--- + +## 3. BACKEND: TEST DE CONTROLLER + +### Template + +```typescript +// user.controller.spec.ts +import { Test, TestingModule } from '@nestjs/testing'; +import { UserController } from './user.controller'; +import { UserService } from '../services/user.service'; +import { CreateUserDto } from '../dto/create-user.dto'; +import { UserEntity } from '../entities/user.entity'; +import { NotFoundException } from '@nestjs/common'; + +describe('UserController', () => { + let controller: UserController; + let service: jest.Mocked; + + const mockService = { + findAll: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + update: jest.fn(), + remove: jest.fn(), + }; + + const mockUser: UserEntity = { + id: '550e8400-e29b-41d4-a716-446655440000', + email: 'test@example.com', + name: 'Test User', + status: 'active', + createdAt: new Date(), + updatedAt: new Date(), + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [UserController], + providers: [ + { + provide: UserService, + useValue: mockService, + }, + ], + }).compile(); + + controller = module.get(UserController); + service = module.get(UserService); + + jest.clearAllMocks(); + }); + + describe('findAll', () => { + it('should return array of users', async () => { + // Arrange + mockService.findAll.mockResolvedValue([mockUser]); + + // Act + const result = await controller.findAll(); + + // Assert + expect(result).toHaveLength(1); + expect(service.findAll).toHaveBeenCalled(); + }); + }); + + describe('findOne', () => { + it('should return user by id', async () => { + // Arrange + mockService.findOne.mockResolvedValue(mockUser); + + // Act + const result = await controller.findOne(mockUser.id); + + // Assert + expect(result).toEqual(mockUser); + expect(service.findOne).toHaveBeenCalledWith(mockUser.id); + }); + + it('should propagate NotFoundException', async () => { + // Arrange + mockService.findOne.mockRejectedValue(new NotFoundException()); + + // Act & Assert + await expect(controller.findOne('non-existent')) + .rejects + .toThrow(NotFoundException); + }); + }); + + describe('create', () => { + it('should create and return user', async () => { + // Arrange + const createDto: CreateUserDto = { + email: 'new@example.com', + name: 'New User', + password: 'Pass123!', + }; + mockService.create.mockResolvedValue(mockUser); + + // Act + const result = await controller.create(createDto); + + // Assert + expect(result).toEqual(mockUser); + expect(service.create).toHaveBeenCalledWith(createDto); + }); + }); + + describe('update', () => { + it('should update and return user', async () => { + // Arrange + const updateDto = { name: 'Updated' }; + const updated = { ...mockUser, ...updateDto }; + mockService.update.mockResolvedValue(updated); + + // Act + const result = await controller.update(mockUser.id, updateDto); + + // Assert + expect(result.name).toBe('Updated'); + expect(service.update).toHaveBeenCalledWith(mockUser.id, updateDto); + }); + }); + + describe('remove', () => { + it('should remove user', async () => { + // Arrange + mockService.remove.mockResolvedValue(undefined); + + // Act + await controller.remove(mockUser.id); + + // Assert + expect(service.remove).toHaveBeenCalledWith(mockUser.id); + }); + }); +}); +``` + +--- + +## 4. BACKEND: TEST E2E + +### Template + +```typescript +// user.e2e-spec.ts +import { Test, TestingModule } from '@nestjs/testing'; +import { INestApplication, ValidationPipe } from '@nestjs/common'; +import * as request from 'supertest'; +import { AppModule } from '../src/app.module'; + +describe('UserController (e2e)', () => { + let app: INestApplication; + let createdUserId: string; + + beforeAll(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + app.useGlobalPipes(new ValidationPipe()); + await app.init(); + }); + + afterAll(async () => { + await app.close(); + }); + + describe('/users (POST)', () => { + it('should create user', () => { + return request(app.getHttpServer()) + .post('/users') + .send({ + email: 'e2e@test.com', + name: 'E2E User', + password: 'SecurePass123!', + }) + .expect(201) + .expect((res) => { + expect(res.body.id).toBeDefined(); + expect(res.body.email).toBe('e2e@test.com'); + createdUserId = res.body.id; + }); + }); + + it('should reject invalid email', () => { + return request(app.getHttpServer()) + .post('/users') + .send({ + email: 'invalid-email', + name: 'Test', + password: 'Pass123!', + }) + .expect(400); + }); + + it('should reject duplicate email', () => { + return request(app.getHttpServer()) + .post('/users') + .send({ + email: 'e2e@test.com', // Ya existe + name: 'Duplicate', + password: 'Pass123!', + }) + .expect(409); + }); + }); + + describe('/users (GET)', () => { + it('should return users list', () => { + return request(app.getHttpServer()) + .get('/users') + .expect(200) + .expect((res) => { + expect(Array.isArray(res.body)).toBe(true); + }); + }); + }); + + describe('/users/:id (GET)', () => { + it('should return user by id', () => { + return request(app.getHttpServer()) + .get(`/users/${createdUserId}`) + .expect(200) + .expect((res) => { + expect(res.body.id).toBe(createdUserId); + }); + }); + + it('should return 404 for non-existent user', () => { + return request(app.getHttpServer()) + .get('/users/550e8400-e29b-41d4-a716-446655440000') + .expect(404); + }); + }); + + describe('/users/:id (PUT)', () => { + it('should update user', () => { + return request(app.getHttpServer()) + .put(`/users/${createdUserId}`) + .send({ name: 'Updated Name' }) + .expect(200) + .expect((res) => { + expect(res.body.name).toBe('Updated Name'); + }); + }); + }); + + describe('/users/:id (DELETE)', () => { + it('should delete user', () => { + return request(app.getHttpServer()) + .delete(`/users/${createdUserId}`) + .expect(204); + }); + }); +}); +``` + +--- + +## 5. FRONTEND: TEST DE COMPONENTE + +### Template con React Testing Library + +```typescript +// UserCard.test.tsx +import { render, screen, fireEvent } from '@testing-library/react'; +import { UserCard } from './UserCard'; +import { User } from '@/types/user.types'; + +describe('UserCard', () => { + const mockUser: User = { + id: '1', + email: 'test@example.com', + name: 'Test User', + status: 'active', + }; + + const mockOnEdit = jest.fn(); + const mockOnDelete = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render user information', () => { + render(); + + expect(screen.getByText('Test User')).toBeInTheDocument(); + expect(screen.getByText('test@example.com')).toBeInTheDocument(); + }); + + it('should call onEdit when edit button clicked', () => { + render( + + ); + + fireEvent.click(screen.getByRole('button', { name: /edit/i })); + + expect(mockOnEdit).toHaveBeenCalledWith(mockUser); + }); + + it('should call onDelete when delete button clicked', () => { + render( + + ); + + fireEvent.click(screen.getByRole('button', { name: /delete/i })); + + expect(mockOnDelete).toHaveBeenCalledWith(mockUser.id); + }); + + it('should show loading state', () => { + render(); + + expect(screen.getByTestId('loading-skeleton')).toBeInTheDocument(); + }); + + it('should hide actions when not provided', () => { + render(); + + expect(screen.queryByRole('button', { name: /edit/i })).not.toBeInTheDocument(); + }); +}); +``` + +--- + +## 6. FRONTEND: TEST DE HOOK + +### Template + +```typescript +// useUsers.test.tsx +import { renderHook, waitFor } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { useUsers, useCreateUser } from './useUsers'; +import { userService } from '@/services/user.service'; + +// Mock del servicio +jest.mock('@/services/user.service'); +const mockUserService = userService as jest.Mocked; + +describe('useUsers', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + + const wrapper = ({ children }) => ( + + {children} + + ); + + beforeEach(() => { + queryClient.clear(); + jest.clearAllMocks(); + }); + + describe('useUsers', () => { + it('should fetch users', async () => { + // Arrange + const mockUsers = [ + { id: '1', name: 'User 1', email: 'u1@test.com' }, + { id: '2', name: 'User 2', email: 'u2@test.com' }, + ]; + mockUserService.getAll.mockResolvedValue(mockUsers); + + // Act + const { result } = renderHook(() => useUsers(), { wrapper }); + + // Assert - Initially loading + expect(result.current.isLoading).toBe(true); + + // Wait for data + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(result.current.data).toEqual(mockUsers); + }); + + it('should handle error', async () => { + // Arrange + mockUserService.getAll.mockRejectedValue(new Error('Network error')); + + // Act + const { result } = renderHook(() => useUsers(), { wrapper }); + + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + + expect(result.current.error).toBeDefined(); + }); + }); + + describe('useCreateUser', () => { + it('should create user and invalidate cache', async () => { + // Arrange + const newUser = { id: '3', name: 'New', email: 'new@test.com' }; + mockUserService.create.mockResolvedValue(newUser); + + // Act + const { result } = renderHook(() => useCreateUser(), { wrapper }); + + await result.current.mutateAsync({ + name: 'New', + email: 'new@test.com', + password: 'Pass123!', + }); + + // Assert + expect(mockUserService.create).toHaveBeenCalled(); + }); + }); +}); +``` + +--- + +## 7. CONVENCIONES DE NOMBRES + +```typescript +// Archivos de test +user.service.spec.ts // Unit test backend +user.controller.spec.ts // Unit test controller +user.e2e-spec.ts // E2E test +UserCard.test.tsx // Component test +useUsers.test.tsx // Hook test + +// Describe blocks +describe('UserService', () => { ... }); +describe('findOne', () => { ... }); + +// Test cases +it('should return user when found', () => { ... }); +it('should throw NotFoundException when user not found', () => { ... }); +``` + +--- + +## 8. CHECKLIST DE TESTING + +``` +Por Service: +[ ] Test de cada mΓ©todo pΓΊblico +[ ] Test de casos de Γ©xito +[ ] Test de casos de error (NotFoundException, etc.) +[ ] Test de validaciones de negocio + +Por Controller: +[ ] Test de cada endpoint +[ ] Test de status codes correctos +[ ] Test de propagaciΓ³n de errores + +Por Componente: +[ ] Test de render correcto +[ ] Test de eventos (click, change) +[ ] Test de estados (loading, error) +[ ] Test de props opcionales + +Por Hook: +[ ] Test de fetch exitoso +[ ] Test de manejo de error +[ ] Test de mutaciones + +Cobertura: +[ ] npm run test:cov muestra 70%+ en services +[ ] npm run test:cov muestra 60%+ en components +[ ] Tests crΓ­ticos e2e pasan +``` + +--- + +## 9. COMANDOS + +```bash +# Backend +npm run test # Unit tests +npm run test:watch # Watch mode +npm run test:cov # Con cobertura +npm run test:e2e # E2E tests + +# Frontend +npm run test # All tests +npm run test -- --watch # Watch mode +npm run test -- --coverage # Con cobertura +npm run test -- UserCard # Test especΓ­fico +``` + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** PatrΓ³n de Testing diff --git a/core/orchestration/patrones/PATRON-TRANSACCIONES.md b/core/orchestration/patrones/PATRON-TRANSACCIONES.md new file mode 100644 index 0000000..b2838ba --- /dev/null +++ b/core/orchestration/patrones/PATRON-TRANSACCIONES.md @@ -0,0 +1,678 @@ +# PATRON DE TRANSACCIONES + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - Seguir para integridad de datos +**Sistema:** SIMCO + CAPVED + +--- + +## PROPOSITO + +Definir patrones de manejo de transacciones de base de datos para garantizar integridad de datos, consistencia y correcta recuperacion de errores. + +--- + +## 1. PRINCIPIOS ACID + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ PROPIEDADES ACID β•‘ +╠══════════════════════════════════════════════════════════════════════╣ +β•‘ β•‘ +β•‘ A - Atomicity (Atomicidad) β•‘ +β•‘ Todo o nada. Si una parte falla, se revierte todo. β•‘ +β•‘ β•‘ +β•‘ C - Consistency (Consistencia) β•‘ +β•‘ La BD pasa de un estado valido a otro estado valido. β•‘ +β•‘ β•‘ +β•‘ I - Isolation (Aislamiento) β•‘ +β•‘ Transacciones concurrentes no interfieren entre si. β•‘ +β•‘ β•‘ +β•‘ D - Durability (Durabilidad) β•‘ +β•‘ Una vez confirmada, la transaccion persiste. β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 2. CUANDO USAR TRANSACCIONES + +### SI Usar Transaccion + +``` +βœ… Multiples operaciones que deben ser atomicas +βœ… Operaciones que afectan multiples tablas relacionadas +βœ… Operaciones financieras o criticas +βœ… Creacion de entidades con relaciones obligatorias +βœ… Actualizaciones que requieren consistencia +``` + +### NO Necesitas Transaccion + +``` +❌ Una sola query simple (SELECT, INSERT, UPDATE) +❌ Operaciones de solo lectura +❌ Operaciones independientes sin relacion +``` + +--- + +## 3. TYPEORM - METODOS DE TRANSACCION + +### 3.1 QueryRunner (Recomendado para control total) + +```typescript +// src/modules/order/services/order.service.ts +import { Injectable } from '@nestjs/common'; +import { DataSource, QueryRunner } from 'typeorm'; + +@Injectable() +export class OrderService { + constructor(private readonly dataSource: DataSource) {} + + async createOrder(dto: CreateOrderDto): Promise { + // Crear QueryRunner + const queryRunner = this.dataSource.createQueryRunner(); + + // Conectar y comenzar transaccion + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + // 1. Crear la orden + const order = queryRunner.manager.create(OrderEntity, { + userId: dto.userId, + status: OrderStatus.PENDING, + total: 0, + }); + await queryRunner.manager.save(order); + + // 2. Crear items y calcular total + let total = 0; + for (const item of dto.items) { + // Verificar stock + const product = await queryRunner.manager.findOne(ProductEntity, { + where: { id: item.productId }, + lock: { mode: 'pessimistic_write' }, // Lock para evitar race condition + }); + + if (!product || product.stock < item.quantity) { + throw new BadRequestException( + `Stock insuficiente para producto ${item.productId}`, + ); + } + + // Crear item + const orderItem = queryRunner.manager.create(OrderItemEntity, { + orderId: order.id, + productId: item.productId, + quantity: item.quantity, + price: product.price, + }); + await queryRunner.manager.save(orderItem); + + // Actualizar stock + product.stock -= item.quantity; + await queryRunner.manager.save(product); + + total += product.price * item.quantity; + } + + // 3. Actualizar total de la orden + order.total = total; + await queryRunner.manager.save(order); + + // 4. Confirmar transaccion + await queryRunner.commitTransaction(); + + return order; + + } catch (error) { + // Revertir en caso de error + await queryRunner.rollbackTransaction(); + throw error; + + } finally { + // Liberar QueryRunner + await queryRunner.release(); + } + } +} +``` + +### 3.2 DataSource.transaction() (Mas simple) + +```typescript +// Para casos mas simples +async createUserWithProfile(dto: CreateUserWithProfileDto): Promise { + return this.dataSource.transaction(async (manager) => { + // Crear usuario + const user = manager.create(UserEntity, { + email: dto.email, + password: await hashPassword(dto.password), + }); + await manager.save(user); + + // Crear perfil + const profile = manager.create(ProfileEntity, { + userId: user.id, + firstName: dto.firstName, + lastName: dto.lastName, + }); + await manager.save(profile); + + return user; + }); +} +``` + +### 3.3 @Transaction Decorator (NestJS) + +```typescript +// src/shared/decorators/transactional.decorator.ts +import { DataSource } from 'typeorm'; + +export function Transactional() { + return function ( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor, + ) { + const originalMethod = descriptor.value; + + descriptor.value = async function (...args: any[]) { + const dataSource: DataSource = this.dataSource; + + return dataSource.transaction(async (manager) => { + // Inyectar manager temporal + const originalManager = this.manager; + this.manager = manager; + + try { + return await originalMethod.apply(this, args); + } finally { + this.manager = originalManager; + } + }); + }; + + return descriptor; + }; +} + +// Uso +@Injectable() +export class OrderService { + constructor( + private readonly dataSource: DataSource, + @InjectRepository(OrderEntity) + private readonly orderRepository: Repository, + ) {} + + private manager: EntityManager; + + @Transactional() + async createOrder(dto: CreateOrderDto): Promise { + // this.manager es el manager transaccional + const order = this.manager.create(OrderEntity, dto); + return this.manager.save(order); + } +} +``` + +--- + +## 4. NIVELES DE AISLAMIENTO + +### Niveles Disponibles + +| Nivel | Dirty Reads | Non-Repeatable Reads | Phantom Reads | +|-------|-------------|---------------------|---------------| +| READ UNCOMMITTED | Posible | Posible | Posible | +| READ COMMITTED | No | Posible | Posible | +| REPEATABLE READ | No | No | Posible | +| SERIALIZABLE | No | No | No | + +### Configurar Nivel de Aislamiento + +```typescript +// Por defecto PostgreSQL usa READ COMMITTED +// Para operaciones criticas, usar SERIALIZABLE + +async processPayment(orderId: string): Promise { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + + // Configurar nivel de aislamiento + await queryRunner.startTransaction('SERIALIZABLE'); + + try { + // Operaciones criticas aqui + await queryRunner.commitTransaction(); + } catch (error) { + await queryRunner.rollbackTransaction(); + + // SERIALIZABLE puede fallar por conflictos + if (error.code === '40001') { // Serialization failure + // Reintentar la transaccion + return this.processPayment(orderId); + } + throw error; + } finally { + await queryRunner.release(); + } +} +``` + +--- + +## 5. LOCKS (BLOQUEOS) + +### 5.1 Pessimistic Locking + +```typescript +// Bloquear fila para escritura (otros esperan) +async updateStock(productId: string, quantity: number): Promise { + return this.dataSource.transaction(async (manager) => { + // Obtener producto con lock exclusivo + const product = await manager.findOne(ProductEntity, { + where: { id: productId }, + lock: { mode: 'pessimistic_write' }, + }); + + if (product.stock < quantity) { + throw new BadRequestException('Stock insuficiente'); + } + + product.stock -= quantity; + await manager.save(product); + }); +} +``` + +### 5.2 Optimistic Locking (Version) + +```typescript +// Entity con columna de version +@Entity() +export class ProductEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + stock: number; + + @VersionColumn() // Auto-incrementa en cada update + version: number; +} + +// El update falla si version cambio (alguien mas modifico) +async updateStock(productId: string, quantity: number): Promise { + const product = await this.productRepository.findOne({ + where: { id: productId }, + }); + + product.stock -= quantity; + + try { + await this.productRepository.save(product); + } catch (error) { + if (error instanceof OptimisticLockVersionMismatchError) { + // Reintentar o notificar conflicto + throw new ConflictException('El producto fue modificado. Reintente.'); + } + throw error; + } +} +``` + +### Cuando Usar Cada Tipo + +| Scenario | Lock Recomendado | +|----------|------------------| +| Alta concurrencia, conflictos raros | Optimistic | +| Operaciones financieras criticas | Pessimistic | +| Updates frecuentes al mismo registro | Pessimistic | +| Lecturas frecuentes, updates raros | Optimistic | + +--- + +## 6. PATRONES COMUNES + +### 6.1 Unit of Work Pattern + +```typescript +// src/shared/database/unit-of-work.ts +@Injectable() +export class UnitOfWork { + private queryRunner: QueryRunner; + + constructor(private readonly dataSource: DataSource) {} + + async begin(): Promise { + this.queryRunner = this.dataSource.createQueryRunner(); + await this.queryRunner.connect(); + await this.queryRunner.startTransaction(); + } + + getRepository(entity: EntityTarget): Repository { + return this.queryRunner.manager.getRepository(entity); + } + + async commit(): Promise { + await this.queryRunner.commitTransaction(); + await this.queryRunner.release(); + } + + async rollback(): Promise { + await this.queryRunner.rollbackTransaction(); + await this.queryRunner.release(); + } +} + +// Uso +@Injectable() +export class OrderService { + constructor(private readonly uow: UnitOfWork) {} + + async createOrder(dto: CreateOrderDto): Promise { + await this.uow.begin(); + + try { + const orderRepo = this.uow.getRepository(OrderEntity); + const productRepo = this.uow.getRepository(ProductEntity); + + // Operaciones... + + await this.uow.commit(); + return order; + } catch (error) { + await this.uow.rollback(); + throw error; + } + } +} +``` + +### 6.2 Saga Pattern (Para transacciones distribuidas) + +```typescript +// Cuando no puedes usar transaccion de BD (microservicios) +interface SagaStep { + execute(): Promise; + compensate(): Promise; // Revertir si falla +} + +class CreateOrderSaga { + private executedSteps: SagaStep[] = []; + + async execute(steps: SagaStep[]): Promise { + try { + for (const step of steps) { + await step.execute(); + this.executedSteps.push(step); + } + } catch (error) { + // Compensar en orden inverso + for (const step of this.executedSteps.reverse()) { + await step.compensate(); + } + throw error; + } + } +} + +// Uso +const saga = new CreateOrderSaga(); +await saga.execute([ + { + execute: () => this.orderService.create(orderDto), + compensate: () => this.orderService.delete(orderId), + }, + { + execute: () => this.inventoryService.reserve(items), + compensate: () => this.inventoryService.release(items), + }, + { + execute: () => this.paymentService.charge(payment), + compensate: () => this.paymentService.refund(payment), + }, +]); +``` + +### 6.3 Retry con Backoff + +```typescript +// Para manejar deadlocks y conflictos +async withRetry( + operation: () => Promise, + maxRetries: number = 3, + baseDelay: number = 100, +): Promise { + let lastError: Error; + + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + return await operation(); + } catch (error) { + lastError = error; + + // Solo reintentar errores transitorios + const isRetryable = + error.code === '40001' || // Serialization failure + error.code === '40P01' || // Deadlock + error.code === '55P03'; // Lock not available + + if (!isRetryable || attempt === maxRetries) { + throw error; + } + + // Exponential backoff con jitter + const delay = baseDelay * Math.pow(2, attempt - 1) * (0.5 + Math.random()); + await new Promise(resolve => setTimeout(resolve, delay)); + } + } + + throw lastError; +} + +// Uso +async createOrder(dto: CreateOrderDto): Promise { + return this.withRetry(() => this.createOrderTransaction(dto)); +} +``` + +--- + +## 7. ERRORES COMUNES Y SOLUCIONES + +### 7.1 Deadlock + +```typescript +// ❌ PROBLEMA: Deadlock por orden inconsistente de locks +// Transaction 1: Lock A, then B +// Transaction 2: Lock B, then A + +// βœ… SOLUCION: Siempre lockear en el mismo orden +async transferFunds(fromId: string, toId: string, amount: number): Promise { + // Ordenar IDs para lockear siempre en el mismo orden + const [firstId, secondId] = [fromId, toId].sort(); + + return this.dataSource.transaction(async (manager) => { + const firstAccount = await manager.findOne(AccountEntity, { + where: { id: firstId }, + lock: { mode: 'pessimistic_write' }, + }); + + const secondAccount = await manager.findOne(AccountEntity, { + where: { id: secondId }, + lock: { mode: 'pessimistic_write' }, + }); + + // Ahora operar + const from = firstId === fromId ? firstAccount : secondAccount; + const to = firstId === toId ? firstAccount : secondAccount; + + from.balance -= amount; + to.balance += amount; + + await manager.save([from, to]); + }); +} +``` + +### 7.2 Connection Leak + +```typescript +// ❌ PROBLEMA: QueryRunner no liberado +async badMethod(): Promise { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + const data = await queryRunner.manager.find(Entity); + // Si hay error aqui, queryRunner nunca se libera! + + await queryRunner.commitTransaction(); + await queryRunner.release(); +} + +// βœ… SOLUCION: Siempre usar try/finally +async goodMethod(): Promise { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + const data = await queryRunner.manager.find(Entity); + await queryRunner.commitTransaction(); + } catch (error) { + await queryRunner.rollbackTransaction(); + throw error; + } finally { + await queryRunner.release(); // SIEMPRE se ejecuta + } +} +``` + +### 7.3 Long-Running Transactions + +```typescript +// ❌ PROBLEMA: Transaccion muy larga +async processAllOrders(): Promise { + return this.dataSource.transaction(async (manager) => { + const orders = await manager.find(OrderEntity); // Puede ser miles + for (const order of orders) { + await this.processOrder(order); // Minutos de bloqueo + } + }); +} + +// βœ… SOLUCION: Procesar en batches con transacciones cortas +async processAllOrders(): Promise { + const BATCH_SIZE = 100; + let processed = 0; + + while (true) { + const orders = await this.orderRepository.find({ + where: { status: OrderStatus.PENDING }, + take: BATCH_SIZE, + }); + + if (orders.length === 0) break; + + // Transaccion corta por batch + await this.dataSource.transaction(async (manager) => { + for (const order of orders) { + await this.processOrderInTransaction(manager, order); + } + }); + + processed += orders.length; + } +} +``` + +--- + +## 8. TESTING DE TRANSACCIONES + +```typescript +// src/modules/order/order.service.spec.ts +describe('OrderService', () => { + let service: OrderService; + let dataSource: DataSource; + + beforeEach(async () => { + const module = await Test.createTestingModule({ + imports: [TypeOrmModule.forRoot(testConfig)], + providers: [OrderService], + }).compile(); + + service = module.get(OrderService); + dataSource = module.get(DataSource); + }); + + afterEach(async () => { + // Limpiar despues de cada test + await dataSource.synchronize(true); + }); + + describe('createOrder', () => { + it('should rollback if stock is insufficient', async () => { + // Arrange + const product = await productRepo.save({ + name: 'Test', + stock: 5, + price: 100, + }); + + // Act & Assert + await expect( + service.createOrder({ + items: [{ productId: product.id, quantity: 10 }], + }), + ).rejects.toThrow('Stock insuficiente'); + + // Verificar que stock no cambio (rollback funciono) + const updatedProduct = await productRepo.findOne({ + where: { id: product.id }, + }); + expect(updatedProduct.stock).toBe(5); + }); + + it('should commit successfully with valid data', async () => { + // ... + }); + }); +}); +``` + +--- + +## 9. CHECKLIST DE TRANSACCIONES + +``` +Antes de implementar: +[ ] ΒΏNecesito atomicidad? (multiples operaciones) +[ ] ΒΏQue nivel de aislamiento necesito? +[ ] ΒΏNecesito locks? ΒΏPesimista u optimista? + +Durante implementacion: +[ ] QueryRunner siempre liberado (finally) +[ ] Rollback en catch +[ ] Manejo de errores transitorios (retry) +[ ] Transacciones lo mas cortas posible +[ ] Orden consistente de locks (evitar deadlocks) + +Testing: +[ ] Test de rollback en error +[ ] Test de commit exitoso +[ ] Test de concurrencia (si aplica) +``` + +--- + +**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Patron de Codigo diff --git a/core/orchestration/patrones/PATRON-VALIDACION.md b/core/orchestration/patrones/PATRON-VALIDACION.md new file mode 100644 index 0000000..9a5f9e8 --- /dev/null +++ b/core/orchestration/patrones/PATRON-VALIDACION.md @@ -0,0 +1,619 @@ +# PATRΓ“N: VALIDACIΓ“N DE DATOS + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Aplica a:** Backend (NestJS/Express), Frontend (React) +**Prioridad:** OBLIGATORIA + +--- + +## PROPΓ“SITO + +Definir patrones estΓ‘ndar de validaciΓ³n de datos para garantizar consistencia en toda la aplicaciΓ³n. + +--- + +## PRINCIPIO FUNDAMENTAL + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ VALIDACIΓ“N EN CAPAS β•‘ +β•‘ β•‘ +β•‘ 1. Frontend: UX inmediata (opcional pero recomendada) β•‘ +β•‘ 2. DTO: ValidaciΓ³n de entrada (OBLIGATORIA) β•‘ +β•‘ 3. Service: ValidaciΓ³n de negocio (cuando aplica) β•‘ +β•‘ 4. Database: Constraints (ΓΊltima lΓ­nea de defensa) β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 1. VALIDACIΓ“N EN DTO (NestJS - class-validator) + +### Decoradores BΓ‘sicos + +```typescript +import { + IsString, + IsEmail, + IsNotEmpty, + IsOptional, + IsUUID, + IsInt, + IsNumber, + IsBoolean, + IsDate, + IsArray, + IsEnum, + IsUrl, + IsPhoneNumber, +} from 'class-validator'; +``` + +### Decoradores de Longitud + +```typescript +import { + Length, + MinLength, + MaxLength, + Min, + Max, + ArrayMinSize, + ArrayMaxSize, +} from 'class-validator'; +``` + +### Decoradores de Formato + +```typescript +import { + Matches, + IsAlpha, + IsAlphanumeric, + IsAscii, + Contains, + IsISO8601, + IsCreditCard, + IsHexColor, + IsJSON, +} from 'class-validator'; +``` + +--- + +## 2. PATRONES POR TIPO DE DATO + +### Email + +```typescript +// PATRΓ“N ESTÁNDAR +@ApiProperty({ + description: 'Correo electrΓ³nico del usuario', + example: 'usuario@empresa.com', +}) +@IsEmail({}, { message: 'El correo electrΓ³nico no es vΓ‘lido' }) +@IsNotEmpty({ message: 'El correo electrΓ³nico es requerido' }) +@MaxLength(255, { message: 'El correo no puede exceder 255 caracteres' }) +@Transform(({ value }) => value?.toLowerCase().trim()) +email: string; +``` + +### Password + +```typescript +// PATRΓ“N ESTÁNDAR - ContraseΓ±a segura +@ApiProperty({ + description: 'ContraseΓ±a (mΓ­n 8 caracteres, 1 mayΓΊscula, 1 nΓΊmero, 1 especial)', + example: 'MiPassword123!', +}) +@IsString() +@IsNotEmpty({ message: 'La contraseΓ±a es requerida' }) +@MinLength(8, { message: 'La contraseΓ±a debe tener al menos 8 caracteres' }) +@MaxLength(100, { message: 'La contraseΓ±a no puede exceder 100 caracteres' }) +@Matches( + /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]+$/, + { message: 'La contraseΓ±a debe contener mayΓΊscula, minΓΊscula, nΓΊmero y carΓ‘cter especial' } +) +password: string; +``` + +### UUID + +```typescript +// PATRΓ“N ESTÁNDAR +@ApiProperty({ + description: 'ID ΓΊnico del recurso', + example: '550e8400-e29b-41d4-a716-446655440000', +}) +@IsUUID('4', { message: 'El ID debe ser un UUID vΓ‘lido' }) +@IsNotEmpty({ message: 'El ID es requerido' }) +id: string; + +// UUID Opcional (para referencias) +@ApiPropertyOptional({ + description: 'ID del usuario relacionado', +}) +@IsOptional() +@IsUUID('4', { message: 'El ID de usuario debe ser un UUID vΓ‘lido' }) +userId?: string; +``` + +### Nombre/Texto Simple + +```typescript +// PATRΓ“N ESTÁNDAR +@ApiProperty({ + description: 'Nombre del usuario', + example: 'Juan PΓ©rez', + minLength: 2, + maxLength: 100, +}) +@IsString({ message: 'El nombre debe ser texto' }) +@IsNotEmpty({ message: 'El nombre es requerido' }) +@MinLength(2, { message: 'El nombre debe tener al menos 2 caracteres' }) +@MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) +@Transform(({ value }) => value?.trim()) +name: string; +``` + +### NΓΊmero Entero + +```typescript +// PATRΓ“N ESTÁNDAR - Entero positivo +@ApiProperty({ + description: 'Cantidad de items', + example: 10, + minimum: 1, +}) +@IsInt({ message: 'La cantidad debe ser un nΓΊmero entero' }) +@Min(1, { message: 'La cantidad mΓ­nima es 1' }) +@Max(10000, { message: 'La cantidad mΓ‘xima es 10,000' }) +quantity: number; + +// Entero con valor por defecto +@ApiPropertyOptional({ + description: 'PΓ‘gina actual', + default: 1, +}) +@IsOptional() +@IsInt() +@Min(1) +@Transform(({ value }) => parseInt(value) || 1) +page?: number = 1; +``` + +### NΓΊmero Decimal (Dinero) + +```typescript +// PATRΓ“N ESTÁNDAR - Precio/Dinero +@ApiProperty({ + description: 'Precio del producto', + example: 99.99, + minimum: 0, +}) +@IsNumber( + { maxDecimalPlaces: 2 }, + { message: 'El precio debe tener mΓ‘ximo 2 decimales' } +) +@Min(0, { message: 'El precio no puede ser negativo' }) +@Max(999999.99, { message: 'El precio mΓ‘ximo es 999,999.99' }) +price: number; +``` + +### Boolean + +```typescript +// PATRΓ“N ESTÁNDAR +@ApiProperty({ + description: 'Estado activo del usuario', + example: true, +}) +@IsBoolean({ message: 'El valor debe ser verdadero o falso' }) +@IsNotEmpty() +isActive: boolean; + +// Boolean opcional con default +@ApiPropertyOptional({ + description: 'Enviar notificaciΓ³n', + default: false, +}) +@IsOptional() +@IsBoolean() +@Transform(({ value }) => value === 'true' || value === true) +sendNotification?: boolean = false; +``` + +### Enum + +```typescript +// PATRΓ“N ESTÁNDAR +export enum UserStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', + SUSPENDED = 'suspended', +} + +@ApiProperty({ + description: 'Estado del usuario', + enum: UserStatus, + example: UserStatus.ACTIVE, +}) +@IsEnum(UserStatus, { message: 'El estado debe ser: active, inactive o suspended' }) +@IsNotEmpty() +status: UserStatus; +``` + +### Fecha + +```typescript +// PATRΓ“N ESTÁNDAR - Fecha ISO +@ApiProperty({ + description: 'Fecha de nacimiento', + example: '1990-05-15', +}) +@IsISO8601({}, { message: 'La fecha debe estar en formato ISO 8601' }) +@IsNotEmpty() +birthDate: string; + +// Fecha como Date object +@ApiProperty({ + description: 'Fecha de inicio', + example: '2024-01-15T10:30:00Z', +}) +@IsDate({ message: 'Debe ser una fecha vΓ‘lida' }) +@Type(() => Date) +@IsNotEmpty() +startDate: Date; +``` + +### URL + +```typescript +// PATRΓ“N ESTÁNDAR +@ApiPropertyOptional({ + description: 'URL del avatar', + example: 'https://example.com/avatar.jpg', +}) +@IsOptional() +@IsUrl({}, { message: 'La URL no es vΓ‘lida' }) +@MaxLength(500) +avatarUrl?: string; +``` + +### TelΓ©fono + +```typescript +// PATRΓ“N ESTÁNDAR - MΓ©xico +@ApiPropertyOptional({ + description: 'NΓΊmero de telΓ©fono', + example: '+521234567890', +}) +@IsOptional() +@IsPhoneNumber('MX', { message: 'El nΓΊmero de telΓ©fono no es vΓ‘lido' }) +phone?: string; + +// Alternativa con Regex +@IsOptional() +@Matches(/^\+?[1-9]\d{1,14}$/, { message: 'Formato de telΓ©fono invΓ‘lido' }) +phone?: string; +``` + +### Array + +```typescript +// PATRΓ“N ESTÁNDAR - Array de strings +@ApiProperty({ + description: 'Etiquetas del producto', + example: ['electrΓ³nica', 'ofertas'], + type: [String], +}) +@IsArray({ message: 'Las etiquetas deben ser un arreglo' }) +@IsString({ each: true, message: 'Cada etiqueta debe ser texto' }) +@ArrayMinSize(1, { message: 'Debe haber al menos una etiqueta' }) +@ArrayMaxSize(10, { message: 'MΓ‘ximo 10 etiquetas permitidas' }) +tags: string[]; + +// Array de UUIDs +@ApiProperty({ + description: 'IDs de categorΓ­as', + type: [String], +}) +@IsArray() +@IsUUID('4', { each: true, message: 'Cada ID debe ser un UUID vΓ‘lido' }) +@ArrayMinSize(1) +categoryIds: string[]; +``` + +### JSON/Object + +```typescript +// PATRΓ“N ESTÁNDAR - Objeto flexible +@ApiPropertyOptional({ + description: 'Metadatos adicionales', + example: { key: 'value' }, +}) +@IsOptional() +@IsObject({ message: 'Los metadatos deben ser un objeto' }) +metadata?: Record; + +// Objeto con estructura definida (usar class anidada) +class AddressDto { + @IsString() + @IsNotEmpty() + street: string; + + @IsString() + @IsNotEmpty() + city: string; + + @IsString() + @Length(5, 5) + zipCode: string; +} + +@ApiProperty({ type: AddressDto }) +@ValidateNested() +@Type(() => AddressDto) +address: AddressDto; +``` + +--- + +## 3. DTOs ESTÁNDAR + +### CreateDto Pattern + +```typescript +/** + * DTO para crear usuario + * + * @example + * { + * "email": "user@example.com", + * "password": "SecurePass123!", + * "name": "Juan PΓ©rez" + * } + */ +export class CreateUserDto { + @ApiProperty({ description: 'Email del usuario', example: 'user@example.com' }) + @IsEmail() + @IsNotEmpty() + @MaxLength(255) + @Transform(({ value }) => value?.toLowerCase().trim()) + email: string; + + @ApiProperty({ description: 'ContraseΓ±a', example: 'SecurePass123!' }) + @IsString() + @IsNotEmpty() + @MinLength(8) + @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])/) + password: string; + + @ApiProperty({ description: 'Nombre completo', example: 'Juan PΓ©rez' }) + @IsString() + @IsNotEmpty() + @MinLength(2) + @MaxLength(100) + @Transform(({ value }) => value?.trim()) + name: string; + + @ApiPropertyOptional({ description: 'TelΓ©fono', example: '+521234567890' }) + @IsOptional() + @IsPhoneNumber('MX') + phone?: string; +} +``` + +### UpdateDto Pattern + +```typescript +import { PartialType, OmitType } from '@nestjs/swagger'; + +/** + * DTO para actualizar usuario + * + * Todos los campos son opcionales. + * Email y password NO se pueden actualizar aquΓ­. + */ +export class UpdateUserDto extends PartialType( + OmitType(CreateUserDto, ['email', 'password'] as const) +) {} +``` + +### QueryDto Pattern (Filtros y PaginaciΓ³n) + +```typescript +/** + * DTO para bΓΊsqueda y paginaciΓ³n de usuarios + */ +export class QueryUsersDto { + @ApiPropertyOptional({ description: 'PΓ‘gina', default: 1 }) + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + page?: number = 1; + + @ApiPropertyOptional({ description: 'Items por pΓ‘gina', default: 20 }) + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + @Max(100) + limit?: number = 20; + + @ApiPropertyOptional({ description: 'Buscar por nombre o email' }) + @IsOptional() + @IsString() + @MaxLength(100) + search?: string; + + @ApiPropertyOptional({ description: 'Filtrar por estado', enum: UserStatus }) + @IsOptional() + @IsEnum(UserStatus) + status?: UserStatus; + + @ApiPropertyOptional({ description: 'Ordenar por campo' }) + @IsOptional() + @IsIn(['name', 'email', 'createdAt']) + sortBy?: string = 'createdAt'; + + @ApiPropertyOptional({ description: 'DirecciΓ³n de orden', enum: ['asc', 'desc'] }) + @IsOptional() + @IsIn(['asc', 'desc']) + sortOrder?: 'asc' | 'desc' = 'desc'; +} +``` + +--- + +## 4. VALIDACIΓ“N EN SERVICE (LΓ³gica de Negocio) + +```typescript +@Injectable() +export class UserService { + async create(dto: CreateUserDto): Promise { + // ValidaciΓ³n de negocio (despuΓ©s de DTO) + + // 1. Verificar unicidad + const existing = await this.repository.findOne({ + where: { email: dto.email }, + }); + if (existing) { + throw new ConflictException('El email ya estΓ‘ registrado'); + } + + // 2. Validar reglas de negocio + if (await this.isEmailDomainBlocked(dto.email)) { + throw new BadRequestException('Dominio de email no permitido'); + } + + // 3. Validar lΓ­mites + const userCount = await this.repository.count({ + where: { tenantId: dto.tenantId }, + }); + if (userCount >= this.MAX_USERS_PER_TENANT) { + throw new ForbiddenException('LΓ­mite de usuarios alcanzado'); + } + + // Proceder con creaciΓ³n + const user = this.repository.create(dto); + return this.repository.save(user); + } +} +``` + +--- + +## 5. VALIDACIΓ“N EN FRONTEND (React) + +### Con React Hook Form + Zod + +```typescript +import { z } from 'zod'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; + +// Schema de validaciΓ³n (espejo del DTO backend) +const createUserSchema = z.object({ + email: z + .string() + .min(1, 'El email es requerido') + .email('Email invΓ‘lido') + .max(255), + password: z + .string() + .min(8, 'MΓ­nimo 8 caracteres') + .regex( + /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])/, + 'Debe contener mayΓΊscula, minΓΊscula, nΓΊmero y carΓ‘cter especial' + ), + name: z + .string() + .min(2, 'MΓ­nimo 2 caracteres') + .max(100, 'MΓ‘ximo 100 caracteres'), + phone: z + .string() + .regex(/^\+?[1-9]\d{1,14}$/, 'TelΓ©fono invΓ‘lido') + .optional(), +}); + +type CreateUserForm = z.infer; + +// Uso en componente +const UserForm = () => { + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(createUserSchema), + }); + + const onSubmit = async (data: CreateUserForm) => { + // data ya estΓ‘ validado + await userService.create(data); + }; + + return ( +
+ + {errors.email && {errors.email.message}} + {/* ... */} +
+ ); +}; +``` + +--- + +## 6. MENSAJES DE ERROR ESTÁNDAR + +```typescript +// Mensajes consistentes en espaΓ±ol +const VALIDATION_MESSAGES = { + required: (field: string) => `${field} es requerido`, + minLength: (field: string, min: number) => `${field} debe tener al menos ${min} caracteres`, + maxLength: (field: string, max: number) => `${field} no puede exceder ${max} caracteres`, + email: 'El correo electrΓ³nico no es vΓ‘lido', + uuid: 'El ID no es vΓ‘lido', + enum: (values: string[]) => `El valor debe ser uno de: ${values.join(', ')}`, + min: (field: string, min: number) => `${field} debe ser mayor o igual a ${min}`, + max: (field: string, max: number) => `${field} debe ser menor o igual a ${max}`, + pattern: (field: string) => `${field} tiene un formato invΓ‘lido`, + unique: (field: string) => `${field} ya existe`, +}; +``` + +--- + +## CHECKLIST DE VALIDACIΓ“N + +``` +DTO: +[ ] Cada campo tiene @ApiProperty o @ApiPropertyOptional +[ ] Campos requeridos tienen @IsNotEmpty +[ ] Campos opcionales tienen @IsOptional +[ ] Tipos validados (@IsString, @IsNumber, etc.) +[ ] Longitudes validadas (@MinLength, @MaxLength) +[ ] Formatos validados (@IsEmail, @IsUUID, etc.) +[ ] Transformaciones aplicadas (@Transform) +[ ] Mensajes de error en espaΓ±ol + +Service: +[ ] ValidaciΓ³n de unicidad +[ ] ValidaciΓ³n de existencia (referencias) +[ ] ValidaciΓ³n de reglas de negocio +[ ] ValidaciΓ³n de permisos + +Frontend: +[ ] Schema Zod espeja DTO backend +[ ] Mensajes de error visibles +[ ] ValidaciΓ³n en submit +[ ] ValidaciΓ³n en blur (opcional) +``` + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** PatrΓ³n de ValidaciΓ³n diff --git a/core/orchestration/procesos/ORDEN-IMPLEMENTACION.md b/core/orchestration/procesos/ORDEN-IMPLEMENTACION.md new file mode 100644 index 0000000..108e436 --- /dev/null +++ b/core/orchestration/procesos/ORDEN-IMPLEMENTACION.md @@ -0,0 +1,413 @@ +# ORDEN DE IMPLEMENTACIΓ“N + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Prioridad:** OBLIGATORIA - DDL-First +**Sistema:** SIMCO + CAPVED + +--- + +## PROPΓ“SITO + +Definir el orden correcto de implementaciΓ³n cuando una tarea toca mΓΊltiples capas. + +--- + +## PRINCIPIO FUNDAMENTAL + +``` +╔══════════════════════════════════════════════════════════════════════╗ +β•‘ DDL-FIRST: La Base de Datos es la Fuente de Verdad β•‘ +β•‘ β•‘ +β•‘ ORDEN OBLIGATORIO: β•‘ +β•‘ β•‘ +β•‘ 1. DATABASE β†’ Tablas existen β•‘ +β•‘ 2. BACKEND β†’ Entity refleja DDL β•‘ +β•‘ 3. FRONTEND β†’ Types reflejan DTOs β•‘ +β•‘ β•‘ +β•‘ ⚠️ NUNCA invertir este orden β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` + +--- + +## 1. FLUJO COMPLETO DE IMPLEMENTACIΓ“N + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FASE 1: BASE DE DATOS β”‚ +β”‚ (Database-Agent) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [ ] 1.1 Crear/modificar archivo DDL β”‚ +β”‚ [ ] 1.2 Definir columnas con tipos correctos β”‚ +β”‚ [ ] 1.3 Definir PK, FK, constraints β”‚ +β”‚ [ ] 1.4 Crear Γ­ndices necesarios β”‚ +β”‚ [ ] 1.5 Ejecutar carga limpia (recreate-database.sh) β”‚ +β”‚ [ ] 1.6 Verificar con \dt, \d {tabla} β”‚ +β”‚ [ ] 1.7 Actualizar DATABASE_INVENTORY.yml β”‚ +β”‚ [ ] 1.8 Registrar en TRAZA-TAREAS-DATABASE.md β”‚ +β”‚ β”‚ +β”‚ GATE: Carga limpia exitosa antes de continuar β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FASE 2: BACKEND β”‚ +β”‚ (Backend-Agent) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [ ] 2.1 Crear Entity alineada con DDL (ver MAPEO-TIPOS.md) β”‚ +β”‚ [ ] 2.2 Crear CreateDto con validaciones β”‚ +β”‚ [ ] 2.3 Crear UpdateDto (extends PartialType) β”‚ +β”‚ [ ] 2.4 Crear ResponseDto β”‚ +β”‚ [ ] 2.5 Crear Service con lΓ³gica de negocio β”‚ +β”‚ [ ] 2.6 Crear Controller con Swagger decorators β”‚ +β”‚ [ ] 2.7 Registrar en Module β”‚ +β”‚ [ ] 2.8 Ejecutar: npm run build β”‚ +β”‚ [ ] 2.9 Ejecutar: npm run lint β”‚ +β”‚ [ ] 2.10 Ejecutar: npm run test (si hay tests) β”‚ +β”‚ [ ] 2.11 Actualizar BACKEND_INVENTORY.yml β”‚ +β”‚ [ ] 2.12 Registrar en TRAZA-TAREAS-BACKEND.md β”‚ +β”‚ β”‚ +β”‚ GATE: Build y lint pasan antes de continuar β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FASE 3: FRONTEND β”‚ +β”‚ (Frontend-Agent) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [ ] 3.1 Crear types/interfaces (alineados con ResponseDto) β”‚ +β”‚ [ ] 3.2 Crear Zod schema (alineado con CreateDto) β”‚ +β”‚ [ ] 3.3 Crear API service β”‚ +β”‚ [ ] 3.4 Crear custom hook (useQuery/useMutation) β”‚ +β”‚ [ ] 3.5 Crear componentes necesarios β”‚ +β”‚ [ ] 3.6 Crear pΓ‘gina/formulario β”‚ +β”‚ [ ] 3.7 Ejecutar: npm run build β”‚ +β”‚ [ ] 3.8 Ejecutar: npm run lint β”‚ +β”‚ [ ] 3.9 Ejecutar: npm run typecheck β”‚ +β”‚ [ ] 3.10 Actualizar FRONTEND_INVENTORY.yml β”‚ +β”‚ [ ] 3.11 Registrar en TRAZA-TAREAS-FRONTEND.md β”‚ +β”‚ β”‚ +β”‚ GATE: Build, lint y typecheck pasan β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FASE 4: INTEGRACIΓ“N β”‚ +β”‚ (Orquestador) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [ ] 4.1 Verificar flujo completo funciona β”‚ +β”‚ [ ] 4.2 Verificar Swagger documenta correctamente β”‚ +β”‚ [ ] 4.3 Tests e2e (si existen) β”‚ +β”‚ [ ] 4.4 Actualizar MASTER_INVENTORY.yml β”‚ +β”‚ [ ] 4.5 Actualizar PROXIMA-ACCION.md β”‚ +β”‚ [ ] 4.6 Propagar a niveles superiores (SIMCO-PROPAGACION.md) β”‚ +β”‚ β”‚ +β”‚ GATE: Todo funciona end-to-end β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 2. POR QUΓ‰ DDL-FIRST + +### Problema: Backend-First + +```typescript +// Alguien crea Entity primero sin DDL... +@Entity() +export class ProductEntity { + @Column() + price: number; // ← Asume que existe en BD +} + +// Resultado: +// - TypeORM syncronize: Crea tabla con tipos incorrectos +// - Sin syncronize: Error en runtime "column not found" +// - Nadie sabe quΓ© tipo deberΓ­a ser price (DECIMAL? NUMERIC? INTEGER?) +``` + +### SoluciΓ³n: DDL-First + +```sql +-- 1. DDL define la verdad +CREATE TABLE products ( + price DECIMAL(10,2) NOT NULL -- ExplΓ­cito: 10 dΓ­gitos, 2 decimales +); +``` + +```typescript +// 2. Entity REFLEJA la verdad +@Column({ type: 'decimal', precision: 10, scale: 2 }) +price: string; // String para precisiΓ³n decimal + +// 3. DTO documenta para Swagger +@ApiProperty({ example: 99.99 }) +@IsNumber({ maxDecimalPlaces: 2 }) +price: number; +``` + +--- + +## 3. DEPENDENCIAS ENTRE CAPAS + +### Diagrama de Dependencias + +``` + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ DATABASE β”‚ + β”‚ (DDL) β”‚ + β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”‚ Entity refleja DDL + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ BACKEND β”‚ + β”‚ (Entity,DTO) β”‚ + β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”‚ Types reflejan DTOs + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ FRONTEND β”‚ + β”‚(Types,Forms) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Reglas de Dependencia + +| Si cambias... | Debes actualizar... | En ese orden | +|---------------|---------------------|--------------| +| DDL columna | Entity β†’ DTO β†’ Types | DDL β†’ BE β†’ FE | +| Entity campo | DTO β†’ Types | BE β†’ FE | +| DTO campo | Types | BE β†’ FE | +| Types | - | FE solo | + +--- + +## 4. ANTI-PATRONES DE ORDEN + +### Anti-PatrΓ³n 1: Frontend First + +``` +❌ INCORRECTO: +1. Frontend-Agent crea formulario +2. Backend-Agent crea endpoint +3. Database-Agent... ΒΏquΓ© campos necesita? + +RESULTADO: +- Frontend asume campos que no existen +- Backend inventa estructura +- Database no sabe quΓ© crear +- Retrabajos mΓΊltiples +``` + +### Anti-PatrΓ³n 2: Parallel sin CoordinaciΓ³n + +``` +❌ INCORRECTO: +1. Database-Agent crea tabla (en paralelo) +2. Backend-Agent crea entity (en paralelo) +3. Frontend-Agent crea types (en paralelo) + +RESULTADO: +- Cada uno asume diferente +- Tipos no coinciden +- Errores en integraciΓ³n +``` + +### Anti-PatrΓ³n 3: Saltar ValidaciΓ³n + +``` +❌ INCORRECTO: +1. Database-Agent crea tabla (OK) +2. Backend-Agent crea entity (sin build) +3. Frontend-Agent crea types (sin typecheck) + +RESULTADO: +- Errores no detectados hasta runtime +- Bugs en producciΓ³n +- Debug difΓ­cil +``` + +--- + +## 5. TEMPLATES POR CASO + +### Caso A: Feature Nueva Completa + +``` +TAREA: Crear sistema de comentarios + +FASE 1: DATABASE (Database-Agent) +═══════════════════════════════════════════════════════════════ +Crear: schemas/core/tables/05-comments.sql + +CREATE TABLE core.comments ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + content TEXT NOT NULL, + user_id UUID NOT NULL REFERENCES auth.users(id), + post_id UUID NOT NULL REFERENCES core.posts(id), + parent_id UUID REFERENCES core.comments(id), + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +CREATE INDEX idx_comments_post ON core.comments(post_id); +CREATE INDEX idx_comments_user ON core.comments(user_id); + +Validar: ./recreate-database.sh && psql -c "\d core.comments" + +FASE 2: BACKEND (Backend-Agent) +═══════════════════════════════════════════════════════════════ +Crear: +- modules/comment/entities/comment.entity.ts +- modules/comment/dto/create-comment.dto.ts +- modules/comment/dto/update-comment.dto.ts +- modules/comment/dto/comment-response.dto.ts +- modules/comment/services/comment.service.ts +- modules/comment/controllers/comment.controller.ts +- modules/comment/comment.module.ts + +Validar: npm run build && npm run lint + +FASE 3: FRONTEND (Frontend-Agent) +═══════════════════════════════════════════════════════════════ +Crear: +- shared/types/comment.types.ts +- shared/services/comment.service.ts +- apps/web/hooks/useComments.ts +- apps/web/components/comments/CommentCard.tsx +- apps/web/components/comments/CommentForm.tsx +- apps/web/components/comments/CommentList.tsx + +Validar: npm run build && npm run lint && npm run typecheck + +FASE 4: INTEGRACIΓ“N +═══════════════════════════════════════════════════════════════ +- Test flujo completo +- Verificar Swagger +- Actualizar inventarios +``` + +### Caso B: Agregar Campo a Feature Existente + +``` +TAREA: Agregar campo "rating" a comments + +FASE 1: DATABASE +═══════════════════════════════════════════════════════════════ +ALTER TABLE core.comments ADD COLUMN rating INTEGER CHECK (rating BETWEEN 1 AND 5); + +Validar: Carga limpia + +FASE 2: BACKEND +═══════════════════════════════════════════════════════════════ +- Agregar @Column en CommentEntity +- Agregar campo en CreateCommentDto con @IsInt @Min(1) @Max(5) +- Agregar en ResponseDto + +Validar: npm run build + +FASE 3: FRONTEND +═══════════════════════════════════════════════════════════════ +- Agregar rating en Comment interface +- Agregar input en CommentForm +- Mostrar en CommentCard + +Validar: npm run build && npm run typecheck +``` + +### Caso C: Cambio Solo en Backend (Nueva LΓ³gica) + +``` +TAREA: Agregar validaciΓ³n de spam en comentarios + +FASE 1: DATABASE +═══════════════════════════════════════════════════════════════ +- SIN CAMBIOS (lΓ³gica no afecta schema) + +FASE 2: BACKEND +═══════════════════════════════════════════════════════════════ +- Agregar SpamService +- Modificar CommentService.create() para validar + +Validar: npm run build && npm run test + +FASE 3: FRONTEND +═══════════════════════════════════════════════════════════════ +- SIN CAMBIOS (endpoint sigue igual) +- Posible: Mostrar error si spam detectado +``` + +--- + +## 6. CHECKLIST RÁPIDO + +``` +Antes de empezar implementaciΓ³n: +[ ] ΒΏLa tabla existe en DDL? Si no β†’ DATABASE primero +[ ] ΒΏEntity refleja DDL actual? Si no β†’ Actualizar Entity +[ ] ΒΏDTOs coinciden con Entity? Si no β†’ Actualizar DTOs +[ ] ΒΏTypes coinciden con DTOs? Si no β†’ Actualizar Types + +Durante implementaciΓ³n: +[ ] No crear Entity sin DDL +[ ] No crear Types sin DTOs +[ ] No modificar DDL sin actualizar Entity +[ ] No modificar DTO sin actualizar Types + +DespuΓ©s de cada capa: +[ ] Build pasa +[ ] Lint pasa +[ ] Tests pasan (si existen) +[ ] Inventario actualizado +``` + +--- + +## 7. COMANDOS DE VALIDACIΓ“N + +```bash +# FASE 1: Validar Database +cd {DB_SCRIPTS_PATH} +./recreate-database.sh +psql -d {DB_NAME} -c "\dt {schema}.*" +psql -d {DB_NAME} -c "\d {schema}.{tabla}" + +# FASE 2: Validar Backend +cd {BACKEND_ROOT} +npm run build +npm run lint +npm run test + +# FASE 3: Validar Frontend +cd {FRONTEND_ROOT} +npm run build +npm run lint +npm run typecheck + +# FASE 4: Validar IntegraciΓ³n +curl http://localhost:3000/api/{endpoint} +# Verificar respuesta correcta +``` + +--- + +## 8. MATRIZ DE DELEGACIΓ“N + +| Tarea | Database-Agent | Backend-Agent | Frontend-Agent | Orquestador | +|-------|----------------|---------------|----------------|-------------| +| Crear tabla | βœ… | ❌ | ❌ | Coordina | +| Modificar DDL | βœ… | ❌ | ❌ | Coordina | +| Crear Entity | ❌ | βœ… | ❌ | Verifica | +| Crear DTO | ❌ | βœ… | ❌ | Verifica | +| Crear Service | ❌ | βœ… | ❌ | Verifica | +| Crear Controller | ❌ | βœ… | ❌ | Verifica | +| Crear Types | ❌ | ❌ | βœ… | Verifica | +| Crear Component | ❌ | ❌ | βœ… | Verifica | +| IntegraciΓ³n | ❌ | ❌ | ❌ | βœ… | + +--- + +**VersiΓ³n:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** GuΓ­a de Proceso diff --git a/core/orchestration/referencias/ALIASES.yml b/core/orchestration/referencias/ALIASES.yml index 3d85cc1..65295a5 100644 --- a/core/orchestration/referencias/ALIASES.yml +++ b/core/orchestration/referencias/ALIASES.yml @@ -79,6 +79,38 @@ global: "@CHK_API": "core/orchestration/checklists/CHECKLIST-CODE-REVIEW-API.md" "@CHK_REFACTOR": "core/orchestration/checklists/CHECKLIST-REFACTORIZACION.md" + # ═══════════════════════════════════════════════════════════════════ + # PATRONES DE CΓ“DIGO (CONSULTAR ANTES DE IMPLEMENTAR) + # ═══════════════════════════════════════════════════════════════════ + "@PATRONES": "core/orchestration/patrones/" + "@MAPEO_TIPOS": "core/orchestration/patrones/MAPEO-TIPOS-DDL-TYPESCRIPT.md" + "@PATRON_VALIDACION": "core/orchestration/patrones/PATRON-VALIDACION.md" + "@PATRON_EXCEPTIONS": "core/orchestration/patrones/PATRON-EXCEPTION-HANDLING.md" + "@PATRON_TESTING": "core/orchestration/patrones/PATRON-TESTING.md" + "@PATRON_LOGGING": "core/orchestration/patrones/PATRON-LOGGING.md" + "@PATRON_CONFIG": "core/orchestration/patrones/PATRON-CONFIGURACION.md" + "@PATRON_SEGURIDAD": "core/orchestration/patrones/PATRON-SEGURIDAD.md" + "@PATRON_PERFORMANCE": "core/orchestration/patrones/PATRON-PERFORMANCE.md" + "@PATRON_TRANSACCIONES": "core/orchestration/patrones/PATRON-TRANSACCIONES.md" + "@ANTIPATRONES": "core/orchestration/patrones/ANTIPATRONES.md" + "@NOMENCLATURA": "core/orchestration/patrones/NOMENCLATURA-UNIFICADA.md" + + # ═══════════════════════════════════════════════════════════════════ + # IMPACTOS DE CAMBIOS (CONSULTAR ANTES DE MODIFICAR) + # ═══════════════════════════════════════════════════════════════════ + "@IMPACTOS": "core/orchestration/impactos/" + "@IMPACTO_DDL": "core/orchestration/impactos/IMPACTO-CAMBIOS-DDL.md" + "@IMPACTO_BACKEND": "core/orchestration/impactos/IMPACTO-CAMBIOS-BACKEND.md" + "@IMPACTO_ENTITY": "core/orchestration/impactos/IMPACTO-CAMBIOS-ENTITY.md" + "@IMPACTO_API": "core/orchestration/impactos/IMPACTO-CAMBIOS-API.md" + "@MATRIZ_DEPENDENCIAS": "core/orchestration/impactos/MATRIZ-DEPENDENCIAS.md" + + # ═══════════════════════════════════════════════════════════════════ + # PROCESOS DE TRABAJO + # ═══════════════════════════════════════════════════════════════════ + "@PROCESOS": "core/orchestration/procesos/" + "@ORDEN_IMPLEMENTACION": "core/orchestration/procesos/ORDEN-IMPLEMENTACION.md" + # ───────────────────────────────────────────────────────────────────────────────── # ALIAS DE OPERACIONES (atajos directos a directivas SIMCO) # ───────────────────────────────────────────────────────────────────────────────── diff --git a/orchestration/ANALISIS-ALINEACION-WORKSPACE-2025-12-08.md b/orchestration/ANALISIS-ALINEACION-WORKSPACE-2025-12-08.md new file mode 100644 index 0000000..b092de4 --- /dev/null +++ b/orchestration/ANALISIS-ALINEACION-WORKSPACE-2025-12-08.md @@ -0,0 +1,434 @@ +# AnΓ‘lisis de AlineaciΓ³n del Workspace +**Fecha:** 2025-12-08 +**VersiΓ³n Sistema:** NEXUS v3.2 + SIMCO + CAPVED + +--- + +## RESUMEN EJECUTIVO + +Este documento presenta el anΓ‘lisis exhaustivo de alineaciΓ³n entre el sistema de orquestaciΓ³n central (`core/orchestration/`) y su implementaciΓ³n en todos los proyectos del workspace. + +### Hallazgos Clave + +| Área | Estado | AcciΓ³n Requerida | +|------|--------|------------------| +| Sistema SIMCO/CAPVED | Completo (20+ directivas) | Base sΓ³lida | +| ERP-Core | 100% docs, 0% cΓ³digo | Implementar | +| Verticales | Parcialmente alineadas | Propagar estΓ‘ndares | +| SaaS Layer | 0% (vacΓ­o) | Crear desde cero | +| Proyectos Standalone | Variable | Homologar | + +--- + +## 1. SISTEMA DE ORQUESTACIΓ“N (CORE) + +### 1.1 Componentes Implementados + +| Componente | UbicaciΓ³n | Archivos | Estado | +|------------|-----------|----------|--------| +| Directivas SIMCO | `core/orchestration/directivas/simco/` | 17 archivos | Completo | +| Principios | `core/orchestration/directivas/principios/` | 5 archivos | Completo | +| Perfiles Agentes | `core/orchestration/agents/perfiles/` | 12 archivos | Completo | +| Templates | `core/orchestration/templates/` | 14 archivos | Completo | +| Checklists | `core/orchestration/checklists/` | 3 archivos | Completo | +| CatΓ‘logo | `core/catalog/` | 8 funcionalidades | Documentado | + +### 1.2 Directivas SIMCO Disponibles + +``` +SIMCO-TAREA.md # Ciclo CAPVED (obligatorio) +SIMCO-CREAR.md # Crear archivos nuevos +SIMCO-MODIFICAR.md # Modificar existentes +SIMCO-VALIDAR.md # ValidaciΓ³n obligatoria +SIMCO-DOCUMENTAR.md # DocumentaciΓ³n +SIMCO-DELEGACION.md # Delegar a subagentes +SIMCO-BUSCAR.md # ExploraciΓ³n +SIMCO-REUTILIZAR.md # Uso del catΓ‘logo +SIMCO-DDL.md # Base de datos +SIMCO-BACKEND.md # NestJS/TypeORM +SIMCO-FRONTEND.md # React/TypeScript +SIMCO-NIVELES.md # JerarquΓ­a de proyectos +SIMCO-PROPAGACION.md # PropagaciΓ³n de cambios +SIMCO-ML.md # Machine Learning +SIMCO-MOBILE.md # Aplicaciones mΓ³viles +SIMCO-ALINEACION.md # AlineaciΓ³n entre capas +SIMCO-DECISION-MATRIZ.md # Matriz de decisiones +``` + +### 1.3 Principios Fundamentales (5) + +1. **PRINCIPIO-CAPVED** - Ciclo obligatorio: Contextoβ†’AnΓ‘lisisβ†’PlaneaciΓ³nβ†’ValidaciΓ³nβ†’EjecuciΓ³nβ†’DocumentaciΓ³n +2. **PRINCIPIO-DOC-PRIMERO** - Documentar antes de implementar +3. **PRINCIPIO-ANTI-DUPLICACION** - Verificar catΓ‘logo/inventarios antes de crear +4. **PRINCIPIO-VALIDACION-OBLIGATORIA** - Build+Lint+Tests deben pasar +5. **PRINCIPIO-ECONOMIA-TOKENS** - Desglosar tareas grandes + +### 1.4 CatΓ‘logo de Funcionalidades Reutilizables + +| Funcionalidad | UbicaciΓ³n | Estado | +|---------------|-----------|--------| +| auth | `core/catalog/auth/` | Documentado | +| session-management | `core/catalog/session-management/` | Documentado | +| rate-limiting | `core/catalog/rate-limiting/` | Documentado | +| notifications | `core/catalog/notifications/` | Documentado | +| multi-tenancy | `core/catalog/multi-tenancy/` | Documentado | +| feature-flags | `core/catalog/feature-flags/` | Documentado | +| websocket | `core/catalog/websocket/` | Documentado | +| payments | `core/catalog/payments/` | Documentado | + +--- + +## 2. ANÁLISIS POR PROYECTO + +### 2.1 ERP-SUITE + +#### Estado General +| Componente | DocumentaciΓ³n | CΓ³digo | BD | OrquestaciΓ³n | +|------------|---------------|--------|-----|--------------| +| ERP-Core | 100% (827 MD) | 0% | 0% | 100% | +| ConstrucciΓ³n | 100% (449 MD) | 25% | 0% | 100% | +| MecΓ‘nicas Diesel | 95% (75 MD) | 0% | 0% | 100% | +| Vidrio Templado | 0% | 0% | 0% | 50% | +| Retail | 0% | 0% | 0% | 50% | +| ClΓ­nicas | 0% | 0% | 0% | 50% | +| SaaS Layer | 10% | 0% | 0% | 0% | + +#### Gaps Identificados en ERP-Suite + +| ID | Gap | Severidad | UbicaciΓ³n | +|----|-----|-----------|-----------| +| GAP-ERP-001 | SaaS layer vacΓ­o | CRÍTICO | `apps/saas/` | +| GAP-ERP-002 | shared-libs vacΓ­o | ALTO | `apps/shared-libs/` | +| GAP-ERP-003 | Verticales sin HERENCIA-ERP-CORE.md | MEDIO | 3 de 5 verticales | +| GAP-ERP-004 | Inventarios desactualizados | MEDIO | Varios | +| GAP-ERP-005 | No existe POS bΓ‘sico minimalista | CRÍTICO | No existe | + +### 2.2 Otros Proyectos + +| Proyecto | Estado | Docs | CΓ³digo | AlineaciΓ³n | +|----------|--------|------|--------|------------| +| Gamilit | ProducciΓ³n | 470 MD | Completo | Alta | +| Trading-Platform | Desarrollo | 259 MD | 70% | Alta | +| Betting-Analytics | PlanificaciΓ³n | 1 MD | 0% | Parcial | +| Inmobiliaria-Analytics | PlanificaciΓ³n | 1 MD | 0% | Parcial | + +--- + +## 3. GAPS DE ALINEACIΓ“N CRÍTICOS + +### 3.1 Gaps Estructurales + +| # | DescripciΓ³n | Proyectos Afectados | Impacto | +|---|-------------|---------------------|---------| +| 1 | Falta estructura SaaS multi-tier | erp-suite | Bloqueante para comercializaciΓ³n | +| 2 | Falta POS minimalista (100 MXN) | erp-suite | Mercado desatendido | +| 3 | Inventarios no propagados | Todos | Trazabilidad incompleta | +| 4 | HERENCIA-DIRECTIVAS inconsistente | Verticales | DuplicaciΓ³n de esfuerzo | + +### 3.2 Gaps de DocumentaciΓ³n + +| # | DescripciΓ³n | UbicaciΓ³n | +|---|-------------|-----------| +| 1 | ERP-Core sin README actualizado con arquitectura SaaS | `erp-suite/apps/erp-core/` | +| 2 | Verticales sin docs de herencia | 3 verticales | +| 3 | CatΓ‘logo sin cΓ³digo de referencia | `core/catalog/*/` | +| 4 | betting/inmobiliaria sin documentaciΓ³n | 2 proyectos | + +### 3.3 Gaps de ImplementaciΓ³n + +| # | DescripciΓ³n | Prioridad | +|---|-------------|-----------| +| 1 | ERP-Core 0% cΓ³digo con 100% docs | P0 | +| 2 | SaaS Layer inexistente | P0 | +| 3 | POS BΓ‘sico no existe | P0 | +| 4 | MecΓ‘nicas Diesel 0% cΓ³digo | P1 | + +--- + +## 4. PROPUESTA: ARQUITECTURA SAAS MULTI-TIER + +### 4.1 Estructura Propuesta + +``` +erp-suite/ +β”œβ”€β”€ apps/ +β”‚ β”œβ”€β”€ erp-core/ # Base compartida (EXISTENTE) +β”‚ β”‚ β”œβ”€β”€ backend/ # API Core +β”‚ β”‚ β”œβ”€β”€ frontend/ # UI Core (componentes base) +β”‚ β”‚ └── database/ # Schemas compartidos +β”‚ β”‚ +β”‚ β”œβ”€β”€ saas/ # Capa SaaS (CREAR) +β”‚ β”‚ β”œβ”€β”€ billing/ # FacturaciΓ³n y suscripciones +β”‚ β”‚ β”œβ”€β”€ portal/ # Portal de clientes +β”‚ β”‚ β”œβ”€β”€ admin/ # Admin multi-tenant +β”‚ β”‚ └── onboarding/ # Autoregistro +β”‚ β”‚ +β”‚ β”œβ”€β”€ products/ # Productos SaaS (CREAR) +β”‚ β”‚ β”‚ +β”‚ β”‚ β”œβ”€β”€ erp-basico/ # ERP SaaS Mediano (~300-500 MXN/mes) +β”‚ β”‚ β”‚ β”œβ”€β”€ backend/ # Hereda erp-core + mΓ³dulos seleccionados +β”‚ β”‚ β”‚ β”œβ”€β”€ frontend/ # UI simplificada +β”‚ β”‚ β”‚ └── config/ # Feature flags para mΓ³dulos +β”‚ β”‚ β”‚ +β”‚ β”‚ └── pos-micro/ # POS Ultra BΓ‘sico (~100 MXN/mes) +β”‚ β”‚ β”œβ”€β”€ backend/ # MΓ­nimo: ventas, inventario bΓ‘sico, reportes +β”‚ β”‚ β”œβ”€β”€ frontend/ # UI ultra simple (mΓ³vil-first) +β”‚ β”‚ β”œβ”€β”€ pwa/ # Progressive Web App +β”‚ β”‚ └── whatsapp/ # IntegraciΓ³n WhatsApp Business +β”‚ β”‚ +β”‚ └── verticales/ # Extensiones por industria (EXISTENTE) +β”‚ β”œβ”€β”€ construccion/ +β”‚ β”œβ”€β”€ mecanicas-diesel/ +β”‚ β”œβ”€β”€ vidrio-templado/ +β”‚ β”œβ”€β”€ retail/ +β”‚ └── clinicas/ +``` + +### 4.2 Producto: ERP SaaS Mediano + +**Target:** PyMEs que necesitan ERP integral pero econΓ³mico +**Precio:** ~300-500 MXN/mes +**CaracterΓ­sticas:** + +| MΓ³dulo | Incluido | DescripciΓ³n | +|--------|----------|-------------| +| Auth | Obligatorio | Login, roles bΓ‘sicos | +| Usuarios | Obligatorio | GestiΓ³n de usuarios | +| Multi-tenant | Obligatorio | Aislamiento por empresa | +| Inventario | Incluido | Control de stock bΓ‘sico | +| Ventas | Incluido | Cotizaciones, pedidos, facturas | +| Compras | Incluido | Γ“rdenes de compra bΓ‘sicas | +| Clientes/Proveedores | Incluido | CRM bΓ‘sico | +| Reportes | Incluido | Reportes esenciales | +| Contabilidad | Opcional | +100 MXN/mes | +| RRHH | Opcional | +100 MXN/mes | +| WhatsApp Bot | Opcional | Por consumo de tokens | + +### 4.3 Producto: POS Micro (Ultra BΓ‘sico) + +**Target:** Mercado informal mexicano +- Puestos de calle +- Tiendas de abarrotes/miscelΓ‘neas +- Puestos de comida +- PequeΓ±os locales + +**Precio:** ~100 MXN/mes +**Modelo:** SaaS + consumo de IA + +**CaracterΓ­sticas MÍNIMAS:** + +| CaracterΓ­stica | DescripciΓ³n | +|----------------|-------------| +| Punto de Venta | Vender productos, calcular cambio | +| Inventario BΓ‘sico | Agregar productos, ver stock | +| CatΓ‘logo Simple | Lista de productos con precio | +| Corte de Caja | Resumen diario de ventas | +| Reportes BΓ‘sicos | Ventas del dΓ­a/semana/mes | +| WhatsApp Bot | Consultas de precio, stock, ventas | +| PWA Offline | Funciona sin internet (sincroniza despuΓ©s) | + +**Arquitectura Minimalista:** + +``` +pos-micro/ +β”œβ”€β”€ backend/ +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ β”œβ”€β”€ modules/ +β”‚ β”‚ β”‚ β”œβ”€β”€ auth/ # Login simple (email/WhatsApp) +β”‚ β”‚ β”‚ β”œβ”€β”€ products/ # CRUD productos +β”‚ β”‚ β”‚ β”œβ”€β”€ sales/ # Registrar ventas +β”‚ β”‚ β”‚ β”œβ”€β”€ inventory/ # Stock bΓ‘sico +β”‚ β”‚ β”‚ └── reports/ # Reportes simples +β”‚ β”‚ └── shared/ +β”‚ β”‚ β”œβ”€β”€ tenant/ # Multi-tenant bΓ‘sico +β”‚ β”‚ └── whatsapp/ # IntegraciΓ³n WA Business +β”œβ”€β”€ frontend/ +β”‚ β”œβ”€β”€ pwa/ # Progressive Web App +β”‚ β”‚ β”œβ”€β”€ pages/ +β”‚ β”‚ β”‚ β”œβ”€β”€ pos/ # Pantalla de venta +β”‚ β”‚ β”‚ β”œβ”€β”€ products/ # GestiΓ³n productos +β”‚ β”‚ β”‚ β”œβ”€β”€ reports/ # Ver reportes +β”‚ β”‚ β”‚ └── settings/ # ConfiguraciΓ³n +β”‚ β”‚ └── offline/ # Service Worker +└── database/ + └── schemas/ + └── pos_micro/ # ~10 tablas mΓ‘ximo +``` + +**Base de Datos Minimalista (~10 tablas):** + +```sql +-- Schema: pos_micro +CREATE TABLE tenants (id, name, whatsapp_number, plan, created_at); +CREATE TABLE users (id, tenant_id, email, password_hash, role); +CREATE TABLE products (id, tenant_id, name, price, stock, barcode); +CREATE TABLE sales (id, tenant_id, user_id, total, payment_method, created_at); +CREATE TABLE sale_items (id, sale_id, product_id, quantity, price); +CREATE TABLE inventory_movements (id, tenant_id, product_id, quantity, type, created_at); +CREATE TABLE daily_closures (id, tenant_id, date, total_sales, total_cash); +CREATE TABLE whatsapp_sessions (id, tenant_id, phone, token, expires_at); +CREATE TABLE ai_usage (id, tenant_id, tokens_used, model, created_at); +CREATE TABLE subscriptions (id, tenant_id, plan, amount, status, next_billing); +``` + +### 4.4 IntegraciΓ³n WhatsApp Business + +``` +Flujo Usuario POS Micro: +1. Usuario envΓ­a "hola" a nΓΊmero de WhatsApp +2. Bot responde: "Hola! Soy tu asistente. Puedo ayudarte con: + - Ver ventas del dΓ­a + - Consultar stock de producto + - Agregar producto + - Ver reporte semanal" +3. Usuario: "ventas del dΓ­a" +4. Bot: "Ventas hoy: $2,450 MXN (23 tickets)" +5. Usuario: "stock de coca cola" +6. Bot: "Coca Cola 600ml: 45 unidades en stock" + +Costo: Tokens consumidos por consulta (~0.01-0.05 USD por consulta) +``` + +--- + +## 5. PLAN DE IMPLEMENTACIΓ“N + +### Fase 1: PreparaciΓ³n (Inmediato) + +| Tarea | DescripciΓ³n | Prioridad | +|-------|-------------|-----------| +| 1.1 | Actualizar HERENCIA-ERP-CORE.md en todas las verticales | P0 | +| 1.2 | Crear estructura `apps/products/` | P0 | +| 1.3 | Crear documentaciΓ³n base para pos-micro | P0 | +| 1.4 | Crear documentaciΓ³n base para erp-basico | P0 | +| 1.5 | Actualizar SaaS layer con billing bΓ‘sico | P0 | + +### Fase 2: POS Micro (Prioridad Alta) + +| Tarea | DescripciΓ³n | EstimaciΓ³n | +|-------|-------------|------------| +| 2.1 | DiseΓ±ar schema BD (~10 tablas) | 2h | +| 2.2 | Implementar backend mΓ­nimo | 8h | +| 2.3 | Implementar PWA frontend | 8h | +| 2.4 | Integrar WhatsApp Business API | 4h | +| 2.5 | Implementar offline-first | 4h | +| 2.6 | Testing y validaciΓ³n | 4h | + +### Fase 3: ERP BΓ‘sico SaaS + +| Tarea | DescripciΓ³n | EstimaciΓ³n | +|-------|-------------|------------| +| 3.1 | Definir mΓ³dulos incluidos vs opcionales | 2h | +| 3.2 | Configurar feature flags | 4h | +| 3.3 | Implementar billing/suscripciones | 8h | +| 3.4 | Portal de onboarding | 8h | +| 3.5 | Testing multi-tenant | 4h | + +### Fase 4: PropagaciΓ³n + +| Tarea | DescripciΓ³n | +|-------|-------------| +| 4.1 | Actualizar inventarios en todos los proyectos | +| 4.2 | Verificar HERENCIA-DIRECTIVAS en cada vertical | +| 4.3 | Ejecutar CHECKLIST-PROPAGACION en todos los niveles | +| 4.4 | Documentar dependencias entre productos | + +--- + +## 6. MΓ‰TRICAS DE ALINEACIΓ“N + +### 6.1 Checklist de AlineaciΓ³n por Proyecto + +```yaml +Proyecto Alineado: + Estructura: + [ ] apps/backend/ existe + [ ] apps/frontend/ existe + [ ] apps/database/ existe + [ ] docs/ con estructura estΓ‘ndar + [ ] orchestration/ con estructura NEXUS + + Orchestration: + [ ] 00-guidelines/CONTEXTO-PROYECTO.md + [ ] PROXIMA-ACCION.md + [ ] inventarios/MASTER_INVENTORY.yml + [ ] trazas/ con archivos por capa + [ ] HERENCIA-DIRECTIVAS.md + + DocumentaciΓ³n: + [ ] README.md actualizado + [ ] Γ‰picas documentadas + [ ] Historias de usuario + [ ] Especificaciones tΓ©cnicas + [ ] Schemas de BD + + CΓ³digo: + [ ] Sigue estΓ‘ndares de nomenclatura + [ ] Entities alineadas con DDL + [ ] DTOs con validaciones + [ ] Tests implementados + [ ] Build + Lint pasan +``` + +### 6.2 Estado Actual de AlineaciΓ³n + +| Proyecto | Estructura | Orchestration | Docs | CΓ³digo | TOTAL | +|----------|------------|---------------|------|--------|-------| +| Gamilit | 100% | 100% | 100% | 90% | **97%** | +| Trading | 100% | 90% | 95% | 70% | **89%** | +| ERP-Core | 100% | 100% | 100% | 0% | **75%** | +| ConstrucciΓ³n | 100% | 100% | 100% | 25% | **81%** | +| MecΓ‘nicas Diesel | 100% | 100% | 95% | 0% | **74%** | +| Vidrio Templado | 80% | 50% | 0% | 0% | **33%** | +| Retail | 80% | 50% | 0% | 0% | **33%** | +| ClΓ­nicas | 80% | 50% | 0% | 0% | **33%** | +| Betting | 80% | 40% | 5% | 0% | **31%** | +| Inmobiliaria | 80% | 40% | 5% | 0% | **31%** | + +--- + +## 7. ACCIONES INMEDIATAS + +### 7.1 Crear Productos SaaS + +```bash +# Crear estructura de productos +mkdir -p projects/erp-suite/apps/products/erp-basico/{backend,frontend,database,docs,orchestration} +mkdir -p projects/erp-suite/apps/products/pos-micro/{backend,frontend,pwa,database,docs,orchestration} +``` + +### 7.2 Propagar HERENCIA-ERP-CORE.md + +Verticales que necesitan el archivo: +- [ ] vidrio-templado +- [ ] retail +- [ ] clinicas + +### 7.3 Actualizar SaaS Layer + +```bash +mkdir -p projects/erp-suite/apps/saas/{billing,portal,admin,onboarding} +``` + +--- + +## 8. CONCLUSIONES + +1. **El sistema de orquestaciΓ³n estΓ‘ completo** - SIMCO, CAPVED, perfiles y catΓ‘logo bien definidos + +2. **La documentaciΓ³n es excelente** - ERP-Core tiene 827 MD, gap analysis completo vs Odoo + +3. **Falta implementaciΓ³n de cΓ³digo** - 0% en ERP-Core a pesar de 100% documentaciΓ³n + +4. **Falta capa SaaS** - CrΓ­tico para comercializaciΓ³n + +5. **Falta producto POS minimalista** - Oportunidad de mercado desatendida (100 MXN/mes) + +6. **Verticales parcialmente alineadas** - 3 de 5 sin HERENCIA-ERP-CORE.md + +7. **Proyectos standalone bien alineados** - Gamilit y Trading-Platform son ejemplos a seguir + +--- + +*Documento generado: 2025-12-08* +*Sistema: NEXUS v3.2 + SIMCO + CAPVED* diff --git a/orchestration/WORKSPACE-STATUS.md b/orchestration/WORKSPACE-STATUS.md index 4ea5eed..8b5c82c 100644 --- a/orchestration/WORKSPACE-STATUS.md +++ b/orchestration/WORKSPACE-STATUS.md @@ -1,8 +1,8 @@ # WORKSPACE STATUS **Nivel:** 0 - Workspace Root -**Actualizado:** 2025-12-08 (Post-Limpieza) -**Sistema:** SIMCO v2.2.0 + CAPVED +**Actualizado:** 2025-12-08 (AnΓ‘lisis AlineaciΓ³n + Productos SaaS) +**Sistema:** SIMCO v3.2 + CAPVED + NEXUS --- @@ -10,10 +10,11 @@ ```yaml estado: "OPERATIVO" -version_simco: "2.2.0" +version_simco: "3.2" ultima_actualizacion: "2025-12-08" proyectos_activos: 5 verticales_activos: 5 +productos_saas: 2 # NUEVO: pos-micro, erp-basico catalogo_funcionalidades: 8 ``` @@ -23,7 +24,25 @@ catalogo_funcionalidades: 8 ### 2025-12-08 -#### CorrecciΓ³n de Gaps de DocumentaciΓ³n (NUEVO) +#### AnΓ‘lisis de AlineaciΓ³n y Productos SaaS (NUEVO) +- **AcciΓ³n:** AnΓ‘lisis exhaustivo del sistema de orquestaciΓ³n y alineaciΓ³n de proyectos +- **Documento generado:** `ANALISIS-ALINEACION-WORKSPACE-2025-12-08.md` +- **Estructuras creadas:** + - `apps/products/pos-micro/` - POS ultra bΓ‘sico (100 MXN/mes) + - `apps/products/erp-basico/` - ERP austero (300-500 MXN/mes) + - `apps/saas/` - Capa de billing, portal, admin, onboarding +- **DocumentaciΓ³n:** + - README.md y CONTEXTO-PROYECTO.md para cada producto + - README.md para SaaS layer + - CONTEXTO-SAAS.md para orquestaciΓ³n SaaS +- **Hallazgos:** + - Sistema SIMCO/CAPVED completo (20+ directivas) + - ERP-Core: 100% docs, 0% cΓ³digo + - Verticales: Todas con HERENCIA-ERP-CORE.md + - Productos SaaS: Nueva lΓ­nea para mercado mexicano +- **Agente:** Claude Code + +#### CorrecciΓ³n de Gaps de DocumentaciΓ³n - **AcciΓ³n:** CorrecciΓ³n de 7 gaps identificados en anΓ‘lisis de documentaciΓ³n - **Archivos creados:** - `PERFIL-REQUIREMENTS-ANALYST.md` (v1.4.0) diff --git a/projects/erp-suite/apps/erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md b/projects/erp-suite/apps/erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md new file mode 100644 index 0000000..4ab69f5 --- /dev/null +++ b/projects/erp-suite/apps/erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md @@ -0,0 +1,211 @@ +# Mapeo de Especificaciones Transversales a Verticales + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Autor:** Sistema SIMCO +**UbicaciΓ³n SPECS:** `docs/04-modelado/especificaciones-tecnicas/transversal/` + +--- + +## PropΓ³sito + +Este documento define quΓ© especificaciones transversales del ERP-Core aplican a cada vertical del ERP-Suite. Sirve como referencia para la propagaciΓ³n de funcionalidades y el desarrollo de cada proyecto vertical. + +--- + +## Leyenda + +| SΓ­mbolo | Significado | +|---------|-------------| +| βœ“ | Aplica - Debe implementarse | +| β—‹ | Opcional - Puede implementarse segΓΊn necesidad | +| βœ— | No aplica - No es relevante para esta vertical | + +--- + +## Matriz de Aplicabilidad + +### SPECS P0 - Funcionales (CrΓ­ticos) + +| SPEC | DescripciΓ³n | ConstrucciΓ³n | MecΓ‘nicas | Vidrio | Retail | ClΓ­nicas | +|------|-------------|:------------:|:---------:|:------:|:------:|:--------:| +| SPEC-SISTEMA-SECUENCIAS | Secuencias automΓ‘ticas de documentos | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-VALORACION-INVENTARIO | FIFO/AVCO valorizaciΓ³n | βœ“ | βœ“ | βœ“ | βœ“ | β—‹ | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | API Keys + ACL + RLS | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-REPORTES-FINANCIEROS | Balance/P&L SAT | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-PORTAL-PROVEEDORES | Portal RFQ | βœ“ | βœ“ | βœ“ | β—‹ | βœ— | +| SPEC-NOMINA-BASICA | hr_payroll | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-GASTOS-EMPLEADOS | hr_expense | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-TAREAS-RECURRENTES | project.task.recurrence | βœ“ | βœ“ | βœ“ | β—‹ | β—‹ | +| SPEC-SCHEDULER-REPORTES | ir.cron + mail | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-INTEGRACION-CALENDAR | calendar integration | β—‹ | βœ— | βœ— | βœ— | βœ“ | + +### SPECS P1 - Complementarios + +| SPEC | DescripciΓ³n | ConstrucciΓ³n | MecΓ‘nicas | Vidrio | Retail | ClΓ­nicas | +|------|-------------|:------------:|:---------:|:------:|:------:|:--------:| +| SPEC-CONTABILIDAD-ANALITICA-MULTIDIMENSIONAL | Centros de costo | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-CONCILIACION-BANCARIA | ConciliaciΓ³n automΓ‘tica | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-FIRMA-ELECTRONICA-NOM151 | Firma electrΓ³nica | βœ“ | β—‹ | β—‹ | β—‹ | βœ“ | +| SPEC-TWO-FACTOR-AUTHENTICATION | 2FA, TOTP, SMS | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes y nΓΊmeros de serie | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-PRICING-RULES | Reglas de precios | β—‹ | βœ“ | βœ“ | βœ“ | β—‹ | +| SPEC-BLANKET-ORDERS | Γ“rdenes marco | βœ“ | βœ“ | βœ“ | βœ“ | βœ— | +| SPEC-OAUTH2-SOCIAL-LOGIN | OAuth2, Google, Microsoft | β—‹ | β—‹ | β—‹ | β—‹ | βœ“ | +| SPEC-INVENTARIOS-CICLICOS | Conteo cΓ­clico | β—‹ | βœ“ | β—‹ | βœ“ | β—‹ | +| SPEC-IMPUESTOS-AVANZADOS | IVA, ISR configurables | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-PLANTILLAS-CUENTAS | Plan de cuentas por paΓ­s | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-CONSOLIDACION-FINANCIERA | Multi-empresa | β—‹ | β—‹ | β—‹ | β—‹ | β—‹ | +| SPEC-TASAS-CAMBIO-AUTOMATICAS | Tipos de cambio | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-ALERTAS-PRESUPUESTO | Alertas de exceso | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-PRESUPUESTOS-REVISIONES | AprobaciΓ³n de presupuestos | βœ“ | βœ“ | βœ“ | β—‹ | β—‹ | +| SPEC-RRHH-EVALUACIONES-SKILLS | Evaluaciones, skills | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | Dependencias, burndown | βœ“ | βœ— | βœ“ | βœ— | βœ— | +| SPEC-LOCALIZACION-PAISES | ConfiguraciΓ³n por paΓ­s | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | + +### Patrones TΓ©cnicos P0 + +| SPEC | DescripciΓ³n | ConstrucciΓ³n | MecΓ‘nicas | Vidrio | Retail | ClΓ­nicas | +|------|-------------|:------------:|:---------:|:------:|:------:|:--------:| +| SPEC-MAIL-THREAD-TRACKING | mail.thread mixin | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| SPEC-WIZARD-TRANSIENT-MODEL | TransientModel | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | + +--- + +## Resumen por Vertical + +### ConstrucciΓ³n (MAI/MAE) +- **SPECS Aplicables:** 26/30 +- **SPECS Obligatorias:** 22 +- **SPECS Opcionales:** 4 +- **SPECS No Aplican:** 4 +- **Enfoque:** Proyectos, control de obra, estimaciones, RRHH construcciΓ³n + +### MecΓ‘nicas-Diesel (MMD) +- **SPECS Aplicables:** 25/30 +- **SPECS Obligatorias:** 23 +- **SPECS Opcionales:** 2 +- **SPECS No Aplican:** 5 +- **Enfoque:** Γ“rdenes de trabajo, inventario refacciones, diagnΓ³sticos + +### Vidrio-Templado (VT) +- **SPECS Aplicables:** 25/30 +- **SPECS Obligatorias:** 22 +- **SPECS Opcionales:** 3 +- **SPECS No Aplican:** 5 +- **Enfoque:** ProducciΓ³n, control de calidad, hornos de templado + +### Retail (RT) +- **SPECS Aplicables:** 24/30 +- **SPECS Obligatorias:** 21 +- **SPECS Opcionales:** 3 +- **SPECS No Aplican:** 6 +- **Enfoque:** POS, inventario multi-sucursal, promociones, caja + +### ClΓ­nicas (CL) +- **SPECS Aplicables:** 24/30 +- **SPECS Obligatorias:** 20 +- **SPECS Opcionales:** 4 +- **SPECS No Aplican:** 6 +- **Enfoque:** Expediente clΓ­nico, citas, calendario, cumplimiento normativo + +--- + +## Detalle por Vertical + +### ConstrucciΓ³n + +**SPECS CrΓ­ticas para el Dominio:** +1. `SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN` - Control de obra y avances +2. `SPEC-VALORACION-INVENTARIO` - Costeo de materiales de construcciΓ³n +3. `SPEC-TRAZABILIDAD-LOTES-SERIES` - Trazabilidad de materiales +4. `SPEC-PRESUPUESTOS-REVISIONES` - Control presupuestal de obras + +**Adaptaciones Requeridas:** +- Proyectos = Obras/Fraccionamientos +- Tareas = Etapas de construcciΓ³n +- Productos = Materiales de construcciΓ³n + +### MecΓ‘nicas-Diesel + +**SPECS CrΓ­ticas para el Dominio:** +1. `SPEC-VALORACION-INVENTARIO` - Costeo de refacciones +2. `SPEC-TRAZABILIDAD-LOTES-SERIES` - Tracking de partes OEM +3. `SPEC-INVENTARIOS-CICLICOS` - Control de stock +4. `SPEC-PRICING-RULES` - Reglas de precio por tipo de servicio + +**Adaptaciones Requeridas:** +- Productos = Refacciones, partes +- Γ“rdenes de venta = Γ“rdenes de servicio +- Partners = Clientes con vehΓ­culos + +### Vidrio-Templado + +**SPECS CrΓ­ticas para el Dominio:** +1. `SPEC-VALORACION-INVENTARIO` - Costeo de materia prima y producto terminado +2. `SPEC-TRAZABILIDAD-LOTES-SERIES` - Lotes de producciΓ³n de vidrio +3. `SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN` - Γ“rdenes de producciΓ³n +4. `SPEC-PRICING-RULES` - Precios por dimensiones y tipos de vidrio + +**Adaptaciones Requeridas:** +- Productos = Tipos de vidrio (templado, laminado, etc.) +- ProducciΓ³n = Control de hornos y parΓ‘metros +- Calidad = Inspecciones de fragmentaciΓ³n + +### Retail + +**SPECS CrΓ­ticas para el Dominio:** +1. `SPEC-PRICING-RULES` - Promociones y descuentos +2. `SPEC-INVENTARIOS-CICLICOS` - Conteos en sucursales +3. `SPEC-TRAZABILIDAD-LOTES-SERIES` - Productos con lote/serie +4. `SPEC-VALORACION-INVENTARIO` - Costeo de mercancΓ­a + +**Adaptaciones Requeridas:** +- Almacenes = Sucursales +- Ventas = Transacciones POS +- Clientes = Programa de lealtad + +### ClΓ­nicas + +**SPECS CrΓ­ticas para el Dominio:** +1. `SPEC-INTEGRACION-CALENDAR` - Agenda de citas mΓ©dicas +2. `SPEC-MAIL-THREAD-TRACKING` - Historial de comunicaciΓ³n con pacientes +3. `SPEC-RRHH-EVALUACIONES-SKILLS` - Credenciales mΓ©dicas +4. `SPEC-FIRMA-ELECTRONICA-NOM151` - Firma de expedientes + +**Adaptaciones Requeridas:** +- Partners = Pacientes +- Productos = Servicios mΓ©dicos, medicamentos +- Calendario = Agenda de consultas +- Cumplimiento = NOM-024-SSA3-2012 + +--- + +## Workflows Aplicables + +| Workflow | ConstrucciΓ³n | MecΓ‘nicas | Vidrio | Retail | ClΓ­nicas | +|----------|:------------:|:---------:|:------:|:------:|:--------:| +| WORKFLOW-CIERRE-PERIODO-CONTABLE | βœ“ | βœ“ | βœ“ | βœ“ | βœ“ | +| WORKFLOW-3-WAY-MATCH | βœ“ | βœ“ | βœ“ | β—‹ | β—‹ | +| WORKFLOW-PAGOS-ANTICIPADOS | βœ“ | βœ“ | βœ“ | βœ— | βœ“ | + +--- + +## PrΓ³ximos Pasos + +1. Crear `HERENCIA-SPECS-CORE.md` en cada vertical con detalle de implementaciΓ³n +2. Actualizar `HERENCIA-ERP-CORE.md` con referencia a SPECS aplicables +3. Documentar adaptaciones especΓ­ficas por vertical en carpeta `transversal-core/` + +--- + +## Referencias + +- SPECS del Core: `erp-core/docs/04-modelado/especificaciones-tecnicas/transversal/` +- AnΓ‘lisis de Gaps: `erp-core/orchestration/01-analisis/ANALISIS-GAPS-CONSOLIDADO.md` +- Directiva de ExtensiΓ³n: `erp-core/orchestration/directivas/DIRECTIVA-EXTENSION-VERTICALES.md` + +--- + +**Documento de referencia canΓ³nico para propagaciΓ³n de SPECS** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml b/projects/erp-suite/apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml index 7ced484..1c57ea6 100644 --- a/projects/erp-suite/apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml +++ b/projects/erp-suite/apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml @@ -231,24 +231,74 @@ modulos: verticales_dependientes: - nombre: construccion - estado: 35% + codigo: MAI/MAE + estado: 40% + fase: EN_DESARROLLO path: ../verticales/construccion/ - - - nombre: vidrio-templado - estado: 0% - path: ../verticales/vidrio-templado/ + modulos: 18 + specs_aplicables: 26 + specs_implementadas: 0 + tablas_heredadas: 124 + tablas_especificas: 33 - nombre: mecanicas-diesel - estado: 0% + codigo: MMD + estado: 20% + fase: DDL_IMPLEMENTADO path: ../verticales/mecanicas-diesel/ + modulos: 6 + specs_aplicables: 25 + specs_implementadas: 0 + tablas_heredadas: 97 + tablas_especificas: 30 + + - nombre: vidrio-templado + codigo: VT + estado: 15% + fase: PLANIFICACION_COMPLETA + path: ../verticales/vidrio-templado/ + modulos: 8 + specs_aplicables: 25 + specs_implementadas: 0 + tablas_heredadas: 97 + tablas_especificas: 25 - nombre: retail - estado: 0% + codigo: RT + estado: 15% + fase: PLANIFICACION_COMPLETA path: ../verticales/retail/ + modulos: 10 + specs_aplicables: 24 + specs_implementadas: 0 + tablas_heredadas: 102 + tablas_especificas: 30 - nombre: clinicas - estado: 0% + codigo: CL + estado: 15% + fase: PLANIFICACION_COMPLETA path: ../verticales/clinicas/ + modulos: 12 + specs_aplicables: 24 + specs_implementadas: 0 + tablas_heredadas: 100 + tablas_especificas: 35 + +# ============================================================================ +# MAPEO DE SPECS A VERTICALES (Referencia) +# ============================================================================ +mapeo_specs_verticales: + documento_completo: docs/04-modelado/MAPEO-SPECS-VERTICALES.md + fecha_actualizacion: 2025-12-08 + resumen: + total_specs: 30 + por_vertical: + construccion: {aplicables: 26, obligatorias: 22, opcionales: 4} + mecanicas_diesel: {aplicables: 25, obligatorias: 23, opcionales: 2} + vidrio_templado: {aplicables: 25, obligatorias: 22, opcionales: 3} + retail: {aplicables: 24, obligatorias: 21, opcionales: 3} + clinicas: {aplicables: 24, obligatorias: 20, opcionales: 4} documentacion: total_archivos: 630 diff --git a/projects/erp-suite/apps/products/erp-basico/README.md b/projects/erp-suite/apps/products/erp-basico/README.md new file mode 100644 index 0000000..c235527 --- /dev/null +++ b/projects/erp-suite/apps/products/erp-basico/README.md @@ -0,0 +1,191 @@ +# ERP BΓ‘sico SaaS - SoluciΓ³n Integral Austera + +## DescripciΓ³n + +Sistema ERP completo pero austero, diseΓ±ado para PyMEs que necesitan funcionalidad integral sin la complejidad ni el costo de soluciones enterprise. + +## Target de Mercado + +- PyMEs con 5-50 empleados +- Negocios que necesitan mΓ‘s que un POS +- Empresas que buscan digitalizaciΓ³n econΓ³mica +- Comercios con operaciones de compra-venta +- PequeΓ±as manufacturas + +## Precio + +**~300-500 MXN/mes** (segΓΊn mΓ³dulos activos) + +## Plan Base (300 MXN/mes) + +| MΓ³dulo | Incluido | DescripciΓ³n | +|--------|----------|-------------| +| AutenticaciΓ³n | Obligatorio | Login, 2FA, roles bΓ‘sicos | +| Usuarios | Obligatorio | Hasta 5 usuarios | +| Multi-tenant | Obligatorio | Aislamiento por empresa | +| CatΓ‘logos | Incluido | Productos, categorΓ­as, unidades | +| Inventario | Incluido | Stock, movimientos, alertas | +| Ventas | Incluido | Cotizaciones, pedidos, facturas | +| Compras | Incluido | Γ“rdenes de compra, proveedores | +| Clientes | Incluido | CRM bΓ‘sico, contactos | +| Reportes | Incluido | Dashboard, reportes esenciales | + +## MΓ³dulos Opcionales + +| MΓ³dulo | Precio | DescripciΓ³n | +|--------|--------|-------------| +| Contabilidad | +150 MXN/mes | PΓ³lizas, balances, estados financieros | +| RRHH | +100 MXN/mes | Empleados, nΓ³mina bΓ‘sica, asistencia | +| FacturaciΓ³n CFDI | +100 MXN/mes | Timbrado SAT MΓ©xico | +| Usuarios extra | +50 MXN/usuario | MΓ‘s de 5 usuarios | +| WhatsApp Bot | Por consumo | Consultas y notificaciones | +| Soporte Premium | +200 MXN/mes | AtenciΓ³n prioritaria | + +## Stack TecnolΓ³gico + +- **Backend:** Node.js + Express/NestJS + TypeScript +- **Frontend:** React 18 + Vite + Tailwind CSS +- **Database:** PostgreSQL 15+ con RLS +- **Cache:** Redis (compartido) +- **Auth:** JWT + bcrypt + +## Arquitectura + +``` +erp-basico/ +β”œβ”€β”€ backend/ +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ β”œβ”€β”€ modules/ +β”‚ β”‚ β”‚ β”œβ”€β”€ auth/ # AutenticaciΓ³n +β”‚ β”‚ β”‚ β”œβ”€β”€ users/ # GestiΓ³n usuarios +β”‚ β”‚ β”‚ β”œβ”€β”€ companies/ # Multi-tenant +β”‚ β”‚ β”‚ β”œβ”€β”€ catalogs/ # CatΓ‘logos maestros +β”‚ β”‚ β”‚ β”œβ”€β”€ inventory/ # Inventario +β”‚ β”‚ β”‚ β”œβ”€β”€ sales/ # Ventas +β”‚ β”‚ β”‚ β”œβ”€β”€ purchases/ # Compras +β”‚ β”‚ β”‚ β”œβ”€β”€ partners/ # Clientes/Proveedores +β”‚ β”‚ β”‚ └── reports/ # Reportes +β”‚ β”‚ └── shared/ +β”‚ β”‚ β”œβ”€β”€ guards/ +β”‚ β”‚ β”œβ”€β”€ decorators/ +β”‚ β”‚ └── utils/ +β”œβ”€β”€ frontend/ +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ β”œβ”€β”€ features/ # Por mΓ³dulo +β”‚ β”‚ β”œβ”€β”€ shared/ # Componentes base +β”‚ β”‚ └── app/ # Layout, routing +β”œβ”€β”€ database/ +β”‚ └── ddl/ +β”‚ β”œβ”€β”€ 00-extensions.sql +β”‚ β”œβ”€β”€ 01-schemas.sql +β”‚ β”œβ”€β”€ 02-core-tables.sql +β”‚ └── 03-business-tables.sql +└── orchestration/ +``` + +## Base de Datos (~40 tablas) + +### Schema: `auth` +- users, roles, permissions, sessions, tokens + +### Schema: `core` +- companies, settings, sequences, audit_logs + +### Schema: `catalog` +- products, categories, units, taxes, payment_methods + +### Schema: `inventory` +- warehouses, stock_moves, stock_quants, adjustments + +### Schema: `sales` +- quotations, sale_orders, invoices, payments + +### Schema: `purchases` +- purchase_orders, supplier_invoices, receipts + +### Schema: `partners` +- partners, contacts, addresses + +### Schema: `reports` +- report_configs, saved_reports + +## DiferenciaciΓ³n vs POS Micro + +| Aspecto | POS Micro | ERP BΓ‘sico | +|---------|-----------|------------| +| Precio | 100 MXN | 300-500 MXN | +| Tablas BD | ~10 | ~40 | +| MΓ³dulos | 4 | 10+ | +| Usuarios | 1 | 5+ | +| Compras | No | SΓ­ | +| Inventario | BΓ‘sico | Completo | +| Reportes | MΓ­nimos | Dashboard | +| FacturaciΓ³n | No | Opcional | +| Contabilidad | No | Opcional | + +## Herencia del Core + +Este producto hereda **directamente** de `erp-core`: + +| Componente | % Herencia | AdaptaciΓ³n | +|------------|------------|------------| +| Auth | 100% | Ninguna | +| Users | 100% | Ninguna | +| Multi-tenant | 100% | Ninguna | +| CatΓ‘logos | 80% | Simplificado | +| Inventario | 70% | Sin lotes/series | +| Ventas | 70% | Sin workflows complejos | +| Compras | 70% | Sin aprobaciones | +| Partners | 90% | Ninguna | +| Reportes | 50% | Subset de reportes | + +## Feature Flags + +```yaml +# ConfiguraciΓ³n por tenant +features: + accounting: false # +150 MXN + hr: false # +100 MXN + cfdi: false # +100 MXN + whatsapp_bot: false # Por consumo + advanced_reports: false + multi_warehouse: false + serial_numbers: false + lot_tracking: false +``` + +## Limitaciones (Por diseΓ±o) + +- MΓ‘ximo 10,000 productos +- MΓ‘ximo 5 usuarios en plan base +- Sin multi-sucursal en plan base +- Sin contabilidad avanzada (solo opcional) +- Sin manufactura +- Sin proyectos +- Sin e-commerce integrado + +## Roadmap + +### MVP (v1.0) +- [x] Auth completo (heredado de core) +- [ ] CatΓ‘logos bΓ‘sicos +- [ ] Inventario simple +- [ ] Ventas (cotizaciΓ³n β†’ pedido β†’ factura) +- [ ] Compras bΓ‘sicas +- [ ] Dashboard inicial + +### v1.1 +- [ ] MΓ³dulo contabilidad (opcional) +- [ ] CFDI MΓ©xico (opcional) +- [ ] Reportes adicionales + +### v1.2 +- [ ] RRHH bΓ‘sico (opcional) +- [ ] Multi-almacΓ©n +- [ ] Integraciones bancarias + +--- + +*Producto: ERP BΓ‘sico SaaS v1.0* +*Precio Target: 300-500 MXN/mes* +*Mercado: PyMEs MΓ©xico* diff --git a/projects/erp-suite/apps/products/erp-basico/orchestration/00-guidelines/CONTEXTO-PROYECTO.md b/projects/erp-suite/apps/products/erp-basico/orchestration/00-guidelines/CONTEXTO-PROYECTO.md new file mode 100644 index 0000000..1f30589 --- /dev/null +++ b/projects/erp-suite/apps/products/erp-basico/orchestration/00-guidelines/CONTEXTO-PROYECTO.md @@ -0,0 +1,238 @@ +# Contexto del Proyecto: ERP BΓ‘sico SaaS + +## IdentificaciΓ³n + +| Campo | Valor | +|-------|-------| +| **Nombre** | ERP BΓ‘sico SaaS | +| **Tipo** | Producto SaaS | +| **Nivel** | 2B.2 (Producto dentro de Suite) | +| **Suite Padre** | erp-suite | +| **Ruta Base** | `projects/erp-suite/apps/products/erp-basico/` | +| **Estado** | En PlanificaciΓ³n | + +## DescripciΓ³n + +ERP completo pero austero para PyMEs. Hereda directamente de erp-core con configuraciΓ³n simplificada y precios accesibles. + +## Target de Mercado + +- PyMEs con 5-50 empleados +- Comercios con operaciones compra-venta +- PequeΓ±as manufacturas +- Distribuidores +- Empresas en proceso de digitalizaciΓ³n + +## Propuesta de Valor + +1. **ERP completo** - No solo POS, gestiΓ³n integral +2. **Precio accesible** - 300-500 MXN/mes vs 2,000+ de SAP/Odoo +3. **Sin complejidad** - ConfiguraciΓ³n mΓ­nima +4. **Modular** - Paga solo lo que usas +5. **Mexicanizado** - CFDI, bancos mexicanos + +## Stack TecnolΓ³gico + +```yaml +backend: + runtime: Node.js 20+ + framework: NestJS (heredado de core) + language: TypeScript 5.3+ + orm: TypeORM + validation: class-validator + +frontend: + framework: React 18 + bundler: Vite + styling: Tailwind CSS + state: Zustand + forms: React Hook Form + +database: + engine: PostgreSQL 15+ + multi_tenant: true (RLS) + schemas: 8 + tables: ~40 + +cache: + engine: Redis + usage: Sessions, rate-limiting +``` + +## Variables del Proyecto + +```yaml +# Identificadores +PROJECT_NAME: erp-basico +PROJECT_CODE: ERPB +SUITE: erp-suite + +# Database +DB_NAME: erp_suite_db # Compartida +SCHEMAS: + - auth + - core + - catalog + - inventory + - sales + - purchases + - partners + - reports + +# Paths +BACKEND_ROOT: apps/products/erp-basico/backend +FRONTEND_ROOT: apps/products/erp-basico/frontend +DATABASE_ROOT: apps/products/erp-basico/database + +# Business +BASE_PRICE_MXN: 300 +MAX_USERS_BASE: 5 +MAX_PRODUCTS: 10000 +``` + +## Herencia del Core + +### MΓ³dulos Heredados (100%) + +| MΓ³dulo Core | Uso en ERP BΓ‘sico | +|-------------|-------------------| +| MGN-001 Auth | Completo | +| MGN-002 Users | Completo | +| MGN-003 Roles | Simplificado (3 roles) | +| MGN-004 Tenants | Completo | +| MGN-005 Catalogs | 80% (sin variantes) | +| MGN-008 Notifications | Simplificado | + +### MΓ³dulos Adaptados + +| MΓ³dulo Core | AdaptaciΓ³n | +|-------------|------------| +| MGN-007 Audit | Solo logs crΓ­ticos | +| MGN-009 Reports | Subset de reportes | +| Inventory | Sin lotes/series | +| Sales | Sin workflows aprobaciΓ³n | +| Purchases | Sin aprobaciones multi-nivel | + +### MΓ³dulos NO Incluidos + +| MΓ³dulo Core | RazΓ³n | +|-------------|-------| +| MGN-010 Financial | Opcional (+150 MXN) | +| Projects | Complejidad innecesaria | +| Manufacturing | Fuera de scope | +| Advanced HR | Opcional (+100 MXN) | + +## MΓ³dulos del Producto + +### Obligatorios (Plan Base) + +| MΓ³dulo | Tablas | Endpoints | Componentes | +|--------|--------|-----------|-------------| +| auth | 5 | 8 | 4 | +| users | 2 | 6 | 3 | +| companies | 3 | 5 | 2 | +| catalogs | 5 | 12 | 6 | +| inventory | 4 | 10 | 5 | +| sales | 4 | 12 | 6 | +| purchases | 3 | 8 | 4 | +| partners | 3 | 8 | 4 | +| reports | 2 | 6 | 3 | + +### Opcionales (Feature Flags) + +| MΓ³dulo | Precio | Tablas Extra | +|--------|--------|--------------| +| accounting | +150 MXN | 8 | +| hr | +100 MXN | 6 | +| cfdi | +100 MXN | 3 | + +## Feature Flags + +```typescript +interface TenantFeatures { + // Plan base + base_erp: true; + max_users: 5; + max_products: 10000; + + // Opcionales + accounting: boolean; // +150 MXN + hr: boolean; // +100 MXN + cfdi: boolean; // +100 MXN + extra_users: number; // +50 MXN c/u + multi_warehouse: boolean; // +100 MXN + whatsapp_bot: boolean; // Por consumo + advanced_reports: boolean;// +50 MXN +} +``` + +## DiferenciaciΓ³n + +### vs POS Micro + +| Aspecto | POS Micro | ERP BΓ‘sico | +|---------|-----------|------------| +| Complejidad | MΓ­nima | Media | +| MΓ³dulos | 4 | 10+ | +| Usuarios | 1 | 5+ | +| Compras | No | SΓ­ | +| Multi-almacΓ©n | No | Opcional | +| Contabilidad | No | Opcional | +| Precio | 100 MXN | 300+ MXN | + +### vs ERP Enterprise (Verticales) + +| Aspecto | ERP BΓ‘sico | Verticales | +|---------|------------|------------| +| Industria | General | Especializado | +| Complejidad | Media | Alta | +| CustomizaciΓ³n | Baja | Alta | +| Workflows | Simples | Complejos | +| Precio | 300-500 MXN | 1,000+ MXN | + +## MΓ©tricas de Γ‰xito + +| MΓ©trica | Target | +|---------|--------| +| Tiempo de onboarding | < 30 minutos | +| Usuarios activos diarios | > 60% | +| NPS | > 40 | +| Churn mensual | < 3% | +| Tickets soporte/usuario | < 0.5/mes | + +## Roadmap + +### MVP (v1.0) +- [ ] Herencia completa de auth/users/tenants +- [ ] CatΓ‘logos (productos, categorΓ­as, unidades) +- [ ] Inventario bΓ‘sico (stock, movimientos) +- [ ] Ventas (cotizaciΓ³n β†’ pedido β†’ factura) +- [ ] Compras bΓ‘sicas +- [ ] Dashboard inicial +- [ ] Billing/suscripciones + +### v1.1 +- [ ] MΓ³dulo contabilidad (opcional) +- [ ] CFDI MΓ©xico (opcional) +- [ ] Reportes financieros + +### v1.2 +- [ ] RRHH bΓ‘sico (opcional) +- [ ] Multi-almacΓ©n (opcional) +- [ ] Integraciones bancarias MΓ©xico + +### v2.0 +- [ ] App mΓ³vil +- [ ] Integraciones marketplace +- [ ] IA para predicciones + +## Documentos Relacionados + +- `../README.md` - DescripciΓ³n general +- `../../erp-core/` - Core heredado +- `../../erp-core/docs/` - DocumentaciΓ³n detallada de mΓ³dulos +- `../../../orchestration/` - OrquestaciΓ³n suite level + +--- + +*Última actualizaciΓ³n: 2025-12-08* diff --git a/projects/erp-suite/apps/products/pos-micro/README.md b/projects/erp-suite/apps/products/pos-micro/README.md new file mode 100644 index 0000000..8dfcf7b --- /dev/null +++ b/projects/erp-suite/apps/products/pos-micro/README.md @@ -0,0 +1,139 @@ +# POS Micro - Punto de Venta Ultra BΓ‘sico + +## DescripciΓ³n + +Sistema de punto de venta minimalista diseΓ±ado para el mercado informal mexicano. Enfocado en simplicidad extrema, bajo costo y funcionalidad offline. + +## Target de Mercado + +- Puestos de calle y ambulantes +- Tiendas de abarrotes y miscelΓ‘neas +- Puestos de comida (tacos, tortas, etc.) +- PequeΓ±os locales comerciales +- Vendedores independientes + +## Precio + +**~100 MXN/mes** + consumo de IA (opcional) + +## CaracterΓ­sticas + +### Incluidas en Plan Base (100 MXN/mes) + +| CaracterΓ­stica | DescripciΓ³n | +|----------------|-------------| +| Punto de Venta | Registrar ventas, calcular cambio | +| CatΓ‘logo | Lista de productos con precios | +| Inventario BΓ‘sico | Control de stock simple | +| Corte de Caja | Resumen diario | +| Reportes | Ventas dΓ­a/semana/mes | +| PWA Offline | Funciona sin internet | +| 1 Usuario | Operador principal | + +### Opcionales (Por Consumo) + +| CaracterΓ­stica | Costo | +|----------------|-------| +| WhatsApp Bot | ~0.02 USD por consulta | +| Usuario adicional | +30 MXN/mes | +| Soporte prioritario | +50 MXN/mes | + +## Stack TecnolΓ³gico + +- **Backend:** Node.js + Express + TypeScript +- **Frontend:** React + PWA + Tailwind CSS +- **Database:** PostgreSQL (compartida multi-tenant) +- **WhatsApp:** WhatsApp Business API +- **IA:** Claude API (para bot) + +## Arquitectura + +``` +pos-micro/ +β”œβ”€β”€ backend/ # API mΓ­nima +β”œβ”€β”€ frontend/ # SPA React +β”œβ”€β”€ pwa/ # Service Worker + Offline +β”œβ”€β”€ database/ # ~10 tablas +β”œβ”€β”€ whatsapp/ # IntegraciΓ³n WA Business +β”œβ”€β”€ docs/ # DocumentaciΓ³n +└── orchestration/ # Sistema NEXUS +``` + +## Base de Datos (~10 tablas) + +1. `tenants` - Empresas/negocios +2. `users` - Usuarios del sistema +3. `products` - CatΓ‘logo de productos +4. `sales` - Ventas registradas +5. `sale_items` - Detalle de ventas +6. `inventory_movements` - Movimientos de inventario +7. `daily_closures` - Cortes de caja +8. `whatsapp_sessions` - Sesiones WA +9. `ai_usage` - Consumo de tokens IA +10. `subscriptions` - Suscripciones y pagos + +## Flujo de Usuario + +### Registro +1. Usuario accede a landing page +2. Ingresa nΓΊmero de WhatsApp +3. Recibe cΓ³digo de verificaciΓ³n +4. Configura nombre del negocio +5. Agrega primeros productos +6. Listo para vender + +### Venta TΓ­pica +1. Abrir PWA (funciona offline) +2. Seleccionar productos +3. Ver total automΓ‘tico +4. Registrar pago (efectivo/tarjeta) +5. Calcular cambio +6. Venta registrada + +### Consulta por WhatsApp +``` +Usuario: "ventas de hoy" +Bot: "Ventas hoy: $1,250 MXN (15 tickets) + Producto mΓ‘s vendido: Coca Cola 600ml (23 unidades)" + +Usuario: "stock de sabritas" +Bot: "Sabritas Original: 12 unidades + Sabritas Adobadas: 8 unidades + Sabritas LimΓ³n: 15 unidades" +``` + +## Principios de DiseΓ±o + +1. **Simplicidad extrema** - MΓ‘ximo 3 clicks para cualquier acciΓ³n +2. **Mobile-first** - DiseΓ±ado para celulares +3. **Offline-first** - Funciona sin internet +4. **Bajo costo** - Infraestructura mΓ­nima +5. **Sin fricciΓ³n** - Onboarding en 5 minutos + +## Limitaciones (Por diseΓ±o) + +- MΓ‘ximo 500 productos +- MΓ‘ximo 1,000 ventas/mes en plan base +- Sin facturaciΓ³n electrΓ³nica (CFDI) +- Sin contabilidad +- Sin multi-sucursal +- Sin CRM avanzado + +## Herencia del Core + +Este producto hereda de `erp-core`: +- Sistema de autenticaciΓ³n bΓ‘sico +- Multi-tenancy (RLS) +- Estructura de proyectos + +NO hereda (por simplicidad): +- MΓ³dulos financieros +- RRHH +- CRM completo +- Reportes avanzados + +--- + +*Producto: POS Micro v1.0* +*Precio Target: 100 MXN/mes* +*Mercado: Informal mexicano* diff --git a/projects/erp-suite/apps/products/pos-micro/orchestration/00-guidelines/CONTEXTO-PROYECTO.md b/projects/erp-suite/apps/products/pos-micro/orchestration/00-guidelines/CONTEXTO-PROYECTO.md new file mode 100644 index 0000000..abb6715 --- /dev/null +++ b/projects/erp-suite/apps/products/pos-micro/orchestration/00-guidelines/CONTEXTO-PROYECTO.md @@ -0,0 +1,164 @@ +# Contexto del Proyecto: POS Micro + +## IdentificaciΓ³n + +| Campo | Valor | +|-------|-------| +| **Nombre** | POS Micro | +| **Tipo** | Producto SaaS | +| **Nivel** | 2B.2 (Producto dentro de Suite) | +| **Suite Padre** | erp-suite | +| **Ruta Base** | `projects/erp-suite/apps/products/pos-micro/` | +| **Estado** | En PlanificaciΓ³n | + +## DescripciΓ³n + +Sistema de punto de venta ultra-minimalista diseΓ±ado para el mercado informal mexicano. Precio target: **100 MXN/mes**. + +## Target de Mercado + +- Puestos ambulantes +- Tiendas de abarrotes +- MiscelΓ‘neas +- Puestos de comida +- PequeΓ±os comercios + +## Propuesta de Valor + +1. **Precio accesible** - 100 MXN/mes (vs 500+ de competidores) +2. **Simplicidad** - Solo lo esencial +3. **Offline** - Funciona sin internet +4. **WhatsApp** - Consultas por chat +5. **Sin fricciΓ³n** - Registro en 5 minutos + +## Stack TecnolΓ³gico + +```yaml +backend: + runtime: Node.js 20+ + framework: Express + language: TypeScript + orm: TypeORM (simplificado) + +frontend: + framework: React 18 + bundler: Vite + styling: Tailwind CSS + pwa: Workbox + +database: + engine: PostgreSQL 15+ + multi_tenant: true (RLS) + max_tables: 10 + +integrations: + whatsapp: WhatsApp Business API + ai: Claude API (opcional) + payments: Stripe/Conekta +``` + +## Variables del Proyecto + +```yaml +# Identificadores +PROJECT_NAME: pos-micro +PROJECT_CODE: POS +SUITE: erp-suite + +# Database +DB_SCHEMA: pos_micro +DB_NAME: erp_suite_db # Compartida +MAX_TABLES: 10 + +# Paths +BACKEND_ROOT: apps/products/pos-micro/backend +FRONTEND_ROOT: apps/products/pos-micro/frontend +PWA_ROOT: apps/products/pos-micro/pwa +DATABASE_ROOT: apps/products/pos-micro/database + +# Business +PRICE_MXN: 100 +PRICE_USD: 6 +MAX_PRODUCTS: 500 +MAX_SALES_MONTH: 1000 +``` + +## Herencia del Core + +### SÍ Hereda + +| Componente | Origen | AdaptaciΓ³n | +|------------|--------|------------| +| Auth bΓ‘sico | erp-core/auth | Simplificado (solo email/WA) | +| Multi-tenant | erp-core/tenant | RLS bΓ‘sico | +| API patterns | erp-core/shared | Endpoints mΓ­nimos | + +### NO Hereda (Por DiseΓ±o) + +| Componente | RazΓ³n | +|------------|-------| +| Contabilidad | Demasiado complejo | +| RRHH | No aplica | +| CRM | Simplificar | +| Compras | No necesario | +| Reportes avanzados | Overkill | + +## MΓ³dulos del Producto + +| MΓ³dulo | Prioridad | Tablas | Endpoints | +|--------|-----------|--------|-----------| +| auth | P0 | 2 | 4 | +| products | P0 | 1 | 5 | +| sales | P0 | 2 | 4 | +| inventory | P0 | 1 | 3 | +| reports | P1 | 1 | 3 | +| whatsapp | P1 | 2 | 2 | +| billing | P1 | 1 | 2 | + +## Restricciones de DiseΓ±o + +1. **MΓ‘ximo 10 tablas** - Simplicidad de BD +2. **MΓ‘ximo 20 endpoints** - API mΓ­nima +3. **MΓ‘ximo 10 pantallas** - UI simple +4. **Offline-first** - Service Worker obligatorio +5. **Mobile-first** - DiseΓ±o responsivo primero mΓ³vil +6. **3-click rule** - Cualquier acciΓ³n en mΓ‘ximo 3 clicks + +## MΓ©tricas de Γ‰xito + +| MΓ©trica | Target | +|---------|--------| +| Tiempo de onboarding | < 5 minutos | +| Tiempo carga PWA | < 2 segundos | +| Funcionalidad offline | 100% ventas | +| Costo infraestructura/usuario | < $1 USD/mes | +| Churn mensual | < 5% | + +## Roadmap + +### MVP (v1.0) +- [ ] Auth por WhatsApp +- [ ] CRUD productos +- [ ] Registro de ventas +- [ ] Corte de caja +- [ ] PWA offline + +### v1.1 +- [ ] WhatsApp Bot bΓ‘sico +- [ ] Reportes por WhatsApp +- [ ] Notificaciones stock bajo + +### v1.2 +- [ ] Dashboard web simple +- [ ] Exportar datos CSV +- [ ] Backup automΓ‘tico + +## Documentos Relacionados + +- `../README.md` - DescripciΓ³n general +- `../../erp-core/orchestration/` - Core heredado +- `../../../orchestration/` - Suite level + +--- + +*Última actualizaciΓ³n: 2025-12-08* diff --git a/projects/erp-suite/apps/saas/README.md b/projects/erp-suite/apps/saas/README.md new file mode 100644 index 0000000..7169ff8 --- /dev/null +++ b/projects/erp-suite/apps/saas/README.md @@ -0,0 +1,198 @@ +# SaaS Layer - ERP Suite + +## DescripciΓ³n + +Capa de servicios SaaS que gestiona multi-tenancy, billing, suscripciones y portal de clientes para todos los productos del ERP Suite. + +## Componentes + +``` +saas/ +β”œβ”€β”€ billing/ # FacturaciΓ³n y cobros +β”œβ”€β”€ portal/ # Portal de clientes +β”œβ”€β”€ admin/ # AdministraciΓ³n multi-tenant +β”œβ”€β”€ onboarding/ # Registro y configuraciΓ³n inicial +β”œβ”€β”€ docs/ # DocumentaciΓ³n +└── orchestration/ # Sistema NEXUS +``` + +## Billing + +GestiΓ³n de suscripciones y cobros. + +### Funcionalidades + +- Planes de suscripciΓ³n (POS Micro, ERP BΓ‘sico, Verticales) +- Cobro recurrente (mensual/anual) +- IntegraciΓ³n con Stripe/Conekta +- FacturaciΓ³n automΓ‘tica (CFDI MΓ©xico) +- GestiΓ³n de mΓ³dulos opcionales + +### Planes + +| Plan | Precio Base | Productos | +|------|-------------|-----------| +| POS Micro | 100 MXN/mes | pos-micro | +| ERP BΓ‘sico | 300 MXN/mes | erp-basico | +| ERP Pro | 500 MXN/mes | erp-basico + mΓ³dulos | +| Vertical | 1,000+ MXN/mes | erp-core + vertical | + +### MΓ³dulos Opcionales + +| MΓ³dulo | Precio | Disponible en | +|--------|--------|---------------| +| Contabilidad | +150 MXN/mes | ERP BΓ‘sico, Verticales | +| RRHH | +100 MXN/mes | ERP BΓ‘sico, Verticales | +| CFDI | +100 MXN/mes | Todos | +| WhatsApp Bot | Por consumo | Todos | +| Usuario extra | +50 MXN/mes | Todos | + +## Portal + +Portal self-service para clientes. + +### Funcionalidades + +- Dashboard de cuenta +- GestiΓ³n de suscripciΓ³n +- Historial de facturas +- Cambio de plan +- Soporte/tickets +- ConfiguraciΓ³n de mΓ³dulos + +## Admin + +Panel de administraciΓ³n para operadores. + +### Funcionalidades + +- GestiΓ³n de tenants +- MΓ©tricas de uso +- FacturaciΓ³n manual +- Soporte nivel 1 +- ConfiguraciΓ³n global +- Feature flags por tenant + +## Onboarding + +Flujo de registro y configuraciΓ³n inicial. + +### Flujo + +1. **Registro** - Email o WhatsApp +2. **SelecciΓ³n de plan** - POS Micro, ERP BΓ‘sico, etc. +3. **Datos de empresa** - RFC, direcciΓ³n, giro +4. **ConfiguraciΓ³n inicial** - Productos, usuarios +5. **Pago** - Tarjeta o transferencia +6. **ActivaciΓ³n** - Acceso inmediato + +## Stack TecnolΓ³gico + +```yaml +backend: + runtime: Node.js 20+ + framework: NestJS + language: TypeScript + payments: Stripe + Conekta + invoicing: PAC CFDI + +frontend: + framework: React 18 + bundler: Vite + styling: Tailwind CSS + +database: + engine: PostgreSQL 15+ + schema: saas + tables: ~15 +``` + +## Base de Datos + +### Schema: `saas` + +```sql +-- GestiΓ³n de tenants y suscripciones + +saas.tenants -- Empresas/clientes +saas.subscriptions -- Suscripciones activas +saas.plans -- CatΓ‘logo de planes +saas.plan_features -- Features por plan +saas.invoices -- Facturas emitidas +saas.payments -- Pagos recibidos +saas.payment_methods -- MΓ©todos de pago guardados +saas.usage_tracking -- Tracking de consumo +saas.support_tickets -- Tickets de soporte +saas.onboarding_sessions -- Sesiones de registro +``` + +## IntegraciΓ³n con Productos + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ SAAS LAYER β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ billing β”‚ β”‚ portal β”‚ β”‚ admin β”‚ β”‚onboardingβ”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ API Gateway β”‚ +β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ POS Microβ”‚ β”‚ERP BΓ‘sicoβ”‚ β”‚Verticalesβ”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Variables de Entorno + +```env +# Payments +STRIPE_SECRET_KEY=sk_xxx +STRIPE_WEBHOOK_SECRET=whsec_xxx +CONEKTA_API_KEY=key_xxx + +# CFDI +PAC_RFC=XXX +PAC_API_KEY=xxx +PAC_ENVIRONMENT=sandbox|production + +# Database +DATABASE_URL=postgresql://... +SAAS_SCHEMA=saas + +# General +ONBOARDING_URL=https://registro.erp-suite.com +PORTAL_URL=https://portal.erp-suite.com +``` + +## Roadmap + +### MVP (v1.0) +- [ ] Modelo de datos billing +- [ ] IntegraciΓ³n Stripe bΓ‘sica +- [ ] Portal mΓ­nimo (ver facturas) +- [ ] Onboarding POS Micro +- [ ] Admin bΓ‘sico + +### v1.1 +- [ ] IntegraciΓ³n Conekta +- [ ] CFDI automΓ‘tico +- [ ] Onboarding ERP BΓ‘sico +- [ ] MΓ©tricas de uso + +### v1.2 +- [ ] Portal completo +- [ ] Cambio de plan self-service +- [ ] Soporte integrado +- [ ] Referidos + +--- + +*SaaS Layer v1.0* +*ERP Suite* diff --git a/projects/erp-suite/apps/saas/orchestration/CONTEXTO-SAAS.md b/projects/erp-suite/apps/saas/orchestration/CONTEXTO-SAAS.md new file mode 100644 index 0000000..3857af0 --- /dev/null +++ b/projects/erp-suite/apps/saas/orchestration/CONTEXTO-SAAS.md @@ -0,0 +1,122 @@ +# Contexto del Proyecto: SaaS Layer + +## IdentificaciΓ³n + +| Campo | Valor | +|-------|-------| +| **Nombre** | SaaS Layer | +| **Tipo** | Infraestructura | +| **Nivel** | 2B.1 (Core de Suite) | +| **Suite** | erp-suite | +| **Ruta Base** | `projects/erp-suite/apps/saas/` | +| **Estado** | En PlanificaciΓ³n | + +## DescripciΓ³n + +Capa de servicios compartidos para gestiΓ³n de multi-tenancy, billing, suscripciones y portal de clientes. + +## Responsabilidades + +1. **Billing** - Cobros, suscripciones, facturaciΓ³n +2. **Portal** - Self-service para clientes +3. **Admin** - GestiΓ³n de tenants +4. **Onboarding** - Registro de nuevos clientes + +## Stack TecnolΓ³gico + +```yaml +backend: + runtime: Node.js 20+ + framework: NestJS + language: TypeScript 5.3+ + +frontend: + framework: React 18 + bundler: Vite + styling: Tailwind CSS + +database: + engine: PostgreSQL 15+ + schema: saas + +integrations: + payments: Stripe, Conekta + invoicing: PAC CFDI (MΓ©xico) + notifications: Email, WhatsApp +``` + +## Variables del Proyecto + +```yaml +PROJECT_NAME: saas-layer +PROJECT_CODE: SAAS +SUITE: erp-suite + +# Paths +BILLING_ROOT: apps/saas/billing +PORTAL_ROOT: apps/saas/portal +ADMIN_ROOT: apps/saas/admin +ONBOARDING_ROOT: apps/saas/onboarding + +# Database +DB_SCHEMA: saas +MAX_TABLES: 15 +``` + +## MΓ³dulos + +| MΓ³dulo | DescripciΓ³n | Prioridad | +|--------|-------------|-----------| +| billing | Suscripciones y cobros | P0 | +| portal | Portal de clientes | P1 | +| admin | Panel de administraciΓ³n | P1 | +| onboarding | Registro de clientes | P0 | + +## Planes de SuscripciΓ³n + +| ID | Plan | Precio | Target | +|----|------|--------|--------| +| pos-micro | POS Micro | 100 MXN/mes | Mercado informal | +| erp-basic | ERP BΓ‘sico | 300 MXN/mes | PyMEs | +| erp-pro | ERP Pro | 500 MXN/mes | PyMEs+ | +| vertical-x | Vertical | 1,000+ MXN/mes | Industrias especΓ­ficas | + +## Dependencias + +### Productos que dependen de SaaS Layer + +- `products/pos-micro` - Billing, onboarding +- `products/erp-basico` - Billing, portal, onboarding +- `verticales/*` - Billing, portal, admin + +### Servicios externos + +- Stripe - Pagos internacionales +- Conekta - Pagos MΓ©xico +- PAC CFDI - FacturaciΓ³n electrΓ³nica +- SendGrid - Email transaccional +- WhatsApp Business API - Notificaciones + +## Roadmap + +### Sprint 1: Billing MVP +- [ ] Modelo de datos +- [ ] IntegraciΓ³n Stripe bΓ‘sica +- [ ] Webhook de pagos +- [ ] API de suscripciones + +### Sprint 2: Onboarding +- [ ] Flujo de registro +- [ ] SelecciΓ³n de plan +- [ ] ConfiguraciΓ³n inicial +- [ ] ActivaciΓ³n automΓ‘tica + +### Sprint 3: Portal +- [ ] Dashboard cliente +- [ ] Ver facturas +- [ ] Cambiar plan +- [ ] Soporte bΓ‘sico + +--- + +*Última actualizaciΓ³n: 2025-12-08* diff --git a/projects/erp-suite/apps/verticales/clinicas/database/HERENCIA-ERP-CORE.md b/projects/erp-suite/apps/verticales/clinicas/database/HERENCIA-ERP-CORE.md new file mode 100644 index 0000000..5030bd2 --- /dev/null +++ b/projects/erp-suite/apps/verticales/clinicas/database/HERENCIA-ERP-CORE.md @@ -0,0 +1,213 @@ +# Herencia de Base de Datos - ERP Core -> ClΓ­nicas + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** ClΓ­nicas +**Nivel:** 2B.2 + +--- + +## RESUMEN + +La vertical de ClΓ­nicas hereda los schemas base del ERP Core y extiende con schemas especΓ­ficos del dominio de gestiΓ³n mΓ©dica y expediente clΓ­nico. + +**UbicaciΓ³n DDL Core:** `apps/erp-core/database/ddl/` + +--- + +## ARQUITECTURA DE HERENCIA + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ERP CORE (Base) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ auth β”‚ β”‚ core β”‚ β”‚financialβ”‚ β”‚inventoryβ”‚ β”‚ hr β”‚ β”‚ +β”‚ β”‚ 26 tbl β”‚ β”‚ 12 tbl β”‚ β”‚ 15 tbl β”‚ β”‚ 15 tbl β”‚ β”‚ 6 tbl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ sales β”‚ β”‚analyticsβ”‚ β”‚ system β”‚ β”‚ crm β”‚ β”‚ +β”‚ β”‚ 6 tbl β”‚ β”‚ 5 tbl β”‚ β”‚ 10 tbl β”‚ β”‚ 5 tbl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ TOTAL: ~100 tablas heredadas β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”‚ HEREDA + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CLÍNICAS (Extensiones) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ medical β”‚ β”‚ appointments β”‚ β”‚ patients β”‚ β”‚ +β”‚ β”‚ (expediente) β”‚ β”‚ (citas) β”‚ β”‚ (pacientes) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ EXTENSIONES: ~35 tablas (planificadas) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## SCHEMAS HEREDADOS DEL CORE + +| Schema | Tablas | Uso en ClΓ­nicas | +|--------|--------|-----------------| +| `auth` | 26 | AutenticaciΓ³n, usuarios mΓ©dicos | +| `core` | 12 | Partners (pacientes), catΓ‘logos | +| `financial` | 15 | Facturas de servicios mΓ©dicos | +| `inventory` | 15 | Medicamentos, insumos | +| `hr` | 6 | Personal mΓ©dico | +| `sales` | 6 | Servicios mΓ©dicos | +| `crm` | 5 | Seguimiento de pacientes | +| `analytics` | 5 | EstadΓ­sticas mΓ©dicas | +| `system` | 10 | Recordatorios, notificaciones | + +**Total heredado:** ~100 tablas + +--- + +## SCHEMAS ESPECÍFICOS DE CLÍNICAS (Planificados) + +### 1. Schema `patients` (estimado 10+ tablas) + +**PropΓ³sito:** GestiΓ³n de pacientes + +```sql +-- Tablas principales planificadas: +patients.patients -- Pacientes (extiende core.partners) +patients.patient_contacts -- Contactos de emergencia +patients.insurance_policies -- PΓ³lizas de seguro +patients.medical_history -- Antecedentes mΓ©dicos +patients.allergies -- Alergias +patients.family_history -- Antecedentes familiares +``` + +### 2. Schema `medical` (estimado 15+ tablas) + +**PropΓ³sito:** Expediente clΓ­nico electrΓ³nico + +```sql +-- Tablas principales planificadas: +medical.consultations -- Consultas mΓ©dicas +medical.diagnoses -- DiagnΓ³sticos (CIE-10) +medical.prescriptions -- Recetas mΓ©dicas +medical.prescription_lines -- Medicamentos recetados +medical.vital_signs -- Signos vitales +medical.lab_results -- Resultados de laboratorio +medical.imaging_studies -- Estudios de imagen +medical.clinical_notes -- Notas clΓ­nicas +medical.treatments -- Tratamientos +``` + +### 3. Schema `appointments` (estimado 10+ tablas) + +**PropΓ³sito:** GestiΓ³n de citas + +```sql +-- Tablas principales planificadas: +appointments.doctors -- MΓ©dicos +appointments.specialties -- Especialidades +appointments.doctor_schedules -- Horarios de mΓ©dicos +appointments.consulting_rooms -- Consultorios +appointments.appointments -- Citas +appointments.appointment_types -- Tipos de cita +appointments.reminders -- Recordatorios +``` + +--- + +## SPECS DEL CORE APLICABLES + +**Documento detallado:** `orchestration/00-guidelines/HERENCIA-SPECS-CORE.md` + +### SPECS Obligatorias + +| Spec Core | AplicaciΓ³n en ClΓ­nicas | SP | Estado | +|-----------|----------------------|----:|--------| +| SPEC-SISTEMA-SECUENCIAS | Foliado de expedientes y citas | 8 | PENDIENTE | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | Control de acceso a expedientes | 31 | PENDIENTE | +| SPEC-INTEGRACION-CALENDAR | Agenda de citas mΓ©dicas | 8 | PENDIENTE | +| SPEC-RRHH-EVALUACIONES-SKILLS | Credenciales mΓ©dicas | 26 | PENDIENTE | +| SPEC-MAIL-THREAD-TRACKING | Historial de comunicaciΓ³n | 13 | PENDIENTE | +| SPEC-WIZARD-TRANSIENT-MODEL | Wizards de receta y referencia | 8 | PENDIENTE | +| SPEC-FIRMA-ELECTRONICA-NOM151 | Firma de expedientes clΓ­nicos | 13 | PENDIENTE | +| SPEC-TWO-FACTOR-AUTHENTICATION | Seguridad de acceso | 13 | PENDIENTE | +| SPEC-OAUTH2-SOCIAL-LOGIN | Portal de pacientes | 8 | PENDIENTE | + +### SPECS Opcionales + +| Spec Core | DecisiΓ³n | RazΓ³n | +|-----------|----------|-------| +| SPEC-VALORACION-INVENTARIO | EVALUAR | Solo si hay farmacia interna | +| SPEC-PRICING-RULES | EVALUAR | Para paquetes de servicios | +| SPEC-TAREAS-RECURRENTES | EVALUAR | Para citas periΓ³dicas | + +### SPECS No Aplican + +| Spec Core | RazΓ³n | +|-----------|-------| +| SPEC-PORTAL-PROVEEDORES | No hay compras complejas | +| SPEC-BLANKET-ORDERS | No aplica en servicios mΓ©dicos | +| SPEC-INVENTARIOS-CICLICOS | Solo si hay farmacia grande | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | No hay proyectos de este tipo | + +### Cumplimiento Normativo + +| Norma | DescripciΓ³n | SPECS Relacionadas | +|-------|-------------|-------------------| +| NOM-024-SSA3-2012 | Expediente clΓ­nico electrΓ³nico | SPEC-SEGURIDAD, SPEC-MAIL-THREAD | +| LFPDPPP | ProtecciΓ³n de datos personales | SPEC-SEGURIDAD, SPEC-2FA | +| NOM-004-SSA3-2012 | Expediente clΓ­nico | SPEC-FIRMA-ELECTRONICA | + +--- + +## CUMPLIMIENTO NORMATIVO + +Este sistema debe cumplir con: + +| Norma | DescripciΓ³n | Impacto | +|-------|-------------|---------| +| NOM-024-SSA3-2012 | Expediente clΓ­nico electrΓ³nico | Estructura de datos | +| LFPDPPP | ProtecciΓ³n de datos personales | Seguridad y acceso | +| NOM-004-SSA3-2012 | Expediente clΓ­nico | Contenido mΓ­nimo | + +--- + +## ORDEN DE EJECUCIΓ“N DDL (Futuro) + +```bash +# PASO 1: Cargar ERP Core (base) +cd apps/erp-core/database +./scripts/reset-database.sh --force + +# PASO 2: Cargar extensiones de ClΓ­nicas +cd apps/verticales/clinicas/database +psql $DATABASE_URL -f init/00-extensions.sql +psql $DATABASE_URL -f init/01-create-schemas.sql +psql $DATABASE_URL -f init/02-patients-tables.sql +psql $DATABASE_URL -f init/03-medical-tables.sql +psql $DATABASE_URL -f init/04-appointments-tables.sql +``` + +--- + +## MAPEO DE NOMENCLATURA + +| Core | ClΓ­nicas | +|------|----------| +| `core.partners` | Pacientes base | +| `hr.employees` | Personal mΓ©dico | +| `inventory.products` | Medicamentos, insumos | +| `sales.sale_orders` | Servicios mΓ©dicos | +| `financial.invoices` | Facturas de consultas | + +--- + +## REFERENCIAS + +- ERP Core DDL: `apps/erp-core/database/ddl/` +- ERP Core README: `apps/erp-core/database/README.md` +- Directivas: `orchestration/directivas/` +- Inventarios: `orchestration/inventarios/` + +--- + +**Documento de herencia oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/clinicas/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md b/projects/erp-suite/apps/verticales/clinicas/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md new file mode 100644 index 0000000..f3bc55d --- /dev/null +++ b/projects/erp-suite/apps/verticales/clinicas/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md @@ -0,0 +1,199 @@ +# Herencia de SPECS del Core - ClΓ­nicas + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** ClΓ­nicas (CL) +**Nivel:** 2B.2 + +--- + +## Resumen + +| MΓ©trica | Valor | +|---------|-------| +| SPECS Aplicables | 24/30 | +| SPECS Obligatorias | 20 | +| SPECS Opcionales | 4 | +| SPECS No Aplican | 6 | +| Estado ImplementaciΓ³n | 0% | + +--- + +## SPECS Obligatorias (Deben Implementarse) + +### P0 - CrΓ­ticas + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-SISTEMA-SECUENCIAS | ir.sequence | 8 | PENDIENTE | CL-001, CL-002, CL-005 | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | API Keys + ACL | 31 | PENDIENTE | CL-001, CL-011 | +| SPEC-REPORTES-FINANCIEROS | Balance/P&L SAT | 13 | PENDIENTE | CL-008, CL-009 | +| SPEC-NOMINA-BASICA | hr_payroll | 21 | PENDIENTE | CL-001 | +| SPEC-GASTOS-EMPLEADOS | hr_expense | 13 | PENDIENTE | CL-001 | +| SPEC-SCHEDULER-REPORTES | ir.cron + mail | 8 | PENDIENTE | CL-009 | +| SPEC-INTEGRACION-CALENDAR | calendar integration | 8 | PENDIENTE | CL-003 | + +### P1 - Complementarias + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-CONTABILIDAD-ANALITICA | Centros de costo | 21 | PENDIENTE | CL-008, CL-009 | +| SPEC-CONCILIACION-BANCARIA | ConciliaciΓ³n | 21 | PENDIENTE | CL-008 | +| SPEC-FIRMA-ELECTRONICA-NOM151 | e.firma | 13 | PENDIENTE | CL-011 | +| SPEC-TWO-FACTOR-AUTHENTICATION | 2FA | 13 | PENDIENTE | CL-001 | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes/Series | 13 | PENDIENTE | CL-007 | +| SPEC-OAUTH2-SOCIAL-LOGIN | OAuth2 | 8 | PENDIENTE | CL-002, CL-010 | +| SPEC-IMPUESTOS-AVANZADOS | IVA, ISR | 8 | PENDIENTE | CL-008 | +| SPEC-PLANTILLAS-CUENTAS | Plan contable | 8 | PENDIENTE | CL-008 | +| SPEC-TASAS-CAMBIO-AUTOMATICAS | Tipos cambio | 5 | PENDIENTE | CL-008 | +| SPEC-ALERTAS-PRESUPUESTO | Alertas | 8 | PENDIENTE | CL-008 | +| SPEC-RRHH-EVALUACIONES-SKILLS | Evaluaciones | 26 | PENDIENTE | CL-001 | +| SPEC-LOCALIZACION-PAISES | LocalizaciΓ³n | 13 | PENDIENTE | CL-001, CL-008 | + +### Patrones TΓ©cnicos + +| SPEC | PatrΓ³n | SP | Estado | AplicaciΓ³n | +|------|--------|----:|--------|------------| +| SPEC-MAIL-THREAD-TRACKING | mail.thread | 13 | PENDIENTE | Expedientes, Citas, ComunicaciΓ³n | +| SPEC-WIZARD-TRANSIENT-MODEL | TransientModel | 8 | PENDIENTE | Wizards de receta, referencia | + +--- + +## SPECS Opcionales + +| SPEC | DescripciΓ³n | SP | DecisiΓ³n | RazΓ³n | +|------|-------------|----:|----------|-------| +| SPEC-VALORACION-INVENTARIO | FIFO/AVCO | 21 | EVALUAR | Solo para farmacia interna | +| SPEC-PRICING-RULES | Reglas precio | 8 | EVALUAR | Para paquetes de servicios | +| SPEC-TAREAS-RECURRENTES | Recurrencia | 13 | EVALUAR | Para citas periΓ³dicas | +| SPEC-PRESUPUESTOS-REVISIONES | AprobaciΓ³n | 8 | EVALUAR | Para tratamientos largos | + +--- + +## SPECS No Aplicables + +| SPEC | RazΓ³n | +|------|-------| +| SPEC-PORTAL-PROVEEDORES | No hay compras complejas | +| SPEC-BLANKET-ORDERS | No aplica en servicios mΓ©dicos | +| SPEC-INVENTARIOS-CICLICOS | Solo si hay farmacia grande | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | No hay proyectos de este tipo | +| SPEC-CONSOLIDACION-FINANCIERA | Generalmente una clΓ­nica | + +--- + +## Adaptaciones Requeridas + +### Mapeo de Conceptos Core β†’ ClΓ­nicas + +| Concepto Core | Concepto ClΓ­nicas | +|---------------|-------------------| +| `core.partners` | Pacientes | +| `sales.sale_orders` | Consultas/Servicios | +| `inventory.products` | Medicamentos, servicios mΓ©dicos | +| `hr.employees` | Personal mΓ©dico | +| `calendar.events` | Citas mΓ©dicas | +| `financial.invoices` | Facturas de consulta | + +### Extensiones de Entidad + +```sql +-- Pacientes (extiende partners) +patients.patients ( + partner_id β†’ core.partners, + numero_expediente VARCHAR UNIQUE, + fecha_nacimiento DATE, + sexo ENUM('M', 'F'), + tipo_sangre VARCHAR(5), + alergias TEXT[], + antecedentes JSONB, + seguro_medico_id β†’ insurance_policies +) + +-- Expediente clΓ­nico +medical.clinical_records ( + id UUID, + patient_id β†’ patients, + fecha TIMESTAMPTZ, + tipo ENUM('consulta', 'urgencia', 'hospitalizacion'), + motivo_consulta TEXT, + diagnostico TEXT, + tratamiento TEXT, + medico_id β†’ hr.employees, + signos_vitales JSONB +) + +-- Citas mΓ©dicas +appointments.appointments ( + id UUID, + patient_id β†’ patients, + doctor_id β†’ hr.employees, + specialty_id β†’ specialties, + fecha_hora TIMESTAMPTZ, + duracion_minutos INTEGER, + estado ENUM('programada', 'confirmada', 'en_progreso', 'completada', 'cancelada'), + notas TEXT +) + +-- Recetas mΓ©dicas +medical.prescriptions ( + id UUID, + clinical_record_id β†’ clinical_records, + fecha TIMESTAMPTZ, + vigencia_dias INTEGER, + firma_electronica BYTEA, + productos JSONB +) +``` + +--- + +## Cumplimiento Normativo + +Esta vertical debe cumplir con normas especΓ­ficas: + +| Norma | DescripciΓ³n | SPECS Relacionadas | +|-------|-------------|-------------------| +| NOM-024-SSA3-2012 | Expediente clΓ­nico electrΓ³nico | SPEC-SEGURIDAD, SPEC-MAIL-THREAD | +| LFPDPPP | ProtecciΓ³n de datos personales | SPEC-SEGURIDAD, SPEC-2FA | +| NOM-004-SSA3-2012 | Expediente clΓ­nico | SPEC-FIRMA-ELECTRONICA | + +--- + +## Plan de ImplementaciΓ³n + +### Fase 1: Fundamentos (SP: 60) +1. SPEC-SISTEMA-SECUENCIAS +2. SPEC-SEGURIDAD-API-KEYS-PERMISOS +3. SPEC-TWO-FACTOR-AUTHENTICATION +4. SPEC-OAUTH2-SOCIAL-LOGIN + +### Fase 2: Agenda y ComunicaciΓ³n (SP: 34) +5. SPEC-INTEGRACION-CALENDAR +6. SPEC-MAIL-THREAD-TRACKING +7. SPEC-WIZARD-TRANSIENT-MODEL + +### Fase 3: Expediente y Cumplimiento (SP: 39) +8. SPEC-FIRMA-ELECTRONICA-NOM151 +9. SPEC-RRHH-EVALUACIONES-SKILLS + +### Fase 4: Financiero (SP: 65) +10. SPEC-REPORTES-FINANCIEROS +11. SPEC-CONTABILIDAD-ANALITICA +12. SPEC-CONCILIACION-BANCARIA +13. SPEC-IMPUESTOS-AVANZADOS + +--- + +## Referencias + +- Documento Core: `erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md` +- SPECS del Core: `erp-core/docs/04-modelado/especificaciones-tecnicas/transversal/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` +- Directivas: `orchestration/directivas/` +- Normatividad: NOM-024-SSA3-2012, LFPDPPP, NOM-004-SSA3-2012 + +--- + +**Documento de herencia de SPECS oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/clinicas/orchestration/inventarios/README.md b/projects/erp-suite/apps/verticales/clinicas/orchestration/inventarios/README.md new file mode 100644 index 0000000..8020d92 --- /dev/null +++ b/projects/erp-suite/apps/verticales/clinicas/orchestration/inventarios/README.md @@ -0,0 +1,103 @@ +# Inventarios - ERP ClΓ­nicas + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Nivel SIMCO:** 2B.2 + +--- + +## DescripciΓ³n + +Este directorio contiene los inventarios YAML que sirven como **Single Source of Truth (SSOT)** para el proyecto ERP ClΓ­nicas. Estos archivos son la referencia canΓ³nica para mΓ©tricas, trazabilidad y componentes del sistema. + +--- + +## Archivos de Inventario + +| Archivo | DescripciΓ³n | Estado | +|---------|-------------|--------| +| [MASTER_INVENTORY.yml](./MASTER_INVENTORY.yml) | Inventario maestro con mΓ©tricas globales | Completo | +| [DATABASE_INVENTORY.yml](./DATABASE_INVENTORY.yml) | Inventario de objetos de base de datos | Planificado | +| [BACKEND_INVENTORY.yml](./BACKEND_INVENTORY.yml) | Inventario de componentes backend | Planificado | +| [FRONTEND_INVENTORY.yml](./FRONTEND_INVENTORY.yml) | Inventario de componentes frontend | Planificado | +| [TRACEABILITY_MATRIX.yml](./TRACEABILITY_MATRIX.yml) | Matriz de trazabilidad RF->ET->US | Completo | +| [DEPENDENCY_GRAPH.yml](./DEPENDENCY_GRAPH.yml) | Grafo de dependencias entre mΓ³dulos | Completo | + +--- + +## Herencia del Core + +Este proyecto hereda del **ERP Core** (nivel 2B.1): + +| Aspecto | Heredado | EspecΓ­fico | +|---------|----------|------------| +| **Tablas DB** | ~100 | Planificado | +| **Schemas** | 8+ | Planificado | +| **Specs** | 3 | - | + +### Specs Heredadas + +1. SPEC-RRHH-EVALUACIONES-SKILLS.md +2. SPEC-INTEGRACION-CALENDAR.md +3. SPEC-MAIL-THREAD-TRACKING.md + +--- + +## Resumen Ejecutivo + +### MΓ©tricas del Proyecto + +| MΓ©trica | Valor | +|---------|-------| +| **MΓ³dulos** | 5 (CL-001 a CL-005) | +| **Estado** | PLANIFICACION_COMPLETA | +| **Completitud** | 15% | + +### Dominio del Negocio + +- Expediente clΓ­nico electrΓ³nico +- GestiΓ³n de citas mΓ©dicas +- Control de consultorios +- FacturaciΓ³n de servicios mΓ©dicos + +--- + +## Directivas EspecΓ­ficas + +1. [DIRECTIVA-EXPEDIENTE-CLINICO.md](../directivas/DIRECTIVA-EXPEDIENTE-CLINICO.md) +2. [DIRECTIVA-GESTION-CITAS.md](../directivas/DIRECTIVA-GESTION-CITAS.md) + +--- + +## ConfiguraciΓ³n de Puertos (Planificado) + +| Servicio | Puerto | +|----------|--------| +| Backend API | 3500 | +| Frontend Web | 5179 | +| Patient Portal | 5180 | + +--- + +## Cumplimiento Normativo + +Este proyecto debe cumplir con: +- NOM-024-SSA3-2012 (Expediente clΓ­nico electrΓ³nico) +- Ley de ProtecciΓ³n de Datos Personales en PosesiΓ³n de Particulares + +--- + +## AlineaciΓ³n con ERP Core + +Estos inventarios siguen la misma estructura que: +- `/erp-core/orchestration/inventarios/` (proyecto padre) + +### Referencias + +- Suite Master: `orchestration/inventarios/SUITE_MASTER_INVENTORY.yml` +- Core: `apps/erp-core/orchestration/inventarios/` +- Status Global: `orchestration/inventarios/STATUS.yml` + +--- + +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/fraccionamiento.controller.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/fraccionamiento.controller.ts new file mode 100644 index 0000000..fd05a6c --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/fraccionamiento.controller.ts @@ -0,0 +1,157 @@ +/** + * Fraccionamiento Controller + * API endpoints para gestiΓ³n de fraccionamientos/obras + * + * @module Construction + * @prefix /api/v1/fraccionamientos + */ + +import { Router, Request, Response, NextFunction } from 'express'; +import { + FraccionamientoService, + CreateFraccionamientoDto, + UpdateFraccionamientoDto +} from '../services/fraccionamiento.service'; + +const router = Router(); +const fraccionamientoService = new FraccionamientoService(); + +/** + * GET /api/v1/fraccionamientos + * Lista todos los fraccionamientos del tenant + */ +router.get('/', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const { proyectoId, estado } = req.query; + + const fraccionamientos = await fraccionamientoService.findAll({ + tenantId, + proyectoId: proyectoId as string, + estado: estado as any, + }); + + return res.json({ + success: true, + data: fraccionamientos, + count: fraccionamientos.length, + }); + } catch (error) { + next(error); + } +}); + +/** + * GET /api/v1/fraccionamientos/:id + * Obtiene un fraccionamiento por ID + */ +router.get('/:id', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const fraccionamiento = await fraccionamientoService.findById(req.params.id, tenantId); + if (!fraccionamiento) { + return res.status(404).json({ error: 'Fraccionamiento no encontrado' }); + } + + return res.json({ success: true, data: fraccionamiento }); + } catch (error) { + next(error); + } +}); + +/** + * POST /api/v1/fraccionamientos + * Crea un nuevo fraccionamiento + */ +router.post('/', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const data: CreateFraccionamientoDto = { + ...req.body, + tenantId, + createdById: (req as any).user?.id, + }; + + // Validate required fields + if (!data.codigo || !data.nombre || !data.proyectoId) { + return res.status(400).json({ + error: 'codigo, nombre y proyectoId son requeridos' + }); + } + + // Check if codigo already exists + const existing = await fraccionamientoService.findByCodigo(data.codigo, tenantId); + if (existing) { + return res.status(409).json({ error: 'Ya existe un fraccionamiento con ese cΓ³digo' }); + } + + const fraccionamiento = await fraccionamientoService.create(data); + return res.status(201).json({ success: true, data: fraccionamiento }); + } catch (error) { + next(error); + } +}); + +/** + * PATCH /api/v1/fraccionamientos/:id + * Actualiza un fraccionamiento + */ +router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const data: UpdateFraccionamientoDto = req.body; + const fraccionamiento = await fraccionamientoService.update( + req.params.id, + tenantId, + data + ); + + if (!fraccionamiento) { + return res.status(404).json({ error: 'Fraccionamiento no encontrado' }); + } + + return res.json({ success: true, data: fraccionamiento }); + } catch (error) { + next(error); + } +}); + +/** + * DELETE /api/v1/fraccionamientos/:id + * Elimina un fraccionamiento + */ +router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const deleted = await fraccionamientoService.delete(req.params.id, tenantId); + if (!deleted) { + return res.status(404).json({ error: 'Fraccionamiento no encontrado' }); + } + + return res.json({ success: true, message: 'Fraccionamiento eliminado' }); + } catch (error) { + next(error); + } +}); + +export default router; diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/index.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/index.ts new file mode 100644 index 0000000..543d60c --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/index.ts @@ -0,0 +1,7 @@ +/** + * Construction Controllers Index + * @module Construction + */ + +export { default as proyectoController } from './proyecto.controller'; +export { default as fraccionamientoController } from './fraccionamiento.controller'; diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/proyecto.controller.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/proyecto.controller.ts new file mode 100644 index 0000000..2a3eb11 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/controllers/proyecto.controller.ts @@ -0,0 +1,165 @@ +/** + * Proyecto Controller + * API endpoints para gestiΓ³n de proyectos + * + * @module Construction + * @prefix /api/v1/proyectos + */ + +import { Router, Request, Response, NextFunction } from 'express'; +import { ProyectoService, CreateProyectoDto, UpdateProyectoDto } from '../services/proyecto.service'; + +const router = Router(); +const proyectoService = new ProyectoService(); + +/** + * GET /api/v1/proyectos + * Lista todos los proyectos del tenant + */ +router.get('/', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const { estadoProyecto, ciudad } = req.query; + + const proyectos = await proyectoService.findAll({ + tenantId, + estadoProyecto: estadoProyecto as any, + ciudad: ciudad as string, + }); + + return res.json({ + success: true, + data: proyectos, + count: proyectos.length, + }); + } catch (error) { + next(error); + } +}); + +/** + * GET /api/v1/proyectos/statistics + * EstadΓ­sticas de proyectos + */ +router.get('/statistics', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const stats = await proyectoService.getStatistics(tenantId); + return res.json({ success: true, data: stats }); + } catch (error) { + next(error); + } +}); + +/** + * GET /api/v1/proyectos/:id + * Obtiene un proyecto por ID + */ +router.get('/:id', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const proyecto = await proyectoService.findById(req.params.id, tenantId); + if (!proyecto) { + return res.status(404).json({ error: 'Proyecto no encontrado' }); + } + + return res.json({ success: true, data: proyecto }); + } catch (error) { + next(error); + } +}); + +/** + * POST /api/v1/proyectos + * Crea un nuevo proyecto + */ +router.post('/', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const data: CreateProyectoDto = { + ...req.body, + tenantId, + createdById: (req as any).user?.id, + }; + + // Validate required fields + if (!data.codigo || !data.nombre) { + return res.status(400).json({ error: 'codigo y nombre son requeridos' }); + } + + // Check if codigo already exists + const existing = await proyectoService.findByCodigo(data.codigo, tenantId); + if (existing) { + return res.status(409).json({ error: 'Ya existe un proyecto con ese cΓ³digo' }); + } + + const proyecto = await proyectoService.create(data); + return res.status(201).json({ success: true, data: proyecto }); + } catch (error) { + next(error); + } +}); + +/** + * PATCH /api/v1/proyectos/:id + * Actualiza un proyecto + */ +router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const data: UpdateProyectoDto = req.body; + const proyecto = await proyectoService.update(req.params.id, tenantId, data); + + if (!proyecto) { + return res.status(404).json({ error: 'Proyecto no encontrado' }); + } + + return res.json({ success: true, data: proyecto }); + } catch (error) { + next(error); + } +}); + +/** + * DELETE /api/v1/proyectos/:id + * Elimina un proyecto + */ +router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => { + try { + const tenantId = req.headers['x-tenant-id'] as string; + if (!tenantId) { + return res.status(400).json({ error: 'X-Tenant-Id header required' }); + } + + const deleted = await proyectoService.delete(req.params.id, tenantId); + if (!deleted) { + return res.status(404).json({ error: 'Proyecto no encontrado' }); + } + + return res.json({ success: true, message: 'Proyecto eliminado' }); + } catch (error) { + next(error); + } +}); + +export default router; diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/fraccionamiento.service.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/fraccionamiento.service.ts new file mode 100644 index 0000000..604b234 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/fraccionamiento.service.ts @@ -0,0 +1,117 @@ +/** + * Fraccionamiento Service + * Servicio para gestiΓ³n de fraccionamientos/obras + * + * @module Construction + */ + +import { Repository, FindOptionsWhere } from 'typeorm'; +import { AppDataSource } from '../../../shared/database/typeorm.config'; +import { Fraccionamiento, EstadoFraccionamiento } from '../entities/fraccionamiento.entity'; + +export interface CreateFraccionamientoDto { + tenantId: string; + proyectoId: string; + codigo: string; + nombre: string; + descripcion?: string; + direccion?: string; + ubicacionGeo?: string; + fechaInicio?: Date; + fechaFinEstimada?: Date; + createdById?: string; +} + +export interface UpdateFraccionamientoDto { + nombre?: string; + descripcion?: string; + direccion?: string; + ubicacionGeo?: string; + fechaInicio?: Date; + fechaFinEstimada?: Date; + estado?: EstadoFraccionamiento; +} + +export interface FraccionamientoFilters { + tenantId: string; + proyectoId?: string; + estado?: EstadoFraccionamiento; +} + +export class FraccionamientoService { + private repository: Repository; + + constructor() { + this.repository = AppDataSource.getRepository(Fraccionamiento); + } + + async findAll(filters: FraccionamientoFilters): Promise { + const where: FindOptionsWhere = { + tenantId: filters.tenantId, + }; + + if (filters.proyectoId) { + where.proyectoId = filters.proyectoId; + } + + if (filters.estado) { + where.estado = filters.estado; + } + + return this.repository.find({ + where, + relations: ['proyecto'], + order: { createdAt: 'DESC' }, + }); + } + + async findById(id: string, tenantId: string): Promise { + return this.repository.findOne({ + where: { id, tenantId }, + relations: ['proyecto', 'createdBy'], + }); + } + + async findByCodigo(codigo: string, tenantId: string): Promise { + return this.repository.findOne({ + where: { codigo, tenantId }, + }); + } + + async findByProyecto(proyectoId: string, tenantId: string): Promise { + return this.repository.find({ + where: { proyectoId, tenantId }, + order: { codigo: 'ASC' }, + }); + } + + async create(data: CreateFraccionamientoDto): Promise { + const fraccionamiento = this.repository.create(data); + return this.repository.save(fraccionamiento); + } + + async update( + id: string, + tenantId: string, + data: UpdateFraccionamientoDto + ): Promise { + const fraccionamiento = await this.findById(id, tenantId); + if (!fraccionamiento) { + return null; + } + + Object.assign(fraccionamiento, data); + return this.repository.save(fraccionamiento); + } + + async delete(id: string, tenantId: string): Promise { + const result = await this.repository.delete({ id, tenantId }); + return result.affected ? result.affected > 0 : false; + } + + async countByProyecto(proyectoId: string, tenantId: string): Promise { + return this.repository.count({ + where: { proyectoId, tenantId }, + }); + } +} diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/index.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/index.ts new file mode 100644 index 0000000..e78e8c4 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/index.ts @@ -0,0 +1,7 @@ +/** + * Construction Services Index + * @module Construction + */ + +export * from './proyecto.service'; +export * from './fraccionamiento.service'; diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/proyecto.service.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/proyecto.service.ts new file mode 100644 index 0000000..ae55f2d --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/construction/services/proyecto.service.ts @@ -0,0 +1,117 @@ +/** + * Proyecto Service + * Servicio para gestiΓ³n de proyectos de construcciΓ³n + * + * @module Construction + */ + +import { Repository, FindOptionsWhere } from 'typeorm'; +import { AppDataSource } from '../../../shared/database/typeorm.config'; +import { Proyecto, EstadoProyecto } from '../entities/proyecto.entity'; + +export interface CreateProyectoDto { + tenantId: string; + codigo: string; + nombre: string; + descripcion?: string; + direccion?: string; + ciudad?: string; + estado?: string; + fechaInicio?: Date; + fechaFinEstimada?: Date; + createdById?: string; +} + +export interface UpdateProyectoDto { + nombre?: string; + descripcion?: string; + direccion?: string; + ciudad?: string; + estado?: string; + fechaInicio?: Date; + fechaFinEstimada?: Date; + estadoProyecto?: EstadoProyecto; +} + +export interface ProyectoFilters { + tenantId: string; + estadoProyecto?: EstadoProyecto; + ciudad?: string; +} + +export class ProyectoService { + private repository: Repository; + + constructor() { + this.repository = AppDataSource.getRepository(Proyecto); + } + + async findAll(filters: ProyectoFilters): Promise { + const where: FindOptionsWhere = { + tenantId: filters.tenantId, + }; + + if (filters.estadoProyecto) { + where.estadoProyecto = filters.estadoProyecto; + } + + if (filters.ciudad) { + where.ciudad = filters.ciudad; + } + + return this.repository.find({ + where, + relations: ['fraccionamientos'], + order: { createdAt: 'DESC' }, + }); + } + + async findById(id: string, tenantId: string): Promise { + return this.repository.findOne({ + where: { id, tenantId }, + relations: ['fraccionamientos', 'createdBy'], + }); + } + + async findByCodigo(codigo: string, tenantId: string): Promise { + return this.repository.findOne({ + where: { codigo, tenantId }, + }); + } + + async create(data: CreateProyectoDto): Promise { + const proyecto = this.repository.create(data); + return this.repository.save(proyecto); + } + + async update(id: string, tenantId: string, data: UpdateProyectoDto): Promise { + const proyecto = await this.findById(id, tenantId); + if (!proyecto) { + return null; + } + + Object.assign(proyecto, data); + return this.repository.save(proyecto); + } + + async delete(id: string, tenantId: string): Promise { + const result = await this.repository.delete({ id, tenantId }); + return result.affected ? result.affected > 0 : false; + } + + async getStatistics(tenantId: string): Promise<{ + total: number; + activos: number; + completados: number; + pausados: number; + }> { + const proyectos = await this.repository.find({ where: { tenantId } }); + + return { + total: proyectos.length, + activos: proyectos.filter(p => p.estadoProyecto === 'activo').length, + completados: proyectos.filter(p => p.estadoProyecto === 'completado').length, + pausados: proyectos.filter(p => p.estadoProyecto === 'pausado').length, + }; + } +} diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/capacitacion.entity.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/capacitacion.entity.ts new file mode 100644 index 0000000..ecbd699 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/capacitacion.entity.ts @@ -0,0 +1,74 @@ +/** + * Capacitacion Entity + * CatΓ‘logo de capacitaciones HSE + * + * @module HSE + * @table hse.capacitaciones + * @ddl schemas/03-hse-schema-ddl.sql + * @rf RF-MAA017-002 + */ + +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, + Index, +} from 'typeorm'; +import { Tenant } from '../../core/entities/tenant.entity'; + +export type TipoCapacitacion = 'induccion' | 'especifica' | 'certificacion' | 'reentrenamiento'; + +@Entity({ schema: 'hse', name: 'capacitaciones' }) +@Index(['tenantId', 'codigo'], { unique: true }) +export class Capacitacion { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ name: 'tenant_id', type: 'uuid' }) + tenantId: string; + + @Column({ type: 'varchar', length: 20 }) + codigo: string; + + @Column({ type: 'varchar', length: 200 }) + nombre: string; + + @Column({ type: 'text', nullable: true }) + descripcion: string; + + @Column({ + type: 'enum', + enum: ['induccion', 'especifica', 'certificacion', 'reentrenamiento'] + }) + tipo: TipoCapacitacion; + + @Column({ name: 'duracion_horas', type: 'integer', default: 1 }) + duracionHoras: number; + + @Column({ name: 'vigencia_meses', type: 'integer', nullable: true }) + vigenciaMeses: number; + + @Column({ name: 'requiere_evaluacion', type: 'boolean', default: false }) + requiereEvaluacion: boolean; + + @Column({ name: 'calificacion_minima', type: 'integer', nullable: true }) + calificacionMinima: number; + + @Column({ type: 'boolean', default: true }) + activo: boolean; + + @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' }) + updatedAt: Date; + + // Relations + @ManyToOne(() => Tenant) + @JoinColumn({ name: 'tenant_id' }) + tenant: Tenant; +} diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente-accion.entity.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente-accion.entity.ts new file mode 100644 index 0000000..4fae042 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente-accion.entity.ts @@ -0,0 +1,71 @@ +/** + * IncidenteAccion Entity + * Acciones correctivas de incidentes + * + * @module HSE + * @table hse.incidente_acciones + * @ddl schemas/03-hse-schema-ddl.sql + * @rf RF-MAA017-001 + */ + +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, +} from 'typeorm'; +import { Incidente } from './incidente.entity'; +import { Employee } from '../../hr/entities/employee.entity'; + +export type EstadoAccion = 'pendiente' | 'en_progreso' | 'completada' | 'verificada'; + +@Entity({ schema: 'hse', name: 'incidente_acciones' }) +export class IncidenteAccion { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ name: 'incidente_id', type: 'uuid' }) + incidenteId: string; + + @Column({ type: 'text' }) + descripcion: string; + + @Column({ type: 'varchar', length: 50 }) + tipo: string; + + @Column({ name: 'responsable_id', type: 'uuid', nullable: true }) + responsableId: string; + + @Column({ name: 'fecha_compromiso', type: 'date' }) + fechaCompromiso: Date; + + @Column({ name: 'fecha_cierre', type: 'date', nullable: true }) + fechaCierre: Date; + + @Column({ type: 'varchar', length: 20, default: 'pendiente' }) + estado: EstadoAccion; + + @Column({ name: 'evidencia_url', type: 'varchar', length: 500, nullable: true }) + evidenciaUrl: string; + + @Column({ type: 'text', nullable: true }) + observaciones: string; + + @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' }) + updatedAt: Date; + + // Relations + @ManyToOne(() => Incidente, (i) => i.acciones, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'incidente_id' }) + incidente: Incidente; + + @ManyToOne(() => Employee) + @JoinColumn({ name: 'responsable_id' }) + responsable: Employee; +} diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente-involucrado.entity.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente-involucrado.entity.ts new file mode 100644 index 0000000..b92eb67 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente-involucrado.entity.ts @@ -0,0 +1,58 @@ +/** + * IncidenteInvolucrado Entity + * Personas involucradas en incidentes + * + * @module HSE + * @table hse.incidente_involucrados + * @ddl schemas/03-hse-schema-ddl.sql + * @rf RF-MAA017-001 + */ + +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + ManyToOne, + JoinColumn, +} from 'typeorm'; +import { Incidente } from './incidente.entity'; +import { Employee } from '../../hr/entities/employee.entity'; + +export type RolInvolucrado = 'lesionado' | 'testigo' | 'responsable'; + +@Entity({ schema: 'hse', name: 'incidente_involucrados' }) +export class IncidenteInvolucrado { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ name: 'incidente_id', type: 'uuid' }) + incidenteId: string; + + @Column({ name: 'employee_id', type: 'uuid' }) + employeeId: string; + + @Column({ type: 'enum', enum: ['lesionado', 'testigo', 'responsable'] }) + rol: RolInvolucrado; + + @Column({ name: 'descripcion_lesion', type: 'text', nullable: true }) + descripcionLesion: string; + + @Column({ name: 'parte_cuerpo', type: 'varchar', length: 100, nullable: true }) + parteCuerpo: string; + + @Column({ name: 'dias_incapacidad', type: 'integer', default: 0 }) + diasIncapacidad: number; + + @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) + createdAt: Date; + + // Relations + @ManyToOne(() => Incidente, (i) => i.involucrados, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'incidente_id' }) + incidente: Incidente; + + @ManyToOne(() => Employee) + @JoinColumn({ name: 'employee_id' }) + employee: Employee; +} diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente.entity.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente.entity.ts new file mode 100644 index 0000000..249c5a6 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/incidente.entity.ts @@ -0,0 +1,111 @@ +/** + * Incidente Entity + * GestiΓ³n de incidentes de seguridad + * + * @module HSE + * @table hse.incidentes + * @ddl schemas/03-hse-schema-ddl.sql + * @rf RF-MAA017-001 + */ + +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + OneToMany, + JoinColumn, + Index, +} from 'typeorm'; +import { Tenant } from '../../core/entities/tenant.entity'; +import { User } from '../../core/entities/user.entity'; +import { Fraccionamiento } from '../../construction/entities/fraccionamiento.entity'; +import { IncidenteInvolucrado } from './incidente-involucrado.entity'; +import { IncidenteAccion } from './incidente-accion.entity'; + +export type TipoIncidente = 'accidente' | 'incidente' | 'casi_accidente'; +export type GravedadIncidente = 'leve' | 'moderado' | 'grave' | 'fatal'; +export type EstadoIncidente = 'abierto' | 'en_investigacion' | 'cerrado'; + +@Entity({ schema: 'hse', name: 'incidentes' }) +@Index(['tenantId', 'folio'], { unique: true }) +export class Incidente { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ name: 'tenant_id', type: 'uuid' }) + tenantId: string; + + @Column({ type: 'varchar', length: 20 }) + folio: string; + + @Column({ name: 'fecha_hora', type: 'timestamptz' }) + fechaHora: Date; + + @Column({ name: 'fraccionamiento_id', type: 'uuid' }) + fraccionamientoId: string; + + @Column({ name: 'ubicacion_descripcion', type: 'text', nullable: true }) + ubicacionDescripcion: string; + + @Column({ + name: 'ubicacion_geo', + type: 'geometry', + spatialFeatureType: 'Point', + srid: 4326, + nullable: true + }) + ubicacionGeo: string; + + @Column({ type: 'enum', enum: ['accidente', 'incidente', 'casi_accidente'] }) + tipo: TipoIncidente; + + @Column({ type: 'enum', enum: ['leve', 'moderado', 'grave', 'fatal'] }) + gravedad: GravedadIncidente; + + @Column({ type: 'text' }) + descripcion: string; + + @Column({ name: 'causa_inmediata', type: 'text', nullable: true }) + causaInmediata: string; + + @Column({ name: 'causa_basica', type: 'text', nullable: true }) + causaBasica: string; + + @Column({ + type: 'enum', + enum: ['abierto', 'en_investigacion', 'cerrado'], + default: 'abierto' + }) + estado: EstadoIncidente; + + @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' }) + updatedAt: Date; + + @Column({ name: 'created_by', type: 'uuid', nullable: true }) + createdById: string; + + // Relations + @ManyToOne(() => Tenant) + @JoinColumn({ name: 'tenant_id' }) + tenant: Tenant; + + @ManyToOne(() => Fraccionamiento) + @JoinColumn({ name: 'fraccionamiento_id' }) + fraccionamiento: Fraccionamiento; + + @ManyToOne(() => User) + @JoinColumn({ name: 'created_by' }) + createdBy: User; + + @OneToMany(() => IncidenteInvolucrado, (ii) => ii.incidente) + involucrados: IncidenteInvolucrado[]; + + @OneToMany(() => IncidenteAccion, (ia) => ia.incidente) + acciones: IncidenteAccion[]; +} diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/index.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/index.ts new file mode 100644 index 0000000..00cea16 --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/modules/hse/entities/index.ts @@ -0,0 +1,23 @@ +/** + * HSE Entities Index + * @module HSE + * + * Entities for Health, Safety & Environment module + * Based on RF-MAA017-001 to RF-MAA017-008 + */ + +// RF-MAA017-001: GestiΓ³n de Incidentes +export * from './incidente.entity'; +export * from './incidente-involucrado.entity'; +export * from './incidente-accion.entity'; + +// RF-MAA017-002: Control de Capacitaciones +export * from './capacitacion.entity'; + +// TODO: Implementar entities adicionales segΓΊn se necesiten: +// - RF-MAA017-003: Inspecciones de Seguridad +// - RF-MAA017-004: Control de EPP +// - RF-MAA017-005: Cumplimiento STPS +// - RF-MAA017-006: GestiΓ³n Ambiental +// - RF-MAA017-007: Permisos de Trabajo +// - RF-MAA017-008: Indicadores HSE diff --git a/projects/erp-suite/apps/verticales/construccion/backend/src/server.ts b/projects/erp-suite/apps/verticales/construccion/backend/src/server.ts index 571dcb4..9797f95 100644 --- a/projects/erp-suite/apps/verticales/construccion/backend/src/server.ts +++ b/projects/erp-suite/apps/verticales/construccion/backend/src/server.ts @@ -47,8 +47,10 @@ app.get('/health', (req, res) => { /** * API Routes - * TODO: Agregar rutas de mΓ³dulos aquΓ­ */ +import { proyectoController, fraccionamientoController } from './modules/construction/controllers'; + +// Root API info app.get(`/api/${API_VERSION}`, (req, res) => { res.status(200).json({ message: 'API MVP Sistema AdministraciΓ³n de Obra', @@ -57,12 +59,16 @@ app.get(`/api/${API_VERSION}`, (req, res) => { health: '/health', docs: `/api/${API_VERSION}/docs`, auth: `/api/${API_VERSION}/auth`, - projects: `/api/${API_VERSION}/projects`, - budgets: `/api/${API_VERSION}/budgets`, + proyectos: `/api/${API_VERSION}/proyectos`, + fraccionamientos: `/api/${API_VERSION}/fraccionamientos`, }, }); }); +// Construction Module Routes +app.use(`/api/${API_VERSION}/proyectos`, proyectoController); +app.use(`/api/${API_VERSION}/fraccionamientos`, fraccionamientoController); + /** * 404 Handler */ diff --git a/projects/erp-suite/apps/verticales/construccion/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md b/projects/erp-suite/apps/verticales/construccion/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md new file mode 100644 index 0000000..c55197b --- /dev/null +++ b/projects/erp-suite/apps/verticales/construccion/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md @@ -0,0 +1,159 @@ +# Herencia de SPECS del Core - ConstrucciΓ³n + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** ConstrucciΓ³n (MAI/MAE) +**Nivel:** 2B.2 + +--- + +## Resumen + +| MΓ©trica | Valor | +|---------|-------| +| SPECS Aplicables | 26/30 | +| SPECS Obligatorias | 22 | +| SPECS Opcionales | 4 | +| SPECS No Aplican | 4 | +| Estado ImplementaciΓ³n | 0% | + +--- + +## SPECS Obligatorias (Deben Implementarse) + +### P0 - CrΓ­ticas + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-SISTEMA-SECUENCIAS | ir.sequence | 8 | PENDIENTE | MAI-001, MAE-001 | +| SPEC-VALORACION-INVENTARIO | FIFO/AVCO | 21 | PENDIENTE | MAI-004, MAI-012 | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | API Keys + ACL | 31 | PENDIENTE | MAI-001 | +| SPEC-REPORTES-FINANCIEROS | Balance/P&L SAT | 13 | PENDIENTE | MAE-003 | +| SPEC-PORTAL-PROVEEDORES | Portal RFQ | 13 | PENDIENTE | MAI-006 | +| SPEC-NOMINA-BASICA | hr_payroll | 21 | PENDIENTE | MAI-008 | +| SPEC-GASTOS-EMPLEADOS | hr_expense | 13 | PENDIENTE | MAI-008 | +| SPEC-TAREAS-RECURRENTES | project.task.recurrence | 13 | PENDIENTE | MAI-002, MAI-005 | +| SPEC-SCHEDULER-REPORTES | ir.cron + mail | 8 | PENDIENTE | MAE-003 | + +### P1 - Complementarias + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-CONTABILIDAD-ANALITICA | Centros de costo | 21 | PENDIENTE | MAE-003 | +| SPEC-CONCILIACION-BANCARIA | ConciliaciΓ³n | 21 | PENDIENTE | MAE-003 | +| SPEC-FIRMA-ELECTRONICA-NOM151 | e.firma | 13 | PENDIENTE | MAE-001, MAI-007 | +| SPEC-TWO-FACTOR-AUTHENTICATION | 2FA | 13 | PENDIENTE | MAI-001 | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes/Series | 13 | PENDIENTE | MAI-004, MAI-012 | +| SPEC-BLANKET-ORDERS | Γ“rdenes marco | 13 | PENDIENTE | MAI-006 | +| SPEC-IMPUESTOS-AVANZADOS | IVA, ISR | 8 | PENDIENTE | MAE-003 | +| SPEC-PLANTILLAS-CUENTAS | Plan contable | 8 | PENDIENTE | MAE-003 | +| SPEC-TASAS-CAMBIO-AUTOMATICAS | Tipos cambio | 5 | PENDIENTE | MAE-003 | +| SPEC-ALERTAS-PRESUPUESTO | Alertas | 8 | PENDIENTE | MAI-012 | +| SPEC-PRESUPUESTOS-REVISIONES | AprobaciΓ³n | 8 | PENDIENTE | MAI-005, MAI-012 | +| SPEC-RRHH-EVALUACIONES-SKILLS | Evaluaciones | 26 | PENDIENTE | MAI-008 | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | Burndown | 13 | PENDIENTE | MAI-002, MAI-005 | +| SPEC-LOCALIZACION-PAISES | LocalizaciΓ³n | 13 | PENDIENTE | MAE-001 | + +### Patrones TΓ©cnicos + +| SPEC | PatrΓ³n | SP | Estado | AplicaciΓ³n | +|------|--------|----:|--------|------------| +| SPEC-MAIL-THREAD-TRACKING | mail.thread | 13 | PENDIENTE | Proyectos, Estimaciones, Obras | +| SPEC-WIZARD-TRANSIENT-MODEL | TransientModel | 8 | PENDIENTE | Wizards de cierre, aprobaciΓ³n | + +--- + +## SPECS Opcionales + +| SPEC | DescripciΓ³n | SP | DecisiΓ³n | RazΓ³n | +|------|-------------|----:|----------|-------| +| SPEC-INTEGRACION-CALENDAR | Calendario | 8 | EVALUAR | Útil para programaciΓ³n de obra | +| SPEC-PRICING-RULES | Reglas precio | 8 | EVALUAR | Para cotizaciones complejas | +| SPEC-OAUTH2-SOCIAL-LOGIN | OAuth2 | 8 | DIFERIR | No prioritario | +| SPEC-CONSOLIDACION-FINANCIERA | Multi-empresa | 13 | DIFERIR | Futuro para constructoras grandes | + +--- + +## SPECS No Aplicables + +| SPEC | RazΓ³n | +|------|-------| +| SPEC-INVENTARIOS-CICLICOS | No hay inventario tradicional de productos | +| SPEC-INTEGRACION-CALENDAR | El mΓ³dulo de proyectos maneja calendario propio | + +--- + +## Adaptaciones Requeridas + +### Mapeo de Conceptos Core β†’ ConstrucciΓ³n + +| Concepto Core | Concepto ConstrucciΓ³n | +|---------------|----------------------| +| `projects.projects` | Obras, Fraccionamientos | +| `projects.tasks` | Etapas de construcciΓ³n | +| `inventory.products` | Materiales de construcciΓ³n | +| `inventory.lots` | Lotes de materiales | +| `hr.employees` | Trabajadores de obra | +| `sales.sale_orders` | Contratos de obra | +| `purchase.purchase_orders` | Γ“rdenes de compra de materiales | + +### Extensiones de Entidad + +```sql +-- ExtensiΓ³n de projects para construcciΓ³n +construction.project_extensions ( + project_id β†’ projects.projects, + tipo_obra ENUM, + numero_licencia VARCHAR, + fecha_inicio_obra DATE, + fecha_fin_estimada DATE, + m2_construccion DECIMAL, + presupuesto_aprobado DECIMAL +) + +-- ExtensiΓ³n de employees para construcciΓ³n +construction.employee_extensions ( + employee_id β†’ hr.employees, + numero_imss VARCHAR, + categoria_obra ENUM, + especialidad VARCHAR, + certificaciones JSONB +) +``` + +--- + +## Plan de ImplementaciΓ³n + +### Fase 1: Fundamentos (SP: 60) +1. SPEC-SISTEMA-SECUENCIAS +2. SPEC-SEGURIDAD-API-KEYS-PERMISOS +3. SPEC-TWO-FACTOR-AUTHENTICATION + +### Fase 2: Core de Negocio (SP: 80) +4. SPEC-VALORACION-INVENTARIO +5. SPEC-TRAZABILIDAD-LOTES-SERIES +6. SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN + +### Fase 3: Financiero (SP: 65) +7. SPEC-REPORTES-FINANCIEROS +8. SPEC-CONTABILIDAD-ANALITICA +9. SPEC-IMPUESTOS-AVANZADOS + +### Fase 4: RRHH (SP: 60) +10. SPEC-NOMINA-BASICA +11. SPEC-GASTOS-EMPLEADOS +12. SPEC-RRHH-EVALUACIONES-SKILLS + +--- + +## Referencias + +- Documento Core: `erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md` +- SPECS del Core: `erp-core/docs/04-modelado/especificaciones-tecnicas/transversal/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` + +--- + +**Documento de herencia de SPECS oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/construccion/orchestration/inventarios/BACKEND_INVENTORY.yml b/projects/erp-suite/apps/verticales/construccion/orchestration/inventarios/BACKEND_INVENTORY.yml index a85da10..debaf97 100644 --- a/projects/erp-suite/apps/verticales/construccion/orchestration/inventarios/BACKEND_INVENTORY.yml +++ b/projects/erp-suite/apps/verticales/construccion/orchestration/inventarios/BACKEND_INVENTORY.yml @@ -53,20 +53,37 @@ resumen: # ESTADO REAL DE IMPLEMENTACIΓ“N (2025-12-08) estado_implementacion: - porcentaje: "5%" - archivos_ts: 7 - entities_implementadas: 2 - services_implementados: 0 - controllers_implementados: 0 + porcentaje: "15%" + archivos_ts: 25 + entities_implementadas: 12 + services_implementados: 2 + controllers_implementados: 2 - archivos_existentes: - - src/types/ - - src/entities/ # Parcialmente definidas + modulos_implementados: + construction: + entities: [Proyecto, Fraccionamiento] + services: [ProyectoService, FraccionamientoService] + controllers: [ProyectoController, FraccionamientoController] + estado: "FUNCIONAL" + hr: + entities: [Employee, Puesto, EmployeeFraccionamiento] + services: [] + controllers: [] + estado: "ENTITIES_COMPLETAS" + hse: + entities: [Incidente, IncidenteInvolucrado, IncidenteAccion, Capacitacion] + services: [] + controllers: [] + estado: "ENTITIES_PARCIALES" + core: + entities: [User, Tenant] + estado: "BASE" gap_documentacion_vs_codigo: documentacion_md: 449 - archivos_codigo: 7 - ratio: "1.5%" + archivos_codigo: 25 + ratio: "5.6%" + nota: "Gap reducido - entities y services base implementados" herencia_core: version_core: "1.1.0" diff --git a/projects/erp-suite/apps/verticales/mecanicas-diesel/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md b/projects/erp-suite/apps/verticales/mecanicas-diesel/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md new file mode 100644 index 0000000..bf5dae8 --- /dev/null +++ b/projects/erp-suite/apps/verticales/mecanicas-diesel/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md @@ -0,0 +1,169 @@ +# Herencia de SPECS del Core - MecΓ‘nicas Diesel + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** MecΓ‘nicas Diesel (MMD) +**Nivel:** 2B.2 + +--- + +## Resumen + +| MΓ©trica | Valor | +|---------|-------| +| SPECS Aplicables | 25/30 | +| SPECS Obligatorias | 23 | +| SPECS Opcionales | 2 | +| SPECS No Aplican | 5 | +| Estado ImplementaciΓ³n | 0% | + +--- + +## SPECS Obligatorias (Deben Implementarse) + +### P0 - CrΓ­ticas + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-SISTEMA-SECUENCIAS | ir.sequence | 8 | PENDIENTE | MMD-001, MMD-002 | +| SPEC-VALORACION-INVENTARIO | FIFO/AVCO | 21 | PENDIENTE | MMD-004 | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | API Keys + ACL | 31 | PENDIENTE | MMD-001 | +| SPEC-REPORTES-FINANCIEROS | Balance/P&L SAT | 13 | PENDIENTE | MMD-006 | +| SPEC-PORTAL-PROVEEDORES | Portal RFQ | 13 | PENDIENTE | MMD-004 | +| SPEC-NOMINA-BASICA | hr_payroll | 21 | PENDIENTE | MMD-001 | +| SPEC-GASTOS-EMPLEADOS | hr_expense | 13 | PENDIENTE | MMD-001 | +| SPEC-TAREAS-RECURRENTES | project.task.recurrence | 13 | PENDIENTE | MMD-002 | +| SPEC-SCHEDULER-REPORTES | ir.cron + mail | 8 | PENDIENTE | MMD-006 | + +### P1 - Complementarias + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-CONTABILIDAD-ANALITICA | Centros de costo | 21 | PENDIENTE | MMD-006 | +| SPEC-CONCILIACION-BANCARIA | ConciliaciΓ³n | 21 | PENDIENTE | MMD-006 | +| SPEC-TWO-FACTOR-AUTHENTICATION | 2FA | 13 | PENDIENTE | MMD-001 | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes/Series | 13 | PENDIENTE | MMD-004 | +| SPEC-PRICING-RULES | Reglas precio | 8 | PENDIENTE | MMD-002, MMD-006 | +| SPEC-BLANKET-ORDERS | Γ“rdenes marco | 13 | PENDIENTE | MMD-004 | +| SPEC-INVENTARIOS-CICLICOS | Conteo cΓ­clico | 13 | PENDIENTE | MMD-004 | +| SPEC-IMPUESTOS-AVANZADOS | IVA, ISR | 8 | PENDIENTE | MMD-006 | +| SPEC-PLANTILLAS-CUENTAS | Plan contable | 8 | PENDIENTE | MMD-006 | +| SPEC-TASAS-CAMBIO-AUTOMATICAS | Tipos cambio | 5 | PENDIENTE | MMD-006 | +| SPEC-ALERTAS-PRESUPUESTO | Alertas | 8 | PENDIENTE | MMD-002, MMD-006 | +| SPEC-PRESUPUESTOS-REVISIONES | AprobaciΓ³n | 8 | PENDIENTE | MMD-002 | +| SPEC-RRHH-EVALUACIONES-SKILLS | Evaluaciones | 26 | PENDIENTE | MMD-001 | +| SPEC-LOCALIZACION-PAISES | LocalizaciΓ³n | 13 | PENDIENTE | MMD-001 | + +### Patrones TΓ©cnicos + +| SPEC | PatrΓ³n | SP | Estado | AplicaciΓ³n | +|------|--------|----:|--------|------------| +| SPEC-MAIL-THREAD-TRACKING | mail.thread | 13 | PENDIENTE | Γ“rdenes de trabajo, DiagnΓ³sticos | +| SPEC-WIZARD-TRANSIENT-MODEL | TransientModel | 8 | PENDIENTE | Wizards de cotizaciΓ³n, cierre | + +--- + +## SPECS Opcionales + +| SPEC | DescripciΓ³n | SP | DecisiΓ³n | RazΓ³n | +|------|-------------|----:|----------|-------| +| SPEC-FIRMA-ELECTRONICA-NOM151 | e.firma | 13 | EVALUAR | Para contratos de servicio | +| SPEC-OAUTH2-SOCIAL-LOGIN | OAuth2 | 8 | DIFERIR | No prioritario | + +--- + +## SPECS No Aplicables + +| SPEC | RazΓ³n | +|------|-------| +| SPEC-INTEGRACION-CALENDAR | No hay agenda de citas compleja | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | No hay gestiΓ³n de proyectos larga | +| SPEC-CONSOLIDACION-FINANCIERA | Negocio de una sola ubicaciΓ³n | + +--- + +## Adaptaciones Requeridas + +### Mapeo de Conceptos Core β†’ MecΓ‘nicas + +| Concepto Core | Concepto MecΓ‘nicas | +|---------------|-------------------| +| `sales.sale_orders` | Γ“rdenes de servicio | +| `inventory.products` | Refacciones, partes | +| `inventory.lots` | Lotes OEM, garantΓ­as | +| `core.partners` | Clientes con vehΓ­culos | +| `projects.tasks` | Trabajos de servicio | + +### Extensiones de Entidad + +```sql +-- VehΓ­culos de clientes +service_management.vehicles ( + id UUID, + partner_id β†’ core.partners, + vin VARCHAR(17), + marca VARCHAR, + modelo VARCHAR, + anio INTEGER, + motor_tipo VARCHAR, + placas VARCHAR +) + +-- Γ“rdenes de servicio +service_management.service_orders ( + id UUID, + vehicle_id β†’ vehicles, + sale_order_id β†’ sales.sale_orders, + tipo_servicio ENUM, + km_entrada INTEGER, + diagnostico TEXT, + estado ENUM +) + +-- Refacciones con compatibilidad +parts_management.parts ( + product_id β†’ inventory.products, + oem_number VARCHAR, + aftermarket_number VARCHAR, + compatibilidad JSONB +) +``` + +--- + +## Plan de ImplementaciΓ³n + +### Fase 1: Fundamentos (SP: 52) +1. SPEC-SISTEMA-SECUENCIAS +2. SPEC-SEGURIDAD-API-KEYS-PERMISOS +3. SPEC-TWO-FACTOR-AUTHENTICATION + +### Fase 2: Inventario (SP: 55) +4. SPEC-VALORACION-INVENTARIO +5. SPEC-TRAZABILIDAD-LOTES-SERIES +6. SPEC-INVENTARIOS-CICLICOS +7. SPEC-PRICING-RULES + +### Fase 3: Operaciones (SP: 34) +8. SPEC-MAIL-THREAD-TRACKING +9. SPEC-WIZARD-TRANSIENT-MODEL +10. SPEC-TAREAS-RECURRENTES + +### Fase 4: Financiero (SP: 65) +11. SPEC-REPORTES-FINANCIEROS +12. SPEC-CONTABILIDAD-ANALITICA +13. SPEC-CONCILIACION-BANCARIA + +--- + +## Referencias + +- Documento Core: `erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md` +- SPECS del Core: `erp-core/docs/04-modelado/especificaciones-tecnicas/transversal/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` +- Directivas: `orchestration/directivas/` + +--- + +**Documento de herencia de SPECS oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/mecanicas-diesel/orchestration/inventarios/README.md b/projects/erp-suite/apps/verticales/mecanicas-diesel/orchestration/inventarios/README.md new file mode 100644 index 0000000..bdff046 --- /dev/null +++ b/projects/erp-suite/apps/verticales/mecanicas-diesel/orchestration/inventarios/README.md @@ -0,0 +1,106 @@ +# Inventarios - ERP MecΓ‘nicas Diesel + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Nivel SIMCO:** 2B.2 + +--- + +## DescripciΓ³n + +Este directorio contiene los inventarios YAML que sirven como **Single Source of Truth (SSOT)** para el proyecto ERP MecΓ‘nicas Diesel. Estos archivos son la referencia canΓ³nica para mΓ©tricas, trazabilidad y componentes del sistema. + +--- + +## Archivos de Inventario + +| Archivo | DescripciΓ³n | Estado | +|---------|-------------|--------| +| [MASTER_INVENTORY.yml](./MASTER_INVENTORY.yml) | Inventario maestro con mΓ©tricas globales | Completo | +| [DATABASE_INVENTORY.yml](./DATABASE_INVENTORY.yml) | Inventario de objetos de base de datos | Completo | +| [BACKEND_INVENTORY.yml](./BACKEND_INVENTORY.yml) | Inventario de componentes backend | Planificado | +| [FRONTEND_INVENTORY.yml](./FRONTEND_INVENTORY.yml) | Inventario de componentes frontend | Planificado | +| [TRACEABILITY_MATRIX.yml](./TRACEABILITY_MATRIX.yml) | Matriz de trazabilidad RF->ET->US | Completo | +| [DEPENDENCY_GRAPH.yml](./DEPENDENCY_GRAPH.yml) | Grafo de dependencias entre mΓ³dulos | Completo | + +--- + +## Herencia del Core + +Este proyecto hereda del **ERP Core** (nivel 2B.1): + +| Aspecto | Heredado | EspecΓ­fico | +|---------|----------|------------| +| **Tablas DB** | 97 | 30+ | +| **Schemas** | 8 | 3 | +| **Specs** | 5 | - | + +### Specs Heredadas + +1. SPEC-VALORACION-INVENTARIO.md +2. SPEC-TRAZABILIDAD-LOTES-SERIES.md +3. SPEC-INVENTARIOS-CICLICOS.md +4. SPEC-MAIL-THREAD-TRACKING.md +5. SPEC-TAREAS-RECURRENTES.md + +### Documento de Herencia + +Ver: [`database/HERENCIA-ERP-CORE.md`](../../database/HERENCIA-ERP-CORE.md) + +--- + +## Resumen Ejecutivo + +### MΓ©tricas del Proyecto + +| MΓ©trica | Valor | +|---------|-------| +| **MΓ³dulos** | 5 (MD-001 a MD-005) | +| **Schemas especΓ­ficos** | 3 | +| **Tablas especΓ­ficas** | 30+ | +| **DDL implementado** | 1,561 lΓ­neas | +| **Estado** | DDL_IMPLEMENTADO | + +### Schemas EspecΓ­ficos + +| Schema | PropΓ³sito | Tablas | +|--------|-----------|--------| +| `service_management` | Γ“rdenes de servicio | 10+ | +| `parts_management` | Inventario refacciones | 12+ | +| `vehicle_management` | GestiΓ³n de vehΓ­culos | 8+ | + +--- + +## ConfiguraciΓ³n de Puertos (Planificado) + +| Servicio | Puerto | +|----------|--------| +| Backend API | 3200 | +| Frontend Web | 5175 | +| PostgreSQL | Compartido con Core | +| Redis | Compartido con Core | + +--- + +## Directivas EspecΓ­ficas + +1. [DIRECTIVA-ORDENES-TRABAJO.md](../directivas/DIRECTIVA-ORDENES-TRABAJO.md) +2. [DIRECTIVA-INVENTARIO-REFACCIONES.md](../directivas/DIRECTIVA-INVENTARIO-REFACCIONES.md) + +--- + +## AlineaciΓ³n con ERP Core + +Estos inventarios siguen la misma estructura que: +- `/erp-core/orchestration/inventarios/` (proyecto padre) +- `/verticales/construccion/orchestration/inventarios/` (vertical hermana) + +### Referencias + +- Suite Master: `orchestration/inventarios/SUITE_MASTER_INVENTORY.yml` +- Core: `apps/erp-core/orchestration/inventarios/` +- Status Global: `orchestration/inventarios/STATUS.yml` + +--- + +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/retail/database/HERENCIA-ERP-CORE.md b/projects/erp-suite/apps/verticales/retail/database/HERENCIA-ERP-CORE.md new file mode 100644 index 0000000..62bf581 --- /dev/null +++ b/projects/erp-suite/apps/verticales/retail/database/HERENCIA-ERP-CORE.md @@ -0,0 +1,187 @@ +# Herencia de Base de Datos - ERP Core -> Retail + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** Retail +**Nivel:** 2B.2 + +--- + +## RESUMEN + +La vertical de Retail hereda los schemas base del ERP Core y extiende con schemas especΓ­ficos del dominio de punto de venta y comercio minorista. + +**UbicaciΓ³n DDL Core:** `apps/erp-core/database/ddl/` + +--- + +## ARQUITECTURA DE HERENCIA + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ERP CORE (Base) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ auth β”‚ β”‚ core β”‚ β”‚financialβ”‚ β”‚inventoryβ”‚ β”‚ purchase β”‚ β”‚ +β”‚ β”‚ 26 tbl β”‚ β”‚ 12 tbl β”‚ β”‚ 15 tbl β”‚ β”‚ 15 tbl β”‚ β”‚ 8 tbl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ sales β”‚ β”‚analyticsβ”‚ β”‚ system β”‚ β”‚ crm β”‚ β”‚ +β”‚ β”‚ 6 tbl β”‚ β”‚ 5 tbl β”‚ β”‚ 10 tbl β”‚ β”‚ 5 tbl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ TOTAL: ~102 tablas heredadas β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”‚ HEREDA + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ RETAIL (Extensiones) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ pos β”‚ β”‚ stores β”‚ β”‚ pricing β”‚ β”‚ +β”‚ β”‚ (punto venta) β”‚ β”‚ (sucursales) β”‚ β”‚ (promociones) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ EXTENSIONES: ~30 tablas (planificadas) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## SCHEMAS HEREDADOS DEL CORE + +| Schema | Tablas | Uso en Retail | +|--------|--------|---------------| +| `auth` | 26 | AutenticaciΓ³n, usuarios por sucursal | +| `core` | 12 | Partners (clientes), catΓ‘logos | +| `financial` | 15 | Facturas, cuentas, caja | +| `inventory` | 15 | Inventario multi-sucursal | +| `purchase` | 8 | Compras a proveedores | +| `sales` | 6 | Ventas base | +| `crm` | 5 | Clientes frecuentes | +| `analytics` | 5 | MΓ©tricas de venta | +| `system` | 10 | Notificaciones | + +**Total heredado:** ~102 tablas + +--- + +## SCHEMAS ESPECÍFICOS DE RETAIL (Planificados) + +### 1. Schema `pos` (estimado 12+ tablas) + +**PropΓ³sito:** Punto de venta y operaciones de caja + +```sql +-- Tablas principales planificadas: +pos.cash_registers -- Cajas registradoras +pos.cash_sessions -- Sesiones de caja +pos.pos_orders -- Tickets/ventas POS +pos.pos_order_lines -- LΓ­neas de ticket +pos.payment_methods -- MΓ©todos de pago +pos.cash_movements -- Movimientos de caja +pos.cash_counts -- Cortes de caja +pos.receipts -- Recibos +``` + +### 2. Schema `stores` (estimado 8+ tablas) + +**PropΓ³sito:** GestiΓ³n de sucursales + +```sql +-- Tablas principales planificadas: +stores.branches -- Sucursales +stores.branch_inventory -- Inventario por sucursal +stores.transfers -- Transferencias entre sucursales +stores.transfer_lines -- LΓ­neas de transferencia +stores.branch_employees -- Empleados por sucursal +``` + +### 3. Schema `pricing` (estimado 10+ tablas) + +**PropΓ³sito:** Precios y promociones + +```sql +-- Extiende: sales schema del core +pricing.price_lists -- Listas de precios +pricing.promotions -- Promociones +pricing.discounts -- Descuentos +pricing.loyalty_programs -- Programas de lealtad +pricing.coupons -- Cupones +pricing.price_history -- Historial de precios +``` + +--- + +## SPECS DEL CORE APLICABLES + +**Documento detallado:** `orchestration/00-guidelines/HERENCIA-SPECS-CORE.md` + +### SPECS Obligatorias + +| Spec Core | AplicaciΓ³n en Retail | SP | Estado | +|-----------|---------------------|----:|--------| +| SPEC-SISTEMA-SECUENCIAS | Foliado de tickets y facturas | 8 | PENDIENTE | +| SPEC-VALORACION-INVENTARIO | Costeo de mercancΓ­a | 21 | PENDIENTE | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | Control de acceso por sucursal | 31 | PENDIENTE | +| SPEC-PRICING-RULES | Precios y promociones | 8 | PENDIENTE | +| SPEC-INVENTARIOS-CICLICOS | Conteos en sucursales | 13 | PENDIENTE | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Productos con lote/serie | 13 | PENDIENTE | +| SPEC-MAIL-THREAD-TRACKING | ComunicaciΓ³n con clientes | 13 | PENDIENTE | +| SPEC-WIZARD-TRANSIENT-MODEL | Wizards de cierre de caja | 8 | PENDIENTE | + +### SPECS Opcionales + +| Spec Core | DecisiΓ³n | RazΓ³n | +|-----------|----------|-------| +| SPEC-PORTAL-PROVEEDORES | EVALUAR | Para compras centralizadas | +| SPEC-TAREAS-RECURRENTES | EVALUAR | Para reorden automΓ‘tico | + +### SPECS No Aplican + +| Spec Core | RazΓ³n | +|-----------|-------| +| SPEC-INTEGRACION-CALENDAR | No requiere calendario de citas | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | No hay proyectos largos | +| SPEC-FIRMA-ELECTRONICA-NOM151 | No aplica para tickets POS | + +--- + +## ORDEN DE EJECUCIΓ“N DDL (Futuro) + +```bash +# PASO 1: Cargar ERP Core (base) +cd apps/erp-core/database +./scripts/reset-database.sh --force + +# PASO 2: Cargar extensiones de Retail +cd apps/verticales/retail/database +psql $DATABASE_URL -f init/00-extensions.sql +psql $DATABASE_URL -f init/01-create-schemas.sql +psql $DATABASE_URL -f init/02-pos-tables.sql +psql $DATABASE_URL -f init/03-stores-tables.sql +psql $DATABASE_URL -f init/04-pricing-tables.sql +``` + +--- + +## MAPEO DE NOMENCLATURA + +| Core | Retail | +|------|--------| +| `core.partners` | Clientes, proveedores | +| `inventory.products` | Productos de venta | +| `inventory.locations` | Almacenes de sucursal | +| `sales.sale_orders` | Base para POS orders | +| `financial.invoices` | Facturas de venta | + +--- + +## REFERENCIAS + +- ERP Core DDL: `apps/erp-core/database/ddl/` +- ERP Core README: `apps/erp-core/database/README.md` +- Directivas: `orchestration/directivas/` +- Inventarios: `orchestration/inventarios/` + +--- + +**Documento de herencia oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/retail/docs/00-vision-general/VISION-RETAIL.md b/projects/erp-suite/apps/verticales/retail/docs/00-vision-general/VISION-RETAIL.md new file mode 100644 index 0000000..300a88d --- /dev/null +++ b/projects/erp-suite/apps/verticales/retail/docs/00-vision-general/VISION-RETAIL.md @@ -0,0 +1,97 @@ +# VisiΓ³n General - ERP Retail + +**VersiΓ³n:** 1.0 +**Fecha:** 2025-12-08 +**Nivel:** 2B.2 (Vertical) + +--- + +## PropΓ³sito del Sistema + +Sistema ERP especializado para comercio minorista con punto de venta (POS), gestiΓ³n de inventario multi-sucursal, control de caja y programas de fidelizaciΓ³n. Optimizado para operaciΓ³n en tienda fΓ­sica con capacidad offline. + +--- + +## Dominio del Negocio + +### Procesos Principales + +1. **Punto de Venta (POS)** + - Venta rΓ‘pida en mostrador + - MΓΊltiples mΓ©todos de pago + - FacturaciΓ³n CFDI 4.0 + - OperaciΓ³n offline + +2. **Inventario Multi-Sucursal** + - Control de stock por sucursal + - Transferencias entre tiendas + - Conteos cΓ­clicos + - Alertas de reorden + +3. **Compras y Reabastecimiento** + - Γ“rdenes de compra centralizadas + - DistribuciΓ³n a sucursales + - Control de proveedores + +4. **Clientes y FidelizaciΓ³n** + - Programa de lealtad + - Puntos y recompensas + - Historial de compras + +5. **GestiΓ³n de Caja** + - Apertura y cierre de caja + - Arqueos + - Control de efectivo + +--- + +## Arquitectura de MΓ³dulos + +``` +RT-001 Fundamentos β†’ Auth, Users, Tenants (hereda 100% core) +RT-002 POS β†’ Punto de venta (20% core) +RT-003 Inventario β†’ Stock multi-sucursal (60% core) +RT-004 Compras β†’ Reabastecimiento (80% core) +RT-005 Clientes β†’ Programa fidelidad (40% core) +RT-006 Precios β†’ Promociones, descuentos (30% core) +RT-007 Caja β†’ Arqueos, cortes (10% core) +RT-008 Reportes β†’ Dashboard ventas (70% core) +RT-009 E-commerce β†’ Tienda online (20% core) +RT-010 FacturaciΓ³n β†’ CFDI 4.0 (60% core) +``` + +--- + +## Stack TecnolΓ³gico + +- **Backend:** NestJS + TypeORM + PostgreSQL +- **Frontend POS:** React + PWA (offline-first) +- **Base de Datos:** PostgreSQL 15+ (hereda ERP Core) +- **Hardware:** Impresora tΓ©rmica, lector de cΓ³digos, cajΓ³n + +--- + +## MΓ©tricas Objetivo + +| MΓ©trica | Valor Objetivo | +|---------|----------------| +| MΓ³dulos | 10 | +| Tablas EspecΓ­ficas | ~30 | +| Tablas Heredadas | ~102 | +| Story Points Est. | ~280 | +| Tiempo Venta | < 30 segundos | +| Disponibilidad | 99.9% | + +--- + +## Referencias + +- ERP Core: `apps/erp-core/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` +- SPECS del Core: `HERENCIA-SPECS-CORE.md` +- Inventarios: `orchestration/inventarios/` + +--- + +**Documento de visiΓ³n oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/retail/docs/02-definicion-modulos/INDICE-MODULOS.md b/projects/erp-suite/apps/verticales/retail/docs/02-definicion-modulos/INDICE-MODULOS.md new file mode 100644 index 0000000..ada07c9 --- /dev/null +++ b/projects/erp-suite/apps/verticales/retail/docs/02-definicion-modulos/INDICE-MODULOS.md @@ -0,0 +1,116 @@ +# Índice de MΓ³dulos - ERP Retail + +**VersiΓ³n:** 1.0 +**Fecha:** 2025-12-08 +**Total MΓ³dulos:** 10 + +--- + +## Resumen + +| CΓ³digo | Nombre | DescripciΓ³n | ReutilizaciΓ³n Core | Estado | +|--------|--------|-------------|-------------------|--------| +| RT-001 | Fundamentos | Auth, Users, Tenants | 100% | PLANIFICADO | +| RT-002 | POS | Punto de venta | 20% | PLANIFICADO | +| RT-003 | Inventario | Stock multi-sucursal | 60% | PLANIFICADO | +| RT-004 | Compras | Reabastecimiento | 80% | PLANIFICADO | +| RT-005 | Clientes | Programa fidelidad | 40% | PLANIFICADO | +| RT-006 | Precios | Promociones y descuentos | 30% | PLANIFICADO | +| RT-007 | Caja | Arqueos y cortes | 10% | PLANIFICADO | +| RT-008 | Reportes | Dashboard de ventas | 70% | PLANIFICADO | +| RT-009 | E-commerce | Tienda online | 20% | PLANIFICADO | +| RT-010 | FacturaciΓ³n | CFDI 4.0 | 60% | PLANIFICADO | + +--- + +## Detalle por MΓ³dulo + +### RT-001: Fundamentos +**Herencia:** 100% del core +- Usuarios por sucursal +- Roles: Cajero, Supervisor, Gerente, Admin + +### RT-002: POS +**Herencia:** 20% +- Venta rΓ‘pida en mostrador +- MΓΊltiples formas de pago +- OperaciΓ³n offline (PWA) +- IntegraciΓ³n con hardware + +### RT-003: Inventario +**Herencia:** 60% +- Stock por sucursal +- Transferencias entre tiendas +- Conteos cΓ­clicos +- Alertas de mΓ­nimos + +### RT-004: Compras +**Herencia:** 80% +- Γ“rdenes de compra centralizadas +- DistribuciΓ³n a sucursales +- Control de proveedores + +### RT-005: Clientes +**Herencia:** 40% +- Programa de lealtad +- Puntos y recompensas +- Historial de compras +- MembresΓ­as + +### RT-006: Precios +**Herencia:** 30% +- Listas de precios +- Promociones temporales +- Descuentos por volumen +- Cupones + +### RT-007: Caja +**Herencia:** 10% +- Sesiones de caja +- Apertura/cierre +- Arqueos +- Movimientos de efectivo + +### RT-008: Reportes +**Herencia:** 70% +- Dashboard de ventas +- AnΓ‘lisis por sucursal +- Top productos +- MΓ©tricas de cajeros + +### RT-009: E-commerce +**Herencia:** 20% +- Tienda online +- Carrito de compras +- Checkout +- SincronizaciΓ³n de inventario + +### RT-010: FacturaciΓ³n +**Herencia:** 60% +- CFDI 4.0 +- Timbrado automΓ‘tico +- Notas de crΓ©dito +- Reportes fiscales + +--- + +## Story Points Estimados + +| MΓ³dulo | SP Backend | SP Frontend | SP Total | +|--------|-----------|-------------|----------| +| RT-001 | 0 | 0 | 0 | +| RT-002 | 34 | 21 | 55 | +| RT-003 | 21 | 13 | 34 | +| RT-004 | 13 | 8 | 21 | +| RT-005 | 21 | 13 | 34 | +| RT-006 | 21 | 13 | 34 | +| RT-007 | 21 | 13 | 34 | +| RT-008 | 13 | 13 | 26 | +| RT-009 | 34 | 21 | 55 | +| RT-010 | 21 | 8 | 29 | +| **Total** | **199** | **123** | **322** | + +--- + +**Índice de mΓ³dulos oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/retail/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md b/projects/erp-suite/apps/verticales/retail/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md new file mode 100644 index 0000000..58041b5 --- /dev/null +++ b/projects/erp-suite/apps/verticales/retail/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md @@ -0,0 +1,184 @@ +# Herencia de SPECS del Core - Retail + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** Retail (RT) +**Nivel:** 2B.2 + +--- + +## Resumen + +| MΓ©trica | Valor | +|---------|-------| +| SPECS Aplicables | 24/30 | +| SPECS Obligatorias | 21 | +| SPECS Opcionales | 3 | +| SPECS No Aplican | 6 | +| Estado ImplementaciΓ³n | 0% | + +--- + +## SPECS Obligatorias (Deben Implementarse) + +### P0 - CrΓ­ticas + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-SISTEMA-SECUENCIAS | ir.sequence | 8 | PENDIENTE | RT-001, RT-002, RT-007 | +| SPEC-VALORACION-INVENTARIO | FIFO/AVCO | 21 | PENDIENTE | RT-003 | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | API Keys + ACL | 31 | PENDIENTE | RT-001 | +| SPEC-REPORTES-FINANCIEROS | Balance/P&L SAT | 13 | PENDIENTE | RT-008, RT-010 | +| SPEC-NOMINA-BASICA | hr_payroll | 21 | PENDIENTE | RT-001 | +| SPEC-GASTOS-EMPLEADOS | hr_expense | 13 | PENDIENTE | RT-001 | +| SPEC-SCHEDULER-REPORTES | ir.cron + mail | 8 | PENDIENTE | RT-008 | + +### P1 - Complementarias + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-CONTABILIDAD-ANALITICA | Centros de costo | 21 | PENDIENTE | RT-008 | +| SPEC-CONCILIACION-BANCARIA | ConciliaciΓ³n | 21 | PENDIENTE | RT-007, RT-008 | +| SPEC-TWO-FACTOR-AUTHENTICATION | 2FA | 13 | PENDIENTE | RT-001 | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes/Series | 13 | PENDIENTE | RT-003 | +| SPEC-PRICING-RULES | Reglas precio | 8 | PENDIENTE | RT-006 | +| SPEC-BLANKET-ORDERS | Γ“rdenes marco | 13 | PENDIENTE | RT-004 | +| SPEC-INVENTARIOS-CICLICOS | Conteo cΓ­clico | 13 | PENDIENTE | RT-003 | +| SPEC-IMPUESTOS-AVANZADOS | IVA, ISR | 8 | PENDIENTE | RT-010 | +| SPEC-PLANTILLAS-CUENTAS | Plan contable | 8 | PENDIENTE | RT-008 | +| SPEC-TASAS-CAMBIO-AUTOMATICAS | Tipos cambio | 5 | PENDIENTE | RT-008 | +| SPEC-ALERTAS-PRESUPUESTO | Alertas | 8 | PENDIENTE | RT-008 | +| SPEC-RRHH-EVALUACIONES-SKILLS | Evaluaciones | 26 | PENDIENTE | RT-001 | +| SPEC-LOCALIZACION-PAISES | LocalizaciΓ³n | 13 | PENDIENTE | RT-001, RT-010 | + +### Patrones TΓ©cnicos + +| SPEC | PatrΓ³n | SP | Estado | AplicaciΓ³n | +|------|--------|----:|--------|------------| +| SPEC-MAIL-THREAD-TRACKING | mail.thread | 13 | PENDIENTE | Γ“rdenes, Clientes | +| SPEC-WIZARD-TRANSIENT-MODEL | TransientModel | 8 | PENDIENTE | Wizards de cierre, arqueo | + +--- + +## SPECS Opcionales + +| SPEC | DescripciΓ³n | SP | DecisiΓ³n | RazΓ³n | +|------|-------------|----:|----------|-------| +| SPEC-PORTAL-PROVEEDORES | Portal RFQ | 13 | EVALUAR | Para compras centralizadas | +| SPEC-TAREAS-RECURRENTES | Recurrencia | 13 | EVALUAR | Para reorden automΓ‘tico | +| SPEC-PRESUPUESTOS-REVISIONES | AprobaciΓ³n | 8 | DIFERIR | Menos relevante en retail | + +--- + +## SPECS No Aplicables + +| SPEC | RazΓ³n | +|------|-------| +| SPEC-INTEGRACION-CALENDAR | No requiere calendario de citas | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | No hay proyectos largos | +| SPEC-FIRMA-ELECTRONICA-NOM151 | No aplica para tickets POS | +| SPEC-OAUTH2-SOCIAL-LOGIN | El personal usa login tradicional | +| SPEC-CONSOLIDACION-FINANCIERA | Generalmente una empresa | + +--- + +## Adaptaciones Requeridas + +### Mapeo de Conceptos Core β†’ Retail + +| Concepto Core | Concepto Retail | +|---------------|-----------------| +| `sales.sale_orders` | Tickets POS | +| `inventory.products` | Productos de venta | +| `inventory.locations` | Sucursales | +| `inventory.stock_moves` | Transferencias entre tiendas | +| `core.partners` | Clientes con membresΓ­a | +| `financial.payments` | Pagos en caja | + +### Extensiones de Entidad + +```sql +-- Sucursales +stores.branches ( + id UUID, + location_id β†’ inventory.locations, + nombre VARCHAR, + direccion TEXT, + gerente_id β†’ hr.employees, + horario JSONB, + activa BOOLEAN +) + +-- Sesiones de caja +pos.cash_sessions ( + id UUID, + branch_id β†’ branches, + cajero_id β†’ hr.employees, + caja_id β†’ cash_registers, + fecha_apertura TIMESTAMPTZ, + fecha_cierre TIMESTAMPTZ, + saldo_inicial DECIMAL, + saldo_final DECIMAL, + estado ENUM +) + +-- Tickets POS +pos.pos_orders ( + id UUID, + session_id β†’ cash_sessions, + sale_order_id β†’ sales.sale_orders, + numero_ticket VARCHAR, + subtotal DECIMAL, + descuentos DECIMAL, + impuestos DECIMAL, + total DECIMAL +) + +-- Programa de lealtad +pricing.loyalty_programs ( + id UUID, + nombre VARCHAR, + tipo ENUM('puntos', 'cashback', 'descuento'), + reglas JSONB, + activo BOOLEAN +) +``` + +--- + +## Plan de ImplementaciΓ³n + +### Fase 1: Fundamentos (SP: 52) +1. SPEC-SISTEMA-SECUENCIAS +2. SPEC-SEGURIDAD-API-KEYS-PERMISOS +3. SPEC-TWO-FACTOR-AUTHENTICATION + +### Fase 2: Inventario (SP: 55) +4. SPEC-VALORACION-INVENTARIO +5. SPEC-TRAZABILIDAD-LOTES-SERIES +6. SPEC-INVENTARIOS-CICLICOS +7. SPEC-PRICING-RULES + +### Fase 3: Operaciones POS (SP: 21) +8. SPEC-MAIL-THREAD-TRACKING +9. SPEC-WIZARD-TRANSIENT-MODEL + +### Fase 4: Financiero (SP: 65) +10. SPEC-REPORTES-FINANCIEROS +11. SPEC-CONTABILIDAD-ANALITICA +12. SPEC-CONCILIACION-BANCARIA +13. SPEC-IMPUESTOS-AVANZADOS + +--- + +## Referencias + +- Documento Core: `erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md` +- SPECS del Core: `erp-core/docs/04-modelado/especificaciones-tecnicas/transversal/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` +- Directivas: `orchestration/directivas/` + +--- + +**Documento de herencia de SPECS oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/retail/orchestration/inventarios/README.md b/projects/erp-suite/apps/verticales/retail/orchestration/inventarios/README.md new file mode 100644 index 0000000..20a7ca9 --- /dev/null +++ b/projects/erp-suite/apps/verticales/retail/orchestration/inventarios/README.md @@ -0,0 +1,95 @@ +# Inventarios - ERP Retail + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Nivel SIMCO:** 2B.2 + +--- + +## DescripciΓ³n + +Este directorio contiene los inventarios YAML que sirven como **Single Source of Truth (SSOT)** para el proyecto ERP Retail. Estos archivos son la referencia canΓ³nica para mΓ©tricas, trazabilidad y componentes del sistema. + +--- + +## Archivos de Inventario + +| Archivo | DescripciΓ³n | Estado | +|---------|-------------|--------| +| [MASTER_INVENTORY.yml](./MASTER_INVENTORY.yml) | Inventario maestro con mΓ©tricas globales | Completo | +| [DATABASE_INVENTORY.yml](./DATABASE_INVENTORY.yml) | Inventario de objetos de base de datos | Planificado | +| [BACKEND_INVENTORY.yml](./BACKEND_INVENTORY.yml) | Inventario de componentes backend | Planificado | +| [FRONTEND_INVENTORY.yml](./FRONTEND_INVENTORY.yml) | Inventario de componentes frontend | Planificado | +| [TRACEABILITY_MATRIX.yml](./TRACEABILITY_MATRIX.yml) | Matriz de trazabilidad RF->ET->US | Completo | +| [DEPENDENCY_GRAPH.yml](./DEPENDENCY_GRAPH.yml) | Grafo de dependencias entre mΓ³dulos | Completo | + +--- + +## Herencia del Core + +Este proyecto hereda del **ERP Core** (nivel 2B.1): + +| Aspecto | Heredado | EspecΓ­fico | +|---------|----------|------------| +| **Tablas DB** | ~100 | Planificado | +| **Schemas** | 8+ | Planificado | +| **Specs** | 3 | - | + +### Specs Heredadas + +1. SPEC-PRICING-RULES.md +2. SPEC-INVENTARIOS-CICLICOS.md +3. SPEC-TRAZABILIDAD-LOTES-SERIES.md + +--- + +## Resumen Ejecutivo + +### MΓ©tricas del Proyecto + +| MΓ©trica | Valor | +|---------|-------| +| **MΓ³dulos** | 5 (RT-001 a RT-005) | +| **Estado** | PLANIFICACION_COMPLETA | +| **Completitud** | 15% | + +### Dominio del Negocio + +- Punto de venta (POS) +- Inventario multi-sucursal +- GestiΓ³n de precios y promociones +- Control de cajas + +--- + +## Directivas EspecΓ­ficas + +1. [DIRECTIVA-PUNTO-VENTA.md](../directivas/DIRECTIVA-PUNTO-VENTA.md) +2. [DIRECTIVA-INVENTARIO-SUCURSALES.md](../directivas/DIRECTIVA-INVENTARIO-SUCURSALES.md) + +--- + +## ConfiguraciΓ³n de Puertos (Planificado) + +| Servicio | Puerto | +|----------|--------| +| Backend API | 3400 | +| Frontend Web | 5177 | +| POS App | 5178 | + +--- + +## AlineaciΓ³n con ERP Core + +Estos inventarios siguen la misma estructura que: +- `/erp-core/orchestration/inventarios/` (proyecto padre) + +### Referencias + +- Suite Master: `orchestration/inventarios/SUITE_MASTER_INVENTORY.yml` +- Core: `apps/erp-core/orchestration/inventarios/` +- Status Global: `orchestration/inventarios/STATUS.yml` + +--- + +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/database/HERENCIA-ERP-CORE.md b/projects/erp-suite/apps/verticales/vidrio-templado/database/HERENCIA-ERP-CORE.md new file mode 100644 index 0000000..a817e75 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/database/HERENCIA-ERP-CORE.md @@ -0,0 +1,182 @@ +# Herencia de Base de Datos - ERP Core -> Vidrio Templado + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** Vidrio Templado +**Nivel:** 2B.2 + +--- + +## RESUMEN + +La vertical de Vidrio Templado hereda los schemas base del ERP Core y extiende con schemas especΓ­ficos del dominio de producciΓ³n de vidrio. + +**UbicaciΓ³n DDL Core:** `apps/erp-core/database/ddl/` + +--- + +## ARQUITECTURA DE HERENCIA + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ERP CORE (Base) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ auth β”‚ β”‚ core β”‚ β”‚financialβ”‚ β”‚inventoryβ”‚ β”‚ purchase β”‚ β”‚ +β”‚ β”‚ 26 tbl β”‚ β”‚ 12 tbl β”‚ β”‚ 15 tbl β”‚ β”‚ 15 tbl β”‚ β”‚ 8 tbl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ sales β”‚ β”‚analyticsβ”‚ β”‚ system β”‚ β”‚ +β”‚ β”‚ 6 tbl β”‚ β”‚ 5 tbl β”‚ β”‚ 10 tbl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ TOTAL: ~97 tablas heredadas β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”‚ HEREDA + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ VIDRIO TEMPLADO (Extensiones) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ production β”‚ β”‚ quality β”‚ β”‚ glass β”‚ β”‚ +β”‚ β”‚ management β”‚ β”‚ control β”‚ β”‚ inventory β”‚ β”‚ +β”‚ β”‚ (hornos) β”‚ β”‚ (inspecciΓ³n) β”‚ β”‚ (lotes) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ EXTENSIONES: ~25 tablas (planificadas) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## SCHEMAS HEREDADOS DEL CORE + +| Schema | Tablas | Uso en Vidrio Templado | +|--------|--------|------------------------| +| `auth` | 26 | AutenticaciΓ³n, usuarios, roles, permisos | +| `core` | 12 | Partners (clientes), catΓ‘logos | +| `financial` | 15 | Facturas, cuentas contables | +| `inventory` | 15 | Base para materia prima y producto terminado | +| `purchase` | 8 | Compras de materiales | +| `sales` | 6 | Cotizaciones, Γ³rdenes de venta | +| `analytics` | 5 | Centros de costo | +| `system` | 10 | Mensajes, notificaciones | + +**Total heredado:** ~97 tablas + +--- + +## SCHEMAS ESPECÍFICOS DE VIDRIO TEMPLADO (Planificados) + +### 1. Schema `production` (estimado 10+ tablas) + +**PropΓ³sito:** GestiΓ³n de producciΓ³n y hornos de templado + +```sql +-- Tablas principales planificadas: +production.production_orders -- Γ“rdenes de producciΓ³n +production.production_lines -- LΓ­neas de producciΓ³n (hornos) +production.work_orders -- Γ“rdenes de trabajo +production.cutting_plans -- Planes de corte +production.oven_schedules -- ProgramaciΓ³n de hornos +production.temperature_logs -- Registros de temperatura +``` + +### 2. Schema `quality` (estimado 8+ tablas) + +**PropΓ³sito:** Control de calidad y trazabilidad + +```sql +-- Tablas principales planificadas: +quality.inspections -- Inspecciones de calidad +quality.defect_types -- CatΓ‘logo de defectos +quality.quality_tests -- Pruebas de calidad +quality.certifications -- Certificaciones de producto +quality.non_conformities -- No conformidades +``` + +### 3. Schema `glass` (estimado 7+ tablas) + +**PropΓ³sito:** Inventario especializado de vidrio + +```sql +-- Extiende: inventory schema del core +glass.glass_types -- Tipos de vidrio +glass.glass_lots -- Lotes de producciΓ³n +glass.glass_dimensions -- Dimensiones estΓ‘ndar +glass.raw_materials -- Materia prima +``` + +--- + +## SPECS DEL CORE APLICABLES + +**Documento detallado:** `orchestration/00-guidelines/HERENCIA-SPECS-CORE.md` + +### SPECS Obligatorias + +| Spec Core | AplicaciΓ³n en Vidrio Templado | SP | Estado | +|-----------|------------------------------|----:|--------| +| SPEC-SISTEMA-SECUENCIAS | Foliado de Γ³rdenes y lotes | 8 | PENDIENTE | +| SPEC-VALORACION-INVENTARIO | Costeo de materia prima y producto | 21 | PENDIENTE | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | Control de acceso | 31 | PENDIENTE | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes de producciΓ³n de vidrio | 13 | PENDIENTE | +| SPEC-PRICING-RULES | Precios por dimensiones y tipo | 8 | PENDIENTE | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | Control de producciΓ³n | 13 | PENDIENTE | +| SPEC-MAIL-THREAD-TRACKING | Historial de Γ³rdenes | 13 | PENDIENTE | +| SPEC-WIZARD-TRANSIENT-MODEL | Wizards de corte y templado | 8 | PENDIENTE | + +### SPECS Opcionales + +| Spec Core | DecisiΓ³n | RazΓ³n | +|-----------|----------|-------| +| SPEC-INVENTARIOS-CICLICOS | EVALUAR | Útil para materia prima | +| SPEC-FIRMA-ELECTRONICA-NOM151 | EVALUAR | Certificados de calidad | + +### SPECS No Aplican + +| Spec Core | RazΓ³n | +|-----------|-------| +| SPEC-INTEGRACION-CALENDAR | No requiere calendario externo | +| SPEC-CONSOLIDACION-FINANCIERA | Negocio de una sola planta | + +--- + +## ORDEN DE EJECUCIΓ“N DDL (Futuro) + +```bash +# PASO 1: Cargar ERP Core (base) +cd apps/erp-core/database +./scripts/reset-database.sh --force + +# PASO 2: Cargar extensiones de Vidrio Templado +cd apps/verticales/vidrio-templado/database +psql $DATABASE_URL -f init/00-extensions.sql +psql $DATABASE_URL -f init/01-create-schemas.sql +psql $DATABASE_URL -f init/02-production-tables.sql +psql $DATABASE_URL -f init/03-quality-tables.sql +psql $DATABASE_URL -f init/04-glass-inventory.sql +``` + +--- + +## MAPEO DE NOMENCLATURA + +| Core | Vidrio Templado | +|------|-----------------| +| `core.partners` | Clientes, proveedores | +| `inventory.products` | Producto terminado base | +| `inventory.locations` | Almacenes de vidrio | +| `sales.sale_orders` | Pedidos de vidrio | +| `purchase.purchase_orders` | Compras de materia prima | + +--- + +## REFERENCIAS + +- ERP Core DDL: `apps/erp-core/database/ddl/` +- ERP Core README: `apps/erp-core/database/README.md` +- Directivas: `orchestration/directivas/` +- Inventarios: `orchestration/inventarios/` + +--- + +**Documento de herencia oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/00-vision-general/VISION-VIDRIO.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/00-vision-general/VISION-VIDRIO.md new file mode 100644 index 0000000..4ab1200 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/00-vision-general/VISION-VIDRIO.md @@ -0,0 +1,104 @@ +# VisiΓ³n General - ERP Vidrio Templado + +**VersiΓ³n:** 1.0 +**Fecha:** 2025-12-08 +**Nivel:** 2B.2 (Vertical) + +--- + +## PropΓ³sito del Sistema + +Sistema ERP especializado para empresas de manufactura de vidrio templado, laminado y procesado. Gestiona todo el ciclo desde la cotizaciΓ³n hasta el despacho, incluyendo control de producciΓ³n, optimizaciΓ³n de corte, control de hornos de templado y gestiΓ³n de calidad. + +--- + +## Dominio del Negocio + +### Procesos Principales + +1. **CotizaciΓ³n y Ventas** + - CotizaciΓ³n por dimensiones, tipo de vidrio y acabados + - CΓ‘lculo automΓ‘tico de precios por mΒ² + - GestiΓ³n de clientes y arquitectos + +2. **ProducciΓ³n** + - Γ“rdenes de producciΓ³n + - OptimizaciΓ³n de corte (nesting) + - Control de hornos de templado + - ProgramaciΓ³n de producciΓ³n + +3. **Inventario** + - Control de materia prima (lΓ‘minas de vidrio) + - Trazabilidad de lotes + - GestiΓ³n de producto terminado + +4. **Control de Calidad** + - Inspecciones de producto + - Pruebas de fragmentaciΓ³n + - Certificaciones + +5. **Despacho** + - LogΓ­stica de entrega + - InstalaciΓ³n (opcional) + +--- + +## Tipos de Vidrio Manejados + +| Tipo | DescripciΓ³n | +|------|-------------| +| Templado | Tratamiento tΓ©rmico para resistencia | +| Laminado | Capas con PVB/EVA | +| Insulado | CΓ‘maras de aire | +| Curvo | Templado con curvatura | +| Esmerilado | Acabado mate | +| Serigrafiado | Con diseΓ±os impresos | + +--- + +## Arquitectura de MΓ³dulos + +``` +VT-001 Fundamentos β†’ Auth, Users, Tenants (hereda 100% core) +VT-002 Cotizaciones β†’ Cotizador de vidrio (30% core) +VT-003 ProducciΓ³n β†’ Γ“rdenes de producciΓ³n (20% core) +VT-004 Inventario β†’ Stock de vidrio (70% core) +VT-005 Corte β†’ OptimizaciΓ³n de corte (0% core - nuevo) +VT-006 Templado β†’ Control de hornos (0% core - nuevo) +VT-007 Calidad β†’ Inspecciones, QC (40% core) +VT-008 Despacho β†’ LogΓ­stica (50% core) +``` + +--- + +## Stack TecnolΓ³gico + +- **Backend:** NestJS + TypeORM + PostgreSQL +- **Frontend:** React + TypeScript + Vite +- **Base de Datos:** PostgreSQL 15+ (hereda ERP Core) +- **Extensiones:** PostGIS (dimensiones) + +--- + +## MΓ©tricas Objetivo + +| MΓ©trica | Valor Objetivo | +|---------|----------------| +| MΓ³dulos | 8 | +| Tablas EspecΓ­ficas | ~25 | +| Tablas Heredadas | ~97 | +| Story Points Est. | ~200 | + +--- + +## Referencias + +- ERP Core: `apps/erp-core/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` +- SPECS del Core: `HERENCIA-SPECS-CORE.md` +- Inventarios: `orchestration/inventarios/` + +--- + +**Documento de visiΓ³n oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/INDICE-MODULOS.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/INDICE-MODULOS.md new file mode 100644 index 0000000..eaa3914 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/INDICE-MODULOS.md @@ -0,0 +1,154 @@ +# Índice de MΓ³dulos - ERP Vidrio Templado + +**VersiΓ³n:** 1.0 +**Fecha:** 2025-12-08 +**Total MΓ³dulos:** 8 + +--- + +## Resumen + +| CΓ³digo | Nombre | DescripciΓ³n | ReutilizaciΓ³n Core | Estado | +|--------|--------|-------------|-------------------|--------| +| VT-001 | Fundamentos | Auth, Users, Tenants | 100% | PLANIFICADO | +| VT-002 | Cotizaciones | Cotizador de vidrio | 30% | PLANIFICADO | +| VT-003 | ProducciΓ³n | Γ“rdenes de producciΓ³n | 20% | PLANIFICADO | +| VT-004 | Inventario | Stock de vidrio y materia prima | 70% | PLANIFICADO | +| VT-005 | Corte | OptimizaciΓ³n de corte | 0% | PLANIFICADO | +| VT-006 | Templado | Control de hornos | 0% | PLANIFICADO | +| VT-007 | Calidad | Control de calidad | 40% | PLANIFICADO | +| VT-008 | Despacho | LogΓ­stica y entregas | 50% | PLANIFICADO | + +--- + +## Detalle por MΓ³dulo + +### VT-001: Fundamentos + +**Herencia:** 100% del core (MGN-001 a MGN-004) +**PropΓ³sito:** AutenticaciΓ³n, usuarios, roles, multi-tenancy + +- Usuarios del sistema (operadores, supervisores, gerentes) +- Roles y permisos por planta +- Multi-tenancy para franquicias + +### VT-002: Cotizaciones + +**Herencia:** 30% del core (sales) +**PropΓ³sito:** CotizaciΓ³n de productos de vidrio + +- Cotizador por dimensiones (alto Γ— ancho) +- Tipos de vidrio y espesores +- CΓ‘lculo de precios por mΒ² +- Acabados y procesamientos adicionales +- GeneraciΓ³n de PDF para cliente + +### VT-003: ProducciΓ³n + +**Herencia:** 20% del core (projects) +**PropΓ³sito:** GestiΓ³n de Γ³rdenes de producciΓ³n + +- Γ“rdenes de producciΓ³n +- Estados: borrador β†’ programado β†’ corte β†’ templado β†’ QC β†’ terminado +- AsignaciΓ³n de recursos +- Tiempos de producciΓ³n + +### VT-004: Inventario + +**Herencia:** 70% del core (inventory) +**PropΓ³sito:** Control de materia prima y producto terminado + +- LΓ‘minas de vidrio (materia prima) +- Control de lotes por proveedor +- Producto terminado +- Merma y desperdicio +- Alertas de reorden + +### VT-005: Corte + +**Herencia:** 0% - MΓ³dulo nuevo +**PropΓ³sito:** OptimizaciΓ³n de corte de vidrio + +- Algoritmo de nesting para optimizar cortes +- Planes de corte +- ReducciΓ³n de desperdicio +- IntegraciΓ³n con mΓ‘quinas CNC (futuro) + +### VT-006: Templado + +**Herencia:** 0% - MΓ³dulo nuevo +**PropΓ³sito:** Control de hornos de templado + +- ProgramaciΓ³n de hornos +- ParΓ‘metros de templado (temperatura, tiempo, velocidad) +- Registro de ciclos de templado +- Mantenimiento preventivo de hornos + +### VT-007: Calidad + +**Herencia:** 40% del core (system) +**PropΓ³sito:** Control de calidad + +- Inspecciones de producto +- Pruebas de fragmentaciΓ³n +- No conformidades +- Certificaciones de producto +- Trazabilidad de defectos + +### VT-008: Despacho + +**Herencia:** 50% del core (inventory, sales) +**PropΓ³sito:** LogΓ­stica de entregas + +- ProgramaciΓ³n de entregas +- Rutas de entrega +- ConfirmaciΓ³n de recepciΓ³n +- InstalaciΓ³n (opcional) +- Evidencia fotogrΓ‘fica + +--- + +## Dependencias entre MΓ³dulos + +``` +VT-001 (Fundamentos) + ↓ +VT-002 (Cotizaciones) ←→ VT-004 (Inventario) + ↓ +VT-003 (ProducciΓ³n) + ↓ +VT-005 (Corte) β†’ VT-006 (Templado) + ↓ + VT-007 (Calidad) + ↓ + VT-008 (Despacho) +``` + +--- + +## Story Points Estimados + +| MΓ³dulo | SP Backend | SP Frontend | SP Total | +|--------|-----------|-------------|----------| +| VT-001 | 0 (hereda) | 0 (hereda) | 0 | +| VT-002 | 21 | 13 | 34 | +| VT-003 | 21 | 13 | 34 | +| VT-004 | 13 | 8 | 21 | +| VT-005 | 34 | 13 | 47 | +| VT-006 | 21 | 13 | 34 | +| VT-007 | 13 | 8 | 21 | +| VT-008 | 13 | 8 | 21 | +| **Total** | **136** | **76** | **212** | + +--- + +## Referencias + +- DocumentaciΓ³n por mΓ³dulo: `VT-XXX-nombre/README.md` +- SPECS heredadas: `orchestration/00-guidelines/HERENCIA-SPECS-CORE.md` +- VisiΓ³n: `00-vision-general/VISION-VIDRIO.md` + +--- + +**Índice de mΓ³dulos oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-001-fundamentos/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-001-fundamentos/README.md new file mode 100644 index 0000000..16fe998 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-001-fundamentos/README.md @@ -0,0 +1,21 @@ +# VT-001: Fundamentos + +**MΓ³dulo:** Fundamentos +**Herencia:** 100% del ERP Core +**Estado:** PLANIFICADO + +## DescripciΓ³n +MΓ³dulo base que hereda completamente del ERP Core. Proporciona autenticaciΓ³n, gestiΓ³n de usuarios, roles y multi-tenancy. + +## Componentes Heredados +- MGN-001: Auth (JWT, OAuth2, 2FA) +- MGN-002: Users (CRUD, perfiles) +- MGN-003: Roles (RBAC) +- MGN-004: Tenants (Multi-tenancy, RLS) + +## ConfiguraciΓ³n EspecΓ­fica +- Roles por defecto: Operador, Supervisor, Gerente, Administrador +- Permisos por mΓ³dulo de vidrio + +## Referencias +- ERP Core: `apps/erp-core/` diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-002-cotizaciones/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-002-cotizaciones/README.md new file mode 100644 index 0000000..d827ed3 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-002-cotizaciones/README.md @@ -0,0 +1,26 @@ +# VT-002: Cotizaciones + +**MΓ³dulo:** Cotizaciones de Vidrio +**Herencia:** 30% del ERP Core (sales) +**Estado:** PLANIFICADO + +## DescripciΓ³n +Cotizador especializado para productos de vidrio. Calcula precios por dimensiones, tipo de vidrio, espesor y acabados. + +## Funcionalidades +- CotizaciΓ³n por dimensiones (alto Γ— ancho Γ— espesor) +- CatΓ‘logo de tipos de vidrio +- Acabados y procesamientos adicionales +- CΓ‘lculo automΓ‘tico de precios por mΒ² +- GeneraciΓ³n de PDF +- ConversiΓ³n a orden de producciΓ³n + +## Entidades +- `quotes.quotes` - Cotizaciones +- `quotes.quote_lines` - LΓ­neas de cotizaciΓ³n +- `quotes.glass_types` - Tipos de vidrio +- `quotes.finishes` - Acabados disponibles + +## SPECS Aplicables +- SPEC-PRICING-RULES +- SPEC-MAIL-THREAD-TRACKING diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-003-produccion/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-003-produccion/README.md new file mode 100644 index 0000000..c1134fb --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-003-produccion/README.md @@ -0,0 +1,33 @@ +# VT-003: ProducciΓ³n + +**MΓ³dulo:** Γ“rdenes de ProducciΓ³n +**Herencia:** 20% del ERP Core (projects) +**Estado:** PLANIFICADO + +## DescripciΓ³n +GestiΓ³n de Γ³rdenes de producciΓ³n desde la cotizaciΓ³n aprobada hasta el producto terminado. + +## Funcionalidades +- CreaciΓ³n de Γ³rdenes desde cotizaciones +- Estados de producciΓ³n +- AsignaciΓ³n de recursos +- ProgramaciΓ³n de producciΓ³n +- Seguimiento de tiempos + +## Estados del Flujo +1. `draft` - Borrador +2. `scheduled` - Programado +3. `cutting` - En corte +4. `tempering` - En templado +5. `quality` - Control de calidad +6. `done` - Terminado +7. `delivered` - Entregado + +## Entidades +- `production.production_orders` - Γ“rdenes de producciΓ³n +- `production.production_lines` - LΓ­neas de horno +- `production.work_orders` - Γ“rdenes de trabajo + +## SPECS Aplicables +- SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN +- SPEC-TAREAS-RECURRENTES diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-004-inventario/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-004-inventario/README.md new file mode 100644 index 0000000..3972aaa --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-004-inventario/README.md @@ -0,0 +1,27 @@ +# VT-004: Inventario + +**MΓ³dulo:** Inventario de Vidrio +**Herencia:** 70% del ERP Core (inventory) +**Estado:** PLANIFICADO + +## DescripciΓ³n +Control de materia prima (lΓ‘minas de vidrio) y producto terminado con trazabilidad de lotes. + +## Funcionalidades +- Control de lΓ‘minas de materia prima +- Trazabilidad de lotes por proveedor +- Producto terminado +- Control de merma y desperdicio +- Alertas de reorden +- ValorizaciΓ³n FIFO/AVCO + +## Entidades +- `glass.glass_inventory` - Inventario de vidrio +- `glass.glass_lots` - Lotes de materia prima +- `glass.raw_materials` - LΓ‘minas de vidrio +- `glass.finished_products` - Producto terminado + +## SPECS Aplicables +- SPEC-VALORACION-INVENTARIO +- SPEC-TRAZABILIDAD-LOTES-SERIES +- SPEC-INVENTARIOS-CICLICOS (opcional) diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-005-corte/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-005-corte/README.md new file mode 100644 index 0000000..a6714bc --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-005-corte/README.md @@ -0,0 +1,26 @@ +# VT-005: Corte + +**MΓ³dulo:** OptimizaciΓ³n de Corte +**Herencia:** 0% - MΓ³dulo nuevo +**Estado:** PLANIFICADO + +## DescripciΓ³n +MΓ³dulo especializado para optimizaciΓ³n de cortes de vidrio (nesting) que minimiza el desperdicio de materia prima. + +## Funcionalidades +- Algoritmo de nesting para optimizar cortes +- Planes de corte por lΓ‘mina +- CΓ‘lculo de desperdicio +- VisualizaciΓ³n de patrones de corte +- IntegraciΓ³n con CNC (futuro) +- HistΓ³rico de eficiencia + +## Entidades +- `cutting.cutting_plans` - Planes de corte +- `cutting.cutting_patterns` - Patrones optimizados +- `cutting.waste_records` - Registro de desperdicio + +## Algoritmos +- First Fit Decreasing (FFD) +- Guillotine cuts +- OptimizaciΓ³n por rotaciΓ³n de piezas diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-006-templado/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-006-templado/README.md new file mode 100644 index 0000000..a12e964 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-006-templado/README.md @@ -0,0 +1,28 @@ +# VT-006: Templado + +**MΓ³dulo:** Control de Hornos +**Herencia:** 0% - MΓ³dulo nuevo +**Estado:** PLANIFICADO + +## DescripciΓ³n +Control de hornos de templado con registro de parΓ‘metros y ciclos de producciΓ³n. + +## Funcionalidades +- ProgramaciΓ³n de hornos +- Registro de parΓ‘metros (temperatura, tiempo, velocidad) +- Ciclos de templado por tipo de vidrio +- Registro de logs de producciΓ³n +- Mantenimiento preventivo +- Alertas de parΓ‘metros fuera de rango + +## Entidades +- `tempering.ovens` - Hornos de templado +- `tempering.oven_schedules` - ProgramaciΓ³n +- `tempering.tempering_cycles` - Ciclos de templado +- `tempering.temperature_logs` - Logs de temperatura +- `tempering.maintenance_records` - Mantenimientos + +## ParΓ‘metros de Control +- Temperatura de calentamiento: 620-720Β°C +- Tiempo en horno: segΓΊn espesor +- Velocidad de enfriamiento: presiΓ³n de aire diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-007-calidad/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-007-calidad/README.md new file mode 100644 index 0000000..cb69ed4 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-007-calidad/README.md @@ -0,0 +1,28 @@ +# VT-007: Calidad + +**MΓ³dulo:** Control de Calidad +**Herencia:** 40% del ERP Core (system) +**Estado:** PLANIFICADO + +## DescripciΓ³n +Control de calidad para producto de vidrio templado, incluyendo inspecciones, pruebas de fragmentaciΓ³n y certificaciones. + +## Funcionalidades +- Inspecciones de producto +- Pruebas de fragmentaciΓ³n (NMX-R-2-1989) +- Registro de no conformidades +- Certificaciones de producto +- Trazabilidad de defectos +- Reportes de calidad + +## Entidades +- `quality.inspections` - Inspecciones +- `quality.fragmentation_tests` - Pruebas de fragmentaciΓ³n +- `quality.non_conformities` - No conformidades +- `quality.certifications` - Certificaciones +- `quality.defect_types` - Tipos de defectos + +## Criterios de AceptaciΓ³n +- FragmentaciΓ³n: mΓ­n 40 partΓ­culas en 5Γ—5cm +- Defectos visuales: segΓΊn tolerancias +- Dimensiones: Β±2mm diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-008-despacho/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-008-despacho/README.md new file mode 100644 index 0000000..9199f4d --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/02-definicion-modulos/VT-008-despacho/README.md @@ -0,0 +1,31 @@ +# VT-008: Despacho + +**MΓ³dulo:** Despacho y LogΓ­stica +**Herencia:** 50% del ERP Core (inventory, sales) +**Estado:** PLANIFICADO + +## DescripciΓ³n +GestiΓ³n de entregas de producto terminado, incluyendo rutas, confirmaciones y evidencia. + +## Funcionalidades +- ProgramaciΓ³n de entregas +- AsignaciΓ³n de rutas +- ConfirmaciΓ³n de recepciΓ³n +- Evidencia fotogrΓ‘fica +- InstalaciΓ³n (opcional) +- Actas de entrega + +## Entidades +- `delivery.deliveries` - Entregas +- `delivery.delivery_lines` - LΓ­neas de entrega +- `delivery.routes` - Rutas +- `delivery.confirmations` - Confirmaciones +- `delivery.installations` - Instalaciones + +## Flujo de Entrega +1. ProgramaciΓ³n de entrega +2. AsignaciΓ³n de ruta y vehΓ­culo +3. Carga de producto +4. Entrega en sitio +5. ConfirmaciΓ³n con evidencia +6. Cierre de entrega diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/docs/08-epicas/EPIC-VT-001-fundamentos.md b/projects/erp-suite/apps/verticales/vidrio-templado/docs/08-epicas/EPIC-VT-001-fundamentos.md new file mode 100644 index 0000000..b2700f7 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/docs/08-epicas/EPIC-VT-001-fundamentos.md @@ -0,0 +1,65 @@ +# Γ‰pica: Fundamentos del Sistema + +**CΓ³digo:** EPIC-VT-001 +**MΓ³dulos:** VT-001 a VT-002 +**Estado:** PLANIFICADO + +--- + +## DescripciΓ³n + +ImplementaciΓ³n de los mΓ³dulos fundacionales del ERP Vidrio Templado, incluyendo la configuraciΓ³n inicial del sistema heredado del core y el mΓ³dulo de cotizaciones. + +--- + +## Objetivos + +1. Configurar el ambiente de desarrollo heredando del ERP Core +2. Implementar el cotizador de vidrio con cΓ‘lculo por mΒ² +3. Establecer el catΓ‘logo de tipos de vidrio y acabados + +--- + +## MΓ³dulos Incluidos + +| MΓ³dulo | DescripciΓ³n | SP Estimados | +|--------|-------------|--------------| +| VT-001 | Fundamentos (hereda core) | 0 | +| VT-002 | Cotizaciones | 34 | + +--- + +## User Stories Principales + +1. Como usuario, quiero iniciar sesiΓ³n en el sistema de vidrio templado +2. Como vendedor, quiero crear una cotizaciΓ³n de vidrio por dimensiones +3. Como vendedor, quiero calcular el precio automΓ‘tico por mΒ² +4. Como vendedor, quiero generar un PDF de cotizaciΓ³n para el cliente + +--- + +## Criterios de AceptaciΓ³n + +- [ ] Sistema de autenticaciΓ³n funcional (heredado) +- [ ] CRUD de cotizaciones implementado +- [ ] CΓ‘lculo de precios por dimensiones correcto +- [ ] GeneraciΓ³n de PDF funcional +- [ ] CatΓ‘logo de tipos de vidrio completo + +--- + +## Dependencias + +- ERP Core instalado y funcional +- Base de datos configurada con schemas heredados + +--- + +## Story Points Totales + +**34 SP** (excluyendo fundamentos heredados) + +--- + +**Γ‰pica fundacional** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md b/projects/erp-suite/apps/verticales/vidrio-templado/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md new file mode 100644 index 0000000..e5e5943 --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/orchestration/00-guidelines/HERENCIA-SPECS-CORE.md @@ -0,0 +1,175 @@ +# Herencia de SPECS del Core - Vidrio Templado + +**Fecha:** 2025-12-08 +**VersiΓ³n:** 1.0 +**Vertical:** Vidrio Templado (VT) +**Nivel:** 2B.2 + +--- + +## Resumen + +| MΓ©trica | Valor | +|---------|-------| +| SPECS Aplicables | 25/30 | +| SPECS Obligatorias | 22 | +| SPECS Opcionales | 3 | +| SPECS No Aplican | 5 | +| Estado ImplementaciΓ³n | 0% | + +--- + +## SPECS Obligatorias (Deben Implementarse) + +### P0 - CrΓ­ticas + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-SISTEMA-SECUENCIAS | ir.sequence | 8 | PENDIENTE | VT-001, VT-002 | +| SPEC-VALORACION-INVENTARIO | FIFO/AVCO | 21 | PENDIENTE | VT-004 | +| SPEC-SEGURIDAD-API-KEYS-PERMISOS | API Keys + ACL | 31 | PENDIENTE | VT-001 | +| SPEC-REPORTES-FINANCIEROS | Balance/P&L SAT | 13 | PENDIENTE | VT-008 | +| SPEC-PORTAL-PROVEEDORES | Portal RFQ | 13 | PENDIENTE | VT-004 | +| SPEC-NOMINA-BASICA | hr_payroll | 21 | PENDIENTE | VT-001 | +| SPEC-GASTOS-EMPLEADOS | hr_expense | 13 | PENDIENTE | VT-001 | +| SPEC-TAREAS-RECURRENTES | project.task.recurrence | 13 | PENDIENTE | VT-003 | +| SPEC-SCHEDULER-REPORTES | ir.cron + mail | 8 | PENDIENTE | VT-008 | + +### P1 - Complementarias + +| SPEC | Gap Original | SP | Estado | MΓ³dulos Afectados | +|------|-------------|----:|--------|-------------------| +| SPEC-CONTABILIDAD-ANALITICA | Centros de costo | 21 | PENDIENTE | VT-008 | +| SPEC-CONCILIACION-BANCARIA | ConciliaciΓ³n | 21 | PENDIENTE | VT-008 | +| SPEC-TWO-FACTOR-AUTHENTICATION | 2FA | 13 | PENDIENTE | VT-001 | +| SPEC-TRAZABILIDAD-LOTES-SERIES | Lotes/Series | 13 | PENDIENTE | VT-004, VT-007 | +| SPEC-PRICING-RULES | Reglas precio | 8 | PENDIENTE | VT-002 | +| SPEC-BLANKET-ORDERS | Γ“rdenes marco | 13 | PENDIENTE | VT-004 | +| SPEC-IMPUESTOS-AVANZADOS | IVA, ISR | 8 | PENDIENTE | VT-008 | +| SPEC-PLANTILLAS-CUENTAS | Plan contable | 8 | PENDIENTE | VT-008 | +| SPEC-TASAS-CAMBIO-AUTOMATICAS | Tipos cambio | 5 | PENDIENTE | VT-008 | +| SPEC-ALERTAS-PRESUPUESTO | Alertas | 8 | PENDIENTE | VT-002, VT-003 | +| SPEC-PRESUPUESTOS-REVISIONES | AprobaciΓ³n | 8 | PENDIENTE | VT-002 | +| SPEC-RRHH-EVALUACIONES-SKILLS | Evaluaciones | 26 | PENDIENTE | VT-001 | +| SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN | Burndown | 13 | PENDIENTE | VT-003 | +| SPEC-LOCALIZACION-PAISES | LocalizaciΓ³n | 13 | PENDIENTE | VT-001 | + +### Patrones TΓ©cnicos + +| SPEC | PatrΓ³n | SP | Estado | AplicaciΓ³n | +|------|--------|----:|--------|------------| +| SPEC-MAIL-THREAD-TRACKING | mail.thread | 13 | PENDIENTE | Γ“rdenes producciΓ³n, Cotizaciones | +| SPEC-WIZARD-TRANSIENT-MODEL | TransientModel | 8 | PENDIENTE | Wizards de corte, templado | + +--- + +## SPECS Opcionales + +| SPEC | DescripciΓ³n | SP | DecisiΓ³n | RazΓ³n | +|------|-------------|----:|----------|-------| +| SPEC-FIRMA-ELECTRONICA-NOM151 | e.firma | 13 | EVALUAR | Para certificados de calidad | +| SPEC-OAUTH2-SOCIAL-LOGIN | OAuth2 | 8 | DIFERIR | No prioritario | +| SPEC-INVENTARIOS-CICLICOS | Conteo cΓ­clico | 13 | EVALUAR | Útil para materia prima | + +--- + +## SPECS No Aplicables + +| SPEC | RazΓ³n | +|------|-------| +| SPEC-INTEGRACION-CALENDAR | No requiere calendario externo | +| SPEC-CONSOLIDACION-FINANCIERA | Negocio de una sola planta | + +--- + +## Adaptaciones Requeridas + +### Mapeo de Conceptos Core β†’ Vidrio + +| Concepto Core | Concepto Vidrio | +|---------------|-----------------| +| `sales.sale_orders` | Pedidos de vidrio | +| `inventory.products` | Tipos de vidrio (templado, laminado, etc.) | +| `inventory.lots` | Lotes de producciΓ³n | +| `projects.projects` | Γ“rdenes de producciΓ³n | +| `projects.tasks` | Etapas (corte, templado, inspecciΓ³n) | + +### Extensiones de Entidad + +```sql +-- Tipos de vidrio +glass.glass_types ( + product_id β†’ inventory.products, + tipo ENUM('templado', 'laminado', 'insulado', 'curvo'), + espesor_mm DECIMAL, + color VARCHAR, + propiedades JSONB +) + +-- Γ“rdenes de producciΓ³n +production.production_orders ( + id UUID, + sale_order_id β†’ sales.sale_orders, + tipo_vidrio_id β†’ glass_types, + dimensiones JSONB, + cantidad INTEGER, + estado ENUM +) + +-- ParΓ‘metros de horno +production.oven_parameters ( + production_order_id β†’ production_orders, + temperatura_c INTEGER, + tiempo_minutos INTEGER, + velocidad_enfriamiento DECIMAL, + fecha_templado TIMESTAMPTZ +) + +-- Inspecciones de calidad +quality.inspections ( + id UUID, + production_order_id β†’ production_orders, + tipo_inspeccion ENUM, + resultado ENUM('aprobado', 'rechazado', 'condicional'), + observaciones TEXT +) +``` + +--- + +## Plan de ImplementaciΓ³n + +### Fase 1: Fundamentos (SP: 52) +1. SPEC-SISTEMA-SECUENCIAS +2. SPEC-SEGURIDAD-API-KEYS-PERMISOS +3. SPEC-TWO-FACTOR-AUTHENTICATION + +### Fase 2: ProducciΓ³n (SP: 55) +4. SPEC-VALORACION-INVENTARIO +5. SPEC-TRAZABILIDAD-LOTES-SERIES +6. SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN +7. SPEC-PRICING-RULES + +### Fase 3: Operaciones (SP: 34) +8. SPEC-MAIL-THREAD-TRACKING +9. SPEC-WIZARD-TRANSIENT-MODEL +10. SPEC-TAREAS-RECURRENTES + +### Fase 4: Financiero (SP: 65) +11. SPEC-REPORTES-FINANCIEROS +12. SPEC-CONTABILIDAD-ANALITICA +13. SPEC-CONCILIACION-BANCARIA + +--- + +## Referencias + +- Documento Core: `erp-core/docs/04-modelado/MAPEO-SPECS-VERTICALES.md` +- SPECS del Core: `erp-core/docs/04-modelado/especificaciones-tecnicas/transversal/` +- Herencia DB: `database/HERENCIA-ERP-CORE.md` +- Directivas: `orchestration/directivas/` + +--- + +**Documento de herencia de SPECS oficial** +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/apps/verticales/vidrio-templado/orchestration/inventarios/README.md b/projects/erp-suite/apps/verticales/vidrio-templado/orchestration/inventarios/README.md new file mode 100644 index 0000000..e52b12e --- /dev/null +++ b/projects/erp-suite/apps/verticales/vidrio-templado/orchestration/inventarios/README.md @@ -0,0 +1,94 @@ +# Inventarios - ERP Vidrio Templado + +**Version:** 1.0.0 +**Fecha:** 2025-12-08 +**Nivel SIMCO:** 2B.2 + +--- + +## DescripciΓ³n + +Este directorio contiene los inventarios YAML que sirven como **Single Source of Truth (SSOT)** para el proyecto ERP Vidrio Templado. Estos archivos son la referencia canΓ³nica para mΓ©tricas, trazabilidad y componentes del sistema. + +--- + +## Archivos de Inventario + +| Archivo | DescripciΓ³n | Estado | +|---------|-------------|--------| +| [MASTER_INVENTORY.yml](./MASTER_INVENTORY.yml) | Inventario maestro con mΓ©tricas globales | Completo | +| [DATABASE_INVENTORY.yml](./DATABASE_INVENTORY.yml) | Inventario de objetos de base de datos | Planificado | +| [BACKEND_INVENTORY.yml](./BACKEND_INVENTORY.yml) | Inventario de componentes backend | Planificado | +| [FRONTEND_INVENTORY.yml](./FRONTEND_INVENTORY.yml) | Inventario de componentes frontend | Planificado | +| [TRACEABILITY_MATRIX.yml](./TRACEABILITY_MATRIX.yml) | Matriz de trazabilidad RF->ET->US | Completo | +| [DEPENDENCY_GRAPH.yml](./DEPENDENCY_GRAPH.yml) | Grafo de dependencias entre mΓ³dulos | Completo | + +--- + +## Herencia del Core + +Este proyecto hereda del **ERP Core** (nivel 2B.1): + +| Aspecto | Heredado | EspecΓ­fico | +|---------|----------|------------| +| **Tablas DB** | ~100 | Planificado | +| **Schemas** | 8+ | Planificado | +| **Specs** | 3 | - | + +### Specs Heredadas + +1. SPEC-VALORACION-INVENTARIO.md +2. SPEC-TRAZABILIDAD-LOTES-SERIES.md +3. SPEC-INVENTARIOS-CICLICOS.md + +--- + +## Resumen Ejecutivo + +### MΓ©tricas del Proyecto + +| MΓ©trica | Valor | +|---------|-------| +| **MΓ³dulos** | 5 (VT-001 a VT-005) | +| **Estado** | PLANIFICACION_COMPLETA | +| **Completitud** | 15% | + +### Dominio del Negocio + +- ProducciΓ³n de vidrio templado +- Control de calidad +- Trazabilidad de lotes +- GestiΓ³n de hornos y procesos + +--- + +## Directivas EspecΓ­ficas + +1. [DIRECTIVA-PRODUCCION-VIDRIO.md](../directivas/DIRECTIVA-PRODUCCION-VIDRIO.md) +2. [DIRECTIVA-CONTROL-CALIDAD.md](../directivas/DIRECTIVA-CONTROL-CALIDAD.md) + +--- + +## ConfiguraciΓ³n de Puertos (Planificado) + +| Servicio | Puerto | +|----------|--------| +| Backend API | 3300 | +| Frontend Web | 5176 | + +--- + +## AlineaciΓ³n con ERP Core + +Estos inventarios siguen la misma estructura que: +- `/erp-core/orchestration/inventarios/` (proyecto padre) + +### Referencias + +- Suite Master: `orchestration/inventarios/SUITE_MASTER_INVENTORY.yml` +- Core: `apps/erp-core/orchestration/inventarios/` +- Status Global: `orchestration/inventarios/STATUS.yml` + +--- + +**Última actualizaciΓ³n:** 2025-12-08 diff --git a/projects/erp-suite/orchestration/inventarios/REFERENCIAS.yml b/projects/erp-suite/orchestration/inventarios/REFERENCIAS.yml index 97d96ac..61e7ad5 100644 --- a/projects/erp-suite/orchestration/inventarios/REFERENCIAS.yml +++ b/projects/erp-suite/orchestration/inventarios/REFERENCIAS.yml @@ -123,39 +123,114 @@ referencias_erp_core: referencias_verticales: construccion: ubicacion_base: apps/verticales/construccion/ - documentacion: docs/ + nivel: 2B.2 + estado: EN_DESARROLLO + completitud: 40% + documentacion: docs/ (449 archivos) orchestration: orchestration/ - total_archivos: 403 - - vidrio_templado: - ubicacion_base: apps/verticales/vidrio-templado/ - documentacion: docs/ - orchestration: orchestration/ - estado: estructura_base + inventarios: + ubicacion: orchestration/inventarios/ + archivos: 6 + readme: true + database: + ubicacion: database/ + herencia: database/HERENCIA-ERP-CORE.md + ddl_implementado: true + tablas_especificas: 33 + backend: + porcentaje: 15% + entities: 12 + services: 2 + controllers: 2 + directivas: + - directivas/DIRECTIVA-CONTROL-OBRA.md + - directivas/DIRECTIVA-ESTIMACIONES.md + - directivas/DIRECTIVA-INTEGRACION-INFONAVIT.md mecanicas_diesel: ubicacion_base: apps/verticales/mecanicas-diesel/ + nivel: 2B.2 + estado: DDL_IMPLEMENTADO + completitud: 20% + documentacion: docs/ (75 archivos) + orchestration: orchestration/ + inventarios: + ubicacion: orchestration/inventarios/ + archivos: 6 + readme: true + database: + ubicacion: database/ + herencia: database/HERENCIA-ERP-CORE.md + ddl_implementado: true + lineas_sql: 1561 + directivas: + - directivas/DIRECTIVA-ORDENES-TRABAJO.md + - directivas/DIRECTIVA-INVENTARIO-REFACCIONES.md + + vidrio_templado: + ubicacion_base: apps/verticales/vidrio-templado/ + nivel: 2B.2 + estado: PLANIFICACION_COMPLETA + completitud: 15% documentacion: docs/ orchestration: orchestration/ - estado: estructura_base + inventarios: + ubicacion: orchestration/inventarios/ + archivos: 6 + readme: true + database: + ubicacion: database/ + herencia: database/HERENCIA-ERP-CORE.md + ddl_implementado: false + directivas: + - directivas/DIRECTIVA-PRODUCCION-VIDRIO.md + - directivas/DIRECTIVA-CONTROL-CALIDAD.md retail: ubicacion_base: apps/verticales/retail/ + nivel: 2B.2 + estado: PLANIFICACION_COMPLETA + completitud: 15% documentacion: docs/ orchestration: orchestration/ - estado: estructura_base + inventarios: + ubicacion: orchestration/inventarios/ + archivos: 6 + readme: true + database: + ubicacion: database/ + herencia: database/HERENCIA-ERP-CORE.md + ddl_implementado: false + directivas: + - directivas/DIRECTIVA-PUNTO-VENTA.md + - directivas/DIRECTIVA-INVENTARIO-SUCURSALES.md clinicas: ubicacion_base: apps/verticales/clinicas/ + nivel: 2B.2 + estado: PLANIFICACION_COMPLETA + completitud: 15% documentacion: docs/ orchestration: orchestration/ - estado: estructura_base + inventarios: + ubicacion: orchestration/inventarios/ + archivos: 6 + readme: true + database: + ubicacion: database/ + herencia: database/HERENCIA-ERP-CORE.md + ddl_implementado: false + directivas: + - directivas/DIRECTIVA-EXPEDIENTE-CLINICO.md + - directivas/DIRECTIVA-GESTION-CITAS.md # ============================================================================ # MATRIZ DE HERENCIA (Verticales -> Core) # ============================================================================ herencia_verticales: descripcion: "Especificaciones del core que cada vertical debe heredar" + fecha_propagacion: 2025-12-08 + estado_propagacion: COMPLETO construccion: specs_heredables: @@ -165,32 +240,92 @@ herencia_verticales: - SPEC-VALORACION-INVENTARIO.md - SPEC-TRAZABILIDAD-LOTES-SERIES.md - SPEC-TAREAS-RECURRENTES.md - documentado: false - - vidrio_templado: - specs_heredables: - - SPEC-VALORACION-INVENTARIO.md - - SPEC-TRAZABILIDAD-LOTES-SERIES.md - - SPEC-INVENTARIOS-CICLICOS.md - documentado: false + documentado: true + documento_herencia: apps/verticales/construccion/database/HERENCIA-ERP-CORE.md + tablas_heredadas: 124 + tablas_especificas: 33 mecanicas_diesel: specs_heredables: - SPEC-VALORACION-INVENTARIO.md - SPEC-TRAZABILIDAD-LOTES-SERIES.md - SPEC-INVENTARIOS-CICLICOS.md - documentado: false + - SPEC-MAIL-THREAD-TRACKING.md + - SPEC-TAREAS-RECURRENTES.md + documentado: true + documento_herencia: apps/verticales/mecanicas-diesel/database/HERENCIA-ERP-CORE.md + tablas_heredadas: 97 + tablas_especificas: 30+ + + vidrio_templado: + specs_heredables: + - SPEC-VALORACION-INVENTARIO.md + - SPEC-TRAZABILIDAD-LOTES-SERIES.md + - SPEC-INVENTARIOS-CICLICOS.md + documentado: true + documento_herencia: apps/verticales/vidrio-templado/database/HERENCIA-ERP-CORE.md + tablas_heredadas: ~97 + tablas_especificas: ~25 (planificado) retail: specs_heredables: - SPEC-PRICING-RULES.md - SPEC-INVENTARIOS-CICLICOS.md - SPEC-TRAZABILIDAD-LOTES-SERIES.md - documentado: false + documentado: true + documento_herencia: apps/verticales/retail/database/HERENCIA-ERP-CORE.md + tablas_heredadas: ~102 + tablas_especificas: ~30 (planificado) clinicas: specs_heredables: - SPEC-RRHH-EVALUACIONES-SKILLS.md - SPEC-INTEGRACION-CALENDAR.md - SPEC-MAIL-THREAD-TRACKING.md - documentado: false + documentado: true + documento_herencia: apps/verticales/clinicas/database/HERENCIA-ERP-CORE.md + tablas_heredadas: ~100 + tablas_especificas: ~35 (planificado) + +# ============================================================================ +# VALIDACION DE PROPAGACION SIMCO +# ============================================================================ +validacion_propagacion: + fecha: 2025-12-08 + sistema: SIMCO v2.2.0 + + niveles: + suite_master: + nivel: 2B + inventarios: [SUITE_MASTER_INVENTORY.yml, STATUS.yml, REFERENCIAS.yml] + estado: COMPLETO + + erp_core: + nivel: 2B.1 + inventarios: 6 + estado: COMPLETO + carga_limpia: EXITOSA + + verticales: + nivel: 2B.2 + total: 5 + inventarios_por_vertical: 6 + readme_por_vertical: 5/5 + herencia_documentada: 5/5 + directivas_por_vertical: 2-3 + + checklist: + - item: "SUITE_MASTER_INVENTORY actualizado" + estado: true + - item: "STATUS.yml sincronizado" + estado: true + - item: "REFERENCIAS.yml completo" + estado: true + - item: "README.md en todas las verticales" + estado: true + - item: "HERENCIA-ERP-CORE.md en todas las verticales" + estado: true + - item: "Directivas especΓ­ficas por vertical" + estado: true + - item: "6 inventarios por proyecto" + estado: true diff --git a/projects/erp-suite/orchestration/inventarios/STATUS.yml b/projects/erp-suite/orchestration/inventarios/STATUS.yml index 9266f22..818fb6c 100644 --- a/projects/erp-suite/orchestration/inventarios/STATUS.yml +++ b/projects/erp-suite/orchestration/inventarios/STATUS.yml @@ -62,7 +62,7 @@ componentes: nivel: "2B.2" ultima_modificacion: "2025-12-08" estado: "EN_DESARROLLO" - completitud: "35%" + completitud: "40%" capas: documentacion: estado: "AVANZADA" @@ -73,10 +73,13 @@ componentes: tablas_especificas: 33 schemas_especificos: ["construccion", "hr", "hse"] backend: - estado: "INICIAL" - archivos_ts: 7 - entities: 2 - porcentaje: "5%" + estado: "EN_PROGRESO" + archivos_ts: 25 + entities: 12 + services: 2 + controllers: 2 + porcentaje: "15%" + modulos_funcionales: ["construction"] frontend: estado: "INICIAL" archivos: 3 @@ -93,8 +96,9 @@ componentes: - SPEC-TRAZABILIDAD-LOTES-SERIES.md - SPEC-TAREAS-RECURRENTES.md gap_analisis: - documentacion_vs_codigo: "449 MD vs 10 cΓ³digo" - ratio_implementacion: "2%" + documentacion_vs_codigo: "449 MD vs 25 cΓ³digo" + ratio_implementacion: "5.6%" + nota: "Gap corregido - entities base implementadas" vidrio_templado: nivel: "2B.2" @@ -226,8 +230,8 @@ alertas: fecha: "2025-12-08" - componente: "construccion" - tipo: "GAP" - mensaje: "Gap significativo: 449 docs vs 10 archivos cΓ³digo (2% implementado)" + tipo: "EN_PROGRESO" + mensaje: "Gap corregido: 12 entities, 2 services, 2 controllers implementados" fecha: "2025-12-08" - componente: "mecanicas_diesel" @@ -239,6 +243,16 @@ alertas: # HISTORIAL DE CAMBIOS RECIENTES # ======================================== historial: + - fecha: "2025-12-08" + componente: "construccion" + cambio: "IMPLEMENTACION GAP FIX - 12 entities, 2 services, 2 controllers creados" + agente: "System" + detalles: + - "Entities: Proyecto, Fraccionamiento, Employee, Puesto, Incidente, Capacitacion" + - "Services: ProyectoService, FraccionamientoService" + - "Controllers: ProyectoController, FraccionamientoController" + - "Backend 15% implementado (25 archivos TS)" + - fecha: "2025-12-08" componente: "erp_core" cambio: "CARGA LIMPIA EXITOSA - 124 tablas, 12 schemas, 6 seeds" diff --git a/projects/erp-suite/orchestration/inventarios/SUITE_MASTER_INVENTORY.yml b/projects/erp-suite/orchestration/inventarios/SUITE_MASTER_INVENTORY.yml index 79ec180..8830cf5 100644 --- a/projects/erp-suite/orchestration/inventarios/SUITE_MASTER_INVENTORY.yml +++ b/projects/erp-suite/orchestration/inventarios/SUITE_MASTER_INVENTORY.yml @@ -1,157 +1,422 @@ # Suite Master Inventory - ERP Suite # Ultima actualizacion: 2025-12-08 # SSOT para metricas de toda la suite (core + verticales) +# Sistema: SIMCO v2.2.0 +# Nivel: 2B (Suite Master) suite: nombre: ERP Suite tipo: Multi-Vertical Suite - version: 0.5.0 + version: 0.6.0 nivel: 2B estado: En Desarrollo ultima_modificacion: 2025-12-08 + # Inventarios de este nivel + inventarios_suite: + - SUITE_MASTER_INVENTORY.yml # Este archivo + - STATUS.yml # Estado de componentes + - REFERENCIAS.yml # Referencias cruzadas + - BACKEND_CONSOLIDATED.yml # Consolidado backend (referencia) + - FRONTEND_CONSOLIDATED.yml # Consolidado frontend (referencia) + - DEPENDENCY_SUITE.yml # Dependencias inter-proyecto + # ============================================================================ -# ERP CORE (Nivel 2B.1) +# ERP CORE (Nivel 2B.1) - PROYECTO PADRE # ============================================================================ erp_core: path: apps/erp-core/ - estado: Gap Analysis COMPLETO - version: 0.6.0 + nivel: 2B.1 + estado: DATABASE_COMPLETO + version: 1.1.0 ultima_modificacion: 2025-12-08 + # Estado de capas + capas: + documentacion: + estado: COMPLETA + archivos: 680+ + especificaciones: 30 + workflows: 3 + + database: + estado: VALIDADO + tablas: 124 + schemas: 12 + ddl_archivos: 15 + carga_limpia: EXITOSA + fecha_validacion: 2025-12-08 + + backend: + estado: PENDIENTE + endpoints_especificados: 148 + services_especificados: 45+ + + frontend: + estado: PENDIENTE + componentes_especificados: 80+ + + # Inventarios del core (6 archivos estΓ‘ndar) + inventarios: + - MASTER_INVENTORY.yml + - DATABASE_INVENTORY.yml + - BACKEND_INVENTORY.yml + - FRONTEND_INVENTORY.yml + - DEPENDENCY_GRAPH.yml + - TRACEABILITY_MATRIX.yml + ubicacion: apps/erp-core/orchestration/inventarios/ + + # MΓ©tricas de documentaciΓ³n metricas: modulos_totales: 15 modulos_p0: 4 modulos_p1: 6 modulos_p2: 5 + gap_analysis_cobertura: "100%" + story_points_cubiertos: 394 - documentacion: - total_archivos: 680+ - especificaciones_transversales: 30 - workflows: 3 - requerimientos_funcionales: 46 - user_stories: 17 - test_plans: 4 - - gap_analysis: - gaps_p0_documentados: 18 - gaps_p1_documentados: 22 - patrones_tecnicos: 2 - cobertura: "100%" - story_points_cubiertos: 394 - - especificaciones_transversales: + # Especificaciones que heredan las verticales + especificaciones_heredables: ubicacion: docs/04-modelado/especificaciones-tecnicas/transversal/ total: 30 - referencia: apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml + lista_principales: + - SPEC-VALORACION-INVENTARIO.md + - SPEC-TRAZABILIDAD-LOTES-SERIES.md + - SPEC-INVENTARIOS-CICLICOS.md + - SPEC-MAIL-THREAD-TRACKING.md + - SPEC-TAREAS-RECURRENTES.md + - SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN.md + - SPEC-INTEGRACION-CALENDAR.md + - SPEC-PRICING-RULES.md + - SPEC-RRHH-EVALUACIONES-SKILLS.md - inventario_local: apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml - analisis_gaps: apps/erp-core/orchestration/01-analisis/ANALISIS-GAPS-CONSOLIDADO.md + referencias: + inventario_local: apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml + analisis_gaps: apps/erp-core/orchestration/01-analisis/ANALISIS-GAPS-CONSOLIDADO.md + database_readme: apps/erp-core/database/README.md # ============================================================================ -# VERTICALES (Nivel 2B.2) +# VERTICALES (Nivel 2B.2) - PROYECTOS HIJOS # ============================================================================ verticales: total: 5 en_desarrollo: 1 - planificacion: 4 + ddl_implementado: 1 + planificacion: 3 + + # Inventarios estΓ‘ndar que debe tener cada vertical + inventarios_requeridos: + - MASTER_INVENTORY.yml + - DATABASE_INVENTORY.yml + - BACKEND_INVENTORY.yml + - FRONTEND_INVENTORY.yml + - DEPENDENCY_GRAPH.yml + - TRACEABILITY_MATRIX.yml lista: + # ------------------------------------------------------------------------- + # CONSTRUCCION - Vertical mΓ‘s avanzada + # ------------------------------------------------------------------------- - nombre: construccion path: apps/verticales/construccion/ - estado: En Desarrollo - completitud: 35% - documentacion: 403+ archivos - modulos: 15 (MAI-001 a MAI-018) - epicas_fase2: 3 (MAE-014 a MAE-016) - ultima_modificacion: 2025-12-05 - herencia_core: - - SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN.md - - SPEC-MAIL-THREAD-TRACKING.md - - SPEC-WIZARD-TRANSIENT-MODEL.md - - SPEC-VALORACION-INVENTARIO.md - - SPEC-TRAZABILIDAD-LOTES-SERIES.md + nivel: 2B.2 + estado: EN_DESARROLLO + completitud: 40% + ultima_modificacion: 2025-12-08 - - nombre: vidrio-templado - path: apps/verticales/vidrio-templado/ - estado: Planificacion - completitud: 0% - documentacion: Estructura base - ultima_modificacion: 2025-12-05 - herencia_core: - - SPEC-VALORACION-INVENTARIO.md - - SPEC-TRAZABILIDAD-LOTES-SERIES.md - - SPEC-INVENTARIOS-CICLICOS.md + capas: + documentacion: + estado: AVANZADA + archivos: 449 + database: + estado: DDL_COMPLETO + tablas_heredadas: 124 + tablas_especificas: 33 + schemas: [construccion, hr, hse] + backend: + estado: EN_PROGRESO + porcentaje: 15% + entities: 12 + services: 2 + controllers: 2 + frontend: + estado: INICIAL + porcentaje: 2% + herencia_core: + specs_heredadas: 6 + documento: database/HERENCIA-ERP-CORE.md + lista: + - SPEC-PROYECTOS-DEPENDENCIAS-BURNDOWN.md + - SPEC-MAIL-THREAD-TRACKING.md + - SPEC-WIZARD-TRANSIENT-MODEL.md + - SPEC-VALORACION-INVENTARIO.md + - SPEC-TRAZABILIDAD-LOTES-SERIES.md + - SPEC-TAREAS-RECURRENTES.md + + directivas_especificas: + - DIRECTIVA-CONTROL-OBRA.md + - DIRECTIVA-ESTIMACIONES.md + - DIRECTIVA-INTEGRACION-INFONAVIT.md + + inventarios_ubicacion: orchestration/inventarios/ + + # ------------------------------------------------------------------------- + # MECANICAS-DIESEL + # ------------------------------------------------------------------------- - nombre: mecanicas-diesel path: apps/verticales/mecanicas-diesel/ - estado: Planificacion - completitud: 0% - documentacion: Estructura base - ultima_modificacion: 2025-12-05 - herencia_core: - - SPEC-VALORACION-INVENTARIO.md - - SPEC-TRAZABILIDAD-LOTES-SERIES.md - - SPEC-INVENTARIOS-CICLICOS.md + nivel: 2B.2 + estado: DDL_IMPLEMENTADO + completitud: 20% + ultima_modificacion: 2025-12-08 + capas: + documentacion: + estado: COMPLETA + archivos: 75 + database: + estado: DDL_DEFINIDO + tablas_heredadas: 97 + tablas_especificas: 30+ + schemas: [service_management, parts_management, vehicle_management] + lineas_sql: 1561 + backend: + estado: PENDIENTE + porcentaje: 0% + frontend: + estado: PENDIENTE + porcentaje: 0% + + herencia_core: + specs_heredadas: 5 + documento: database/HERENCIA-ERP-CORE.md + lista: + - SPEC-VALORACION-INVENTARIO.md + - SPEC-TRAZABILIDAD-LOTES-SERIES.md + - SPEC-INVENTARIOS-CICLICOS.md + - SPEC-MAIL-THREAD-TRACKING.md + - SPEC-TAREAS-RECURRENTES.md + + directivas_especificas: + - DIRECTIVA-ORDENES-TRABAJO.md + - DIRECTIVA-INVENTARIO-REFACCIONES.md + + inventarios_ubicacion: orchestration/inventarios/ + + # ------------------------------------------------------------------------- + # VIDRIO-TEMPLADO + # ------------------------------------------------------------------------- + - nombre: vidrio-templado + path: apps/verticales/vidrio-templado/ + nivel: 2B.2 + estado: PLANIFICACION_COMPLETA + completitud: 15% + ultima_modificacion: 2025-12-08 + + capas: + documentacion: + estado: ESTRUCTURA_BASE + database: + estado: PLANIFICADO + backend: + estado: PENDIENTE + frontend: + estado: PENDIENTE + + herencia_core: + specs_heredadas: 3 + lista: + - SPEC-VALORACION-INVENTARIO.md + - SPEC-TRAZABILIDAD-LOTES-SERIES.md + - SPEC-INVENTARIOS-CICLICOS.md + + directivas_especificas: + - DIRECTIVA-PRODUCCION-VIDRIO.md + - DIRECTIVA-CONTROL-CALIDAD.md + + inventarios_ubicacion: orchestration/inventarios/ + + # ------------------------------------------------------------------------- + # RETAIL + # ------------------------------------------------------------------------- - nombre: retail path: apps/verticales/retail/ - estado: Planificacion - completitud: 0% - documentacion: Estructura base - ultima_modificacion: 2025-12-05 - herencia_core: - - SPEC-PRICING-RULES.md - - SPEC-INVENTARIOS-CICLICOS.md - - SPEC-TRAZABILIDAD-LOTES-SERIES.md + nivel: 2B.2 + estado: PLANIFICACION_COMPLETA + completitud: 15% + ultima_modificacion: 2025-12-08 + capas: + documentacion: + estado: ESTRUCTURA_BASE + database: + estado: PLANIFICADO + backend: + estado: PENDIENTE + frontend: + estado: PENDIENTE + + herencia_core: + specs_heredadas: 3 + lista: + - SPEC-PRICING-RULES.md + - SPEC-INVENTARIOS-CICLICOS.md + - SPEC-TRAZABILIDAD-LOTES-SERIES.md + + directivas_especificas: + - DIRECTIVA-PUNTO-VENTA.md + - DIRECTIVA-INVENTARIO-SUCURSALES.md + + inventarios_ubicacion: orchestration/inventarios/ + + # ------------------------------------------------------------------------- + # CLINICAS + # ------------------------------------------------------------------------- - nombre: clinicas path: apps/verticales/clinicas/ - estado: Planificacion - completitud: 0% - documentacion: Estructura base - ultima_modificacion: 2025-12-05 + nivel: 2B.2 + estado: PLANIFICACION_COMPLETA + completitud: 15% + ultima_modificacion: 2025-12-08 + + capas: + documentacion: + estado: ESTRUCTURA_BASE + database: + estado: PLANIFICADO + backend: + estado: PENDIENTE + frontend: + estado: PENDIENTE + herencia_core: - - SPEC-RRHH-EVALUACIONES-SKILLS.md - - SPEC-INTEGRACION-CALENDAR.md - - SPEC-MAIL-THREAD-TRACKING.md + specs_heredadas: 3 + lista: + - SPEC-RRHH-EVALUACIONES-SKILLS.md + - SPEC-INTEGRACION-CALENDAR.md + - SPEC-MAIL-THREAD-TRACKING.md + + directivas_especificas: + - DIRECTIVA-EXPEDIENTE-CLINICO.md + - DIRECTIVA-GESTION-CITAS.md + + inventarios_ubicacion: orchestration/inventarios/ # ============================================================================ -# SHARED LIBS +# SHARED LIBS (Futuro) # ============================================================================ shared_libs: path: apps/shared-libs/ - estado: Planificado - documentacion: Pendiente + nivel: 2B.3 + estado: PLANIFICADO + documentacion: PENDIENTE + proposito: "Componentes compartidos entre verticales" # ============================================================================ -# SAAS LAYER +# SAAS LAYER (Futuro) # ============================================================================ saas: path: apps/saas/ - estado: Planificado - documentacion: Pendiente + nivel: 2B.4 + estado: PLANIFICADO + documentacion: PENDIENTE + proposito: "Capa de servicios multi-tenant cloud" # ============================================================================ -# METRICAS CONSOLIDADAS +# METRICAS CONSOLIDADAS DE LA SUITE # ============================================================================ metricas_suite: - total_archivos_docs: 1100+ - modulos_core: 15 - verticales: 5 - story_points_documentados: 734 - cobertura_gaps_core: 100% + fecha_actualizacion: 2025-12-08 + + documentacion: + total_archivos: 1200+ + core: 680+ + verticales: 520+ + + database: + tablas_core: 124 + schemas_core: 12 + verticales_con_ddl: 2 + tablas_especificas_total: 63+ # construccion(33) + mecanicas(30+) + + backend: + core_implementado: 0% + construccion_implementado: 15% + entities_totales: 12 + services_totales: 2 + controllers_totales: 2 + + frontend: + core_implementado: 0% + construccion_implementado: 2% + + cobertura: + gap_analysis_core: "100%" + story_points_cubiertos: 734 + specs_transversales: 30 + workflows: 3 # ============================================================================ -# PROXIMA ACCION SUITE +# PROPAGACION SIMCO # ============================================================================ -proxima_accion: - prioridad: ALTA - descripcion: Implementar modulos P0 del core - modulos: - - MGN-001 Auth - - MGN-002 Users - - MGN-003 Roles - - MGN-004 Tenants - specs_disponibles: 30 - workflows_disponibles: 3 +propagacion: + sistema: SIMCO v2.2.0 + niveles: + - nivel: 2B + nombre: Suite Master + ubicacion: orchestration/inventarios/ + archivos: [SUITE_MASTER_INVENTORY.yml, STATUS.yml, REFERENCIAS.yml] + + - nivel: 2B.1 + nombre: ERP Core + ubicacion: apps/erp-core/orchestration/inventarios/ + archivos: 6 # Inventarios estΓ‘ndar + + - nivel: 2B.2 + nombre: Verticales + ubicacion: apps/verticales/*/orchestration/inventarios/ + archivos: 6 # Inventarios estΓ‘ndar por vertical + verticales: 5 + + herencia: + direccion: "Core -> Verticales" + documento_base: "HERENCIA-ERP-CORE.md" + specs_heredables: 30 + propagacion_completada: true + fecha_propagacion: 2025-12-08 + + validacion: + inventarios_completos: true + directivas_propagadas: true + herencia_documentada: true + status_sincronizado: true + +# ============================================================================ +# PROXIMAS ACCIONES SUITE +# ============================================================================ +proximas_acciones: + prioridad_1: + descripcion: "Completar backend construcciΓ³n" + modulos: [MAI-001, MAI-002, MAI-003] + porcentaje_actual: 15% + porcentaje_objetivo: 50% + + prioridad_2: + descripcion: "Cargar DDL mecanicas-diesel" + prerequisito: "Validar DDL contra core" + estado: PENDIENTE + + prioridad_3: + descripcion: "Iniciar DDL para verticales restantes" + verticales: [vidrio-templado, retail, clinicas] + +# ============================================================================ +# REFERENCIAS CRUZADAS +# ============================================================================ +referencias: + status_global: orchestration/inventarios/STATUS.yml + referencias_herencia: orchestration/inventarios/REFERENCIAS.yml + core_master: apps/erp-core/orchestration/inventarios/MASTER_INVENTORY.yml + core_database: apps/erp-core/database/README.md + guidelines: orchestration/00-guidelines/ diff --git a/projects/platform_marketing_content/docs/00-vision-general/ARQUITECTURA-TECNICA.md b/projects/platform_marketing_content/docs/00-vision-general/ARQUITECTURA-TECNICA.md new file mode 100644 index 0000000..b32f604 --- /dev/null +++ b/projects/platform_marketing_content/docs/00-vision-general/ARQUITECTURA-TECNICA.md @@ -0,0 +1,967 @@ +# Arquitectura TθŒ…cnica - Platform Marketing Content + +**Versiθ΄Έn:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** Propuesta + +--- + +## 1. Visiθ΄Έn de Arquitectura + +### 1.1 Principios Arquitectθ΄Έnicos + +```yaml +Principios: + 1. API-First: Todo servicio expuesto via REST/GraphQL + 2. Modular: Componentes desacoplados por dominio + 3. Multi-tenant Ready: Aislamiento de datos por tenant + 4. Open Source First: Priorizar modelos auto-hosteados + 5. Escalabilidad Horizontal: Preparado para mη…€ltiples GPUs + 6. Event-Driven: Comunicaciθ΄Έn as铆ncrona entre servicios +``` + +### 1.2 Diagrama de Arquitectura de Alto Nivel + +``` +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? CAPA DE PRESENTACIθ„«N 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? Web App Admin 鉁? 鉁? Portal Cliente 鉁? 鉁? +鉁? 鉁? (React + Vite) 鉁? 鉁? (Opcional) 鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? + 鈻? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? API GATEWAY 鉁? +鉁? (NestJS + JWT Auth) 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? 鉁? 鉁? 鉁? + 鈻? 鈻? 鈻? 鈻? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? CAPA DE SERVICIOS 鉁? +鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? CRM 鉁? 鉁? Projects 鉁? 鉁? Assets 鉁? 鉁? Auth 鉁? 鉁? +鉁? 鉁? Service 鉁? 鉁? Service 鉁? 鉁? Service 鉁? 鉁? Service 鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? Generation 鉁? 鉁? Automation 鉁? 鉁? +鉁? 鉁? Service 鉁? 鉁? Service 鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? 鉁? 鉁? 鉁? + 鈻? 鈻? 鈻? 鈻? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? CAPA DE INFRAESTRUCTURA 鉁? +鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? PostgreSQL 鉁? 鉁? Redis 鉁? 鉁? S3/MinIO 鉁? 鉁? ComfyUI 鉁? 鉁? +鉁? 鉁? 15+ 鉁? 鉁? (Cache) 鉁? 鉁? (Storage)鉁? 鉁? (GPU) 鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? n8n 鉁? 鉁? Bull/BullMQ 鉁? 鉁? +鉁? 鉁? (Workflows) 鉁? 鉁? (Job Queues) 鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +``` + +--- + +## 2. Stack Tecnolθ΄Έgico Detallado + +### 2.1 Backend + +```yaml +Framework: NestJS 10+ +Runtime: Node.js 20 LTS +Lenguaje: TypeScript 5.x + +Dependencias Core: + - @nestjs/core + - @nestjs/platform-express + - @nestjs/typeorm + - @nestjs/jwt + - @nestjs/passport + - @nestjs/bull + - class-validator + - class-transformer + +ORM/Database: + - TypeORM 0.3+ + - pg (PostgreSQL driver) + +Queues: + - bull / bullmq + - @nestjs/bull + +Caching: + - ioredis + - @nestjs/cache-manager + +HTTP Client: + - axios (llamadas a ComfyUI) + +File Storage: + - @aws-sdk/client-s3 (o minio compatible) + +Logging: + - winston + - @nestjs/winston +``` + +### 2.2 Frontend + +```yaml +Framework: React 18 +Build Tool: Vite 5+ +Lenguaje: TypeScript 5.x + +UI Framework: + - TailwindCSS 3.x + - Shadcn/UI (componentes) + - Radix UI (primitivos) + +State Management: + - Zustand (global state) + - React Query / TanStack Query (server state) + +Routing: + - React Router 6 + +Forms: + - React Hook Form + - Zod (validaciθ΄Έn) + +Charts/Visualizaciθ΄Έn: + - Recharts + - Apache ECharts (opcional) + +Utilities: + - date-fns + - lodash-es +``` + +### 2.3 Motor de Generaciθ΄Έn IA + +```yaml +Orquestador Principal: ComfyUI + - Interfaz de nodos para workflows + - Soporte para mη…€ltiples modelos + - Custom nodes extensibles + +Exposiciθ΄Έn API: ComfyDeploy + - Convierte workflows en APIs HTTP + - Manejo de colas integrado + - Webhooks para resultados + +Modelos Base: + Text-to-Image: + - Stable Diffusion XL 1.0 + - SD 1.5 / 2.1 (fallback para menos VRAM) + + Checkpoints Especializados: + - Realistic Vision (rostros) + - Product Photography (e-commerce) + - Juggernaut XL (general alta calidad) + + ControlNets: + - OpenPose (control de poses) + - Canny (bordes) + - Depth (profundidad) + - Segmentation (mθ°©scaras) + + Upscalers: + - RealESRGAN x4 + - SwinIR + - SDXL refiner + + Inpainting: + - SDXL Inpaint model + - SD 1.5 Inpaint (fallback) + +Requisitos Hardware: + M铆nimo: NVIDIA GPU 12GB VRAM (RTX 3060 12GB) + Recomendado: NVIDIA GPU 24GB VRAM (RTX 4090, L4, A5000) + θ„«ptimo: Mη…€ltiples GPUs para colas paralelas +``` + +### 2.4 Base de Datos + +```yaml +Motor: PostgreSQL 15+ + +Schemas: + - auth: Usuarios, sesiones, permisos + - crm: Clientes, contactos, marcas, productos + - projects: Proyectos, campaεΈ½as, briefs + - assets: Imθ°©genes, copys, metadatos + - generation: Jobs, workflows, resultados + - config: Configuraciθ΄Έn por tenant + +Extensiones: + - uuid-ossp (UUIDs) + - pgcrypto (encriptaciθ΄Έn) + - pg_trgm (bη…€squeda fuzzy) + +Estrategia Multi-tenant: + - Discriminador: tenant_id en todas las tablas + - Row-Level Security (RLS) por tenant + - Contexto de sesiθ΄Έn: app.current_tenant_id +``` + +### 2.5 Automatizaciθ΄Έn + +```yaml +Orquestador: n8n (self-hosted) + +Triggers Soportados: + - Webhooks desde backend + - Cron / schedules + - Eventos de base de datos + +Integraciones: + - HTTP/REST (cualquier API) + - PostgreSQL queries + - S3/MinIO operations + - Email (SMTP) + - Slack/Discord (opcional) +``` + +--- + +## 3. Estructura de Mθ΄Έdulos Backend + +### 3.1 Organizaciθ΄Έn de Cθ΄Έdigo + +``` +apps/backend/src/ +鉁斺攒鉁? modules/ +鉁? 鉁斺攒鉁? auth/ +鉁? 鉁? 鉁斺攒鉁? controllers/ +鉁? 鉁? 鉁斺攒鉁? services/ +鉁? 鉁? 鉁斺攒鉁? entities/ +鉁? 鉁? 鉁斺攒鉁? dto/ +鉁? 鉁? 鉁斺攒鉁? guards/ +鉁? 鉁? 鉁斺攒鉁? strategies/ +鉁? 鉁? 鉁斺攒鉁? auth.module.ts +鉁? 鉁? +鉁? 鉁斺攒鉁? crm/ +鉁? 鉁? 鉁斺攒鉁? controllers/ +鉁? 鉁? 鉁? 鉁斺攒鉁? clients.controller.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? brands.controller.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? products.controller.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? contacts.controller.ts +鉁? 鉁? 鉁斺攒鉁? services/ +鉁? 鉁? 鉁斺攒鉁? entities/ +鉁? 鉁? 鉁斺攒鉁? dto/ +鉁? 鉁? 鉁斺攒鉁? crm.module.ts +鉁? 鉁? +鉁? 鉁斺攒鉁? projects/ +鉁? 鉁? 鉁斺攒鉁? controllers/ +鉁? 鉁? 鉁? 鉁斺攒鉁? projects.controller.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? campaigns.controller.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? briefs.controller.ts +鉁? 鉁? 鉁斺攒鉁? services/ +鉁? 鉁? 鉁斺攒鉁? entities/ +鉁? 鉁? 鉁斺攒鉁? dto/ +鉁? 鉁? 鉁斺攒鉁? projects.module.ts +鉁? 鉁? +鉁? 鉁斺攒鉁? generation/ +鉁? 鉁? 鉁斺攒鉁? controllers/ +鉁? 鉁? 鉁? 鉁斺攒鉁? generation.controller.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? workflows.controller.ts +鉁? 鉁? 鉁斺攒鉁? services/ +鉁? 鉁? 鉁? 鉁斺攒鉁? generation.service.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? comfyui.service.ts +鉁? 鉁? 鉁? 鉁斺攒鉁? llm.service.ts +鉁? 鉁? 鉁斺攒鉁? processors/ +鉁? 鉁? 鉁? 鉁斺攒鉁? generation.processor.ts +鉁? 鉁? 鉁斺攒鉁? entities/ +鉁? 鉁? 鉁斺攒鉁? dto/ +鉁? 鉁? 鉁斺攒鉁? generation.module.ts +鉁? 鉁? +鉁? 鉁斺攒鉁? assets/ +鉁? 鉁? 鉁斺攒鉁? controllers/ +鉁? 鉁? 鉁斺攒鉁? services/ +鉁? 鉁? 鉁斺攒鉁? entities/ +鉁? 鉁? 鉁斺攒鉁? dto/ +鉁? 鉁? 鉁斺攒鉁? assets.module.ts +鉁? 鉁? +鉁? 鉁斺攒鉁? admin/ +鉁? 鉁斺攒鉁? controllers/ +鉁? 鉁斺攒鉁? services/ +鉁? 鉁斺攒鉁? admin.module.ts +鉁? +鉁斺攒鉁? shared/ +鉁? 鉁斺攒鉁? decorators/ +鉁? 鉁斺攒鉁? guards/ +鉁? 鉁? 鉁斺攒鉁? tenant.guard.ts +鉁? 鉁? 鉁斺攒鉁? roles.guard.ts +鉁? 鉁斺攒鉁? interceptors/ +鉁? 鉁? 鉁斺攒鉁? tenant-context.interceptor.ts +鉁? 鉁斺攒鉁? filters/ +鉁? 鉁斺攒鉁? pipes/ +鉁? 鉁斺攒鉁? utils/ +鉁? +鉁斺攒鉁? config/ +鉁? 鉁斺攒鉁? database.config.ts +鉁? 鉁斺攒鉁? redis.config.ts +鉁? 鉁斺攒鉁? storage.config.ts +鉁? 鉁斺攒鉁? comfyui.config.ts +鉁? +鉁斺攒鉁? app.module.ts +鉁斺攒鉁? main.ts +``` + +### 3.2 API Endpoints (Borrador) + +```yaml +Auth: + POST /api/v1/auth/login + POST /api/v1/auth/register + POST /api/v1/auth/refresh + POST /api/v1/auth/logout + GET /api/v1/auth/me + +CRM - Clients: + GET /api/v1/crm/clients + POST /api/v1/crm/clients + GET /api/v1/crm/clients/:id + PATCH /api/v1/crm/clients/:id + DELETE /api/v1/crm/clients/:id + +CRM - Brands: + GET /api/v1/crm/brands + POST /api/v1/crm/brands + GET /api/v1/crm/brands/:id + PATCH /api/v1/crm/brands/:id + GET /api/v1/crm/brands/:id/products + +CRM - Products: + GET /api/v1/crm/products + POST /api/v1/crm/products + GET /api/v1/crm/products/:id + PATCH /api/v1/crm/products/:id + +Projects: + GET /api/v1/projects + POST /api/v1/projects + GET /api/v1/projects/:id + PATCH /api/v1/projects/:id + GET /api/v1/projects/:id/campaigns + GET /api/v1/projects/:id/assets + +Campaigns: + GET /api/v1/campaigns + POST /api/v1/campaigns + GET /api/v1/campaigns/:id + PATCH /api/v1/campaigns/:id + POST /api/v1/campaigns/:id/generate + GET /api/v1/campaigns/:id/assets + +Generation: + POST /api/v1/generation/image + POST /api/v1/generation/copy + GET /api/v1/generation/jobs/:id + GET /api/v1/generation/workflows + POST /api/v1/generation/workflows/:id/execute + +Assets: + GET /api/v1/assets + GET /api/v1/assets/:id + PATCH /api/v1/assets/:id + DELETE /api/v1/assets/:id + POST /api/v1/assets/:id/approve + GET /api/v1/assets/:id/download + +Admin: + GET /api/v1/admin/users + POST /api/v1/admin/users + GET /api/v1/admin/tenants + GET /api/v1/admin/metrics +``` + +--- + +## 4. Modelo de Datos (Entidades Principales) + +### 4.1 Schema: auth + +```sql +-- Tabla: auth.users +CREATE TABLE auth.users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + email VARCHAR(255) NOT NULL, + password_hash VARCHAR(255) NOT NULL, + first_name VARCHAR(100), + last_name VARCHAR(100), + role VARCHAR(50) NOT NULL DEFAULT 'user', + status VARCHAR(20) NOT NULL DEFAULT 'active', + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE(tenant_id, email) +); + +-- Tabla: auth.sessions +CREATE TABLE auth.sessions ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES auth.users(id), + refresh_token VARCHAR(500) NOT NULL, + expires_at TIMESTAMPTZ NOT NULL, + ip_address VARCHAR(45), + user_agent TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +``` + +### 4.2 Schema: crm + +```sql +-- Tabla: crm.clients +CREATE TABLE crm.clients ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + name VARCHAR(255) NOT NULL, + industry VARCHAR(100), + status VARCHAR(20) NOT NULL DEFAULT 'active', + notes TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: crm.brands +CREATE TABLE crm.brands ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + client_id UUID NOT NULL REFERENCES crm.clients(id), + name VARCHAR(255) NOT NULL, + description TEXT, + tone_of_voice VARCHAR(100), + color_palette JSONB, + restrictions JSONB, + logo_url VARCHAR(500), + lora_model_id UUID, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: crm.products +CREATE TABLE crm.products ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + brand_id UUID NOT NULL REFERENCES crm.brands(id), + name VARCHAR(255) NOT NULL, + description TEXT, + category VARCHAR(100), + reference_images JSONB, + lora_model_id UUID, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: crm.contacts +CREATE TABLE crm.contacts ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + client_id UUID REFERENCES crm.clients(id), + first_name VARCHAR(100) NOT NULL, + last_name VARCHAR(100), + email VARCHAR(255), + phone VARCHAR(50), + position VARCHAR(100), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +``` + +### 4.3 Schema: projects + +```sql +-- Tabla: projects.projects +CREATE TABLE projects.projects ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + client_id UUID REFERENCES crm.clients(id), + name VARCHAR(255) NOT NULL, + description TEXT, + status VARCHAR(20) NOT NULL DEFAULT 'draft', + start_date DATE, + end_date DATE, + created_by UUID REFERENCES auth.users(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: projects.campaigns +CREATE TABLE projects.campaigns ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + project_id UUID NOT NULL REFERENCES projects.projects(id), + brand_id UUID REFERENCES crm.brands(id), + name VARCHAR(255) NOT NULL, + type VARCHAR(50) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'draft', + channels JSONB, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: projects.briefs +CREATE TABLE projects.briefs ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + campaign_id UUID NOT NULL REFERENCES projects.campaigns(id), + objective TEXT NOT NULL, + target_audience TEXT, + tone_of_voice VARCHAR(100), + key_messages JSONB, + restrictions JSONB, + reference_images JSONB, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +``` + +### 4.4 Schema: assets + +```sql +-- Tabla: assets.assets +CREATE TABLE assets.assets ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + campaign_id UUID REFERENCES projects.campaigns(id), + type VARCHAR(20) NOT NULL, + name VARCHAR(255), + status VARCHAR(20) NOT NULL DEFAULT 'draft', + file_url VARCHAR(500), + file_size INTEGER, + mime_type VARCHAR(100), + width INTEGER, + height INTEGER, + metadata JSONB, + version INTEGER NOT NULL DEFAULT 1, + parent_id UUID REFERENCES assets.assets(id), + created_by UUID REFERENCES auth.users(id), + approved_by UUID REFERENCES auth.users(id), + approved_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: assets.tags +CREATE TABLE assets.tags ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + name VARCHAR(100) NOT NULL, + UNIQUE(tenant_id, name) +); + +-- Tabla: assets.asset_tags +CREATE TABLE assets.asset_tags ( + asset_id UUID NOT NULL REFERENCES assets.assets(id), + tag_id UUID NOT NULL REFERENCES assets.tags(id), + PRIMARY KEY (asset_id, tag_id) +); +``` + +### 4.5 Schema: generation + +```sql +-- Tabla: generation.jobs +CREATE TABLE generation.jobs ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES config.tenants(id), + campaign_id UUID REFERENCES projects.campaigns(id), + workflow_id VARCHAR(100) NOT NULL, + type VARCHAR(20) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'pending', + priority INTEGER NOT NULL DEFAULT 0, + input_params JSONB NOT NULL, + result JSONB, + error_message TEXT, + started_at TIMESTAMPTZ, + completed_at TIMESTAMPTZ, + created_by UUID REFERENCES auth.users(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: generation.workflows +CREATE TABLE generation.workflows ( + id VARCHAR(100) PRIMARY KEY, + tenant_id UUID REFERENCES config.tenants(id), + name VARCHAR(255) NOT NULL, + description TEXT, + type VARCHAR(50) NOT NULL, + comfyui_workflow JSONB NOT NULL, + input_schema JSONB, + is_system BOOLEAN NOT NULL DEFAULT false, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Tabla: generation.models +CREATE TABLE generation.models ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID REFERENCES config.tenants(id), + name VARCHAR(255) NOT NULL, + type VARCHAR(50) NOT NULL, + file_path VARCHAR(500), + description TEXT, + training_images JSONB, + is_system BOOLEAN NOT NULL DEFAULT false, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +``` + +--- + +## 5. Flujo de Generaciθ΄Έn de Contenido + +### 5.1 Secuencia de Generaciθ΄Έn de Imagen + +``` +1. Usuario solicita generaciθ΄Έn + 鈻? + Frontend 鈫? POST /api/v1/generation/image + { + "campaign_id": "uuid", + "workflow_id": "product_photography", + "params": { + "prompt": "...", + "product_id": "uuid", + "style": "commercial" + } + } + +2. Backend crea Job + 鈻? + GenerationService.createJob() + 鈫? Valida permisos + 鈫? Crea registro en generation.jobs + 鈫? Encola job en Bull queue + +3. Worker procesa Job + 鈻? + GenerationProcessor.process() + 鈫? Obtiene workflow de ComfyUI + 鈫? Inyecta parθ°©metros (prompt, LoRA, etc.) + 鈫? Env铆a a ComfyUI API + 鈫? Espera resultado (webhook o polling) + +4. ComfyUI ejecuta workflow + 鈻? + 鈫? Carga modelo SDXL + 鈫? Aplica LoRAs (si hay) + 鈫? Ejecuta pipeline de difusiθ΄Έn + 鈫? Aplica upscaling + 鈫? Retorna imagen + +5. Worker procesa resultado + 鈻? + 鈫? Descarga imagen de ComfyUI + 鈫? Sube a S3/MinIO + 鈫? Crea registro en assets.assets + 鈫? Actualiza job como completado + 鈫? Emite evento (webhook a n8n) + +6. Frontend recibe notificaciθ΄Έn + 鈻? + WebSocket / Polling 鈫? Job completado + 鈫? Muestra imagen al usuario +``` + +### 5.2 Integraciθ΄Έn con ComfyUI + +```typescript +// services/comfyui.service.ts + +interface ComfyUIWorkflowParams { + prompt: string; + negativePrompt?: string; + width?: number; + height?: number; + steps?: number; + cfg?: number; + seed?: number; + loraModels?: string[]; + controlNet?: { + type: string; + image: string; + strength: number; + }; +} + +@Injectable() +export class ComfyUIService { + constructor( + private httpService: HttpService, + @Inject('COMFYUI_CONFIG') private config: ComfyUIConfig, + ) {} + + async executeWorkflow( + workflowId: string, + params: ComfyUIWorkflowParams, + ): Promise { + // 1. Cargar workflow template + const workflow = await this.getWorkflowTemplate(workflowId); + + // 2. Inyectar parθ°©metros + const modifiedWorkflow = this.injectParams(workflow, params); + + // 3. Enviar a ComfyUI + const response = await this.httpService.post( + `${this.config.baseUrl}/prompt`, + { prompt: modifiedWorkflow }, + ).toPromise(); + + return response.data.prompt_id; + } + + async getResult(promptId: string): Promise { + // Polling o webhook para obtener resultado + const history = await this.httpService.get( + `${this.config.baseUrl}/history/${promptId}`, + ).toPromise(); + + const outputNode = this.findOutputNode(history.data); + const imageUrl = `${this.config.baseUrl}/view?filename=${outputNode.filename}`; + + const imageResponse = await this.httpService.get(imageUrl, { + responseType: 'arraybuffer', + }).toPromise(); + + return Buffer.from(imageResponse.data); + } +} +``` + +--- + +## 6. Seguridad + +### 6.1 Autenticaciθ΄Έn + +```yaml +MθŒ…todo: JWT (JSON Web Tokens) + +Access Token: + - Expiraciθ΄Έn: 15 minutos + - Payload: userId, tenantId, role + - Almacenamiento: Memory (frontend) + +Refresh Token: + - Expiraciθ΄Έn: 7 d铆as + - Almacenamiento: HTTP-only cookie + - Rotaciθ΄Έn en cada uso +``` + +### 6.2 Autorizaciθ΄Έn (RBAC) + +```yaml +Roles: + super_admin: + - Acceso total a todos los tenants + - Configuraciθ΄Έn global + - Gestiθ΄Έn de modelos del sistema + + admin: + - Gestiθ΄Έn de usuarios del tenant + - Configuraciθ΄Έn del tenant + - Aprobaciθ΄Έn de workflows + + manager: + - CRUD completo de proyectos/campaεΈ½as + - Aprobaciθ΄Έn de assets + - Acceso a anal铆ticas + + creative: + - Crear proyectos y campaεΈ½as + - Generar contenido + - Editar assets propios + + viewer: + - Solo lectura + - Descargar assets aprobados +``` + +### 6.3 Multi-tenancy + +```sql +-- Pol铆tica RLS ejemplo +CREATE POLICY "crm_clients_tenant_isolation" ON crm.clients + FOR ALL + TO authenticated + USING (tenant_id::text = current_setting('app.current_tenant_id', true)) + WITH CHECK (tenant_id::text = current_setting('app.current_tenant_id', true)); +``` + +--- + +## 7. Despliegue + +### 7.1 Docker Compose (Desarrollo/Staging) + +```yaml +version: '3.8' + +services: + backend: + build: ./apps/backend + ports: + - "3000:3000" + environment: + - DATABASE_URL=postgresql://... + - REDIS_URL=redis://redis:6379 + - COMFYUI_URL=http://comfyui:8188 + - S3_ENDPOINT=http://minio:9000 + depends_on: + - postgres + - redis + - minio + + frontend: + build: ./apps/frontend + ports: + - "5173:80" + depends_on: + - backend + + postgres: + image: postgres:15-alpine + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + - POSTGRES_DB=pmc + - POSTGRES_USER=pmc + - POSTGRES_PASSWORD=${DB_PASSWORD} + + redis: + image: redis:7-alpine + volumes: + - redis_data:/data + + minio: + image: minio/minio + ports: + - "9000:9000" + - "9001:9001" + volumes: + - minio_data:/data + command: server /data --console-address ":9001" + + comfyui: + image: comfyui/comfyui:latest + ports: + - "8188:8188" + volumes: + - comfyui_models:/models + - comfyui_output:/output + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: [gpu] + + n8n: + image: n8nio/n8n + ports: + - "5678:5678" + volumes: + - n8n_data:/home/node/.n8n + +volumes: + postgres_data: + redis_data: + minio_data: + comfyui_models: + comfyui_output: + n8n_data: +``` + +### 7.2 Requisitos de Hardware (Producciθ΄Έn) + +```yaml +Backend + Frontend: + CPU: 4 cores + RAM: 8 GB + Storage: 50 GB SSD + +PostgreSQL: + CPU: 2 cores + RAM: 8 GB + Storage: 100 GB SSD + +ComfyUI (GPU Server): + CPU: 8 cores + RAM: 32 GB + GPU: NVIDIA RTX 4090 (24GB) o similar + Storage: 500 GB NVMe (modelos) + +Storage (S3/MinIO): + Storage: 1 TB+ (escalable) +``` + +--- + +## 8. Monitoreo y Observabilidad + +### 8.1 Logs + +```yaml +Backend: + - Winston con formato JSON estructurado + - Niveles: error, warn, info, debug + - Rotaciθ΄Έn diaria + +Agregaciθ΄Έn: + - ELK Stack (Elasticsearch, Logstash, Kibana) + - O alternativa: Loki + Grafana +``` + +### 8.2 MθŒ…tricas + +```yaml +Application Metrics: + - API response times (p50, p95, p99) + - Queue depths y processing times + - Generation success rate + - Error rates por tipo + +Business Metrics: + - Assets generados por d铆a + - Tiempo promedio de generaciθ΄Έn + - Assets aprobados vs rechazados + - Uso por tenant/usuario + +Infrastructure: + - CPU, RAM, disk usage + - GPU utilization + - Network I/O +``` + +### 8.3 Alertas + +```yaml +Cr铆ticas: + - API down > 1 min + - GPU unavailable + - Queue backlog > 100 jobs + - Error rate > 5% + +Advertencias: + - Response time p95 > 2s + - Disk usage > 80% + - Queue processing slow +``` + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/00-vision-general/GLOSARIO.md b/projects/platform_marketing_content/docs/00-vision-general/GLOSARIO.md new file mode 100644 index 0000000..57aab86 --- /dev/null +++ b/projects/platform_marketing_content/docs/00-vision-general/GLOSARIO.md @@ -0,0 +1,199 @@ +# Glosario - Platform Marketing Content + +**Versiθ΄Έn:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## TθŒ…rminos del Dominio + +### A + +**Asset** +: Recurso digital generado o almacenado en la plataforma (imagen, copy, video, etc.). + +**Avatar Virtual / Influencer Virtual** +: Personaje generado por IA que mantiene consistencia visual a travθŒ…s de mη…€ltiples imθ°©genes/videos. Ejemplo: Aitana Lθ΄Έpez. + +### B + +**Brief** +: Documento estructurado que define los parθ°©metros de una campaεΈ½a o generaciθ΄Έn: objetivo, pη…€blico, tono, canales, restricciones. + +### C + +**CampaεΈ½a** +: Iniciativa de marketing con objetivo espec铆fico que agrupa mη…€ltiples assets generados para diferentes canales. + +**Checkpoint** +: Versiθ΄Έn guardada de un modelo de IA entrenado. Puede ser especializado (fotograf铆a de producto, rostros, etc.). + +**ComfyUI** +: Interfaz de nodos para construir flujos de generaciθ΄Έn con Stable Diffusion y otros modelos. Permite encadenar procesos de forma visual. + +**ComfyDeploy** +: Herramienta que permite exponer workflows de ComfyUI como APIs HTTP para consumo desde aplicaciones. + +**Consistencia de Personaje** +: Capacidad de mantener los mismos rasgos faciales y caracter铆sticas visuales de un personaje a travθŒ…s de mη…€ltiples generaciones. + +**ControlNet** +: Adaptador para modelos de difusiθ΄Έn que permite controlar la generaciθ΄Έn mediante gu铆as visuales (poses, bordes, profundidad, segmentaciθ΄Έn). + +**Copy** +: Texto publicitario generado para acompaεΈ½ar imθ°©genes (t铆tulos, descripciones, hashtags, CTAs). + +**CRM (Customer Relationship Management)** +: Sistema de gestiθ΄Έn de relaciones con clientes. En esta plataforma, integrado con el motor de generaciθ΄Έn. + +### D + +**DAM (Digital Asset Management)** +: Sistema de gestiθ΄Έn de activos digitales. Repositorio centralizado para almacenar, organizar y buscar contenido generado. + +**Difusiθ΄Έn / Diffusion** +: TθŒ…cnica de IA generativa que crea imθ°©genes partiendo de ruido aleatorio y eliminando ruido gradualmente siguiendo indicaciones de texto. + +**DreamBooth** +: TθŒ…cnica de fine-tuning que permite personalizar un modelo con pocas imθ°©genes de un sujeto espec铆fico. + +### F + +**Fine-tuning** +: Proceso de re-entrenar un modelo pre-existente con datos espec铆ficos para especializarlo en un dominio o estilo particular. + +**Fotograf铆a SintθŒ…tica** +: Imθ°©genes generadas por IA que simulan fotograf铆as reales de productos, personas o escenas. + +### G + +**Generaciθ΄Έn de Contenido** +: Proceso de crear imθ°©genes, textos u otros medios mediante modelos de IA. + +### I + +**Image Prompt** +: Imagen de referencia utilizada como entrada adicional al texto para guiar la generaciθ΄Έn hacia un estilo o sujeto espec铆fico. + +**Inpainting** +: TθŒ…cnica de ediciθ΄Έn que permite regenerar solo una porciθ΄Έn seleccionada de una imagen manteniendo el resto intacto. + +**IP-Adapter** +: Adaptador que permite inyectar caracter铆sticas de una imagen de referencia en la generaciθ΄Έn, logrando consistencia visual. + +### L + +**LLM (Large Language Model)** +: Modelo de lenguaje de gran escala usado para generar texto (GPT-4, Claude, Llama, etc.). + +**LoRA (Low-Rank Adaptation)** +: TθŒ…cnica de fine-tuning eficiente que permite personalizar un modelo con pocos recursos. Crea archivos pequeεΈ½os que modifican el comportamiento del modelo base. + +### M + +**Multi-tenant** +: Arquitectura donde una sola instancia del software sirve a mη…€ltiples clientes (tenants) con datos aislados. + +### N + +**n8n** +: Plataforma de automatizaciθ΄Έn de workflows que conecta diferentes servicios y APIs mediante flujos visuales. + +### O + +**Orquestador** +: Sistema que coordina la ejecuciθ΄Έn de mη…€ltiples tareas o servicios en un flujo definido. + +### P + +**Plantilla / Template** +: Workflow predefinido de generaciθ΄Έn que puede ser reutilizado para crear contenido con parθ°©metros espec铆ficos. + +**Prompt** +: Texto de instrucciθ΄Έn que gu铆a al modelo de IA sobre quθŒ… generar. Puede incluir descripciθ΄Έn de la imagen, estilo, elementos a incluir/excluir. + +### R + +**RBAC (Role-Based Access Control)** +: Sistema de permisos basado en roles donde los usuarios heredan permisos segη…€n su rol asignado. + +**Rollout** +: Despliegue gradual de una funcionalidad a grupos de usuarios. + +### S + +**SaaS (Software as a Service)** +: Modelo de distribuciθ΄Έn de software donde la aplicaciθ΄Έn se aloja en la nube y se accede v铆a web bajo suscripciθ΄Έn. + +**SDXL (Stable Diffusion XL)** +: Versiθ΄Έn avanzada de Stable Diffusion con mayor resoluciθ΄Έn y mejor comprensiθ΄Έn de prompts. + +**Stable Diffusion** +: Modelo de difusiθ΄Έn de cθ΄Έdigo abierto para generaciθ΄Έn de imθ°©genes a partir de texto. + +### T + +**Tenant** +: Cliente/organizaciθ΄Έn en una arquitectura multi-tenant. Cada tenant tiene sus datos aislados. + +**Text-to-Image (T2I)** +: Proceso de generar imθ°©genes a partir de descripciones textuales. + +**Textual Inversion** +: TθŒ…cnica que permite enseεΈ½ar a un modelo un nuevo concepto asociado a una palabra clave espec铆fica. + +### U + +**Upscaling** +: Proceso de aumentar la resoluciθ΄Έn de una imagen utilizando tθŒ…cnicas de IA para mantener o mejorar la calidad. + +### V + +**VRAM (Video RAM)** +: Memoria dedicada de la tarjeta grθ°©fica. Los modelos de difusiθ΄Έn requieren 8-24GB VRAM para funcionar. + +### W + +**Workflow** +: Flujo de trabajo que define una secuencia de pasos para completar un proceso (ej: generaciθ΄Έn de imθ°©genes con postprocesado). + +--- + +## Acrθ΄Έnimos Comunes + +| Acrθ΄Έnimo | Significado | +|----------|-------------| +| **API** | Application Programming Interface | +| **CRM** | Customer Relationship Management | +| **DAM** | Digital Asset Management | +| **GPU** | Graphics Processing Unit | +| **JWT** | JSON Web Token | +| **LLM** | Large Language Model | +| **LoRA** | Low-Rank Adaptation | +| **MVP** | Minimum Viable Product | +| **NLP** | Natural Language Processing | +| **RBAC** | Role-Based Access Control | +| **RLS** | Row-Level Security | +| **SaaS** | Software as a Service | +| **SDXL** | Stable Diffusion XL | +| **T2I** | Text-to-Image | +| **VRAM** | Video Random Access Memory | + +--- + +## Modelos de IA Relevantes + +| Modelo | Tipo | Descripciθ΄Έn | +|--------|------|-------------| +| **Stable Diffusion XL** | Text-to-Image | Modelo base open-source de alta calidad | +| **Fooocus** | Frontend SDXL | Interfaz simplificada para SDXL | +| **Gemini 3 Pro Image** | Text-to-Image | Modelo de Google con texto perfecto en imθ°©genes | +| **Seedream 4.0** | Multimodal | Modelo de ByteDance con imagen, video y avatares | +| **DeepFloyd IF** | Text-to-Image | Especializado en renderizado de texto | +| **GPT-4** | LLM | Modelo de OpenAI para generaciθ΄Έn de texto | +| **Claude** | LLM | Modelo de Anthropic para generaciθ΄Έn de texto | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/00-vision-general/InvestigaciΓ³n Profunda_ Plataforma de GeneraciΓ³n de Contenido de Morfeo Academy y Desarrollo de una .pdf b/projects/platform_marketing_content/docs/00-vision-general/InvestigaciΓ³n Profunda_ Plataforma de GeneraciΓ³n de Contenido de Morfeo Academy y Desarrollo de una .pdf new file mode 100644 index 0000000..ad26fe8 Binary files /dev/null and b/projects/platform_marketing_content/docs/00-vision-general/InvestigaciΓ³n Profunda_ Plataforma de GeneraciΓ³n de Contenido de Morfeo Academy y Desarrollo de una .pdf differ diff --git a/projects/platform_marketing_content/docs/00-vision-general/MVP_Plataforma_SaaS_Contenido_CRM.md b/projects/platform_marketing_content/docs/00-vision-general/MVP_Plataforma_SaaS_Contenido_CRM.md new file mode 100644 index 0000000..1c2e7b6 --- /dev/null +++ b/projects/platform_marketing_content/docs/00-vision-general/MVP_Plataforma_SaaS_Contenido_CRM.md @@ -0,0 +1,327 @@ + +# MVP – Plataforma SaaS de GeneraciΓ³n de Contenido y CRM Creativo +*(Basada en la investigaciΓ³n de la plataforma tipo Morfeo Academy y tecnologΓ­as open source)* + +--- + +## 1. Objetivo General del MVP + +Construir una **plataforma SaaS interna** (modo β€œSaaS para uso propio”) para una **agencia de publicidad y generaciΓ³n de contenido**, que permita: + +- Generar contenido visual y textual (imΓ‘genes, piezas publicitarias, posts para redes, etc.) con IA. +- Gestionar campaΓ±as, clientes y oportunidades desde un **CRM integrado**. +- Automatizar flujos creativos y procesos operativos (desde brief β†’ contenido β†’ aprobaciΓ³n β†’ publicaciΓ³n/entrega). +- Operar bajo un **admin con uso ilimitado** + roles internos, con base tΓ©cnica preparada para futura multi-empresa/multi-tenant. + +La prioridad del MVP es usar **modelos open source auto-hosteados** y, cuando sea estrictamente necesario, **APIs de terceros** para capacidades avanzadas (texto perfecto en imΓ‘genes, video/avatares, etc.). + +--- + +## 2. Alcance del MVP + +### 2.1 Incluido + +- NΓΊcleo de generaciΓ³n de **imΓ‘genes** + **copys** para marketing. +- GestiΓ³n bΓ‘sica de **clientes, marcas, productos y campaΓ±as**. +- MΓ³dulo para **workflows creativos predefinidos** (plantillas de generaciΓ³n). +- **AutomatizaciΓ³n bΓ‘sica**: triggers desde CRM hacia el motor de generaciΓ³n. +- **GestiΓ³n de usuarios internos** (equipo de la agencia) con permisos por rol. +- Panel de **administraciΓ³n SaaS** para el sΓΊper admin (configuraciΓ³n global, lΓ­mites, monitoreo). + +### 2.2 Fuera de alcance inmediato (para fases posteriores) + +- GeneraciΓ³n de video avanzada (SORA, Seedream, etc.) como core. +- Entrenamiento auto-servicio 100% self-service de LoRAs por parte del cliente final (en MVP serΓ‘ gestionado por el equipo tΓ©cnico). +- Integraciones profundas con mΓΊltiples CRMs externos (inicialmente solo 1 CRM interno y 1 integraciΓ³n externa simple). +- Marketplace pΓΊblico multi-tenant con planes comerciales complejos. + +--- + +## 3. Perfiles de Usuario + +1. **SΓΊper Admin SaaS (DueΓ±o/CTO)** + - Acceso ilimitado a todos los mΓ³dulos y recursos (sin restricciones de uso). + - Configura parΓ‘metros globales de infraestructura, colas de tareas y modelos. + - Gestiona planes/limitaciones (aunque en MVP sΓ³lo se usa el plan interno β€œilimitado”). + +2. **Admin de Agencia** + - Configura clientes, marcas, equipos y usuarios internos. + - Define plantillas y workflows creativos estΓ‘ndar. + - Aprueba solicitudes de entrenamiento de modelos personalizados (LoRAs, estilos). + +3. **Creativo/Media Buyer** + - Crea proyectos y campaΓ±as. + - Lanza generaciones de contenido (imΓ‘genes y copys) usando plantillas. + - Solicita entrenamiento de modelos personalizados (avatar de marca, producto, estilo). + - InteractΓΊa con el sistema para iterar versiones. + +4. **Analista/CRM** + - Administra leads, contactos, oportunidades y campaΓ±as en CRM. + - Dispara automatizaciones (por ejemplo, al crear un nuevo producto). + - Consulta mΓ©tricas de campaΓ±as y uso de contenido. + +5. **Cliente (externo) – Modo opcional MVP** + - Acceso restringido (portal ligero): revisar piezas generadas, aprobar/rechazar, descargar assets. + - No lanza generaciones directamente en MVP (esto puede aΓ±adirse en una fase posterior). + +--- + +## 4. MΓ³dulos Funcionales del MVP + +### 4.1 MΓ³dulo de GestiΓ³n de Cuentas y Tenants + +> Aunque el uso principal es interno, la arquitectura debe soportar **multi-tenant** futuro. + +- **Tenant β€œAgencia Propia”** como tenant principal. +- Estructuras para futuros tenants (clientes/agencias externas) aunque en MVP solo haya uno. +- ConfiguraciΓ³n por tenant: + - Nombre, branding (logo, colores base). + - LΓ­mites de uso (imΓ‘genes mensuales, entrenamientos, etc.) – aunque el tenant interno tenga lΓ­mites desactivados. + - Conexiones a CRM interno y/o externo. + +### 4.2 MΓ³dulo CRM Integrado + +- **Entidades bΓ‘sicas**: + - Contactos (personas). + - Empresas / Clientes. + - Productos / Servicios. + - Oportunidades / Deals. + - CampaΓ±as de marketing. + +- **Funcionalidades**: + - Alta/ediciΓ³n de clientes y contactos. + - Registro de oportunidades asociadas a campaΓ±as. + - SegmentaciΓ³n bΓ‘sica de leads (por industria, tamaΓ±o, estado, etc.). + - Historial de interacciones (notas, actividades, tareas). + - Campos clave para conectar con generaciΓ³n de contenido (ej. tipo de producto, fotos de referencia, identidad de marca, tono de comunicaciΓ³n). + +- **IntegraciΓ³n**: + - API interna para conectarse con el motor de generaciΓ³n (ej. β€œnuevo producto β†’ generar pack de 5 imΓ‘genes de catΓ‘logo y 3 posts de redes”). + - IntegraciΓ³n mΓ­nima con 1 CRM externo (ej. webhooks/REST) para sincronizar datos bΓ‘sicos (opcional en MVP). + +### 4.3 MΓ³dulo de Proyectos y CampaΓ±as + +- **Proyectos**: + - Agrupan campaΓ±as y assets por cliente o iniciativa interna. + - Estados: Borrador, En curso, En revisiΓ³n, Cerrado. + +- **CampaΓ±as**: + - Tipos: redes sociales, performance ads, catΓ‘logos, landing pages, etc. + - Brief estructurado: + - Objetivo de la campaΓ±a. + - PΓΊblico objetivo. + - Tono de voz. + - Canales (IG, FB, TikTok, Google Ads, etc.). + - Restricciones (palabras prohibidas, colores de marca, etc.). + +- **Flujos del MVP**: + - Crear campaΓ±a β†’ seleccionar plantillas de generaciΓ³n (ej. pack de 10 imΓ‘genes + 10 copys). + - Disparar generaciΓ³n β†’ monitorizar estado β†’ revisiΓ³n interna β†’ aprobaciΓ³n/entrega. + +### 4.4 MΓ³dulo de Motor de GeneraciΓ³n de Contenido (IA) + +#### 4.4.1 NΓΊcleo de Modelos y Runtime + +- **Modelos locales (open source, auto-hosteados)**: + - Modelo principal **text-to-image** tipo **Stable Diffusion XL** o similar, optimizado para marketing. + - Checkpoints especializados: + - FotografΓ­a de producto (e-commerce, fondo blanco/contextos comerciales). + - Rostros humanos realistas / lifestyle. + - Estilos ilustrados (diseΓ±o publicitario, vintage, cartoon, etc.). + - **ControlNets / Adaptadores**: + - Pose humana (OpenPose) para controlar poses de modelos/influencers. + - SegmentaciΓ³n (fondo/primer plano). + - Otros de utilidad (canny, depth) para composiciΓ³n y ajustes. + - Modelos de **upscaling** para entregar imΓ‘genes en alta resoluciΓ³n (2x–4x). + - Modelos de **inpainting** para correcciones localizadas (ej. arreglar manos, insertar elementos). + +- **Modelos de texto (NLP)**: + - IntegraciΓ³n con **modelo de lenguaje** (open source o API external) para: + - Generar copys, tΓ­tulos, descripciones, hashtags. + - Ajustar tono segΓΊn el brief. + - El MVP puede usar un modelo de OpenAI vΓ­a API para texto, dado su bajo costo relativo. + +#### 4.4.2 Workflows de GeneraciΓ³n (ComfyUI / Orquestador) + +- Uso de **ComfyUI** como base de construcciΓ³n de flujos de generaciΓ³n y automatizaciΓ³n creativa. +- DiseΓ±o de varios workflows estΓ‘ndar: + 1. **FotografΓ­a sintΓ©tica de producto** + - Entrada: fotos de referencia (opcional), descripciΓ³n de producto, estilo o contexto. + - Salida: pack de imΓ‘genes listas para catΓ‘logo y redes. + 2. **Post de redes sociales (imagen + copy)** + - Entrada: brief corto, producto/servicio, canal objetivo. + - Salida: 1–N imΓ‘genes + textos sugeridos. + 3. **Influencer virtual / avatar de marca** (ver mΓ‘s abajo). + 4. **Variaciones de anuncio** + - GeneraciΓ³n de mΓΊltiples variantes (colores, encuadres, fondos) para pruebas A/B. + +- ExposiciΓ³n de estos workflows como **APIs internas** (ComfyDeploy u otro mecanismo) para que el backend los consuma. + +#### 4.4.3 PersonalizaciΓ³n de Identidad Visual y Avatares + +- **LoRAs / Fine-tuning**: + - Entrenamiento dirigido por el equipo tΓ©cnico de: + - Estilos de marca. + - Productos especΓ­ficos (lΓ­neas completas de producto). + - Avatares e influencers virtuales (rostros/personajes consistentes). + - Interfaz para: + - Registrar un β€œModelo personalizado” (LoRA/Checkpoint). + - Asignarlo a una marca/cliente. + - Seleccionarlo en plantillas de generaciΓ³n. + +- **Consistencia de personajes**: + - Uso de image prompts, IP-Adapters y nodos tipo Consistent Characters para mantener la misma apariencia a travΓ©s de mΓΊltiples piezas. + - Flujos de β€œreciclaje de referencia”: la ΓΊltima imagen aprobada de un avatar se reutiliza como referencia para nuevas generaciones. + +#### 4.4.4 GeneraciΓ³n con Texto Integrado en la Imagen + +- **Modo base (open source)**: + - Mejor esfuerzo con SDXL + tΓ©cnicas complementarias (inpainting, ControlNet, postprocesado). + - Alternativa hΓ­brida: generar imagen base y superponer texto con capa vectorial (HTML/CSS/Canvas) desde el front. + +- **Modo premium vΓ­a API (opcional)**: + - IntegraciΓ³n con algΓΊn modelo propietario tipo **Gemini 3 Pro Image (Nano Banana Pro)** u otro similar para casos en que se requiera texto perfectamente legible integrado (posters densos, infografΓ­as). + - Expuesto al usuario como opciΓ³n β€œCalidad premium de texto”. + +#### 4.4.5 Contenido Animado y Video (MVP reducido) + +- MVP: + - CreaciΓ³n de **GIFs/cinemagraphs** a partir de secuencias de imΓ‘genes generadas. + - Pipeline bΓ‘sico de β€œfotogramas clave + interpolaciΓ³n” (usando herramientas IA cuando sea viable). + +- Futuro (fuera del MVP, pero preparado en arquitectura): + - IntegraciΓ³n con APIs de texto-a-video (Runway, Seedream, SORA, etc.). + - IntegraciΓ³n con servicios de avatares parlantes (HeyGen u otros). + +--- + +### 4.5 MΓ³dulo de AutomatizaciΓ³n Creativa y Flujos (OrquestaciΓ³n) + +- IntegraciΓ³n con un orquestador tipo **n8n** o similar para automatizar tareas entre: + - CRM interno. + - Motor de generaciΓ³n de contenido. + - Sistemas externos (por ejemplo, herramientas de email marketing, redes sociales). + +- Flujos MVP: + 1. **Nuevo producto en CRM β†’ Generar Kit de Assets** + - Dispara workflow de fotografΓ­a de producto + posts base. + 2. **Nueva campaΓ±a β†’ Generar lote de creatividades** + - Crea assets iniciales para revisiΓ³n interna. + 3. **Cambio de estado de campaΓ±a (Aprobada) β†’ NotificaciΓ³n/Entrega** + - Notifica a responsables; genera zip descargable o publica en espacio compartido. + +- Sistema de **colas de tareas**: + - DistribuciΓ³n de trabajos en GPU(s). + - Manejo de prioridades (trabajos urgentes vs batch). + +--- + +### 4.6 MΓ³dulo de Biblioteca de Activos (DAM) + +- Repositorio central de: + - ImΓ‘genes generadas. + - Copys, prompts y briefs. + - Modelos personalizados (LoRAs, checkpoints, presets de workflows). + +- Funciones: + - BΓΊsqueda avanzada (por cliente, campaΓ±a, tags, tipo de contenido, fecha). + - Versionado de assets (iteraciones sobre una misma pieza). + - Estados: borrador, en revisiΓ³n, aprobado, publicado. + - Descarga individual o en paquetes. + +--- + +### 4.7 MΓ³dulo de AdministraciΓ³n SaaS y ConfiguraciΓ³n + +- GestiΓ³n de: + - Usuarios, roles y permisos. + - Tenants (al menos el tenant β€œAgencia Propia” en el MVP). + - ParΓ‘metros globales: + - LΓ­mites de tamaΓ±o/formatos de salida. + - Modelos activos/inactivos. + - PolΓ­tica de retenciΓ³n de assets. + +- AuditorΓ­a bΓ‘sica: + - Log de acciones relevantes (generaciones, entrenamientos, cambios de configuraciΓ³n). + - MΓ©tricas de uso por usuario y campaΓ±a (nΓΊmero de imΓ‘genes generadas, GPU time estimado, etc.). + +- PreparaciΓ³n para **planes de suscripciΓ³n** (aunque en MVP no se comercializa externamente): + - Estructura para planes (Free, Pro, Enterprise, Interno Ilimitado). + - ParΓ‘metros por plan: generaciones/mes, entrenamientos, acceso a modo premium de texto, etc. + +--- + +### 4.8 MΓ³dulo de AnalΓ­tica y Reporting + +- **Dashboards bΓ‘sicos**: + - Volumen de contenido generado por periodo, cliente, campaΓ±a. + - Tiempo promedio de generaciΓ³n y aprobaciΓ³n. + - Uso de modelos personalizados (cuΓ‘ntas campaΓ±as usan cada LoRA/estilo). + - RelaciΓ³n entre campaΓ±as y assets generados (para anΓ‘lisis posterior de performance). + +- **KPI iniciales**: + - NΒΊ de campaΓ±as activas. + - NΒΊ de assets por campaΓ±a. + - Porcentaje de assets aprobados en primera iteraciΓ³n. + +- ExportaciΓ³n: + - Descarga de reportes en CSV/Excel. + - API para integraciΓ³n con herramientas de BI. + +--- + +### 4.9 MΓ³dulo de Seguridad, Permisos y Cumplimiento + +- **AutenticaciΓ³n y autorizaciΓ³n**: + - Login con email + password (mΓ‘s adelante SSO/OAuth). + - Roles y permisos por mΓ³dulo/acciΓ³n (RBAC). + +- **Aislamiento lΓ³gico por tenant** pese a que inicialmente sΓ³lo se use uno. +- **GestiΓ³n de datos sensibles**: + - Cifrado en trΓ‘nsito (HTTPS). + - Buenas prΓ‘cticas de manejo de imΓ‘genes de personas (consentimiento, uso de datos, etc.). + +--- + +## 5. Requisitos TΓ©cnicos de Alto Nivel + +### 5.1 Infraestructura + +- Servidor con **GPU dedicada** (idealmente 12–24 GB VRAM) para ejecutar los modelos de imagen (SDXL, LoRAs, ControlNets, upscaling). +- Arquitectura con: + - **Backend monolΓ­tico** (API REST/GraphQL) para lΓ³gica de negocio, colas y orquestaciΓ³n. + - **Servicio(s) de inferencia** (ComfyUI/Deploy, pipelines Diffusers, etc.) comunicados vΓ­a HTTP/ gRPC. + - **Base de datos** relacional para CRM, proyectos, campaΓ±as, usuarios, configuraciΓ³n. + - Almacenamiento de archivos (local o S3-compatible) para assets e imΓ‘genes generadas. + +- Sistema de **colado y scheduling de tareas**: + - GestiΓ³n eficiente de jobs de generaciΓ³n y entrenamiento. + - Posibilidad de aΓ±adir mΓ‘s GPUs/instancias a futuro. + +### 5.2 Integraciones Clave + +- Orquestador (n8n u otro) para flujos entre mΓ³dulos. +- APIs externas **opcionales**: + - Modelos de texto avanzados (LLMs). + - Modelos de imΓ‘genes con texto perfecto (Gemini/Seedream u otros) – sΓ³lo para casos premium. + - Servicios de video/avatares (etapa futura). + +--- + +## 6. Roadmap de EvoluciΓ³n (en alto nivel) + +> No forma parte estricta del MVP, pero orienta el desglose posterior. + +1. **Fase 1 – Core MVP** + - MΓ³dulos: usuarios/roles, CRM bΓ‘sico, proyectos y campaΓ±as, motor de generaciΓ³n de imΓ‘genes + copys, DAM bΓ‘sico. + - Workflows estΓ‘ndar de generaciΓ³n de producto y posts. + +2. **Fase 2 – PersonalizaciΓ³n Avanzada** + - Entrenamiento recurrente de LoRAs/estilos. + - Avatares/influencers virtuales consistentes. + - IntegraciΓ³n mΓ‘s profunda con CRM e orquestador. + +3. **Fase 3 – Contenido Enriquecido y Multi-tenant Comercial** + - Video, avatares parlantes, modos premium con APIs externas. + - Apertura a clientes externos (modo SaaS completo). + - Planes de suscripciΓ³n y lΓ­mites de uso. diff --git a/projects/platform_marketing_content/docs/00-vision-general/VISION-GENERAL.md b/projects/platform_marketing_content/docs/00-vision-general/VISION-GENERAL.md new file mode 100644 index 0000000..33ce7df --- /dev/null +++ b/projects/platform_marketing_content/docs/00-vision-general/VISION-GENERAL.md @@ -0,0 +1,466 @@ +# Platform Marketing Content - Plataforma SaaS de Generaciθ΄Έn de Contenido y CRM Creativo + +**Versiθ΄Έn:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** Fase de Anθ°©lisis y Documentaciθ΄Έn +**Modelo de Negocio:** SaaS Multi-tenant (uso interno inicial) + +--- + +## 1. Resumen Ejecutivo + +### 1.1 Visiθ΄Έn del Producto + +**Platform Marketing Content** es una plataforma SaaS interna para **agencias de publicidad y generaciθ΄Έn de contenido** que combina: + +1. **Motor de Generaciθ΄Έn de Contenido con IA** - Imθ°©genes, copys, posts para redes sociales +2. **CRM Integrado** - Gestiθ΄Έn de clientes, marcas, campaεΈ½as y oportunidades +3. **Automatizaciθ΄Έn Creativa** - Flujos desde brief 鈫? contenido 鈫? aprobaciθ΄Έn 鈫? entrega +4. **DAM (Digital Asset Management)** - Biblioteca centralizada de activos generados + +### 1.2 Propuesta de Valor + +| Problema Actual | Soluciθ΄Έn Propuesta | +|-----------------|-------------------| +| Creaciθ΄Έn manual de contenido visual costosa y lenta | Generaciθ΄Έn automθ°©tica con IA (Stable Diffusion, ComfyUI) | +| Dependencia de fotθ΄Έgrafos y sets f铆sicos | Fotograf铆a sintθŒ…tica de productos hiperrealista | +| Inconsistencia de marca entre campaεΈ½as | LoRAs entrenados por marca/producto | +| Gestiθ΄Έn fragmentada de clientes y campaεΈ½as | CRM integrado con motor de generaciθ΄Έn | +| Costos elevados por APIs comerciales (Midjourney, DALL-E) | Modelos open-source auto-hosteados | +| Flujos manuales de aprobaciθ΄Έn | Automatizaciθ΄Έn con n8n + workflows predefinidos | + +### 1.3 Diferenciadores Clave + +``` +鉁? Modelos Open Source + Auto-hosting = Costos controlados +鉁? LoRAs personalizados por marca = Consistencia visual +鉁? CRM + Generaciθ΄Έn integrados = Flujo end-to-end +鉁? ComfyUI como orquestador = Workflows visuales y escalables +鉁? Arquitectura preparada para multi-tenant = Escalabilidad futura +``` + +--- + +## 2. Objetivos del MVP + +### 2.1 Objetivos de Negocio + +| Objetivo | MθŒ…trica de θ„‘xito | Plazo | +|----------|------------------|-------| +| Reducir tiempo de creaciθ΄Έn de contenido | -70% tiempo vs proceso manual | MVP | +| Eliminar dependencia de servicios externos | 100% generaciθ΄Έn local | MVP | +| Centralizar gestiθ΄Έn de clientes y campaεΈ½as | 1 plataforma unificada | MVP | +| Habilitar personalizaciθ΄Έn por marca | LoRAs entrenados por cliente | Fase 2 | + +### 2.2 Objetivos TθŒ…cnicos + +| Objetivo | Descripciθ΄Έn | +|----------|-------------| +| **Auto-hosting** | Ejecutar modelos en GPU dedicada (12-24GB VRAM) | +| **Arquitectura modular** | Separaciθ΄Έn clara: CRM, Motor IA, DAM, Automatizaciθ΄Έn | +| **Multi-tenant ready** | Estructura preparada para mη…€ltiples tenants | +| **API-first** | Todos los servicios expuestos v铆a REST/GraphQL | +| **Escalabilidad** | Colas de tareas, distribuciθ΄Έn en GPUs | + +--- + +## 3. Alcance del MVP + +### 3.1 Incluido en MVP (Fase 1) + +| Mθ΄Έdulo | Funcionalidades Core | +|--------|---------------------| +| **CRM Integrado** | Clientes, marcas, productos, campaεΈ½as, oportunidades | +| **Motor de Generaciθ΄Έn** | Text-to-image (SDXL), copys con LLM, upscaling | +| **Workflows Creativos** | Fotograf铆a de producto, posts para redes, variaciones | +| **DAM Bθ°©sico** | Repositorio de imθ°©genes, bη…€squeda, estados (borrador/aprobado) | +| **Automatizaciθ΄Έn Bθ°©sica** | Triggers CRM 鈫? Generaciθ΄Έn | +| **Admin SaaS** | Usuarios, roles, configuraciθ΄Έn global | + +### 3.2 Fuera de Alcance MVP (Fases Posteriores) + +| Feature | Fase Planificada | +|---------|------------------| +| Generaciθ΄Έn de video avanzada (SORA, Seedream) | Fase 3 | +| Entrenamiento self-service de LoRAs | Fase 2 | +| Marketplace multi-tenant pη…€blico | Fase 4 | +| Integraciones profundas con CRMs externos | Fase 2 | +| Avatares parlantes (HeyGen, etc.) | Fase 3 | +| Texto perfecto en imθ°©genes (Gemini API) | Fase 2 (opcional) | + +--- + +## 4. Perfiles de Usuario + +### 4.1 Usuarios Internos (MVP) + +| Perfil | Descripciθ΄Έn | Permisos Principales | +|--------|-------------|---------------------| +| **Sη…€per Admin SaaS** | DueεΈ½o/CTO de la plataforma | Acceso ilimitado, configuraciθ΄Έn global, modelos | +| **Admin de Agencia** | Configura clientes, equipos, plantillas | Gestiθ΄Έn de usuarios, workflows, aprobaciones | +| **Creativo/Media Buyer** | Lanza generaciones, itera versiones | Crear proyectos, generar contenido, solicitar LoRAs | +| **Analista/CRM** | Gestiona leads, campaεΈ½as, mθŒ…tricas | CRM completo, triggers de automatizaciθ΄Έn | + +### 4.2 Usuarios Externos (Opcional MVP) + +| Perfil | Descripciθ΄Έn | Permisos | +|--------|-------------|----------| +| **Cliente (portal ligero)** | Revisa piezas, aprueba/rechaza | Solo lectura + aprobaciθ΄Έn | + +--- + +## 5. Mθ΄Έdulos Funcionales + +### 5.1 Mθ΄Έdulo 1: Gestiθ΄Έn de Cuentas y Tenants (PMC-001) + +**Objetivo:** Arquitectura multi-tenant preparada para escalar. + +```yaml +Funcionalidades: + - Tenant principal "Agencia Propia" + - Estructura para futuros tenants externos + - Configuraciθ΄Έn por tenant: branding, l铆mites, conexiones + - L铆mites de uso (imθ°©genes/mes, entrenamientos) +``` + +### 5.2 Mθ΄Έdulo 2: CRM Integrado (PMC-002) + +**Objetivo:** Gestionar clientes, marcas y campaεΈ½as con conexiθ΄Έn directa al motor de generaciθ΄Έn. + +```yaml +Entidades: + - Contactos (personas) + - Empresas/Clientes + - Marcas (brand identity, tono, restricciones) + - Productos/Servicios + - Oportunidades/Deals + - CampaεΈ½as de Marketing + +Funcionalidades: + - Alta/ediciθ΄Έn de clientes y contactos + - Segmentaciθ΄Έn de leads + - Historial de interacciones + - Campos para generaciθ΄Έn: fotos referencia, identidad marca, tono + - API interna 鈫? motor de generaciθ΄Έn +``` + +### 5.3 Mθ΄Έdulo 3: Proyectos y CampaεΈ½as (PMC-003) + +**Objetivo:** Organizar el trabajo creativo por iniciativa. + +```yaml +Proyectos: + - Agrupan campaεΈ½as y assets por cliente + - Estados: Borrador, En curso, En revisiθ΄Έn, Cerrado + +CampaεΈ½as: + - Tipos: redes sociales, performance ads, catθ°©logos, landing pages + - Brief estructurado: + - Objetivo de campaεΈ½a + - Pη…€blico objetivo + - Tono de voz + - Canales (IG, FB, TikTok, Google Ads) + - Restricciones (palabras prohibidas, colores marca) + +Flujos: + - Crear campaεΈ½a 鈫? seleccionar plantillas 鈫? disparar generaciθ΄Έn 鈫? revisiθ΄Έn 鈫? entrega +``` + +### 5.4 Mθ΄Έdulo 4: Motor de Generaciθ΄Έn de Contenido IA (PMC-004) + +**Objetivo:** Nη…€cleo de generaciθ΄Έn de imθ°©genes y copys. + +```yaml +4.1 Modelos Locales (Open Source): + Imagen: + - Stable Diffusion XL (principal) + - Checkpoints especializados: + - Fotograf铆a de producto (e-commerce) + - Rostros humanos realistas + - Estilos ilustrados (publicidad, vintage) + - ControlNets: OpenPose, segmentaciθ΄Έn, canny, depth + - Upscaling: 2x-4x + - Inpainting: correcciones localizadas + + Texto (NLP): + - LLM para copys, t铆tulos, hashtags + - Ajuste de tono segη…€n brief + - OpenAI API (bajo costo) o modelo local + +4.2 Workflows ComfyUI: + Predefinidos: + - Fotograf铆a sintθŒ…tica de producto + - Post redes sociales (imagen + copy) + - Variaciones de anuncio (A/B testing) + - Influencer virtual / avatar de marca + + Caracter铆sticas: + - Exposiciθ΄Έn como APIs internas (ComfyDeploy) + - Workflows personalizables por usuario + +4.3 Personalizaciθ΄Έn (LoRAs): + - Entrenamiento dirigido por equipo tθŒ…cnico: + - Estilos de marca + - Productos espec铆ficos + - Avatares/influencers virtuales + - Interfaz para registrar y asignar modelos personalizados + - Consistencia de personajes (IP-Adapters, Consistent Characters) + +4.4 Texto en Imθ°©genes: + Modo base: + - SDXL + tθŒ…cnicas complementarias + - Superposiciθ΄Έn vectorial (HTML/CSS/Canvas) + Modo premium (opcional): + - API Gemini 3 Pro Image para tipograf铆a perfecta +``` + +### 5.5 Mθ΄Έdulo 5: Automatizaciθ΄Έn Creativa (PMC-005) + +**Objetivo:** Conectar CRM con motor de generaciθ΄Έn mediante flujos automatizados. + +```yaml +Orquestador: n8n (o similar) + +Flujos MVP: + 1. Nuevo producto en CRM 鈫? Generar Kit de Assets + - Dispara workflow de fotograf铆a + posts base + + 2. Nueva campaεΈ½a 鈫? Generar lote de creatividades + - Crea assets iniciales para revisiθ΄Έn + + 3. Cambio estado campaεΈ½a (Aprobada) 鈫? Notificaciθ΄Έn/Entrega + - Notifica responsables + - Genera zip descargable + +Sistema de Colas: + - Distribuciθ΄Έn de jobs en GPU(s) + - Manejo de prioridades (urgente vs batch) +``` + +### 5.6 Mθ΄Έdulo 6: Biblioteca de Activos DAM (PMC-006) + +**Objetivo:** Repositorio central de contenido generado. + +```yaml +Contenido: + - Imθ°©genes generadas + - Copys, prompts, briefs + - Modelos personalizados (LoRAs, checkpoints, presets) + +Funciones: + - Bη…€squeda avanzada (cliente, campaεΈ½a, tags, tipo, fecha) + - Versionado de assets + - Estados: borrador, en revisiθ΄Έn, aprobado, publicado + - Descarga individual o en paquetes +``` + +### 5.7 Mθ΄Έdulo 7: Administraciθ΄Έn SaaS (PMC-007) + +**Objetivo:** Panel de control de la plataforma. + +```yaml +Gestiθ΄Έn: + - Usuarios, roles, permisos (RBAC) + - Tenants (al menos "Agencia Propia" en MVP) + - Parθ°©metros globales: + - L铆mites de tamaεΈ½o/formatos + - Modelos activos/inactivos + - Pol铆tica de retenciθ΄Έn de assets + +Auditor铆a: + - Log de acciones (generaciones, entrenamientos, cambios) + - MθŒ…tricas de uso por usuario y campaεΈ½a + +Preparaciθ΄Έn para planes: + - Estructura: Free, Pro, Enterprise, Interno Ilimitado + - Parθ°©metros por plan: generaciones/mes, entrenamientos, etc. +``` + +### 5.8 Mθ΄Έdulo 8: Anal铆tica y Reporting (PMC-008) + +**Objetivo:** Visibilidad del rendimiento y uso. + +```yaml +Dashboards: + - Volumen generado por periodo/cliente/campaεΈ½a + - Tiempo promedio de generaciθ΄Έn y aprobaciθ΄Έn + - Uso de modelos personalizados + - Relaciθ΄Έn campaεΈ½as-assets + +KPIs Iniciales: + - Nη…€mero de campaεΈ½as activas + - Assets por campaεΈ½a + - % assets aprobados en primera iteraciθ΄Έn + +Exportaciθ΄Έn: + - CSV/Excel + - API para herramientas BI +``` + +--- + +## 6. Requisitos TθŒ…cnicos + +### 6.1 Stack Tecnolθ΄Έgico + +```yaml +Backend: + - Node.js 20+ / NestJS + TypeScript + - PostgreSQL 15+ (multi-tenant ready) + - Redis (caching, colas) + - Bull/BullMQ (jobs de generaciθ΄Έn) + +Frontend: + - React 18 + Vite + TypeScript + - TailwindCSS / Shadcn UI + - React Query (data fetching) + +Motor IA: + - ComfyUI (orquestaciθ΄Έn de workflows) + - ComfyDeploy (API de inferencia) + - Stable Diffusion XL + checkpoints + - Python 3.10+ / Diffusers (alternativa) + +Automatizaciθ΄Έn: + - n8n (flujos entre mθ΄Έdulos) + +Almacenamiento: + - S3 / MinIO (assets e imθ°©genes) + - PostgreSQL (metadata, CRM) + +Infraestructura: + - Docker / Docker Compose + - GPU: NVIDIA 12-24GB VRAM (L4, RTX 3090/4090, A5000) +``` + +### 6.2 Arquitectura de Alto Nivel + +``` +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? Frontend (React + Vite) 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? + 鈻? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? Backend API (NestJS) 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁? 鉁? CRM 鉁? 鉁? Projects鉁? 鉁? Assets 鉁? 鉁? +鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? 鉁? 鉁? + 鈻? 鈻? 鈻? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +鉁? PostgreSQL 鉁? 鉁? ComfyUI 鉁? 鉁? n8n 鉁? +鉁? + Redis 鉁? 鉁? (GPU GPU) 鉁? 鉁? (Workflows) 鉁? +鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? + 鈻? + 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? + 鉁? S3/MinIO 鉁? + 鉁? (Assets) 鉁? + 鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁斺攒鉁? +``` + +### 6.3 Integraciones Clave + +| Integraciθ΄Έn | Prioridad | Descripciθ΄Έn | +|-------------|-----------|-------------| +| ComfyUI / ComfyDeploy | Alta | Motor de workflows de generaciθ΄Έn | +| n8n | Alta | Orquestaciθ΄Έn de automatizaciones | +| OpenAI API | Media | LLM para generaciθ΄Έn de copys | +| Gemini API | Baja | Texto perfecto en imθ°©genes (opcional) | +| CRM Externo | Baja | Sincronizaciθ΄Έn bθ°©sica via webhooks | + +--- + +## 7. Roadmap + +### Fase 1: MVP Core (Semanas 1-8) + +```yaml +Entregables: + - Arquitectura base (backend + frontend) + - CRM bθ°©sico (clientes, marcas, productos) + - Motor de generaciθ΄Έn con 2-3 workflows + - DAM bθ°©sico + - Admin de usuarios y roles + +MθŒ…trica de θ„‘xito: + - Generar 100 imθ°©genes de producto + - 3 campaεΈ½as completas end-to-end +``` + +### Fase 2: Personalizaciθ΄Έn Avanzada (Semanas 9-14) + +```yaml +Entregables: + - Entrenamiento de LoRAs por marca + - Avatares/influencers virtuales consistentes + - Integraciθ΄Έn profunda CRM 鈫? Generaciθ΄Έn + - Workflows adicionales + +MθŒ…trica de θ„‘xito: + - 5 LoRAs entrenados por marca + - 90% consistencia en personajes +``` + +### Fase 3: Contenido Enriquecido (Semanas 15-22) + +```yaml +Entregables: + - GIFs/cinemagraphs + - Integraciθ΄Έn de video bθ°©sico + - APIs premium opcionales (Gemini para texto) + - Portal cliente externo + +MθŒ…trica de θ„‘xito: + - 50% de campaεΈ½as con contenido animado + - 3 clientes externos usando portal +``` + +### Fase 4: Multi-tenant Comercial (Semanas 23+) + +```yaml +Entregables: + - Apertura a clientes externos (SaaS completo) + - Planes de suscripciθ΄Έn y l铆mites + - Marketplace de extensiones + +MθŒ…trica de θ„‘xito: + - 10 tenants activos + - MRR positivo +``` + +--- + +## 8. Riesgos y Mitigaciones + +| Riesgo | Impacto | Probabilidad | Mitigaciθ΄Έn | +|--------|---------|--------------|------------| +| Calidad de generaciθ΄Έn insuficiente | Alto | Media | Checkpoints especializados, postprocesado | +| Requisitos de GPU elevados | Medio | Alta | Optimizaciθ΄Έn de modelos, colas de prioridad | +| Texto ilegible en imθ°©genes | Medio | Alta | Modo h铆brido (IA + superposiciθ΄Έn) | +| Inconsistencia de personajes | Medio | Media | LoRAs + IP-Adapters + image prompts | +| Complejidad de ComfyUI | Medio | Media | Workflows pre-construidos, documentaciθ΄Έn | + +--- + +## 9. Referencias + +### 9.1 Documentaciθ΄Έn del Proyecto + +- [MVP Original](./MVP_Plataforma_SaaS_Contenido_CRM.md) - Definiciθ΄Έn inicial +- [Investigaciθ΄Έn Morfeo Academy](./Investigaciθ΄Έn%20Profunda_%20Plataforma%20de%20Generaciθ΄Έn%20de%20Contenido%20de%20Morfeo%20Academy%20y%20Desarrollo%20de%20una%20.pdf) - Anθ°©lisis de referencia + +### 9.2 Tecnolog铆as de Referencia + +- [Morfeo Academy](https://www.morfeoacademy.com/) - Referencia de plataforma similar +- [ComfyUI](https://github.com/comfyanonymous/ComfyUI) - Motor de workflows +- [ComfyDeploy](https://www.comfydeploy.com/) - API de inferencia +- [Stable Diffusion XL](https://stability.ai/) - Modelo base de generaciθ΄Έn + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 +**Prθ΄Έxima revisiθ΄Έn:** Al completar Fase 1 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-001-TENANTS.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-001-TENANTS.md new file mode 100644 index 0000000..986b4c9 --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-001-TENANTS.md @@ -0,0 +1,275 @@ +# PMC-001: MΓ³dulo de Tenants + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Alta + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Tenants proporciona la arquitectura multi-tenant que permite aislar datos y configuraciones entre diferentes organizaciones (agencias) que utilicen la plataforma. + +--- + +## Objetivos + +1. Aislar completamente los datos entre tenants +2. Permitir configuraciΓ³n personalizada por tenant +3. Soportar branding personalizado (logo, colores) +4. Gestionar lΓ­mites y cuotas por tenant +5. Preparar arquitectura para comercializaciΓ³n SaaS futura + +--- + +## Entidades del Dominio + +### Tenant + +```yaml +Entidad: Tenant +DescripciΓ³n: OrganizaciΓ³n/agencia que utiliza la plataforma +Atributos: + - id: UUID (PK) + - name: string (nombre de la organizaciΓ³n) + - slug: string (identificador URL-friendly, ΓΊnico) + - status: enum [active, suspended, trial, cancelled] + - plan_id: UUID (FK a Plan) + - settings: JSONB (configuraciΓ³n personalizada) + - branding: JSONB (logo_url, primary_color, secondary_color) + - limits: JSONB (cuotas y lΓ­mites) + - created_at: timestamp + - updated_at: timestamp + - deleted_at: timestamp (soft delete) + +Relaciones: + - 1:N con User + - 1:N con Client (CRM) + - 1:N con Project + - 1:N con Asset + - N:1 con Plan +``` + +### Plan + +```yaml +Entidad: Plan +DescripciΓ³n: Plan de suscripciΓ³n con lΓ­mites definidos +Atributos: + - id: UUID (PK) + - name: string (Free, Pro, Enterprise, Internal) + - code: string (identificador ΓΊnico) + - features: JSONB (funcionalidades habilitadas) + - limits: JSONB + - generations_per_month: number + - trainings_per_month: number + - storage_gb: number + - users_max: number + - projects_max: number + - price_monthly: decimal + - price_yearly: decimal + - is_active: boolean + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - 1:N con Tenant +``` + +### TenantSettings + +```yaml +Estructura JSONB: settings +Campos: + - default_language: string (es, en) + - timezone: string + - date_format: string + - currency: string + - notifications: + email_enabled: boolean + slack_webhook: string + - integrations: + crm_external_url: string + n8n_webhook_base: string + - generation: + default_model: string + default_quality: string + watermark_enabled: boolean +``` + +--- + +## Funcionalidades + +### F-001.1: GestiΓ³n de Tenants + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-001.1.1 | Crear tenant | Registro de nueva organizaciΓ³n | Alta | +| F-001.1.2 | Editar tenant | Modificar datos y configuraciΓ³n | Alta | +| F-001.1.3 | Suspender tenant | Desactivar acceso temporalmente | Media | +| F-001.1.4 | Eliminar tenant | Soft delete con retenciΓ³n de datos | Baja | + +### F-001.2: ConfiguraciΓ³n por Tenant + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-001.2.1 | Branding | Personalizar logo y colores | Media | +| F-001.2.2 | LΓ­mites | Configurar cuotas de uso | Alta | +| F-001.2.3 | Integraciones | URLs de webhooks y APIs externas | Media | +| F-001.2.4 | Preferencias | Idioma, zona horaria, formatos | Baja | + +### F-001.3: Aislamiento de Datos + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-001.3.1 | RLS PostgreSQL | Row-Level Security por tenant_id | Alta | +| F-001.3.2 | Middleware | InyecciΓ³n automΓ‘tica de tenant_id | Alta | +| F-001.3.3 | Storage isolation | Prefijos S3 por tenant | Alta | + +--- + +## Reglas de Negocio + +```yaml +RN-001.1: + DescripciΓ³n: Todo tenant debe tener un plan asignado + ValidaciΓ³n: plan_id NOT NULL + Default: Plan "Free" o "Internal" + +RN-001.2: + DescripciΓ³n: El slug del tenant debe ser ΓΊnico y URL-safe + ValidaciΓ³n: Regex ^[a-z0-9-]+$, ΓΊnico en BD + +RN-001.3: + DescripciΓ³n: Tenant suspendido no permite login de usuarios + AcciΓ³n: Validar status en middleware de autenticaciΓ³n + +RN-001.4: + DescripciΓ³n: LΓ­mites del plan se heredan al tenant + Override: Tenant puede tener lΓ­mites personalizados que sobreescriban el plan + +RN-001.5: + DescripciΓ³n: Soft delete conserva datos 90 dΓ­as + AcciΓ³n: deleted_at marca fecha, cron job limpia despuΓ©s +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/tenants + +Endpoints: + POST /tenants: + DescripciΓ³n: Crear nuevo tenant (Super Admin) + Body: { name, slug, plan_id, settings? } + Response: 201 Created + + GET /tenants: + DescripciΓ³n: Listar tenants (Super Admin) + Query: ?status=active&page=1&limit=20 + Response: 200 OK (paginado) + + GET /tenants/:id: + DescripciΓ³n: Obtener tenant por ID + Response: 200 OK + + PUT /tenants/:id: + DescripciΓ³n: Actualizar tenant + Body: { name?, settings?, branding?, limits? } + Response: 200 OK + + PATCH /tenants/:id/status: + DescripciΓ³n: Cambiar estado del tenant + Body: { status: "suspended" | "active" } + Response: 200 OK + + DELETE /tenants/:id: + DescripciΓ³n: Soft delete tenant + Response: 204 No Content + + GET /tenants/current: + DescripciΓ³n: Obtener tenant del usuario actual + Response: 200 OK +``` + +--- + +## Dependencias + +```yaml +Dependencias del CatΓ‘logo: + - @CATALOG_TENANT: PatrΓ³n base multi-tenancy (adaptar) + +Dependencias de MΓ³dulos: + - PMC-007 Admin: GestiΓ³n de planes y configuraciΓ³n global + +Servicios Externos: + - Ninguno requerido +``` + +--- + +## Consideraciones TΓ©cnicas + +### Estrategia Multi-Tenant + +```yaml +Tipo: Single Database, Shared Schema +Aislamiento: Row-Level Security (RLS) en PostgreSQL + +ImplementaciΓ³n: + 1. Columna tenant_id en todas las tablas principales + 2. PolΓ­ticas RLS que filtran por tenant_id + 3. Middleware que extrae tenant del JWT/sesiΓ³n + 4. SET app.current_tenant antes de cada query +``` + +### Ejemplo RLS PostgreSQL + +```sql +-- PolΓ­tica para tabla clients +CREATE POLICY tenant_isolation_policy ON clients + USING (tenant_id = current_setting('app.current_tenant')::uuid); + +-- Habilitar RLS +ALTER TABLE clients ENABLE ROW LEVEL SECURITY; +``` + +### Storage Isolation + +```yaml +Estructura S3: + bucket/ + β”œβ”€β”€ {tenant_slug}/ + β”‚ β”œβ”€β”€ assets/ + β”‚ β”œβ”€β”€ generated/ + β”‚ β”œβ”€β”€ models/ + β”‚ └── temp/ +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] Tenant puede ser creado con datos mΓ­nimos (name, slug, plan) +- [ ] RLS impide acceso a datos de otros tenants +- [ ] Branding se refleja en UI del tenant +- [ ] LΓ­mites del plan se validan antes de operaciones +- [ ] Soft delete funciona correctamente +- [ ] API responde correctamente a todos los endpoints + +--- + +## Referencias + +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [@CATALOG_TENANT](../../../core/catalog/modules/multi-tenancy/) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-002-CRM.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-002-CRM.md new file mode 100644 index 0000000..ed3ce07 --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-002-CRM.md @@ -0,0 +1,387 @@ +# PMC-002: MΓ³dulo CRM + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Alta + +--- + +## DescripciΓ³n General + +El mΓ³dulo CRM (Customer Relationship Management) gestiona clientes, marcas, productos y la relaciΓ³n entre estos elementos. EstΓ‘ diseΓ±ado para integrarse directamente con el motor de generaciΓ³n de contenido IA. + +--- + +## Objetivos + +1. Gestionar clientes y contactos de la agencia +2. Organizar marcas y productos por cliente +3. Almacenar identidad visual y lineamientos de marca +4. Registrar oportunidades comerciales +5. Conectar datos de CRM con generaciΓ³n de contenido + +--- + +## Entidades del Dominio + +### Client + +```yaml +Entidad: Client +DescripciΓ³n: Empresa/organizaciΓ³n cliente de la agencia +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - name: string + - legal_name: string + - tax_id: string (RFC/NIF) + - industry: string + - size: enum [micro, small, medium, large, enterprise] + - website: string + - status: enum [prospect, active, inactive, churned] + - notes: text + - metadata: JSONB + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - 1:N con Contact + - 1:N con Brand + - 1:N con Opportunity + - 1:N con Project +``` + +### Contact + +```yaml +Entidad: Contact +DescripciΓ³n: Persona de contacto en un cliente +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - client_id: UUID (FK) + - first_name: string + - last_name: string + - email: string + - phone: string + - position: string + - department: string + - is_primary: boolean + - status: enum [active, inactive] + - metadata: JSONB + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Client + - N:1 con Tenant +``` + +### Brand + +```yaml +Entidad: Brand +DescripciΓ³n: Marca de un cliente con su identidad visual +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - client_id: UUID (FK) + - name: string + - description: text + - status: enum [active, inactive] + - identity: JSONB + - logo_url: string + - logo_variations: array + - primary_color: string + - secondary_colors: array + - typography: object + - tone_of_voice: string (formal, casual, playful, etc.) + - keywords: array + - forbidden_words: array + - visual_style: string + - lora_models: array[UUID] (referencias a modelos entrenados) + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Client + - N:1 con Tenant + - 1:N con Product + - 1:N con Campaign + - N:N con CustomModel (LoRAs) +``` + +### Product + +```yaml +Entidad: Product +DescripciΓ³n: Producto o servicio de una marca +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - brand_id: UUID (FK) + - name: string + - sku: string + - description: text + - category: string + - status: enum [active, discontinued, coming_soon] + - attributes: JSONB + - price: decimal + - features: array + - target_audience: string + - use_cases: array + - reference_images: array[string] (URLs) + - lora_model_id: UUID (modelo especΓ­fico del producto) + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Brand + - N:1 con Tenant + - 1:N con Asset (imΓ‘genes generadas) +``` + +### Opportunity + +```yaml +Entidad: Opportunity +DescripciΓ³n: Oportunidad de negocio/deal +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - client_id: UUID (FK) + - contact_id: UUID (FK, opcional) + - name: string + - description: text + - value: decimal + - currency: string + - stage: enum [lead, qualified, proposal, negotiation, won, lost] + - probability: integer (0-100) + - expected_close_date: date + - actual_close_date: date + - lost_reason: string + - notes: text + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Client + - N:1 con Contact + - N:1 con Tenant + - 1:N con Project (al convertirse) +``` + +--- + +## Funcionalidades + +### F-002.1: GestiΓ³n de Clientes + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-002.1.1 | CRUD Clientes | Alta, ediciΓ³n, listado, eliminaciΓ³n | Alta | +| F-002.1.2 | BΓΊsqueda y filtros | Por nombre, industria, estado | Alta | +| F-002.1.3 | Vista de cliente | Dashboard con marcas, contactos, proyectos | Alta | +| F-002.1.4 | Historial | Timeline de actividades y cambios | Media | + +### F-002.2: GestiΓ³n de Contactos + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-002.2.1 | CRUD Contactos | GestiΓ³n de personas de contacto | Alta | +| F-002.2.2 | Contacto primario | Marcar contacto principal por cliente | Media | +| F-002.2.3 | Directorio | Vista consolidada de todos los contactos | Media | + +### F-002.3: GestiΓ³n de Marcas + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-002.3.1 | CRUD Marcas | Alta y gestiΓ³n de marcas | Alta | +| F-002.3.2 | Identidad visual | Definir colores, tipografΓ­a, tono | Alta | +| F-002.3.3 | Brand guidelines | Subir y almacenar guΓ­as de marca | Media | +| F-002.3.4 | Asociar LoRAs | Vincular modelos entrenados a marca | Alta | + +### F-002.4: GestiΓ³n de Productos + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-002.4.1 | CRUD Productos | Alta y gestiΓ³n de productos | Alta | +| F-002.4.2 | ImΓ‘genes referencia | Subir fotos del producto real | Alta | +| F-002.4.3 | CatΓ‘logo | Vista de productos por marca | Media | +| F-002.4.4 | Trigger generaciΓ³n | BotΓ³n "Generar pack de imΓ‘genes" | Alta | + +### F-002.5: Pipeline de Ventas + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-002.5.1 | CRUD Oportunidades | GestiΓ³n de deals | Media | +| F-002.5.2 | Kanban pipeline | Vista drag & drop por etapas | Media | +| F-002.5.3 | Convertir a proyecto | Crear proyecto desde oportunidad ganada | Media | + +--- + +## Reglas de Negocio + +```yaml +RN-002.1: + DescripciΓ³n: Cliente debe tener al menos un contacto + ValidaciΓ³n: Warning si no hay contactos, no bloquea + +RN-002.2: + DescripciΓ³n: Marca requiere identidad visual mΓ­nima + ValidaciΓ³n: Al menos logo_url o primary_color definido + +RN-002.3: + DescripciΓ³n: Producto hereda identidad de su marca + Comportamiento: Si no tiene LoRA propio, usa el de la marca + +RN-002.4: + DescripciΓ³n: Oportunidad ganada puede generar proyecto + AcciΓ³n: BotΓ³n "Crear proyecto" disponible en stage=won + +RN-002.5: + DescripciΓ³n: Datos de marca se inyectan en generaciΓ³n + Comportamiento: Al generar contenido, se cargan automΓ‘ticamente colores, tono, keywords +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/crm + +# Clients +POST /clients +GET /clients +GET /clients/:id +PUT /clients/:id +DELETE /clients/:id +GET /clients/:id/brands +GET /clients/:id/contacts +GET /clients/:id/projects + +# Contacts +POST /contacts +GET /contacts +GET /contacts/:id +PUT /contacts/:id +DELETE /contacts/:id + +# Brands +POST /brands +GET /brands +GET /brands/:id +PUT /brands/:id +DELETE /brands/:id +GET /brands/:id/products +POST /brands/:id/loras # Asociar LoRA +DELETE /brands/:id/loras/:loraId # Desasociar LoRA + +# Products +POST /products +GET /products +GET /products/:id +PUT /products/:id +DELETE /products/:id +POST /products/:id/generate # Trigger generaciΓ³n + +# Opportunities +POST /opportunities +GET /opportunities +GET /opportunities/:id +PUT /opportunities/:id +DELETE /opportunities/:id +POST /opportunities/:id/convert # Convertir a proyecto +``` + +--- + +## Integraciones + +### Con Motor de GeneraciΓ³n (PMC-004) + +```yaml +Trigger: POST /products/:id/generate +Payload: + product_id: UUID + brand_id: UUID + workflow_template: string + options: + quantity: number + formats: array + +Comportamiento: + 1. Cargar datos de producto (nombre, descripciΓ³n, referencias) + 2. Cargar identidad de marca (colores, tono, LoRAs) + 3. Encolar job de generaciΓ³n con parΓ‘metros combinados +``` + +### Con Proyectos (PMC-003) + +```yaml +Trigger: POST /opportunities/:id/convert +Crea: + - Proyecto vinculado al cliente + - CampaΓ±a inicial (opcional) + - Copia brief de la oportunidad +``` + +--- + +## Dependencias + +```yaml +Dependencias de MΓ³dulos: + - PMC-001 Tenants: Aislamiento de datos + - PMC-003 Projects: ConversiΓ³n de oportunidades + - PMC-004 Generation: Trigger de generaciΓ³n + - PMC-006 Assets: Almacenamiento de logos y referencias + +Servicios Externos: + - Storage (S3/MinIO): Logos, imΓ‘genes de referencia +``` + +--- + +## UI/UX Consideraciones + +```yaml +Vistas principales: + - Lista de clientes con filtros y bΓΊsqueda + - Ficha de cliente con tabs (info, contactos, marcas, proyectos) + - Lista de marcas con preview de identidad + - Ficha de producto con galerΓ­a de referencias + - Pipeline kanban de oportunidades + +Acciones rΓ‘pidas: + - Desde producto: "Generar contenido" + - Desde cliente: "Nueva marca", "Nuevo proyecto" + - Desde oportunidad: "Convertir a proyecto" +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] CRUD completo para Clients, Contacts, Brands, Products, Opportunities +- [ ] Identidad de marca se almacena y muestra correctamente +- [ ] Trigger de generaciΓ³n funciona desde producto +- [ ] Pipeline de oportunidades permite drag & drop +- [ ] ConversiΓ³n de oportunidad crea proyecto +- [ ] BΓΊsqueda y filtros funcionan en todas las listas +- [ ] RLS aΓ­sla datos por tenant + +--- + +## Referencias + +- [VISION-GENERAL.md](../00-vision-general/VISION-GENERAL.md) +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-003-PROJECTS.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-003-PROJECTS.md new file mode 100644 index 0000000..16d9ab8 --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-003-PROJECTS.md @@ -0,0 +1,381 @@ +# PMC-003: MΓ³dulo de Projects + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Alta + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Projects gestiona proyectos y campaΓ±as de marketing. Cada proyecto agrupa mΓΊltiples campaΓ±as, y cada campaΓ±a contiene un brief estructurado que guΓ­a la generaciΓ³n de contenido. + +--- + +## Objetivos + +1. Organizar el trabajo por proyectos y campaΓ±as +2. Estructurar briefs creativos para generaciΓ³n de contenido +3. Gestionar estados y flujos de aprobaciΓ³n +4. Vincular proyectos con clientes y marcas del CRM +5. Coordinar entregas de assets generados + +--- + +## Entidades del Dominio + +### Project + +```yaml +Entidad: Project +DescripciΓ³n: Contenedor de campaΓ±as para un cliente/iniciativa +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - client_id: UUID (FK) + - name: string + - description: text + - code: string (identificador corto, ej: "PRJ-2025-001") + - status: enum [draft, active, on_hold, completed, cancelled] + - start_date: date + - end_date: date + - budget: decimal + - currency: string + - owner_id: UUID (FK a User, responsable) + - team_members: array[UUID] (usuarios asignados) + - settings: JSONB + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con Client + - N:1 con User (owner) + - 1:N con Campaign + - 1:N con Asset (assets del proyecto) +``` + +### Campaign + +```yaml +Entidad: Campaign +DescripciΓ³n: CampaΓ±a de marketing con brief y assets +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - project_id: UUID (FK) + - brand_id: UUID (FK) + - name: string + - description: text + - type: enum [social_media, performance_ads, catalog, landing, email, other] + - status: enum [draft, briefing, in_production, review, approved, published, archived] + - brief: JSONB (ver estructura abajo) + - channels: array[string] (instagram, facebook, tiktok, google_ads, etc.) + - start_date: date + - end_date: date + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Project + - N:1 con Brand + - N:1 con Tenant + - 1:N con GenerationJob + - 1:N con Asset +``` + +### Brief (JSONB Structure) + +```yaml +Estructura: Campaign.brief +Campos: + objective: + description: string (objetivo de la campaΓ±a) + kpis: array[string] (mΓ©tricas de Γ©xito) + + audience: + demographics: string + psychographics: string + pain_points: array[string] + desires: array[string] + + messaging: + main_message: string + tone_of_voice: string (override del brand) + call_to_action: string + hashtags: array[string] + + visual: + style: string (fotogrΓ‘fico, ilustrado, minimalista, etc.) + mood: string (energΓ©tico, sereno, profesional, etc.) + color_palette: array[string] (override o adicionales) + references: array[string] (URLs de referencias visuales) + + constraints: + forbidden_words: array[string] + forbidden_elements: array[string] + legal_disclaimers: array[string] + brand_guidelines_url: string + + deliverables: + formats: array[object] + - type: string (post, story, banner, etc.) + dimensions: string (1080x1080, 1080x1920, etc.) + quantity: number + total_images: number + total_copies: number + variations_per_piece: number +``` + +### CampaignAsset + +```yaml +Entidad: CampaignAsset (tabla pivote) +DescripciΓ³n: RelaciΓ³n entre campaΓ±a y assets generados +Atributos: + - id: UUID (PK) + - campaign_id: UUID (FK) + - asset_id: UUID (FK) + - status: enum [pending, approved, rejected, revision_requested] + - feedback: text + - approved_by: UUID (FK a User) + - approved_at: timestamp + - created_at: timestamp +``` + +--- + +## Funcionalidades + +### F-003.1: GestiΓ³n de Proyectos + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-003.1.1 | CRUD Proyectos | Alta, ediciΓ³n, listado, archivado | Alta | +| F-003.1.2 | Dashboard proyecto | Vista general con campaΓ±as y progreso | Alta | +| F-003.1.3 | Asignar equipo | Agregar/quitar miembros al proyecto | Media | +| F-003.1.4 | Timeline | VisualizaciΓ³n de fechas y milestones | Media | + +### F-003.2: GestiΓ³n de CampaΓ±as + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-003.2.1 | CRUD CampaΓ±as | Alta, ediciΓ³n, listado | Alta | +| F-003.2.2 | Editor de brief | Formulario estructurado | Alta | +| F-003.2.3 | Plantillas de brief | Briefs predefinidos por tipo | Media | +| F-003.2.4 | Duplicar campaΓ±a | Clonar con modificaciones | Media | + +### F-003.3: Flujo de Trabajo + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-003.3.1 | Cambio de estado | Transiciones controladas | Alta | +| F-003.3.2 | Notificaciones | Alertar cambios de estado | Media | +| F-003.3.3 | AprobaciΓ³n de assets | Aprobar/rechazar contenido | Alta | +| F-003.3.4 | Solicitar revisiΓ³n | Pedir cambios con feedback | Alta | + +### F-003.4: GeneraciΓ³n de Contenido + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-003.4.1 | Lanzar generaciΓ³n | Desde brief, iniciar jobs | Alta | +| F-003.4.2 | Seleccionar plantillas | Elegir workflows de generaciΓ³n | Alta | +| F-003.4.3 | Monitor de progreso | Ver estado de generaciones | Alta | +| F-003.4.4 | Regenerar | Volver a generar con ajustes | Media | + +--- + +## MΓ‘quina de Estados + +### Project Status + +``` +draft ─────────────────────► active + β”‚ β”‚ + β”‚ β”œβ”€β”€β”€β–Ί on_hold ───► active + β”‚ β”‚ + β”‚ └───► completed + β”‚ + └────────────────────────────────► cancelled +``` + +### Campaign Status + +``` +draft ───► briefing ───► in_production ───► review ───► approved ───► published + β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ (revision_requested) β”‚ + β”‚ β”‚ β”‚ + └───────────┴────────────────────────────────────────────┴───► archived +``` + +--- + +## Reglas de Negocio + +```yaml +RN-003.1: + DescripciΓ³n: Proyecto requiere cliente asignado + ValidaciΓ³n: client_id NOT NULL + +RN-003.2: + DescripciΓ³n: CampaΓ±a requiere brief mΓ­nimo para pasar a producciΓ³n + ValidaciΓ³n: brief.objective y brief.deliverables definidos + +RN-003.3: + DescripciΓ³n: Solo owner o admin puede cambiar estado del proyecto + AutorizaciΓ³n: Verificar rol del usuario + +RN-003.4: + DescripciΓ³n: Assets aprobados no pueden eliminarse + ValidaciΓ³n: Bloquear DELETE si status=approved + +RN-003.5: + DescripciΓ³n: Brief hereda identidad de la marca + Comportamiento: Cargar colores, tono, etc. de Brand al crear campaΓ±a + +RN-003.6: + DescripciΓ³n: CampaΓ±a solo puede publicarse si tiene assets aprobados + ValidaciΓ³n: Al menos 1 asset con status=approved +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/projects + +# Projects +POST /projects +GET /projects +GET /projects/:id +PUT /projects/:id +DELETE /projects/:id +PATCH /projects/:id/status +GET /projects/:id/campaigns +GET /projects/:id/assets +POST /projects/:id/team # Agregar miembro +DELETE /projects/:id/team/:userId + +# Campaigns +POST /campaigns +GET /campaigns +GET /campaigns/:id +PUT /campaigns/:id +DELETE /campaigns/:id +PATCH /campaigns/:id/status +PUT /campaigns/:id/brief +GET /campaigns/:id/assets +POST /campaigns/:id/generate # Lanzar generaciΓ³n + +# Campaign Assets +POST /campaigns/:id/assets/:assetId/approve +POST /campaigns/:id/assets/:assetId/reject +POST /campaigns/:id/assets/:assetId/request-revision + +# Brief Templates +GET /brief-templates +GET /brief-templates/:id +POST /brief-templates # Admin only +PUT /brief-templates/:id +DELETE /brief-templates/:id +``` + +--- + +## Integraciones + +### Con CRM (PMC-002) + +```yaml +RelaciΓ³n: Proyecto vinculado a Cliente y Marca +Datos heredados: + - Identidad visual de Brand + - InformaciΓ³n de productos + - Contactos para notificaciones +``` + +### Con Motor de GeneraciΓ³n (PMC-004) + +```yaml +Trigger: POST /campaigns/:id/generate +Payload: + campaign_id: UUID + workflow_templates: array[string] + options: + use_brand_lora: boolean + quality: string + +Respuesta: + job_ids: array[UUID] + estimated_time: number +``` + +### Con DAM (PMC-006) + +```yaml +Assets generados se almacenan en DAM +VinculaciΓ³n automΓ‘tica campaign_id β†’ asset +Metadatos del brief copiados al asset +``` + +### Con AutomatizaciΓ³n (PMC-005) + +```yaml +Eventos disparados: + - campaign.status_changed β†’ Notificaciones + - campaign.approved β†’ Preparar entrega + - assets.all_approved β†’ Trigger siguiente paso +``` + +--- + +## UI/UX Consideraciones + +```yaml +Vistas principales: + - Lista de proyectos con filtros (cliente, estado, fecha) + - Board kanban de campaΓ±as por estado + - Editor de brief con preview + - GalerΓ­a de assets de campaΓ±a con acciones + +Acciones rΓ‘pidas: + - "Nueva campaΓ±a" desde proyecto + - "Generar contenido" desde campaΓ±a + - "Aprobar todo" en vista de revisiΓ³n + - "Descargar pack" de assets aprobados + +Componentes: + - BriefEditor: Formulario estructurado con secciones colapsables + - AssetReviewer: GalerΓ­a con zoom, comparaciΓ³n, acciones + - ProgressTracker: Timeline visual de estado de campaΓ±a +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] CRUD completo para Projects y Campaigns +- [ ] Editor de brief funcional con todas las secciones +- [ ] Transiciones de estado respetan reglas +- [ ] GeneraciΓ³n se lanza correctamente desde campaΓ±a +- [ ] Flujo de aprobaciΓ³n de assets funciona +- [ ] Assets rechazados permiten regeneraciΓ³n +- [ ] Notificaciones se disparan en cambios de estado +- [ ] Plantillas de brief funcionan correctamente + +--- + +## Referencias + +- [VISION-GENERAL.md](../00-vision-general/VISION-GENERAL.md) +- [PMC-002-CRM.md](./PMC-002-CRM.md) +- [PMC-004-GENERATION.md](./PMC-004-GENERATION.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-004-GENERATION.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-004-GENERATION.md new file mode 100644 index 0000000..f8f3c8b --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-004-GENERATION.md @@ -0,0 +1,489 @@ +# PMC-004: MΓ³dulo de Generation + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Alta + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Generation es el nΓΊcleo de la plataforma. Gestiona la generaciΓ³n de contenido mediante IA, incluyendo imΓ‘genes con Stable Diffusion/ComfyUI y textos con LLMs. Orquesta workflows, colas de tareas, y la integraciΓ³n con modelos personalizados (LoRAs). + +--- + +## Objetivos + +1. Generar imΓ‘genes de alta calidad para marketing +2. Generar copys y textos publicitarios +3. Ejecutar workflows predefinidos de ComfyUI +4. Gestionar modelos personalizados (LoRAs, checkpoints) +5. Mantener consistencia de marca en generaciones +6. Procesar tareas en cola con prioridades + +--- + +## Entidades del Dominio + +### GenerationJob + +```yaml +Entidad: GenerationJob +DescripciΓ³n: Tarea de generaciΓ³n en cola +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - campaign_id: UUID (FK, opcional) + - product_id: UUID (FK, opcional) + - user_id: UUID (FK, quien solicitΓ³) + - type: enum [image, text, image_batch, mixed] + - status: enum [queued, processing, completed, failed, cancelled] + - priority: integer (1-10, mayor = mΓ‘s urgente) + - workflow_id: UUID (FK a WorkflowTemplate) + - input_params: JSONB (parΓ‘metros de entrada) + - output_assets: array[UUID] (assets generados) + - error_message: text + - progress: integer (0-100) + - started_at: timestamp + - completed_at: timestamp + - created_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con Campaign + - N:1 con Product + - N:1 con User + - N:1 con WorkflowTemplate + - 1:N con Asset (outputs) +``` + +### WorkflowTemplate + +```yaml +Entidad: WorkflowTemplate +DescripciΓ³n: Plantilla de workflow de generaciΓ³n +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK, null = global) + - name: string + - description: text + - type: enum [product_photo, social_post, banner, avatar, variation, custom] + - category: string (para organizaciΓ³n) + - comfyui_workflow: JSONB (definiciΓ³n del workflow) + - input_schema: JSONB (parΓ‘metros esperados) + - output_config: JSONB + - format: string (png, jpg, webp) + - dimensions: array[string] + - quantity_default: number + - models_required: array[string] (checkpoints, LoRAs requeridos) + - estimated_time_seconds: integer + - is_active: boolean + - is_system: boolean (plantilla del sistema vs personalizada) + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant (opcional) + - 1:N con GenerationJob +``` + +### CustomModel + +```yaml +Entidad: CustomModel +DescripciΓ³n: Modelo personalizado (LoRA, checkpoint, embedding) +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - brand_id: UUID (FK, opcional) + - name: string + - type: enum [lora, checkpoint, embedding, controlnet] + - purpose: string (product, avatar, style, character) + - description: text + - file_path: string (ruta en storage) + - file_size: bigint + - status: enum [training, ready, failed, archived] + - training_params: JSONB + - base_model: string + - steps: number + - learning_rate: number + - training_images: array[string] + - trigger_word: string (palabra para activar en prompt) + - preview_images: array[string] + - metadata: JSONB + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con Brand (opcional) + - N:N con WorkflowTemplate +``` + +### TextGeneration + +```yaml +Entidad: TextGeneration +DescripciΓ³n: GeneraciΓ³n de texto/copy +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - job_id: UUID (FK a GenerationJob, opcional) + - campaign_id: UUID (FK, opcional) + - type: enum [copy, title, description, hashtags, cta, full_post] + - prompt: text (instrucciΓ³n al LLM) + - context: JSONB (datos de marca, producto, brief) + - output: text + - variations: array[text] (si se generaron mΓΊltiples) + - model_used: string + - tokens_used: integer + - status: enum [pending, completed, failed] + - created_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con GenerationJob + - N:1 con Campaign +``` + +--- + +## Funcionalidades + +### F-004.1: GeneraciΓ³n de ImΓ‘genes + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-004.1.1 | Text-to-Image | Generar imagen desde prompt | Alta | +| F-004.1.2 | Image-to-Image | Transformar imagen existente | Alta | +| F-004.1.3 | Inpainting | Editar partes de una imagen | Media | +| F-004.1.4 | Upscaling | Aumentar resoluciΓ³n | Alta | +| F-004.1.5 | Batch generation | Generar mΓΊltiples variaciones | Alta | + +### F-004.2: GeneraciΓ³n de Texto + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-004.2.1 | Copy generation | Generar textos publicitarios | Alta | +| F-004.2.2 | Hashtag generation | Sugerir hashtags relevantes | Media | +| F-004.2.3 | Title generation | Crear tΓ­tulos/headlines | Alta | +| F-004.2.4 | Tone adaptation | Ajustar tono segΓΊn brief | Alta | + +### F-004.3: Workflows + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-004.3.1 | Plantillas predefinidas | Workflows listos para usar | Alta | +| F-004.3.2 | Ejecutar workflow | Correr workflow con parΓ‘metros | Alta | +| F-004.3.3 | Crear plantillas | Admin puede crear nuevos workflows | Media | +| F-004.3.4 | Previsualizar | Ver ejemplo antes de ejecutar | Media | + +### F-004.4: Modelos Personalizados + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-004.4.1 | Registrar LoRA | Subir modelo entrenado | Alta | +| F-004.4.2 | Entrenar LoRA | Iniciar entrenamiento (bΓ‘sico) | Media | +| F-004.4.3 | Asociar a marca | Vincular modelo con brand | Alta | +| F-004.4.4 | Selector de modelos | Elegir LoRAs en generaciΓ³n | Alta | + +### F-004.5: Cola de Tareas + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-004.5.1 | Encolar job | Agregar tarea a la cola | Alta | +| F-004.5.2 | Priorizar | Ajustar prioridad de jobs | Media | +| F-004.5.3 | Monitor | Ver estado de cola | Alta | +| F-004.5.4 | Cancelar | Cancelar job pendiente | Media | +| F-004.5.5 | Reintentar | Re-ejecutar job fallido | Media | + +--- + +## Workflows Predefinidos (MVP) + +### WF-001: FotografΓ­a SintΓ©tica de Producto + +```yaml +Nombre: product_photo_synthetic +DescripciΓ³n: Genera fotos de producto en contextos comerciales +Inputs: + - product_description: string + - reference_images: array[string] (opcional) + - background: string (white, lifestyle, custom) + - style: string (minimalist, premium, casual) + - brand_colors: array[string] + - lora_id: UUID (opcional) + +Outputs: + - 5 variaciones del producto + - Formato: PNG 1024x1024 + - Fondo transparente disponible + +ComfyUI Nodes: + - SDXL Base + - ControlNet (si hay referencia) + - IP-Adapter (consistencia) + - Background Removal + - Upscaler +``` + +### WF-002: Post para Redes Sociales + +```yaml +Nombre: social_media_post +DescripciΓ³n: Genera imagen + copy para redes +Inputs: + - brief: object (objetivo, audiencia, tono) + - product_id: UUID (opcional) + - channel: string (instagram, facebook, linkedin) + - format: string (post, story, carousel) + - brand_id: UUID + +Outputs: + - 3-5 variaciones de imagen + - Copy sugerido por variaciΓ³n + - Hashtags recomendados + +Proceso: + 1. Cargar identidad de marca + 2. Generar imagen base con SDXL + LoRA + 3. Aplicar composiciΓ³n segΓΊn formato + 4. Generar copy con LLM + 5. Combinar outputs +``` + +### WF-003: Variaciones de Anuncio + +```yaml +Nombre: ad_variations +DescripciΓ³n: Genera mΓΊltiples versiones para A/B testing +Inputs: + - base_image: string (URL o asset_id) + - variations_count: number + - variation_type: string (color, background, composition) + +Outputs: + - N variaciones segΓΊn configuraciΓ³n + - Metadatos de diferencias + +Uso: + - Testing de creatividades + - Adaptaciones por canal +``` + +### WF-004: Avatar/Influencer Virtual + +```yaml +Nombre: virtual_avatar +DescripciΓ³n: Genera imΓ‘genes consistentes de un personaje +Inputs: + - character_lora_id: UUID + - pose: string (standing, sitting, action) + - outfit: string + - background: string + - expression: string + +Outputs: + - Imagen del avatar + - Consistencia facial garantizada + +TΓ©cnicas: + - IP-Adapter para consistencia + - ControlNet OpenPose para poses + - LoRA especΓ­fico del personaje +``` + +--- + +## Arquitectura de IntegraciΓ³n ComfyUI + +```yaml +Componentes: + Backend (NestJS): + - GenerationService: LΓ³gica de negocio + - QueueService: GestiΓ³n de cola (Bull) + - ComfyUIClient: Cliente HTTP para ComfyUI + + ComfyUI Server: + - API REST nativa o ComfyDeploy + - Websocket para progreso + - Storage compartido para outputs + +Flujo: + 1. Backend recibe solicitud de generaciΓ³n + 2. Valida permisos y lΓ­mites del tenant + 3. Construye payload del workflow + 4. Encola job en Bull/Redis + 5. Worker toma job y llama a ComfyUI + 6. ComfyUI ejecuta workflow + 7. Worker recibe resultado y crea Asset + 8. Notifica completion via websocket +``` + +### Ejemplo de Llamada a ComfyUI + +```typescript +interface ComfyUIRequest { + workflow_id: string; + inputs: { + positive_prompt: string; + negative_prompt: string; + seed: number; + steps: number; + cfg_scale: number; + width: number; + height: number; + lora_name?: string; + lora_strength?: number; + controlnet_image?: string; + }; + webhook_url: string; +} + +// Respuesta +interface ComfyUIResponse { + job_id: string; + status: 'queued' | 'processing' | 'completed' | 'failed'; + outputs?: { + images: string[]; // URLs + }; + error?: string; +} +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/generation + +# Jobs +POST /jobs # Crear job de generaciΓ³n +GET /jobs # Listar jobs del usuario +GET /jobs/:id # Detalle de job +DELETE /jobs/:id # Cancelar job +POST /jobs/:id/retry # Reintentar job fallido + +# Quick Generate (shortcuts) +POST /generate/image # GeneraciΓ³n rΓ‘pida de imagen +POST /generate/text # GeneraciΓ³n rΓ‘pida de texto +POST /generate/batch # Batch de imΓ‘genes + +# Workflows +GET /workflows # Listar plantillas disponibles +GET /workflows/:id # Detalle de plantilla +POST /workflows # Crear plantilla (admin) +PUT /workflows/:id # Editar plantilla +POST /workflows/:id/execute # Ejecutar workflow + +# Custom Models +GET /models # Listar modelos del tenant +GET /models/:id # Detalle de modelo +POST /models # Registrar modelo +DELETE /models/:id # Eliminar modelo +POST /models/train # Iniciar entrenamiento + +# Queue Management (admin) +GET /queue/status # Estado de la cola +GET /queue/jobs # Jobs en cola +POST /queue/jobs/:id/priority # Cambiar prioridad +``` + +--- + +## Reglas de Negocio + +```yaml +RN-004.1: + DescripciΓ³n: Generaciones limitadas por plan del tenant + ValidaciΓ³n: Verificar cuota antes de encolar + AcciΓ³n: Rechazar si lΓ­mite alcanzado + +RN-004.2: + DescripciΓ³n: LoRA de marca se aplica automΓ‘ticamente + Comportamiento: Si brand tiene LoRA y no se especifica otro, usar el de marca + +RN-004.3: + DescripciΓ³n: Jobs prioritarios para planes premium + CΓ‘lculo: priority_base + plan_bonus + +RN-004.4: + DescripciΓ³n: Outputs se almacenan 30 dΓ­as mΓ­nimo + PolΓ­tica: Assets generados tienen retenciΓ³n mΓ­nima + +RN-004.5: + DescripciΓ³n: Entrenamiento requiere mΓ­nimo 10 imΓ‘genes + ValidaciΓ³n: Verificar cantidad antes de iniciar + +RN-004.6: + DescripciΓ³n: Negative prompts por defecto + Comportamiento: Agregar prompts negativos estΓ‘ndar de calidad +``` + +--- + +## Dependencias + +```yaml +Dependencias de MΓ³dulos: + - PMC-001 Tenants: LΓ­mites y cuotas + - PMC-002 CRM: Datos de marca y producto + - PMC-003 Projects: Contexto de campaΓ±a + - PMC-006 Assets: Almacenamiento de outputs + +Servicios Externos: + - ComfyUI: Motor de generaciΓ³n de imΓ‘genes + - OpenAI/Claude API: GeneraciΓ³n de texto + - Redis: Cola de tareas + - S3/MinIO: Almacenamiento de modelos y outputs + +Dependencias del CatΓ‘logo: + - @CATALOG_RATELIMIT: Rate limiting por tenant +``` + +--- + +## Consideraciones de Performance + +```yaml +Optimizaciones: + - Cola con workers paralelos segΓΊn GPUs disponibles + - Cache de modelos frecuentes en VRAM + - Batch processing cuando sea posible + - CompresiΓ³n de outputs antes de storage + +Monitoreo: + - Tiempo promedio por tipo de workflow + - UtilizaciΓ³n de GPU + - Cola depth y wait time + - Tasa de errores +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] GeneraciΓ³n de imagen funciona con SDXL base +- [ ] Workflows predefinidos ejecutan correctamente +- [ ] LoRAs se cargan y aplican correctamente +- [ ] Cola procesa jobs en orden de prioridad +- [ ] Progreso se reporta via websocket +- [ ] Jobs fallidos permiten reintento +- [ ] LΓ­mites de tenant se respetan +- [ ] Outputs se almacenan como Assets +- [ ] GeneraciΓ³n de texto produce copys coherentes + +--- + +## Referencias + +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [ComfyUI Documentation](https://github.com/comfyanonymous/ComfyUI) +- [ComfyDeploy](https://www.comfydeploy.com/) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-005-AUTOMATION.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-005-AUTOMATION.md new file mode 100644 index 0000000..c171cd7 --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-005-AUTOMATION.md @@ -0,0 +1,447 @@ +# PMC-005: MΓ³dulo de Automation + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Media + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Automation gestiona flujos automatizados entre los diferentes componentes de la plataforma. Utiliza n8n como orquestador principal para conectar CRM, motor de generaciΓ³n, notificaciones y sistemas externos. + +--- + +## Objetivos + +1. Automatizar flujos creativos desde brief hasta entrega +2. Integrar CRM con motor de generaciΓ³n +3. Disparar acciones basadas en eventos del sistema +4. Conectar con servicios externos (email, redes, etc.) +5. Reducir tareas manuales repetitivas + +--- + +## Entidades del Dominio + +### AutomationFlow + +```yaml +Entidad: AutomationFlow +DescripciΓ³n: DefiniciΓ³n de un flujo automatizado +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - name: string + - description: text + - type: enum [trigger_based, scheduled, manual] + - trigger_event: string (evento que dispara el flujo) + - n8n_workflow_id: string (ID del workflow en n8n) + - is_active: boolean + - last_run: timestamp + - run_count: integer + - config: JSONB + - retry_on_failure: boolean + - max_retries: number + - timeout_seconds: number + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - 1:N con AutomationRun +``` + +### AutomationRun + +```yaml +Entidad: AutomationRun +DescripciΓ³n: EjecuciΓ³n de un flujo automatizado +Atributos: + - id: UUID (PK) + - flow_id: UUID (FK) + - tenant_id: UUID (FK) + - status: enum [running, completed, failed, cancelled] + - trigger_data: JSONB (datos del evento que disparΓ³) + - output_data: JSONB (resultados) + - error_message: text + - started_at: timestamp + - completed_at: timestamp + - duration_ms: integer + +Relaciones: + - N:1 con AutomationFlow + - N:1 con Tenant +``` + +### WebhookEndpoint + +```yaml +Entidad: WebhookEndpoint +DescripciΓ³n: Endpoint para recibir eventos externos +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - name: string + - slug: string (parte de la URL) + - secret_key: string (para validaciΓ³n) + - target_flow_id: UUID (FK) + - is_active: boolean + - last_called: timestamp + - call_count: integer + - created_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con AutomationFlow +``` + +--- + +## Eventos del Sistema + +### Eventos Disponibles para Triggers + +```yaml +CRM Events: + - client.created + - client.updated + - brand.created + - brand.updated + - product.created + - product.updated + - opportunity.stage_changed + - opportunity.won + - opportunity.lost + +Project Events: + - project.created + - project.status_changed + - campaign.created + - campaign.status_changed + - campaign.brief_completed + - campaign.approved + +Generation Events: + - job.completed + - job.failed + - batch.completed + - model.training_completed + +Asset Events: + - asset.created + - asset.approved + - asset.rejected + - all_assets.approved (todos los assets de campaΓ±a) + +User Events: + - user.created + - user.invited + - user.activated +``` + +--- + +## Flujos Predefinidos (MVP) + +### FLOW-001: Nuevo Producto β†’ Generar Kit de Assets + +```yaml +Nombre: product_asset_kit +Trigger: product.created +DescripciΓ³n: Al crear producto, genera pack de imΓ‘genes automΓ‘ticamente + +Pasos: + 1. Recibir evento product.created + 2. Cargar datos del producto y su marca + 3. Verificar si tiene imΓ‘genes de referencia + 4. Llamar a GenerationService con workflow "product_photo_synthetic" + 5. Esperar completaciΓ³n del job + 6. Notificar al usuario creador + +ConfiguraciΓ³n: + images_count: 5 + auto_approve: false + notify_on_complete: true +``` + +### FLOW-002: Nueva CampaΓ±a β†’ Generar Lote Inicial + +```yaml +Nombre: campaign_initial_batch +Trigger: campaign.brief_completed +DescripciΓ³n: Al completar brief, genera creatividades iniciales + +Pasos: + 1. Recibir evento campaign.brief_completed + 2. Extraer deliverables del brief + 3. Para cada formato solicitado: + - Llamar a GenerationService + - Generar imΓ‘genes segΓΊn especificaciones + 4. Generar copys con LLM + 5. Vincular assets a la campaΓ±a + 6. Cambiar estado campaΓ±a a "in_production" + 7. Notificar al equipo asignado + +ConfiguraciΓ³n: + parallel_generations: true + generate_copies: true + auto_link_assets: true +``` + +### FLOW-003: CampaΓ±a Aprobada β†’ Preparar Entrega + +```yaml +Nombre: campaign_delivery_prep +Trigger: campaign.approved +DescripciΓ³n: Prepara paquete de entrega al aprobar campaΓ±a + +Pasos: + 1. Recibir evento campaign.approved + 2. Recopilar todos los assets aprobados + 3. Generar ZIP con estructura organizada + 4. Crear enlace de descarga temporal + 5. Si cliente tiene acceso al portal: + - Crear notificaciΓ³n en portal + 6. Enviar email al contacto del cliente + 7. Registrar entrega en historial + +ConfiguraciΓ³n: + zip_structure: "by_format" | "flat" + include_copies: true + link_expiry_days: 7 + notify_client: true +``` + +### FLOW-004: Job Fallido β†’ Notificar y Reintentar + +```yaml +Nombre: job_failure_handler +Trigger: job.failed +DescripciΓ³n: Maneja fallos de generaciΓ³n + +Pasos: + 1. Recibir evento job.failed + 2. Evaluar tipo de error + 3. Si error transitorio (GPU, timeout): + - Reintentar hasta max_retries + 4. Si error persistente: + - Notificar al usuario + - Crear ticket/tarea de revisiΓ³n + 5. Registrar en logs de auditorΓ­a + +ConfiguraciΓ³n: + max_retries: 3 + retry_delay_seconds: 60 + notify_on_permanent_failure: true +``` + +--- + +## Funcionalidades + +### F-005.1: GestiΓ³n de Flujos + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-005.1.1 | Listar flujos | Ver flujos disponibles y activos | Alta | +| F-005.1.2 | Activar/Desactivar | Toggle de flujos | Alta | +| F-005.1.3 | Configurar | Ajustar parΓ‘metros de flujo | Media | +| F-005.1.4 | Ver historial | Ejecuciones pasadas | Media | + +### F-005.2: EjecuciΓ³n Manual + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-005.2.1 | Ejecutar ahora | Disparar flujo manualmente | Media | +| F-005.2.2 | Test run | Ejecutar en modo prueba | Baja | +| F-005.2.3 | Cancelar | Detener ejecuciΓ³n en curso | Media | + +### F-005.3: Webhooks + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-005.3.1 | Crear endpoint | Generar URL de webhook | Media | +| F-005.3.2 | Validar payload | Verificar firma/secret | Media | +| F-005.3.3 | Ver logs | Historial de llamadas | Baja | + +### F-005.4: Integraciones Externas + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-005.4.1 | Email | EnvΓ­o de notificaciones | Alta | +| F-005.4.2 | Slack | Notificaciones a canales | Media | +| F-005.4.3 | CRM externo | Sync bidireccional | Baja | + +--- + +## Arquitectura de IntegraciΓ³n n8n + +```yaml +Componentes: + Backend (NestJS): + - EventEmitter: Emite eventos del sistema + - WebhookController: Recibe llamadas de n8n + - AutomationService: Gestiona flujos y ejecuciones + + n8n Server: + - Workflows definidos + - Credenciales de integraciΓ³n + - Webhooks de entrada/salida + +ComunicaciΓ³n: + Backend β†’ n8n: Webhooks HTTP POST + n8n β†’ Backend: API calls con auth token + +Flujo: + 1. Evento ocurre en Backend (ej: product.created) + 2. EventEmitter notifica a AutomationService + 3. AutomationService busca flujos suscritos al evento + 4. Para cada flujo activo: + - POST a webhook de n8n con datos del evento + 5. n8n ejecuta workflow + 6. n8n llama a API del Backend para acciones + 7. n8n reporta resultado via webhook de completion +``` + +### Ejemplo de Webhook Payload + +```json +{ + "event": "product.created", + "timestamp": "2025-12-08T10:30:00Z", + "tenant_id": "uuid-tenant", + "data": { + "product_id": "uuid-product", + "brand_id": "uuid-brand", + "name": "Producto X", + "description": "...", + "reference_images": ["url1", "url2"] + }, + "metadata": { + "user_id": "uuid-user", + "source": "api" + } +} +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/automation + +# Flows +GET /flows # Listar flujos +GET /flows/:id # Detalle de flujo +POST /flows/:id/activate # Activar flujo +POST /flows/:id/deactivate # Desactivar flujo +PUT /flows/:id/config # Configurar flujo +POST /flows/:id/execute # Ejecutar manualmente + +# Runs +GET /runs # Historial de ejecuciones +GET /runs/:id # Detalle de ejecuciΓ³n +POST /runs/:id/cancel # Cancelar ejecuciΓ³n + +# Webhooks +GET /webhooks # Listar endpoints +POST /webhooks # Crear endpoint +DELETE /webhooks/:id # Eliminar endpoint +POST /webhooks/:id/regenerate # Regenerar secret + +# Incoming webhooks (public, con autenticaciΓ³n por secret) +POST /hooks/:tenant_slug/:webhook_slug +``` + +--- + +## Reglas de Negocio + +```yaml +RN-005.1: + DescripciΓ³n: Flujos desactivados no procesan eventos + Comportamiento: Eventos ignorados si flow.is_active = false + +RN-005.2: + DescripciΓ³n: Reintentos con backoff exponencial + CΓ‘lculo: delay = retry_delay * (2 ^ attempt_number) + +RN-005.3: + DescripciΓ³n: Ejecuciones fallidas notifican a admins + AcciΓ³n: Email + notificaciΓ³n in-app a usuarios con rol admin + +RN-005.4: + DescripciΓ³n: Webhooks requieren validaciΓ³n de secret + ValidaciΓ³n: HMAC-SHA256 del payload con secret key + +RN-005.5: + DescripciΓ³n: LΓ­mite de ejecuciones por hora + ValidaciΓ³n: Rate limit segΓΊn plan del tenant +``` + +--- + +## Dependencias + +```yaml +Dependencias de MΓ³dulos: + - PMC-001 Tenants: ConfiguraciΓ³n y lΓ­mites + - PMC-002 CRM: Eventos de clientes/productos + - PMC-003 Projects: Eventos de campaΓ±as + - PMC-004 Generation: Llamadas a generaciΓ³n + - PMC-006 Assets: GestiΓ³n de outputs + +Servicios Externos: + - n8n: Orquestador de workflows + - SMTP/SendGrid: EnvΓ­o de emails + - Slack API: Notificaciones (opcional) +``` + +--- + +## Consideraciones de Seguridad + +```yaml +AutenticaciΓ³n: + - Webhooks internos usan JWT del sistema + - Webhooks externos usan HMAC con secret por endpoint + - n8n autenticado con API key exclusiva + +Aislamiento: + - Flujos aislados por tenant + - Eventos solo visible para el tenant que los genera + +ValidaciΓ³n: + - Payload size mΓ‘ximo: 1MB + - Rate limiting por endpoint + - Timeout de ejecuciΓ³n: 5 minutos +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] Flujos predefinidos funcionan correctamente +- [ ] Eventos del sistema disparan flujos suscritos +- [ ] n8n recibe y procesa webhooks +- [ ] Ejecuciones se registran con estado y resultado +- [ ] Reintentos automΓ‘ticos funcionan en errores transitorios +- [ ] Webhooks externos validan correctamente el secret +- [ ] Notificaciones se envΓ­an segΓΊn configuraciΓ³n +- [ ] Rate limiting funciona segΓΊn plan + +--- + +## Referencias + +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [n8n Documentation](https://docs.n8n.io/) +- [PMC-004-GENERATION.md](./PMC-004-GENERATION.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-006-ASSETS.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-006-ASSETS.md new file mode 100644 index 0000000..557bb5d --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-006-ASSETS.md @@ -0,0 +1,449 @@ +# PMC-006: MΓ³dulo de Assets (DAM) + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Alta + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Assets implementa un Digital Asset Management (DAM) simplificado para almacenar, organizar y gestionar todos los recursos digitales generados o subidos a la plataforma: imΓ‘genes, copys, videos, modelos IA, y documentos. + +--- + +## Objetivos + +1. Centralizar todos los activos digitales del tenant +2. Organizar assets por cliente, campaΓ±a, tipo +3. Gestionar versiones y estados de aprobaciΓ³n +4. Facilitar bΓΊsqueda y descubrimiento de assets +5. Controlar acceso y permisos por rol + +--- + +## Entidades del Dominio + +### Asset + +```yaml +Entidad: Asset +DescripciΓ³n: Recurso digital almacenado en la plataforma +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - name: string + - description: text + - type: enum [image, copy, video, document, model, template] + - mime_type: string + - file_path: string (ruta en storage) + - file_size: bigint (bytes) + - dimensions: JSONB (width, height para imΓ‘genes/videos) + - duration: integer (segundos, para video/audio) + - status: enum [draft, pending_review, approved, rejected, archived] + - visibility: enum [private, team, client] + - source: enum [generated, uploaded, imported] + - generation_job_id: UUID (FK, si fue generado) + - metadata: JSONB + - prompt: string (si fue generado) + - model_used: string + - seed: number + - parameters: object + - tags: array[string] + - created_by: UUID (FK a User) + - created_at: timestamp + - updated_at: timestamp + - deleted_at: timestamp (soft delete) + +Relaciones: + - N:1 con Tenant + - N:1 con User (creator) + - N:1 con GenerationJob + - N:N con Campaign + - N:N con Collection + - 1:N con AssetVersion +``` + +### AssetVersion + +```yaml +Entidad: AssetVersion +DescripciΓ³n: VersiΓ³n histΓ³rica de un asset +Atributos: + - id: UUID (PK) + - asset_id: UUID (FK) + - version_number: integer + - file_path: string + - file_size: bigint + - changes_description: text + - created_by: UUID (FK) + - created_at: timestamp + +Relaciones: + - N:1 con Asset + - N:1 con User +``` + +### Collection + +```yaml +Entidad: Collection +DescripciΓ³n: AgrupaciΓ³n lΓ³gica de assets +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - name: string + - description: text + - type: enum [manual, smart, campaign, brand] + - smart_filters: JSONB (criterios para smart collections) + - cover_asset_id: UUID (FK, opcional) + - is_public: boolean + - created_by: UUID (FK) + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:N con Asset + - N:1 con User +``` + +### AssetComment + +```yaml +Entidad: AssetComment +DescripciΓ³n: Comentario o feedback sobre un asset +Atributos: + - id: UUID (PK) + - asset_id: UUID (FK) + - user_id: UUID (FK) + - content: text + - position: JSONB (x, y para comentarios en imagen) + - is_resolved: boolean + - parent_id: UUID (FK, para respuestas) + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Asset + - N:1 con User + - Self-referencial (parent/children) +``` + +### Download + +```yaml +Entidad: Download +DescripciΓ³n: Registro de descargas de assets +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - asset_id: UUID (FK, opcional - puede ser colecciΓ³n) + - collection_id: UUID (FK, opcional) + - user_id: UUID (FK) + - download_type: enum [single, batch, collection] + - format: string (original, converted) + - ip_address: string + - user_agent: string + - created_at: timestamp + +Relaciones: + - N:1 con Asset + - N:1 con Collection + - N:1 con User +``` + +--- + +## Funcionalidades + +### F-006.1: GestiΓ³n de Assets + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-006.1.1 | Upload | Subir archivos manualmente | Alta | +| F-006.1.2 | Ver asset | Detalle con preview y metadata | Alta | +| F-006.1.3 | Editar metadata | Nombre, descripciΓ³n, tags | Alta | +| F-006.1.4 | Eliminar | Soft delete con papelera | Alta | +| F-006.1.5 | Restaurar | Recuperar de papelera | Media | + +### F-006.2: OrganizaciΓ³n + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-006.2.1 | Colecciones | Agrupar assets manualmente | Alta | +| F-006.2.2 | Smart collections | Colecciones automΓ‘ticas por criterios | Media | +| F-006.2.3 | Tags | Etiquetar assets | Alta | +| F-006.2.4 | Filtros | Filtrar por tipo, estado, fecha, etc. | Alta | + +### F-006.3: BΓΊsqueda + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-006.3.1 | BΓΊsqueda texto | Por nombre, descripciΓ³n, tags | Alta | +| F-006.3.2 | Filtros avanzados | Combinar mΓΊltiples criterios | Alta | +| F-006.3.3 | BΓΊsqueda por similar | Encontrar imΓ‘genes similares | Baja | + +### F-006.4: Versiones y AprobaciΓ³n + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-006.4.1 | Versionar | Subir nueva versiΓ³n de asset | Media | +| F-006.4.2 | Comparar versiones | Ver diferencias | Baja | +| F-006.4.3 | Aprobar/Rechazar | Cambiar estado de revisiΓ³n | Alta | +| F-006.4.4 | Comentarios | Feedback sobre assets | Alta | + +### F-006.5: Descargas y ExportaciΓ³n + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-006.5.1 | Descargar individual | Bajar un asset | Alta | +| F-006.5.2 | Descargar batch | Bajar mΓΊltiples como ZIP | Alta | +| F-006.5.3 | Convertir formato | Descargar en formato diferente | Media | +| F-006.5.4 | Enlace temporal | URL con expiraciΓ³n | Media | + +--- + +## Tipos de Assets Soportados + +```yaml +ImΓ‘genes: + Formatos: PNG, JPG, JPEG, WebP, GIF, SVG + Max size: 50MB + Procesamiento: + - GeneraciΓ³n de thumbnails + - ExtracciΓ³n de dimensiones + - OptimizaciΓ³n automΓ‘tica + +Copys/Textos: + Tipos: Copy publicitario, tΓ­tulo, descripciΓ³n, hashtags + Almacenamiento: En BD + archivo .txt opcional + Metadata: Tone, language, character count + +Videos: + Formatos: MP4, MOV, WebM + Max size: 500MB + Procesamiento: + - GeneraciΓ³n de thumbnail + - ExtracciΓ³n de duraciΓ³n + - Preview de baja resoluciΓ³n + +Documentos: + Formatos: PDF, DOC, DOCX + Max size: 100MB + Uso: Brand guidelines, briefs, contratos + +Modelos IA: + Tipos: LoRA (.safetensors), Checkpoint, Embedding + Max size: 10GB + Metadata: Base model, trigger word, training params + +Templates: + Tipos: Workflow ComfyUI, plantillas de brief + Formato: JSON +``` + +--- + +## Storage Structure + +```yaml +S3/MinIO Bucket Structure: + {bucket}/ + β”œβ”€β”€ {tenant_slug}/ + β”‚ β”œβ”€β”€ assets/ + β”‚ β”‚ β”œβ”€β”€ images/ + β”‚ β”‚ β”‚ β”œβ”€β”€ {year}/ + β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ {month}/ + β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ {asset_id}/ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ original.{ext} + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ thumb_200.jpg + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ thumb_800.jpg + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── versions/ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ v1.{ext} + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── v2.{ext} + β”‚ β”‚ β”œβ”€β”€ videos/ + β”‚ β”‚ β”œβ”€β”€ documents/ + β”‚ β”‚ └── copies/ + β”‚ β”œβ”€β”€ models/ + β”‚ β”‚ β”œβ”€β”€ loras/ + β”‚ β”‚ β”œβ”€β”€ checkpoints/ + β”‚ β”‚ └── embeddings/ + β”‚ └── temp/ + β”‚ └── (archivos temporales, limpiados periΓ³dicamente) +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/assets + +# Assets CRUD +POST /assets/upload # Subir archivo(s) +GET /assets # Listar con filtros y paginaciΓ³n +GET /assets/:id # Detalle de asset +PUT /assets/:id # Actualizar metadata +DELETE /assets/:id # Soft delete + +# Bulk operations +POST /assets/bulk/move # Mover a colecciΓ³n +POST /assets/bulk/tag # Agregar tags +POST /assets/bulk/delete # Eliminar mΓΊltiples +POST /assets/bulk/status # Cambiar estado + +# Versions +GET /assets/:id/versions # Listar versiones +POST /assets/:id/versions # Subir nueva versiΓ³n +GET /assets/:id/versions/:v # Obtener versiΓ³n especΓ­fica + +# Status & Approval +PATCH /assets/:id/status # Cambiar estado +POST /assets/:id/approve # Aprobar +POST /assets/:id/reject # Rechazar con feedback + +# Comments +GET /assets/:id/comments # Listar comentarios +POST /assets/:id/comments # Agregar comentario +PUT /assets/:id/comments/:cid # Editar comentario +DELETE /assets/:id/comments/:cid # Eliminar comentario + +# Downloads +GET /assets/:id/download # Descargar asset +POST /assets/download/batch # Descargar mΓΊltiples (ZIP) +POST /assets/:id/share # Generar enlace temporal + +# Collections +GET /collections # Listar colecciones +POST /collections # Crear colecciΓ³n +GET /collections/:id # Detalle de colecciΓ³n +PUT /collections/:id # Actualizar colecciΓ³n +DELETE /collections/:id # Eliminar colecciΓ³n +POST /collections/:id/assets # Agregar assets +DELETE /collections/:id/assets # Quitar assets + +# Search +POST /assets/search # BΓΊsqueda avanzada +GET /assets/tags # Listar tags usados +``` + +--- + +## Reglas de Negocio + +```yaml +RN-006.1: + DescripciΓ³n: Assets generados heredan metadata del job + Comportamiento: Copiar prompt, modelo, parΓ‘metros automΓ‘ticamente + +RN-006.2: + DescripciΓ³n: Thumbnails se generan automΓ‘ticamente + TamaΓ±os: 200px y 800px de ancho, manteniendo aspect ratio + +RN-006.3: + DescripciΓ³n: Soft delete retiene archivos 30 dΓ­as + AcciΓ³n: Cron job limpia despuΓ©s del perΓ­odo + +RN-006.4: + DescripciΓ³n: Versionado mantiene historial completo + LΓ­mite: MΓ‘ximo 10 versiones por asset + +RN-006.5: + DescripciΓ³n: Links temporales expiran segΓΊn configuraciΓ³n + Default: 7 dΓ­as, mΓ‘ximo 30 dΓ­as + +RN-006.6: + DescripciΓ³n: Storage cuenta contra cuota del tenant + ValidaciΓ³n: Verificar lΓ­mite antes de upload +``` + +--- + +## UI/UX Consideraciones + +```yaml +Vistas principales: + - Grid view: Thumbnails en cuadrΓ­cula + - List view: Lista con metadata + - Detail view: Asset grande con panel de info + +Componentes: + - AssetUploader: Drag & drop, multi-file + - AssetPreview: Lightbox con navegaciΓ³n + - AssetFilters: Panel de filtros colapsable + - CollectionPicker: Modal para agregar a colecciΓ³n + - CommentPanel: Sidebar con comentarios + +Acciones rΓ‘pidas: + - Quick preview (spacebar) + - Quick download (d) + - Quick approve (a) + - Add to collection (c) +``` + +--- + +## Dependencias + +```yaml +Dependencias de MΓ³dulos: + - PMC-001 Tenants: Cuotas de storage + - PMC-003 Projects: VinculaciΓ³n con campaΓ±as + - PMC-004 Generation: Assets generados + +Servicios Externos: + - S3/MinIO: Almacenamiento de archivos + - Sharp: Procesamiento de imΓ‘genes + - FFmpeg: Procesamiento de video (opcional) + +Dependencias del CatΓ‘logo: + - (ninguna directa) +``` + +--- + +## Consideraciones de Performance + +```yaml +Optimizaciones: + - Lazy loading de thumbnails + - PaginaciΓ³n con cursor para grandes volΓΊmenes + - CDN para servir assets estΓ‘ticos + - CompresiΓ³n de uploads grandes + - Pre-signed URLs para uploads directos a S3 + +Índices BD: + - tenant_id + type + status + - tenant_id + created_at + - tenant_id + tags (GIN index) + - Full-text search en name, description +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] Upload funciona con drag & drop y file picker +- [ ] Thumbnails se generan automΓ‘ticamente +- [ ] BΓΊsqueda y filtros funcionan correctamente +- [ ] Colecciones permiten organizar assets +- [ ] Versionado mantiene historial +- [ ] Flujo de aprobaciΓ³n funciona +- [ ] Descargas individuales y batch funcionan +- [ ] Links temporales se generan y expiran +- [ ] Comentarios se pueden agregar y resolver +- [ ] Storage se cuenta contra cuota + +--- + +## Referencias + +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [GLOSARIO.md](../00-vision-general/GLOSARIO.md) - DefiniciΓ³n de DAM + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-007-ADMIN.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-007-ADMIN.md new file mode 100644 index 0000000..3e67898 --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-007-ADMIN.md @@ -0,0 +1,495 @@ +# PMC-007: MΓ³dulo de Admin + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Media + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Admin proporciona las funcionalidades de administraciΓ³n del sistema SaaS: gestiΓ³n de usuarios, roles, permisos, planes de suscripciΓ³n, configuraciΓ³n global y herramientas de supervisiΓ³n. + +--- + +## Objetivos + +1. Gestionar usuarios y sus roles dentro del tenant +2. Controlar permisos de acceso por mΓ³dulo/acciΓ³n +3. Administrar planes y suscripciones (preparaciΓ³n SaaS) +4. Configurar parΓ‘metros globales del sistema +5. Monitorear uso y salud del sistema + +--- + +## Entidades del Dominio + +### User + +```yaml +Entidad: User +DescripciΓ³n: Usuario del sistema +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - email: string (ΓΊnico por tenant) + - password_hash: string + - first_name: string + - last_name: string + - avatar_url: string + - status: enum [pending, active, suspended, deactivated] + - role_id: UUID (FK) + - preferences: JSONB + - language: string + - timezone: string + - theme: string + - notifications: object + - last_login_at: timestamp + - email_verified_at: timestamp + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con Role + - 1:N con Project (como owner) + - 1:N con Asset (como creator) + - 1:N con GenerationJob +``` + +### Role + +```yaml +Entidad: Role +DescripciΓ³n: Rol con conjunto de permisos +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK, null = rol de sistema) + - name: string + - description: text + - permissions: array[string] (lista de permisos) + - is_system: boolean (no editable si true) + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant (opcional) + - 1:N con User + +Roles de Sistema: + - super_admin: Acceso total, sin lΓ­mites + - tenant_admin: Admin del tenant + - creative: Crear contenido, gestionar campaΓ±as + - analyst: CRM, reportes + - viewer: Solo lectura +``` + +### Permission (definiciΓ³n estΓ‘tica) + +```yaml +Permisos del Sistema: + # Tenants + - tenants.view + - tenants.create + - tenants.edit + - tenants.delete + + # Users + - users.view + - users.create + - users.edit + - users.delete + - users.invite + + # CRM + - clients.view + - clients.create + - clients.edit + - clients.delete + - brands.view + - brands.create + - brands.edit + - brands.delete + - products.view + - products.create + - products.edit + - products.delete + + # Projects + - projects.view + - projects.create + - projects.edit + - projects.delete + - campaigns.view + - campaigns.create + - campaigns.edit + - campaigns.delete + - campaigns.approve + + # Generation + - generation.execute + - generation.view_queue + - generation.manage_queue + - models.view + - models.create + - models.delete + - models.train + + # Assets + - assets.view + - assets.upload + - assets.edit + - assets.delete + - assets.approve + - assets.download + + # Automation + - automation.view + - automation.configure + - automation.execute + + # Admin + - admin.users + - admin.roles + - admin.settings + - admin.billing + - admin.audit +``` + +### Invitation + +```yaml +Entidad: Invitation +DescripciΓ³n: InvitaciΓ³n pendiente para unirse al tenant +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - email: string + - role_id: UUID (FK) + - invited_by: UUID (FK a User) + - token: string (ΓΊnico) + - status: enum [pending, accepted, expired, cancelled] + - expires_at: timestamp + - accepted_at: timestamp + - created_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con Role + - N:1 con User (inviter) +``` + +### AuditLog + +```yaml +Entidad: AuditLog +DescripciΓ³n: Registro de acciones importantes +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - user_id: UUID (FK) + - action: string (ej: user.created, asset.deleted) + - entity_type: string + - entity_id: UUID + - old_values: JSONB + - new_values: JSONB + - ip_address: string + - user_agent: string + - created_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con User +``` + +### Setting + +```yaml +Entidad: Setting +DescripciΓ³n: ConfiguraciΓ³n del sistema/tenant +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK, null = global) + - key: string + - value: JSONB + - type: enum [string, number, boolean, json] + - category: string + - is_secret: boolean + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant (opcional) +``` + +--- + +## Funcionalidades + +### F-007.1: GestiΓ³n de Usuarios + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-007.1.1 | Listar usuarios | Ver todos los usuarios del tenant | Alta | +| F-007.1.2 | Invitar usuario | Enviar invitaciΓ³n por email | Alta | +| F-007.1.3 | Editar usuario | Modificar datos y rol | Alta | +| F-007.1.4 | Suspender usuario | Bloquear acceso temporalmente | Media | +| F-007.1.5 | Eliminar usuario | Desactivar cuenta | Media | + +### F-007.2: GestiΓ³n de Roles + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-007.2.1 | Listar roles | Ver roles disponibles | Alta | +| F-007.2.2 | Crear rol | Definir rol personalizado | Media | +| F-007.2.3 | Editar permisos | Modificar permisos de rol | Media | +| F-007.2.4 | Eliminar rol | Solo si no tiene usuarios | Baja | + +### F-007.3: ConfiguraciΓ³n + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-007.3.1 | Settings generales | Nombre, branding, etc. | Alta | +| F-007.3.2 | Settings de generaciΓ³n | Modelos por defecto, calidad | Media | +| F-007.3.3 | Integraciones | Configurar n8n, APIs externas | Media | +| F-007.3.4 | Notificaciones | Templates de email, webhooks | Media | + +### F-007.4: AuditorΓ­a + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-007.4.1 | Ver logs | Historial de acciones | Media | +| F-007.4.2 | Filtrar logs | Por usuario, acciΓ³n, fecha | Media | +| F-007.4.3 | Exportar logs | Descargar en CSV | Baja | + +### F-007.5: Monitoreo (Super Admin) + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-007.5.1 | Dashboard sistema | MΓ©tricas globales | Media | +| F-007.5.2 | Estado de servicios | GPU, queue, storage | Alta | +| F-007.5.3 | Uso por tenant | Consumo de recursos | Media | + +--- + +## Roles del Sistema + +### Matriz de Permisos por Rol + +```yaml +super_admin: + description: "Administrador del sistema completo" + permissions: ["*"] # Todos los permisos + notes: "Solo para el owner/CTO. Sin lΓ­mites de uso." + +tenant_admin: + description: "Administrador del tenant/agencia" + permissions: + - users.* + - roles.view + - clients.* + - brands.* + - products.* + - projects.* + - campaigns.* + - generation.* + - assets.* + - automation.view + - automation.configure + - admin.users + - admin.settings + - admin.audit + +creative: + description: "Creativo/Media Buyer" + permissions: + - clients.view + - brands.view + - products.view + - products.create + - projects.view + - projects.create + - projects.edit + - campaigns.* + - generation.execute + - generation.view_queue + - models.view + - assets.view + - assets.upload + - assets.edit + +analyst: + description: "Analista/CRM" + permissions: + - clients.* + - brands.view + - products.view + - projects.view + - campaigns.view + - assets.view + - assets.download + - automation.view + +viewer: + description: "Solo lectura" + permissions: + - clients.view + - brands.view + - products.view + - projects.view + - campaigns.view + - assets.view + +client_portal: + description: "Cliente externo (portal)" + permissions: + - campaigns.view # Solo sus campaΓ±as + - assets.view # Solo sus assets + - assets.download +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/admin + +# Users +GET /users # Listar usuarios +GET /users/:id # Detalle de usuario +POST /users/invite # Invitar usuario +PUT /users/:id # Actualizar usuario +PATCH /users/:id/status # Cambiar estado +DELETE /users/:id # Desactivar usuario + +# Invitations +GET /invitations # Listar invitaciones +POST /invitations/:id/resend # Reenviar +DELETE /invitations/:id # Cancelar + +# Roles +GET /roles # Listar roles +GET /roles/:id # Detalle de rol +POST /roles # Crear rol +PUT /roles/:id # Actualizar rol +DELETE /roles/:id # Eliminar rol + +# Settings +GET /settings # Listar settings +GET /settings/:key # Obtener setting +PUT /settings/:key # Actualizar setting +DELETE /settings/:key # Eliminar setting (custom) + +# Audit +GET /audit # Listar logs +GET /audit/export # Exportar logs + +# System (Super Admin only) +GET /system/status # Estado del sistema +GET /system/metrics # MΓ©tricas globales +GET /system/tenants # Listar todos los tenants +GET /system/tenants/:id/usage # Uso de un tenant +``` + +--- + +## Reglas de Negocio + +```yaml +RN-007.1: + DescripciΓ³n: Email ΓΊnico por tenant + ValidaciΓ³n: No puede haber dos usuarios con mismo email en un tenant + +RN-007.2: + DescripciΓ³n: Roles de sistema no editables + ValidaciΓ³n: is_system = true bloquea ediciΓ³n + +RN-007.3: + DescripciΓ³n: No eliminar rol con usuarios asignados + ValidaciΓ³n: Verificar user_count = 0 antes de DELETE + +RN-007.4: + DescripciΓ³n: InvitaciΓ³n expira en 7 dΓ­as + ValidaciΓ³n: expires_at = created_at + 7 days + +RN-007.5: + DescripciΓ³n: Super admin no puede ser suspendido + ValidaciΓ³n: Bloquear cambio de status si role = super_admin + +RN-007.6: + DescripciΓ³n: Audit logs son inmutables + ValidaciΓ³n: Solo INSERT, no UPDATE ni DELETE +``` + +--- + +## Dependencias + +```yaml +Dependencias de MΓ³dulos: + - PMC-001 Tenants: ConfiguraciΓ³n de tenant + - Todos los mΓ³dulos: Para verificaciΓ³n de permisos + +Dependencias del CatΓ‘logo: + - @CATALOG_AUTH: AutenticaciΓ³n JWT + OAuth + - @CATALOG_SESSION: GestiΓ³n de sesiones + +Servicios Externos: + - SMTP: EnvΓ­o de invitaciones + - (OAuth providers si se implementa SSO) +``` + +--- + +## Flujos de Usuario + +### Invitar Usuario + +``` +1. Admin navega a Users β†’ Invite +2. Ingresa email y selecciona rol +3. Sistema genera token ΓΊnico +4. Sistema envΓ­a email con link +5. Usuario hace clic en link +6. Usuario completa registro (password, nombre) +7. Usuario queda activo en el tenant +``` + +### Cambiar Rol de Usuario + +``` +1. Admin navega a Users β†’ [Usuario] +2. Selecciona nuevo rol +3. Sistema verifica que no sea el ΓΊnico admin +4. Sistema actualiza rol +5. Permisos se aplican inmediatamente +6. Se registra en audit log +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] CRUD completo de usuarios funciona +- [ ] Sistema de invitaciones por email funciona +- [ ] Roles controlan acceso a mΓ³dulos correctamente +- [ ] Permisos se verifican en cada endpoint +- [ ] Settings se guardan y cargan correctamente +- [ ] Audit logs registran acciones importantes +- [ ] Dashboard de sistema muestra mΓ©tricas +- [ ] Super admin tiene acceso a todo + +--- + +## Referencias + +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [@CATALOG_AUTH](../../../core/catalog/modules/auth/) +- [PMC-001-TENANTS.md](./PMC-001-TENANTS.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-008-ANALYTICS.md b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-008-ANALYTICS.md new file mode 100644 index 0000000..fabafbd --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/PMC-008-ANALYTICS.md @@ -0,0 +1,443 @@ +# PMC-008: MΓ³dulo de Analytics + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 +**Estado:** DefiniciΓ³n +**Prioridad:** Baja + +--- + +## DescripciΓ³n General + +El mΓ³dulo de Analytics proporciona dashboards, reportes y mΓ©tricas sobre el uso de la plataforma, rendimiento de campaΓ±as, y consumo de recursos. Permite tomar decisiones basadas en datos. + +--- + +## Objetivos + +1. Visualizar mΓ©tricas clave de operaciΓ³n +2. Analizar rendimiento de campaΓ±as +3. Monitorear uso de recursos (generaciones, storage) +4. Generar reportes exportables +5. Identificar tendencias y oportunidades + +--- + +## Dashboards + +### Dashboard Principal (Home) + +```yaml +Widgets: + - quick_stats: + - CampaΓ±as activas + - Assets generados (mes) + - Tasa de aprobaciΓ³n + - Jobs en cola + + - recent_activity: + - Últimos assets generados + - CampaΓ±as reciΓ©n creadas + - Jobs completados + + - pending_actions: + - Assets pendientes de revisiΓ³n + - CampaΓ±as esperando aprobaciΓ³n +``` + +### Dashboard de ProducciΓ³n + +```yaml +Widgets: + - generation_volume: + Tipo: Line chart + Datos: Generaciones por dΓ­a/semana/mes + Filtros: Tipo (imagen/texto), workflow + + - queue_status: + Tipo: Real-time gauge + Datos: Jobs en cola, procesando, completados + + - model_usage: + Tipo: Pie chart + Datos: DistribuciΓ³n de uso de workflows/LoRAs + + - error_rate: + Tipo: Line chart + Datos: % de jobs fallidos por perΓ­odo + + - processing_time: + Tipo: Bar chart + Datos: Tiempo promedio por tipo de workflow +``` + +### Dashboard de CampaΓ±as + +```yaml +Widgets: + - campaign_funnel: + Tipo: Funnel chart + Datos: CampaΓ±as por estado + + - approval_metrics: + Tipo: Stats cards + Datos: + - Tasa de aprobaciΓ³n primera iteraciΓ³n + - Promedio de revisiones por campaΓ±a + - Tiempo desde brief hasta aprobaciΓ³n + + - assets_per_campaign: + Tipo: Bar chart + Datos: Promedio de assets por campaΓ±a + + - top_clients: + Tipo: Table + Datos: Clientes con mΓ‘s campaΓ±as/assets +``` + +### Dashboard de Recursos + +```yaml +Widgets: + - storage_usage: + Tipo: Progress bar + breakdown + Datos: GB usados vs cuota, por tipo de archivo + + - generation_quota: + Tipo: Progress bar + Datos: Generaciones usadas vs lΓ­mite mensual + + - gpu_utilization: + Tipo: Real-time gauge (si aplica) + Datos: % de uso de GPU + + - cost_estimate: + Tipo: Stats card + Datos: Costo estimado de APIs externas (LLM, etc.) +``` + +--- + +## Reportes + +### Reporte de Actividad Mensual + +```yaml +Nombre: monthly_activity_report +PerΓ­odo: Mes natural +Contenido: + - Resumen ejecutivo + - CampaΓ±as creadas/completadas + - Assets generados por tipo + - Clientes mΓ‘s activos + - Uso de recursos + - Comparativa con mes anterior + +Formatos: PDF, Excel +ProgramaciΓ³n: AutomΓ‘tico primer dΓ­a del mes +``` + +### Reporte de CampaΓ±a + +```yaml +Nombre: campaign_report +PerΓ­odo: DuraciΓ³n de la campaΓ±a +Contenido: + - Datos de la campaΓ±a y brief + - Assets generados + - Historial de revisiones + - Tiempo total de producciΓ³n + - Participantes (usuarios) + +Formatos: PDF +GeneraciΓ³n: Manual o al cerrar campaΓ±a +``` + +### Reporte de Cliente + +```yaml +Nombre: client_report +PerΓ­odo: Configurable +Contenido: + - Proyectos y campaΓ±as del cliente + - Assets entregados + - HistΓ³rico de actividad + - MΓ©tricas de satisfacciΓ³n (si aplica) + +Formatos: PDF, Excel +GeneraciΓ³n: Manual +``` + +### Reporte de Uso (Admin) + +```yaml +Nombre: usage_report +PerΓ­odo: Configurable +Contenido: + - Generaciones por usuario + - Storage consumido + - Costo de APIs externas + - Comparativa por perΓ­odo + +Formatos: Excel, CSV +Audiencia: Admin/Finance +``` + +--- + +## Entidades del Dominio + +### Metric + +```yaml +Entidad: Metric (tabla de hechos) +DescripciΓ³n: Registro agregado de mΓ©tricas +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - metric_type: string (generation_count, storage_used, etc.) + - dimension_1: string (ej: workflow_type) + - dimension_2: string (ej: user_id) + - value: decimal + - period_type: enum [hour, day, week, month] + - period_start: timestamp + - created_at: timestamp + +Índices: + - tenant_id + metric_type + period_start + - tenant_id + period_type + period_start +``` + +### Report + +```yaml +Entidad: Report +DescripciΓ³n: Reporte generado +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - name: string + - type: string (monthly_activity, campaign, client, usage) + - parameters: JSONB (filtros aplicados) + - file_path: string + - file_format: enum [pdf, xlsx, csv] + - generated_by: UUID (FK a User) + - created_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con User +``` + +### SavedView + +```yaml +Entidad: SavedView +DescripciΓ³n: Vista personalizada guardada +Atributos: + - id: UUID (PK) + - tenant_id: UUID (FK) + - user_id: UUID (FK) + - name: string + - dashboard: string (production, campaigns, resources) + - config: JSONB (filtros, widgets visibles, layout) + - is_default: boolean + - created_at: timestamp + - updated_at: timestamp + +Relaciones: + - N:1 con Tenant + - N:1 con User +``` + +--- + +## Funcionalidades + +### F-008.1: Dashboards + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-008.1.1 | Dashboard home | Vista principal con KPIs | Alta | +| F-008.1.2 | Dashboard producciΓ³n | MΓ©tricas de generaciΓ³n | Media | +| F-008.1.3 | Dashboard campaΓ±as | MΓ©tricas de campaΓ±as | Media | +| F-008.1.4 | Dashboard recursos | Uso de recursos | Media | +| F-008.1.5 | Filtros globales | Por fecha, cliente, usuario | Alta | + +### F-008.2: Reportes + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-008.2.1 | Generar reporte | Crear reporte bajo demanda | Media | +| F-008.2.2 | Programar reporte | GeneraciΓ³n automΓ‘tica | Baja | +| F-008.2.3 | Descargar reporte | PDF, Excel, CSV | Media | +| F-008.2.4 | Historial reportes | Ver reportes generados | Baja | + +### F-008.3: PersonalizaciΓ³n + +| ID | Funcionalidad | DescripciΓ³n | Prioridad | +|----|---------------|-------------|-----------| +| F-008.3.1 | Guardar vista | Guardar configuraciΓ³n de dashboard | Baja | +| F-008.3.2 | Vista por defecto | Establecer vista inicial | Baja | + +--- + +## KPIs Principales + +```yaml +OperaciΓ³n: + - Generaciones totales (dΓ­a/semana/mes) + - Tiempo promedio de generaciΓ³n + - Tasa de Γ©xito de jobs (%) + - Cola promedio (tiempo de espera) + +CampaΓ±as: + - CampaΓ±as activas + - Tiempo promedio brief β†’ aprobaciΓ³n + - Tasa de aprobaciΓ³n primera iteraciΓ³n (%) + - Assets por campaΓ±a (promedio) + +Recursos: + - Storage utilizado vs cuota (%) + - Generaciones usadas vs lΓ­mite (%) + - Costo estimado de APIs externas + +Usuarios: + - Usuarios activos (dΓ­a/semana/mes) + - Generaciones por usuario + - Acciones por usuario +``` + +--- + +## API Endpoints + +```yaml +Base: /api/v1/analytics + +# Dashboards +GET /dashboards/:name # Datos de dashboard +GET /dashboards/:name/widgets/:widget # Datos de widget especΓ­fico + +# Metrics +GET /metrics # Query de mΓ©tricas +POST /metrics/aggregate # AgregaciΓ³n personalizada + +# Reports +GET /reports # Listar reportes generados +POST /reports # Generar nuevo reporte +GET /reports/:id # Detalle de reporte +GET /reports/:id/download # Descargar archivo +DELETE /reports/:id # Eliminar reporte + +# Saved Views +GET /views # Listar vistas guardadas +POST /views # Crear vista +PUT /views/:id # Actualizar vista +DELETE /views/:id # Eliminar vista +PATCH /views/:id/default # Establecer como default + +# Quick stats (para widgets) +GET /stats/overview # Resumen general +GET /stats/generations # Stats de generaciΓ³n +GET /stats/campaigns # Stats de campaΓ±as +GET /stats/storage # Stats de storage +``` + +--- + +## Arquitectura de Datos + +### Pipeline de MΓ©tricas + +```yaml +Flujo: + 1. Evento ocurre (generaciΓ³n, campaΓ±a creada, etc.) + 2. EventEmitter emite evento + 3. MetricsService captura y procesa + 4. Se inserta en tabla metrics (agregado horario) + 5. Job nocturno consolida a dΓ­a/semana/mes + +RetenciΓ³n: + - MΓ©tricas horarias: 7 dΓ­as + - MΓ©tricas diarias: 90 dΓ­as + - MΓ©tricas semanales: 1 aΓ±o + - MΓ©tricas mensuales: indefinido +``` + +### Queries Optimizadas + +```yaml +Estrategias: + - Tablas de mΓ©tricas pre-agregadas + - Índices por tenant + perΓ­odo + - Cache en Redis para datos frecuentes + - Refresh periΓ³dico de materialized views +``` + +--- + +## Dependencias + +```yaml +Dependencias de MΓ³dulos: + - PMC-001 Tenants: Contexto de datos + - PMC-003 Projects: Datos de campaΓ±as + - PMC-004 Generation: Datos de generaciΓ³n + - PMC-006 Assets: Datos de almacenamiento + +Servicios Externos: + - Redis: Cache de mΓ©tricas + - (Opcional) Chart library frontend + +Dependencias del CatΓ‘logo: + - (ninguna directa) +``` + +--- + +## UI/UX Consideraciones + +```yaml +Componentes: + - DashboardGrid: Layout responsivo de widgets + - ChartWidget: Wrapper para grΓ‘ficos + - FilterBar: Barra de filtros global + - DateRangePicker: Selector de perΓ­odo + - ExportButton: Descarga de datos/reportes + +Interactividad: + - Drill-down en grΓ‘ficos + - Tooltips con detalles + - Filtros aplicables a toda la pΓ‘gina + - Auto-refresh configurable + +Responsividad: + - Widgets se reordenan en mΓ³vil + - GrΓ‘ficos adaptan tamaΓ±o + - Tablas con scroll horizontal +``` + +--- + +## Criterios de AceptaciΓ³n + +- [ ] Dashboard home muestra KPIs correctos +- [ ] Filtros de fecha funcionan globalmente +- [ ] GrΓ‘ficos cargan datos correctamente +- [ ] Reportes se generan en PDF y Excel +- [ ] MΓ©tricas se agregan correctamente +- [ ] Cache mejora tiempos de carga +- [ ] Datos se aΓ­slan por tenant + +--- + +## Referencias + +- [VISION-GENERAL.md](../00-vision-general/VISION-GENERAL.md) +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/02-definicion-modulos/_INDEX.md b/projects/platform_marketing_content/docs/02-definicion-modulos/_INDEX.md new file mode 100644 index 0000000..c524def --- /dev/null +++ b/projects/platform_marketing_content/docs/02-definicion-modulos/_INDEX.md @@ -0,0 +1,148 @@ +# Índice de MΓ³dulos - Platform Marketing Content + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## Resumen de MΓ³dulos + +| ID | MΓ³dulo | DescripciΓ³n | Prioridad | Estado | +|----|--------|-------------|-----------|--------| +| PMC-001 | [Tenants](./PMC-001-TENANTS.md) | Arquitectura multi-tenant, planes, configuraciΓ³n | Alta | Definido | +| PMC-002 | [CRM](./PMC-002-CRM.md) | Clientes, marcas, productos, oportunidades | Alta | Definido | +| PMC-003 | [Projects](./PMC-003-PROJECTS.md) | Proyectos, campaΓ±as, briefs, flujos de trabajo | Alta | Definido | +| PMC-004 | [Generation](./PMC-004-GENERATION.md) | Motor de IA, workflows ComfyUI, modelos custom | Alta | Definido | +| PMC-005 | [Automation](./PMC-005-AUTOMATION.md) | Flujos automatizados con n8n, triggers, webhooks | Media | Definido | +| PMC-006 | [Assets](./PMC-006-ASSETS.md) | DAM, biblioteca de activos, versionado | Alta | Definido | +| PMC-007 | [Admin](./PMC-007-ADMIN.md) | Usuarios, roles, permisos, configuraciΓ³n SaaS | Media | Definido | +| PMC-008 | [Analytics](./PMC-008-ANALYTICS.md) | Dashboards, reportes, mΓ©tricas | Baja | Definido | + +--- + +## Dependencias entre MΓ³dulos + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ PMC-001 Tenants β”‚ +β”‚ (Base de aislamiento) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ PMC-007 β”‚ β”‚ PMC-002 β”‚ β”‚ PMC-006 β”‚ +β”‚ Admin β”‚ β”‚ CRM β”‚ β”‚ Assets β”‚ +β”‚ (Users/Roles)β”‚ β”‚ (Clientes) β”‚ β”‚ (DAM) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β–² + β”‚ β”‚ β”‚ + β”‚ β–Ό β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ PMC-003 β”‚ β”‚ + β”‚ β”‚ Projects │─────────────── + β”‚ β”‚ (CampaΓ±as) β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ β”‚ + β”‚ β–Ό β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ PMC-004 β”‚ β”‚ + β”‚ β”‚ Generation β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ (Motor IA) β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ β–Ό + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + └───────────►│ PMC-005 β”‚ + β”‚ Automation β”‚ + β”‚ (n8n) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ PMC-008 β”‚ + β”‚ Analytics β”‚ + β”‚ (MΓ©tricas) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Orden de ImplementaciΓ³n Sugerido + +### Fase 1 - Core MVP + +1. **PMC-001 Tenants** - Base de la arquitectura +2. **PMC-007 Admin** - Usuarios y autenticaciΓ³n +3. **PMC-002 CRM** - GestiΓ³n de clientes y marcas +4. **PMC-006 Assets** - Almacenamiento de activos +5. **PMC-003 Projects** - Proyectos y campaΓ±as bΓ‘sicos +6. **PMC-004 Generation** - Motor de generaciΓ³n (2-3 workflows) + +### Fase 2 - AutomatizaciΓ³n + +7. **PMC-005 Automation** - Flujos automatizados + +### Fase 3 - Analytics + +8. **PMC-008 Analytics** - Dashboards y reportes + +--- + +## Entidades Compartidas + +| Entidad | MΓ³dulo Principal | MΓ³dulos que Referencian | +|---------|------------------|------------------------| +| Tenant | PMC-001 | Todos | +| User | PMC-007 | Todos | +| Client | PMC-002 | PMC-003, PMC-008 | +| Brand | PMC-002 | PMC-003, PMC-004, PMC-006 | +| Product | PMC-002 | PMC-004, PMC-006 | +| Campaign | PMC-003 | PMC-004, PMC-005, PMC-006, PMC-008 | +| Asset | PMC-006 | PMC-002, PMC-003, PMC-004 | +| GenerationJob | PMC-004 | PMC-003, PMC-006, PMC-008 | + +--- + +## APIs por MΓ³dulo + +| MΓ³dulo | Base Path | Endpoints Principales | +|--------|-----------|----------------------| +| Tenants | `/api/v1/tenants` | CRUD tenants, config | +| CRM | `/api/v1/crm` | clients, contacts, brands, products, opportunities | +| Projects | `/api/v1/projects` | projects, campaigns, briefs | +| Generation | `/api/v1/generation` | jobs, workflows, models | +| Automation | `/api/v1/automation` | flows, runs, webhooks | +| Assets | `/api/v1/assets` | assets, collections, downloads | +| Admin | `/api/v1/admin` | users, roles, settings, audit | +| Analytics | `/api/v1/analytics` | dashboards, metrics, reports | + +--- + +## Conteo de Funcionalidades + +| MΓ³dulo | Funcionalidades | Prioridad Alta | Prioridad Media | Prioridad Baja | +|--------|-----------------|----------------|-----------------|----------------| +| PMC-001 | 10 | 6 | 3 | 1 | +| PMC-002 | 18 | 12 | 5 | 1 | +| PMC-003 | 16 | 10 | 5 | 1 | +| PMC-004 | 20 | 12 | 6 | 2 | +| PMC-005 | 12 | 4 | 6 | 2 | +| PMC-006 | 18 | 10 | 6 | 2 | +| PMC-007 | 14 | 7 | 5 | 2 | +| PMC-008 | 10 | 3 | 5 | 2 | +| **TOTAL** | **118** | **64** | **41** | **13** | + +--- + +## Referencias + +- [VISION-GENERAL.md](../00-vision-general/VISION-GENERAL.md) +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [GLOSARIO.md](../00-vision-general/GLOSARIO.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-001-TENANTS.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-001-TENANTS.md new file mode 100644 index 0000000..a2c74df --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-001-TENANTS.md @@ -0,0 +1,512 @@ +# Requerimientos Funcionales - PMC-001 Tenants + +**MΓ³dulo:** Tenants +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## RF-PMC-001-001: Crear Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-001 | +| **Nombre** | Crear Tenant | +| **Prioridad** | P1 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir crear un nuevo tenant con datos bΓ‘sicos. + +**Precondiciones:** +- Usuario autenticado como Super Admin + +**Datos de entrada:** +- name: string (requerido, 3-100 caracteres) +- slug: string (requerido, ΓΊnico, formato URL-safe) +- plan_id: UUID (requerido) +- settings: object (opcional) +- branding: object (opcional) + +**Flujo principal:** +1. Super Admin accede a gestiΓ³n de tenants +2. Selecciona "Crear tenant" +3. Completa formulario con datos requeridos +4. Sistema valida unicidad del slug +5. Sistema crea tenant con status "active" +6. Sistema crea usuario admin inicial (opcional) +7. Sistema retorna tenant creado + +**Postcondiciones:** +- Tenant existe en base de datos +- Tenant tiene plan asignado +- RLS configurado para nuevo tenant + +**Criterios de aceptaciΓ³n:** +- [ ] ValidaciΓ³n de slug ΓΊnico funciona +- [ ] Tenant se crea con status "active" +- [ ] Plan se asocia correctamente + +--- + +## RF-PMC-001-002: Editar Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-002 | +| **Nombre** | Editar Tenant | +| **Prioridad** | P2 | +| **Actor** | Super Admin, Tenant Admin | + +**DescripciΓ³n:** +El sistema debe permitir modificar datos de un tenant existente. + +**Precondiciones:** +- Usuario autenticado con permisos de ediciΓ³n +- Tenant existe + +**Datos de entrada:** +- name: string (opcional) +- settings: object (opcional) +- branding: object (opcional) +- limits: object (opcional, solo Super Admin) + +**Flujo principal:** +1. Usuario accede a configuraciΓ³n del tenant +2. Modifica campos permitidos segΓΊn rol +3. Sistema valida datos +4. Sistema actualiza tenant +5. Sistema registra cambio en audit log + +**Restricciones:** +- Tenant Admin no puede modificar limits ni plan +- Slug no es editable despuΓ©s de creaciΓ³n + +**Criterios de aceptaciΓ³n:** +- [ ] Campos se actualizan correctamente +- [ ] Permisos por rol se respetan +- [ ] Audit log registra cambios + +--- + +## RF-PMC-001-003: Suspender Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-003 | +| **Nombre** | Suspender Tenant | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir suspender un tenant, bloqueando acceso de usuarios. + +**Precondiciones:** +- Usuario autenticado como Super Admin +- Tenant existe con status "active" + +**Flujo principal:** +1. Super Admin selecciona tenant a suspender +2. Sistema solicita confirmaciΓ³n +3. Sistema cambia status a "suspended" +4. Sistema invalida todas las sesiones del tenant +5. Sistema notifica a admins del tenant + +**Postcondiciones:** +- Usuarios del tenant no pueden hacer login +- Datos permanecen intactos +- Jobs pendientes se pausan + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "suspended" +- [ ] Login bloqueado para usuarios del tenant +- [ ] Sesiones existentes invalidadas + +--- + +## RF-PMC-001-004: Reactivar Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-004 | +| **Nombre** | Reactivar Tenant | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir reactivar un tenant suspendido. + +**Precondiciones:** +- Tenant existe con status "suspended" + +**Flujo principal:** +1. Super Admin selecciona tenant suspendido +2. Selecciona "Reactivar" +3. Sistema cambia status a "active" +4. Sistema notifica a admins del tenant + +**Postcondiciones:** +- Usuarios pueden hacer login +- Jobs pausados se reactivan + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "active" +- [ ] Login permitido nuevamente + +--- + +## RF-PMC-001-005: Eliminar Tenant (Soft Delete) + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-005 | +| **Nombre** | Eliminar Tenant | +| **Prioridad** | P3 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir eliminar un tenant mediante soft delete. + +**Precondiciones:** +- Tenant existe + +**Flujo principal:** +1. Super Admin selecciona tenant a eliminar +2. Sistema solicita confirmaciΓ³n con texto de verificaciΓ³n +3. Sistema marca tenant como eliminado (deleted_at) +4. Sistema invalida sesiones +5. Sistema programa limpieza de datos (90 dΓ­as) + +**Postcondiciones:** +- Tenant marcado con deleted_at +- Datos retenidos por 90 dΓ­as +- Acceso completamente bloqueado + +**Criterios de aceptaciΓ³n:** +- [ ] Soft delete funciona correctamente +- [ ] Datos no se eliminan inmediatamente +- [ ] Tenant no aparece en listados + +--- + +## RF-PMC-001-006: Listar Tenants + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-006 | +| **Nombre** | Listar Tenants | +| **Prioridad** | P1 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir listar todos los tenants con filtros y paginaciΓ³n. + +**Datos de entrada (query params):** +- status: string (filtro por estado) +- plan_id: UUID (filtro por plan) +- search: string (bΓΊsqueda por nombre) +- page: number +- limit: number (max 100) + +**Datos de salida:** +- Lista de tenants con datos bΓ‘sicos +- Total de registros +- InformaciΓ³n de paginaciΓ³n + +**Criterios de aceptaciΓ³n:** +- [ ] PaginaciΓ³n funciona correctamente +- [ ] Filtros se aplican correctamente +- [ ] BΓΊsqueda por nombre funciona + +--- + +## RF-PMC-001-007: Ver Detalle de Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-007 | +| **Nombre** | Ver Detalle de Tenant | +| **Prioridad** | P1 | +| **Actor** | Super Admin, Tenant Admin | + +**DescripciΓ³n:** +El sistema debe mostrar informaciΓ³n detallada de un tenant. + +**Datos de salida:** +- Datos bΓ‘sicos del tenant +- Plan asociado con lΓ­mites +- ConfiguraciΓ³n (settings) +- Branding +- EstadΓ­sticas de uso +- Usuarios activos (count) + +**Criterios de aceptaciΓ³n:** +- [ ] Todos los datos se muestran correctamente +- [ ] Tenant Admin solo ve su propio tenant + +--- + +## RF-PMC-001-008: Configurar Branding + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-008 | +| **Nombre** | Configurar Branding | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +El sistema debe permitir personalizar el branding del tenant. + +**Datos de entrada:** +- logo_url: string (URL o upload) +- primary_color: string (hex color) +- secondary_color: string (hex color) +- favicon_url: string (opcional) + +**Flujo principal:** +1. Admin accede a configuraciΓ³n de branding +2. Sube logo o proporciona URL +3. Selecciona colores +4. Sistema valida formatos +5. Sistema actualiza branding +6. Cambios se reflejan en UI + +**Criterios de aceptaciΓ³n:** +- [ ] Logo se almacena/referencia correctamente +- [ ] Colores se aplican en UI +- [ ] Preview disponible antes de guardar + +--- + +## RF-PMC-001-009: Configurar LΓ­mites Personalizados + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-009 | +| **Nombre** | Configurar LΓ­mites Personalizados | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir sobreescribir lΓ­mites del plan para un tenant especΓ­fico. + +**Datos de entrada:** +- generations_per_month: number (null = usar plan) +- storage_gb: number (null = usar plan) +- users_max: number (null = usar plan) +- custom_limits: object + +**Flujo principal:** +1. Super Admin accede a lΓ­mites del tenant +2. Modifica valores especΓ­ficos +3. Sistema valida que valores sean >= 0 +4. Sistema guarda lΓ­mites personalizados +5. LΓ­mites se aplican sobre los del plan + +**Criterios de aceptaciΓ³n:** +- [ ] LΓ­mites personalizados sobreescriben plan +- [ ] Valores null usan defaults del plan +- [ ] Cambios se aplican inmediatamente + +--- + +## RF-PMC-001-010: Obtener Tenant Actual + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-010 | +| **Nombre** | Obtener Tenant Actual | +| **Prioridad** | P1 | +| **Actor** | Usuario autenticado | + +**DescripciΓ³n:** +El sistema debe proporcionar los datos del tenant del usuario actual. + +**Flujo principal:** +1. Usuario hace request a /tenants/current +2. Sistema extrae tenant_id del JWT +3. Sistema retorna datos del tenant + +**Datos de salida:** +- Datos bΓ‘sicos del tenant +- Plan con lΓ­mites efectivos +- Branding +- Settings relevantes para el usuario + +**Criterios de aceptaciΓ³n:** +- [ ] Endpoint retorna tenant correcto +- [ ] LΓ­mites efectivos calculados correctamente + +--- + +## RF-PMC-001-011: Validar Cuota de Uso + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-011 | +| **Nombre** | Validar Cuota de Uso | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +El sistema debe validar cuotas antes de operaciones que consumen recursos. + +**Operaciones validadas:** +- GeneraciΓ³n de imΓ‘genes +- Entrenamiento de modelos +- Subida de archivos (storage) +- CreaciΓ³n de usuarios + +**Flujo principal:** +1. Usuario solicita operaciΓ³n +2. Sistema obtiene lΓ­mites del tenant +3. Sistema obtiene uso actual +4. Sistema compara uso vs lΓ­mite +5. Si excede: rechaza con error especΓ­fico +6. Si no excede: permite operaciΓ³n + +**Criterios de aceptaciΓ³n:** +- [ ] ValidaciΓ³n ocurre antes de cada operaciΓ³n +- [ ] Mensaje de error indica lΓ­mite y uso actual +- [ ] Operaciones no se ejecutan si exceden lΓ­mite + +--- + +## RF-PMC-001-012: Aplicar RLS por Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-012 | +| **Nombre** | Aplicar RLS por Tenant | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +El sistema debe garantizar aislamiento de datos entre tenants mediante RLS. + +**ImplementaciΓ³n:** +1. Todas las tablas principales tienen columna tenant_id +2. PolΓ­ticas RLS filtran por tenant_id +3. Middleware inyecta tenant_id en cada request +4. SET app.current_tenant ejecutado antes de queries + +**Tablas afectadas:** +- clients, contacts, brands, products +- projects, campaigns +- assets, collections +- users, roles +- generation_jobs, custom_models +- automation_flows, automation_runs + +**Criterios de aceptaciΓ³n:** +- [ ] Queries solo retornan datos del tenant actual +- [ ] INSERT automΓ‘ticamente incluye tenant_id +- [ ] No es posible acceder a datos de otro tenant + +--- + +## RF-PMC-001-013: Gestionar Planes + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-013 | +| **Nombre** | Gestionar Planes | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir crear y gestionar planes de suscripciΓ³n. + +**Datos de entrada:** +- name: string +- code: string (ΓΊnico) +- features: object (funcionalidades habilitadas) +- limits: object (cuotas) +- price_monthly: decimal +- price_yearly: decimal +- is_active: boolean + +**Operaciones:** +- Crear plan +- Editar plan +- Activar/desactivar plan +- Ver tenants por plan + +**Criterios de aceptaciΓ³n:** +- [ ] CRUD de planes funciona +- [ ] Planes inactivos no asignables a nuevos tenants +- [ ] Cambio de plan en tenant actualiza lΓ­mites + +--- + +## RF-PMC-001-014: Cambiar Plan de Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-014 | +| **Nombre** | Cambiar Plan de Tenant | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**DescripciΓ³n:** +El sistema debe permitir cambiar el plan de un tenant. + +**Flujo principal:** +1. Super Admin selecciona tenant +2. Selecciona nuevo plan +3. Sistema valida compatibilidad +4. Sistema actualiza plan_id +5. Nuevos lΓ­mites se aplican inmediatamente +6. Sistema notifica a admins del tenant + +**Validaciones:** +- Si downgrade: verificar que uso actual no exceda nuevos lΓ­mites +- Warning si usuarios exceden nuevo lΓ­mite + +**Criterios de aceptaciΓ³n:** +- [ ] Plan se actualiza correctamente +- [ ] LΓ­mites se aplican inmediatamente +- [ ] Warnings apropiados en downgrade + +--- + +## RF-PMC-001-015: Ver Uso del Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-001-015 | +| **Nombre** | Ver Uso del Tenant | +| **Prioridad** | P2 | +| **Actor** | Super Admin, Tenant Admin | + +**DescripciΓ³n:** +El sistema debe mostrar mΓ©tricas de uso del tenant. + +**Datos de salida:** +- Generaciones: usado/lΓ­mite +- Storage: usado/lΓ­mite (GB) +- Usuarios: activos/lΓ­mite +- Entrenamientos: usado/lΓ­mite +- PerΓ­odo de facturaciΓ³n actual + +**Criterios de aceptaciΓ³n:** +- [ ] MΓ©tricas se calculan correctamente +- [ ] Porcentajes y grΓ‘ficos visuales +- [ ] Alertas cuando se acerca al lΓ­mite (>80%) + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 6 | +| P2 | 6 | +| P3 | 3 | +| **Total** | **15** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-002-CRM.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-002-CRM.md new file mode 100644 index 0000000..bf78881 --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-002-CRM.md @@ -0,0 +1,587 @@ +# Requerimientos Funcionales - PMC-002 CRM + +**MΓ³dulo:** CRM +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## GestiΓ³n de Clientes + +### RF-PMC-002-001: Crear Cliente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-001 | +| **Nombre** | Crear Cliente | +| **Prioridad** | P1 | +| **Actor** | Creative, Analyst, Tenant Admin | + +**DescripciΓ³n:** +El sistema debe permitir registrar un nuevo cliente de la agencia. + +**Datos de entrada:** +- name: string (requerido) +- legal_name: string (opcional) +- tax_id: string (opcional) +- industry: string (opcional) +- size: enum (opcional) +- website: string (opcional) +- notes: text (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Cliente se crea con status "prospect" +- [ ] tenant_id se asigna automΓ‘ticamente +- [ ] ValidaciΓ³n de datos funciona + +--- + +### RF-PMC-002-002: Editar Cliente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-002 | +| **Nombre** | Editar Cliente | +| **Prioridad** | P1 | +| **Actor** | Creative, Analyst, Tenant Admin | + +**DescripciΓ³n:** +El sistema debe permitir modificar datos de un cliente existente. + +**Criterios de aceptaciΓ³n:** +- [ ] Todos los campos editables se actualizan +- [ ] Cambio de status registra historial +- [ ] Audit log registra modificaciones + +--- + +### RF-PMC-002-003: Listar Clientes + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-003 | +| **Nombre** | Listar Clientes | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**DescripciΓ³n:** +El sistema debe mostrar lista de clientes con filtros y paginaciΓ³n. + +**Filtros disponibles:** +- status: prospect, active, inactive, churned +- industry: string +- size: enum +- search: nombre o legal_name + +**Criterios de aceptaciΓ³n:** +- [ ] PaginaciΓ³n funciona correctamente +- [ ] Filtros se combinan con AND +- [ ] Ordenamiento por nombre/fecha + +--- + +### RF-PMC-002-004: Ver Ficha de Cliente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-004 | +| **Nombre** | Ver Ficha de Cliente | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**DescripciΓ³n:** +El sistema debe mostrar vista detallada del cliente con informaciΓ³n relacionada. + +**Datos mostrados:** +- InformaciΓ³n bΓ‘sica +- Contactos asociados +- Marcas del cliente +- Proyectos activos +- Oportunidades abiertas +- Historial de actividad + +**Criterios de aceptaciΓ³n:** +- [ ] Tabs organizan informaciΓ³n +- [ ] Datos relacionados cargan correctamente +- [ ] Acciones rΓ‘pidas disponibles + +--- + +### RF-PMC-002-005: Eliminar Cliente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-005 | +| **Nombre** | Eliminar Cliente | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +El sistema debe permitir eliminar un cliente (soft delete). + +**Validaciones:** +- No tiene proyectos activos +- ConfirmaciΓ³n requerida + +**Criterios de aceptaciΓ³n:** +- [ ] Soft delete funciona +- [ ] Validaciones impiden eliminaciΓ³n si hay dependencias activas + +--- + +## GestiΓ³n de Contactos + +### RF-PMC-002-006: Crear Contacto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-006 | +| **Nombre** | Crear Contacto | +| **Prioridad** | P1 | +| **Actor** | Creative, Analyst, Tenant Admin | + +**Datos de entrada:** +- client_id: UUID (requerido) +- first_name: string (requerido) +- last_name: string (requerido) +- email: string (requerido) +- phone: string (opcional) +- position: string (opcional) +- is_primary: boolean (default false) + +**Criterios de aceptaciΓ³n:** +- [ ] Contacto se asocia al cliente +- [ ] Email validado (formato) +- [ ] Solo un contacto primario por cliente + +--- + +### RF-PMC-002-007: Editar Contacto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-007 | +| **Nombre** | Editar Contacto | +| **Prioridad** | P2 | +| **Actor** | Creative, Analyst, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Campos se actualizan correctamente +- [ ] Cambio de is_primary actualiza otros contactos + +--- + +### RF-PMC-002-008: Listar Contactos + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-008 | +| **Nombre** | Listar Contactos | +| **Prioridad** | P2 | +| **Actor** | Todos los roles | + +**DescripciΓ³n:** +Listar contactos del tenant o de un cliente especΓ­fico. + +**Criterios de aceptaciΓ³n:** +- [ ] Filtro por cliente funciona +- [ ] BΓΊsqueda por nombre/email +- [ ] PaginaciΓ³n implementada + +--- + +### RF-PMC-002-009: Marcar Contacto Primario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-009 | +| **Nombre** | Marcar Contacto Primario | +| **Prioridad** | P2 | +| **Actor** | Creative, Analyst, Tenant Admin | + +**DescripciΓ³n:** +Designar un contacto como principal del cliente. + +**Criterios de aceptaciΓ³n:** +- [ ] Solo un contacto primario por cliente +- [ ] Al marcar uno, otros se desmarcan automΓ‘ticamente + +--- + +## GestiΓ³n de Marcas + +### RF-PMC-002-010: Crear Marca + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-010 | +| **Nombre** | Crear Marca | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- client_id: UUID (requerido) +- name: string (requerido) +- description: text (opcional) +- identity: object (opcional) + - logo_url + - primary_color + - secondary_colors + - typography + - tone_of_voice + - keywords + - forbidden_words + - visual_style + +**Criterios de aceptaciΓ³n:** +- [ ] Marca se asocia al cliente +- [ ] Identity se almacena como JSONB +- [ ] Logo se puede subir o referenciar URL + +--- + +### RF-PMC-002-011: Editar Marca + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-011 | +| **Nombre** | Editar Marca | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Todos los campos de identity editables +- [ ] Preview de colores en tiempo real +- [ ] Cambios se propagan a nuevas generaciones + +--- + +### RF-PMC-002-012: Definir Identidad Visual + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-012 | +| **Nombre** | Definir Identidad Visual | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**DescripciΓ³n:** +Configurar todos los elementos de identidad visual de la marca. + +**Campos de identidad:** +- Logo (principal y variaciones) +- Paleta de colores +- TipografΓ­as +- Tono de voz +- Keywords positivas +- Palabras prohibidas +- Estilo visual preferido + +**Criterios de aceptaciΓ³n:** +- [ ] Formulario estructurado para cada secciΓ³n +- [ ] Upload de logos funciona +- [ ] Preview visual de paleta de colores + +--- + +### RF-PMC-002-013: Asociar LoRA a Marca + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-013 | +| **Nombre** | Asociar LoRA a Marca | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**DescripciΓ³n:** +Vincular modelos LoRA entrenados con una marca. + +**Flujo:** +1. Usuario accede a configuraciΓ³n de marca +2. Selecciona "Modelos IA" +3. Elige LoRA(s) del catΓ‘logo del tenant +4. Sistema vincula LoRA con marca +5. LoRA se usa automΓ‘ticamente en generaciones de la marca + +**Criterios de aceptaciΓ³n:** +- [ ] MΓΊltiples LoRAs pueden asociarse +- [ ] LoRA se aplica por defecto en generaciΓ³n +- [ ] DesasociaciΓ³n funciona + +--- + +### RF-PMC-002-014: Listar Marcas + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-014 | +| **Nombre** | Listar Marcas | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Criterios de aceptaciΓ³n:** +- [ ] Filtro por cliente funciona +- [ ] Preview de logo/colores en lista +- [ ] BΓΊsqueda por nombre + +--- + +## GestiΓ³n de Productos + +### RF-PMC-002-015: Crear Producto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-015 | +| **Nombre** | Crear Producto | +| **Prioridad** | P1 | +| **Actor** | Creative, Analyst | + +**Datos de entrada:** +- brand_id: UUID (requerido) +- name: string (requerido) +- sku: string (opcional) +- description: text (opcional) +- category: string (opcional) +- attributes: object (precio, features, etc.) +- reference_images: array[file] (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Producto se asocia a marca +- [ ] ImΓ‘genes de referencia se almacenan +- [ ] Status inicial "active" + +--- + +### RF-PMC-002-016: Editar Producto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-016 | +| **Nombre** | Editar Producto | +| **Prioridad** | P2 | +| **Actor** | Creative, Analyst | + +**Criterios de aceptaciΓ³n:** +- [ ] Campos se actualizan correctamente +- [ ] ImΓ‘genes de referencia pueden agregarse/quitarse + +--- + +### RF-PMC-002-017: Subir ImΓ‘genes de Referencia + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-017 | +| **Nombre** | Subir ImΓ‘genes de Referencia | +| **Prioridad** | P1 | +| **Actor** | Creative, Analyst | + +**DescripciΓ³n:** +Agregar fotos reales del producto para usar como referencia en generaciΓ³n. + +**Criterios de aceptaciΓ³n:** +- [ ] Upload mΓΊltiple funciona +- [ ] Formatos: JPG, PNG, WebP +- [ ] TamaΓ±o mΓ‘ximo: 10MB por imagen +- [ ] Thumbnails generados automΓ‘ticamente + +--- + +### RF-PMC-002-018: Trigger GeneraciΓ³n desde Producto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-018 | +| **Nombre** | Trigger GeneraciΓ³n desde Producto | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**DescripciΓ³n:** +Iniciar generaciΓ³n de contenido directamente desde la ficha de producto. + +**Flujo:** +1. Usuario ve ficha de producto +2. Selecciona "Generar contenido" +3. Elige workflow template +4. Configura opciones (cantidad, estilo) +5. Sistema crea job de generaciΓ³n +6. Sistema redirige a monitor o muestra progreso + +**Criterios de aceptaciΓ³n:** +- [ ] Datos del producto se cargan al job +- [ ] Identidad de marca se incluye +- [ ] LoRAs se aplican automΓ‘ticamente + +--- + +### RF-PMC-002-019: Listar Productos + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-019 | +| **Nombre** | Listar Productos | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Criterios de aceptaciΓ³n:** +- [ ] Filtro por marca funciona +- [ ] Vista de catΓ‘logo con imΓ‘genes +- [ ] BΓΊsqueda por nombre/SKU + +--- + +## GestiΓ³n de Oportunidades + +### RF-PMC-002-020: Crear Oportunidad + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-020 | +| **Nombre** | Crear Oportunidad | +| **Prioridad** | P2 | +| **Actor** | Analyst, Tenant Admin | + +**Datos de entrada:** +- client_id: UUID (requerido) +- name: string (requerido) +- description: text (opcional) +- value: decimal (opcional) +- currency: string (default: USD) +- expected_close_date: date (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Stage inicial "lead" +- [ ] Probability calculada por stage + +--- + +### RF-PMC-002-021: Mover Oportunidad en Pipeline + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-021 | +| **Nombre** | Mover Oportunidad en Pipeline | +| **Prioridad** | P2 | +| **Actor** | Analyst, Tenant Admin | + +**DescripciΓ³n:** +Cambiar stage de una oportunidad mediante drag & drop o acciΓ³n directa. + +**Stages:** +- lead β†’ qualified β†’ proposal β†’ negotiation β†’ won/lost + +**Criterios de aceptaciΓ³n:** +- [ ] Drag & drop en vista Kanban +- [ ] Probability se actualiza automΓ‘ticamente +- [ ] Registro de historial de cambios + +--- + +### RF-PMC-002-022: Cerrar Oportunidad como Ganada + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-022 | +| **Nombre** | Cerrar Oportunidad como Ganada | +| **Prioridad** | P2 | +| **Actor** | Analyst, Tenant Admin | + +**Flujo:** +1. Usuario mueve a stage "won" +2. Sistema solicita valor final confirmado +3. Sistema marca como ganada +4. Sistema ofrece crear proyecto + +**Criterios de aceptaciΓ³n:** +- [ ] actual_close_date se registra +- [ ] OpciΓ³n de crear proyecto disponible + +--- + +### RF-PMC-002-023: Cerrar Oportunidad como Perdida + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-023 | +| **Nombre** | Cerrar Oportunidad como Perdida | +| **Prioridad** | P2 | +| **Actor** | Analyst, Tenant Admin | + +**Flujo:** +1. Usuario mueve a stage "lost" +2. Sistema solicita motivo de pΓ©rdida +3. Sistema registra lost_reason +4. Sistema marca como perdida + +**Criterios de aceptaciΓ³n:** +- [ ] lost_reason es requerido +- [ ] Oportunidad no editable despuΓ©s de cerrar + +--- + +### RF-PMC-002-024: Convertir Oportunidad en Proyecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-024 | +| **Nombre** | Convertir Oportunidad en Proyecto | +| **Prioridad** | P2 | +| **Actor** | Analyst, Tenant Admin | + +**DescripciΓ³n:** +Crear proyecto automΓ‘ticamente desde oportunidad ganada. + +**Flujo:** +1. Usuario selecciona "Convertir a proyecto" +2. Sistema muestra formulario pre-llenado +3. Usuario confirma/modifica datos +4. Sistema crea proyecto vinculado al cliente +5. Sistema vincula oportunidad con proyecto + +**Criterios de aceptaciΓ³n:** +- [ ] Datos del cliente se heredan +- [ ] DescripciΓ³n de oportunidad se copia a proyecto +- [ ] RelaciΓ³n bidireccional establecida + +--- + +### RF-PMC-002-025: Vista Kanban de Oportunidades + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-002-025 | +| **Nombre** | Vista Kanban de Oportunidades | +| **Prioridad** | P2 | +| **Actor** | Analyst, Tenant Admin | + +**DescripciΓ³n:** +Mostrar pipeline de oportunidades en formato Kanban. + +**CaracterΓ­sticas:** +- Columnas por stage +- Cards con info resumida +- Drag & drop entre columnas +- Filtros por cliente, fecha, valor +- Totales por columna + +**Criterios de aceptaciΓ³n:** +- [ ] Drag & drop funciona +- [ ] Totales se calculan correctamente +- [ ] Filtros se aplican en tiempo real + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 14 | +| P2 | 10 | +| P3 | 1 | +| **Total** | **25** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-003-PROJECTS.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-003-PROJECTS.md new file mode 100644 index 0000000..459253a --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-003-PROJECTS.md @@ -0,0 +1,503 @@ +# Requerimientos Funcionales - PMC-003 Projects + +**MΓ³dulo:** Projects +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## GestiΓ³n de Proyectos + +### RF-PMC-003-001: Crear Proyecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-001 | +| **Nombre** | Crear Proyecto | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- client_id: UUID (requerido) +- name: string (requerido) +- description: text (opcional) +- start_date: date (opcional) +- end_date: date (opcional) +- budget: decimal (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Proyecto se crea con status "draft" +- [ ] CΓ³digo autogenerado (PRJ-YYYY-XXX) +- [ ] Owner asignado al creador + +--- + +### RF-PMC-003-002: Editar Proyecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-002 | +| **Nombre** | Editar Proyecto | +| **Prioridad** | P1 | +| **Actor** | Project Owner, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Campos bΓ‘sicos editables +- [ ] Cambio de cliente requiere confirmaciΓ³n +- [ ] Historial de cambios registrado + +--- + +### RF-PMC-003-003: Cambiar Estado de Proyecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-003 | +| **Nombre** | Cambiar Estado de Proyecto | +| **Prioridad** | P1 | +| **Actor** | Project Owner, Tenant Admin | + +**Estados vΓ‘lidos:** +- draft β†’ active +- active β†’ on_hold, completed +- on_hold β†’ active +- cualquiera β†’ cancelled + +**Criterios de aceptaciΓ³n:** +- [ ] Transiciones vΓ‘lidas se permiten +- [ ] Transiciones invΓ‘lidas se bloquean +- [ ] NotificaciΓ³n al equipo en cambio de estado + +--- + +### RF-PMC-003-004: Asignar Equipo a Proyecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-004 | +| **Nombre** | Asignar Equipo a Proyecto | +| **Prioridad** | P2 | +| **Actor** | Project Owner, Tenant Admin | + +**DescripciΓ³n:** +Agregar o quitar miembros del equipo de un proyecto. + +**Criterios de aceptaciΓ³n:** +- [ ] Usuarios del tenant pueden asignarse +- [ ] Owner siempre estΓ‘ en el equipo +- [ ] NotificaciΓ³n al agregar miembro + +--- + +### RF-PMC-003-005: Listar Proyectos + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-005 | +| **Nombre** | Listar Proyectos | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Filtros:** +- client_id +- status +- owner_id +- date_range + +**Criterios de aceptaciΓ³n:** +- [ ] PaginaciΓ³n funciona +- [ ] Filtros combinables +- [ ] Vista lista y tarjetas + +--- + +### RF-PMC-003-006: Ver Dashboard de Proyecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-006 | +| **Nombre** | Ver Dashboard de Proyecto | +| **Prioridad** | P1 | +| **Actor** | Miembros del proyecto | + +**InformaciΓ³n mostrada:** +- Resumen del proyecto +- CampaΓ±as con estado +- Assets recientes +- Actividad del equipo +- MΓ©tricas de progreso + +**Criterios de aceptaciΓ³n:** +- [ ] Dashboard carga correctamente +- [ ] MΓ©tricas calculadas en tiempo real +- [ ] Acciones rΓ‘pidas disponibles + +--- + +## GestiΓ³n de CampaΓ±as + +### RF-PMC-003-007: Crear CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-007 | +| **Nombre** | Crear CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- project_id: UUID (requerido) +- brand_id: UUID (requerido) +- name: string (requerido) +- type: enum (requerido) +- channels: array[string] +- start_date: date (opcional) +- end_date: date (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] CampaΓ±a se crea con status "draft" +- [ ] Brand se vincula correctamente +- [ ] Brief vacΓ­o se inicializa + +--- + +### RF-PMC-003-008: Editar CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-008 | +| **Nombre** | Editar CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Criterios de aceptaciΓ³n:** +- [ ] Campos bΓ‘sicos editables en cualquier estado +- [ ] Brief editable hasta "in_production" + +--- + +### RF-PMC-003-009: Completar Brief de CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-009 | +| **Nombre** | Completar Brief de CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Secciones del Brief:** +- Objetivo: descripciΓ³n, KPIs +- Audiencia: demographics, psychographics, pain_points +- Mensajes: main_message, tone, CTA, hashtags +- Visual: style, mood, color_palette, references +- Restricciones: forbidden_words, disclaimers +- Entregables: formatos, cantidades + +**Criterios de aceptaciΓ³n:** +- [ ] Formulario con secciones colapsables +- [ ] ValidaciΓ³n de campos mΓ­nimos +- [ ] Guardado automΓ‘tico (draft) +- [ ] Al completar: estado β†’ "briefing" + +--- + +### RF-PMC-003-010: Usar Plantilla de Brief + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-010 | +| **Nombre** | Usar Plantilla de Brief | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**DescripciΓ³n:** +Cargar brief desde una plantilla predefinida. + +**Criterios de aceptaciΓ³n:** +- [ ] Listado de plantillas disponibles +- [ ] Preview de plantilla antes de aplicar +- [ ] Campos se pre-llenan pero son editables + +--- + +### RF-PMC-003-011: Cambiar Estado de CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-011 | +| **Nombre** | Cambiar Estado de CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Estados y transiciones:** +``` +draft β†’ briefing β†’ in_production β†’ review β†’ approved β†’ published + ↑_______________| + (revision_requested) +``` + +**Validaciones:** +- briefing β†’ in_production: brief mΓ­nimo completado +- review β†’ approved: al menos 1 asset aprobado +- approved β†’ published: confirmaciΓ³n requerida + +**Criterios de aceptaciΓ³n:** +- [ ] Transiciones vΓ‘lidas funcionan +- [ ] Validaciones se aplican +- [ ] Notificaciones en cada cambio + +--- + +### RF-PMC-003-012: Listar CampaΓ±as + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-012 | +| **Nombre** | Listar CampaΓ±as | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Vistas:** +- Lista con filtros +- Kanban por estado +- Calendario por fechas + +**Criterios de aceptaciΓ³n:** +- [ ] Filtro por proyecto, brand, status, type +- [ ] Vista Kanban con drag & drop +- [ ] BΓΊsqueda por nombre + +--- + +### RF-PMC-003-013: Ver Detalle de CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-013 | +| **Nombre** | Ver Detalle de CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Miembros del proyecto | + +**InformaciΓ³n mostrada:** +- Datos de campaΓ±a +- Brief completo +- Assets generados con estados +- Historial de actividad +- Jobs de generaciΓ³n + +**Criterios de aceptaciΓ³n:** +- [ ] Todas las secciones visibles +- [ ] Assets organizados por estado +- [ ] Acciones contextuales disponibles + +--- + +## GeneraciΓ³n de Contenido + +### RF-PMC-003-014: Lanzar GeneraciΓ³n desde CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-014 | +| **Nombre** | Lanzar GeneraciΓ³n desde CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Flujo:** +1. Usuario abre campaΓ±a en status "briefing" o superior +2. Selecciona "Generar contenido" +3. Elige workflows segΓΊn deliverables del brief +4. Configura opciones adicionales +5. Sistema crea jobs de generaciΓ³n +6. Sistema cambia status a "in_production" si no lo estΓ‘ + +**Criterios de aceptaciΓ³n:** +- [ ] Brief se usa para configurar generaciΓ³n +- [ ] MΓΊltiples workflows ejecutables +- [ ] Progreso visible en tiempo real + +--- + +### RF-PMC-003-015: Seleccionar Workflows de GeneraciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-015 | +| **Nombre** | Seleccionar Workflows de GeneraciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**DescripciΓ³n:** +Elegir quΓ© workflows ejecutar basado en deliverables del brief. + +**Criterios de aceptaciΓ³n:** +- [ ] Workflows sugeridos segΓΊn tipo de campaΓ±a +- [ ] Preview de cada workflow +- [ ] ConfiguraciΓ³n de cantidad por workflow + +--- + +### RF-PMC-003-016: Monitorear Progreso de GeneraciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-016 | +| **Nombre** | Monitorear Progreso de GeneraciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**InformaciΓ³n mostrada:** +- Jobs en cola +- Jobs procesando (con %) +- Jobs completados +- Jobs fallidos + +**Criterios de aceptaciΓ³n:** +- [ ] ActualizaciΓ³n en tiempo real (websocket) +- [ ] Posibilidad de cancelar jobs pendientes +- [ ] Reintentar jobs fallidos + +--- + +## Flujo de AprobaciΓ³n + +### RF-PMC-003-017: Aprobar Asset de CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-017 | +| **Nombre** | Aprobar Asset de CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Flujo:** +1. Usuario revisa asset en vista de revisiΓ³n +2. Selecciona "Aprobar" +3. Sistema marca asset como aprobado +4. Sistema registra aprobador y timestamp + +**Criterios de aceptaciΓ³n:** +- [ ] Asset cambia a status "approved" +- [ ] Metadata de aprobaciΓ³n registrada +- [ ] No editable despuΓ©s de aprobar + +--- + +### RF-PMC-003-018: Rechazar Asset de CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-018 | +| **Nombre** | Rechazar Asset de CampaΓ±a | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Flujo:** +1. Usuario revisa asset +2. Selecciona "Rechazar" +3. Sistema solicita feedback obligatorio +4. Sistema marca asset como rechazado + +**Criterios de aceptaciΓ³n:** +- [ ] Feedback es requerido +- [ ] Asset puede regenerarse +- [ ] Historial de rechazos visible + +--- + +### RF-PMC-003-019: Solicitar RevisiΓ³n de Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-019 | +| **Nombre** | Solicitar RevisiΓ³n de Asset | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**DescripciΓ³n:** +Pedir cambios especΓ­ficos en un asset antes de decidir. + +**Criterios de aceptaciΓ³n:** +- [ ] Comentario con posiciΓ³n en imagen +- [ ] Asset queda en "revision_requested" +- [ ] NotificaciΓ³n a equipo + +--- + +### RF-PMC-003-020: Aprobar Todos los Assets + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-020 | +| **Nombre** | Aprobar Todos los Assets | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +AcciΓ³n bulk para aprobar todos los assets pendientes. + +**Criterios de aceptaciΓ³n:** +- [ ] ConfirmaciΓ³n requerida +- [ ] Solo assets en "pending_review" +- [ ] Registro individual por asset + +--- + +### RF-PMC-003-021: Regenerar Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-021 | +| **Nombre** | Regenerar Asset | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**DescripciΓ³n:** +Crear nueva versiΓ³n de un asset rechazado o en revisiΓ³n. + +**Flujo:** +1. Usuario selecciona asset rechazado +2. Selecciona "Regenerar" +3. Opcionalmente ajusta parΓ‘metros +4. Sistema crea nuevo job +5. Nuevo asset se vincula como versiΓ³n + +**Criterios de aceptaciΓ³n:** +- [ ] ParΓ‘metros originales pre-cargados +- [ ] Historial de versiones mantenido +- [ ] Original no se elimina + +--- + +### RF-PMC-003-022: Descargar Assets Aprobados + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-003-022 | +| **Nombre** | Descargar Assets Aprobados | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**DescripciΓ³n:** +Descargar pack de todos los assets aprobados de la campaΓ±a. + +**Criterios de aceptaciΓ³n:** +- [ ] ZIP generado con estructura organizada +- [ ] Solo assets aprobados incluidos +- [ ] Copys incluidos como .txt +- [ ] OpciΓ³n de selecciΓ³n manual + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 15 | +| P2 | 7 | +| **Total** | **22** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-004-GENERATION.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-004-GENERATION.md new file mode 100644 index 0000000..b36aa46 --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-004-GENERATION.md @@ -0,0 +1,641 @@ +# Requerimientos Funcionales - PMC-004 Generation + +**MΓ³dulo:** Generation (Motor IA) +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## GeneraciΓ³n de ImΓ‘genes + +### RF-PMC-004-001: Generar Imagen Text-to-Image + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-001 | +| **Nombre** | Generar Imagen Text-to-Image | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- prompt: string (requerido) +- negative_prompt: string (opcional) +- width: number (default: 1024) +- height: number (default: 1024) +- seed: number (opcional, aleatorio si no se especifica) +- steps: number (default: 30) +- cfg_scale: number (default: 7.5) +- lora_id: UUID (opcional) +- brand_id: UUID (opcional, para cargar LoRA automΓ‘ticamente) + +**Criterios de aceptaciΓ³n:** +- [ ] Imagen se genera correctamente +- [ ] ParΓ‘metros se aplican +- [ ] LoRA se carga si especificado +- [ ] Asset se crea automΓ‘ticamente + +--- + +### RF-PMC-004-002: Generar Imagen Image-to-Image + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-002 | +| **Nombre** | Generar Imagen Image-to-Image | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- input_image: file/URL (requerido) +- prompt: string (requerido) +- strength: number (0.0-1.0, default: 0.75) +- Otros parΓ‘metros de T2I + +**Criterios de aceptaciΓ³n:** +- [ ] Imagen input se procesa correctamente +- [ ] Strength afecta resultado +- [ ] Formatos soportados: PNG, JPG, WebP + +--- + +### RF-PMC-004-003: Aplicar Inpainting + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-003 | +| **Nombre** | Aplicar Inpainting | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Datos de entrada:** +- input_image: file/URL (requerido) +- mask_image: file (requerido) +- prompt: string (requerido) +- Otros parΓ‘metros de generaciΓ³n + +**DescripciΓ³n:** +Regenerar solo la parte enmascarada de una imagen. + +**Criterios de aceptaciΓ³n:** +- [ ] MΓ‘scara define Γ‘rea a regenerar +- [ ] Resto de imagen preservado +- [ ] Editor de mΓ‘scara en UI + +--- + +### RF-PMC-004-004: Aplicar Upscaling + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-004 | +| **Nombre** | Aplicar Upscaling | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- input_image: file/URL (requerido) +- scale: number (2 o 4) +- model: string (default: "RealESRGAN") + +**Criterios de aceptaciΓ³n:** +- [ ] Imagen se escala correctamente +- [ ] Calidad mejorada, no solo interpolaciΓ³n +- [ ] Formatos de salida preservados + +--- + +### RF-PMC-004-005: Generar Batch de ImΓ‘genes + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-005 | +| **Nombre** | Generar Batch de ImΓ‘genes | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- base_params: object (parΓ‘metros comunes) +- count: number (cantidad a generar) +- variation_type: string (seed, prompt_variation) + +**Criterios de aceptaciΓ³n:** +- [ ] N imΓ‘genes generadas +- [ ] Seeds diferentes por imagen +- [ ] Todas vinculadas al mismo job + +--- + +### RF-PMC-004-006: Remover Fondo + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-006 | +| **Nombre** | Remover Fondo | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Datos de entrada:** +- input_image: file/URL (requerido) + +**Criterios de aceptaciΓ³n:** +- [ ] Fondo removido correctamente +- [ ] Salida PNG con transparencia +- [ ] Bordes suaves en objetos + +--- + +## GeneraciΓ³n de Texto + +### RF-PMC-004-007: Generar Copy Publicitario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-007 | +| **Nombre** | Generar Copy Publicitario | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- context: object + - product_name: string + - product_description: string + - brand_tone: string + - target_audience: string + - objective: string +- type: enum (title, description, cta, full_post) +- max_length: number (opcional) +- variations: number (default: 3) + +**Criterios de aceptaciΓ³n:** +- [ ] Texto generado coherente +- [ ] Tono respeta brand guidelines +- [ ] MΓΊltiples variaciones disponibles + +--- + +### RF-PMC-004-008: Generar Hashtags + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-008 | +| **Nombre** | Generar Hashtags | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Datos de entrada:** +- context: string (descripciΓ³n del contenido) +- count: number (default: 10) +- platform: string (instagram, twitter, linkedin) + +**Criterios de aceptaciΓ³n:** +- [ ] Hashtags relevantes generados +- [ ] Formato correcto (#hashtag) +- [ ] Sin espacios ni caracteres invΓ‘lidos + +--- + +### RF-PMC-004-009: Adaptar Tono de Texto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-009 | +| **Nombre** | Adaptar Tono de Texto | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Datos de entrada:** +- input_text: string (requerido) +- target_tone: string (formal, casual, playful, professional) + +**Criterios de aceptaciΓ³n:** +- [ ] Mensaje preservado, tono cambiado +- [ ] Opciones de tono claras + +--- + +## Workflows + +### RF-PMC-004-010: Listar Workflow Templates + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-010 | +| **Nombre** | Listar Workflow Templates | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de salida:** +- Lista de workflows disponibles +- Por cada uno: nombre, descripciΓ³n, tipo, inputs requeridos + +**Criterios de aceptaciΓ³n:** +- [ ] Workflows de sistema incluidos +- [ ] Workflows custom del tenant incluidos +- [ ] Filtro por tipo/categorΓ­a + +--- + +### RF-PMC-004-011: Ver Detalle de Workflow + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-011 | +| **Nombre** | Ver Detalle de Workflow | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de salida:** +- DescripciΓ³n completa +- Inputs requeridos y opcionales +- Outputs esperados +- Ejemplos de resultado +- Tiempo estimado + +**Criterios de aceptaciΓ³n:** +- [ ] Schema de inputs documentado +- [ ] Ejemplos visuales disponibles + +--- + +### RF-PMC-004-012: Ejecutar Workflow + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-012 | +| **Nombre** | Ejecutar Workflow | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- workflow_id: UUID (requerido) +- inputs: object (segΓΊn schema del workflow) +- campaign_id: UUID (opcional) +- brand_id: UUID (opcional) + +**Flujo:** +1. Sistema valida inputs contra schema +2. Sistema verifica cuotas del tenant +3. Sistema crea GenerationJob +4. Sistema encola job +5. Sistema retorna job_id + +**Criterios de aceptaciΓ³n:** +- [ ] ValidaciΓ³n de inputs funciona +- [ ] Job se crea correctamente +- [ ] ID retornado para tracking + +--- + +### RF-PMC-004-013: Crear Workflow Template (Admin) + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-013 | +| **Nombre** | Crear Workflow Template | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- name: string +- description: text +- type: enum +- comfyui_workflow: JSON +- input_schema: JSON +- output_config: object + +**Criterios de aceptaciΓ³n:** +- [ ] Workflow se almacena correctamente +- [ ] Schema de inputs validado +- [ ] Disponible para usuarios del tenant + +--- + +## Modelos Personalizados + +### RF-PMC-004-014: Listar Modelos Custom + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-014 | +| **Nombre** | Listar Modelos Custom | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de salida:** +- Lista de LoRAs, checkpoints disponibles +- Status de cada uno +- Brand asociada (si aplica) + +**Criterios de aceptaciΓ³n:** +- [ ] Solo modelos del tenant +- [ ] Filtro por tipo y brand +- [ ] Preview images mostradas + +--- + +### RF-PMC-004-015: Registrar Modelo Custom + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-015 | +| **Nombre** | Registrar Modelo Custom | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- name: string (requerido) +- type: enum (lora, checkpoint, embedding) +- file: upload (requerido) +- purpose: string +- trigger_word: string (para LoRAs) +- brand_id: UUID (opcional) +- preview_images: array[file] + +**Criterios de aceptaciΓ³n:** +- [ ] Archivo subido a storage +- [ ] Registro en BD +- [ ] Disponible para generaciΓ³n + +--- + +### RF-PMC-004-016: Eliminar Modelo Custom + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-016 | +| **Nombre** | Eliminar Modelo Custom | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] ConfirmaciΓ³n requerida +- [ ] Archivo eliminado de storage +- [ ] Registro eliminado de BD + +--- + +### RF-PMC-004-017: Iniciar Entrenamiento de LoRA + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-017 | +| **Nombre** | Iniciar Entrenamiento de LoRA | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- name: string +- training_images: array[file] (mΓ­nimo 10) +- base_model: string +- steps: number (default: 1000) +- learning_rate: number (default: 0.0001) +- trigger_word: string (requerido) + +**Criterios de aceptaciΓ³n:** +- [ ] MΓ­nimo 10 imΓ‘genes validado +- [ ] Job de entrenamiento creado +- [ ] Status actualizado durante entrenamiento +- [ ] Modelo disponible al completar + +--- + +## Cola de Tareas + +### RF-PMC-004-018: Ver Estado de Cola + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-018 | +| **Nombre** | Ver Estado de Cola | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de salida:** +- Jobs en cola (pending) +- Jobs procesando +- Jobs completados (recientes) +- Jobs fallidos (recientes) + +**Criterios de aceptaciΓ³n:** +- [ ] ActualizaciΓ³n en tiempo real +- [ ] Filtro por usuario/campaΓ±a +- [ ] Progreso visible para jobs activos + +--- + +### RF-PMC-004-019: Ver Detalle de Job + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-019 | +| **Nombre** | Ver Detalle de Job | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de salida:** +- ParΓ‘metros de entrada +- Status y progreso +- Timestamps +- Outputs generados +- Error (si fallΓ³) + +**Criterios de aceptaciΓ³n:** +- [ ] Toda la informaciΓ³n visible +- [ ] Links a assets generados + +--- + +### RF-PMC-004-020: Cancelar Job + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-020 | +| **Nombre** | Cancelar Job | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Precondiciones:** +- Job en status "queued" + +**Criterios de aceptaciΓ³n:** +- [ ] Job cambia a "cancelled" +- [ ] No se ejecuta +- [ ] Cuota no consumida + +--- + +### RF-PMC-004-021: Reintentar Job Fallido + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-021 | +| **Nombre** | Reintentar Job Fallido | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Precondiciones:** +- Job en status "failed" + +**Criterios de aceptaciΓ³n:** +- [ ] Nuevo job creado con mismos parΓ‘metros +- [ ] Original marcado como "retried" +- [ ] Hasta 3 reintentos permitidos + +--- + +### RF-PMC-004-022: Cambiar Prioridad de Job (Admin) + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-022 | +| **Nombre** | Cambiar Prioridad de Job | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Precondiciones:** +- Job en status "queued" + +**Criterios de aceptaciΓ³n:** +- [ ] Prioridad actualizada +- [ ] PosiciΓ³n en cola recalculada + +--- + +## IntegraciΓ³n ComfyUI + +### RF-PMC-004-023: Enviar Workflow a ComfyUI + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-023 | +| **Nombre** | Enviar Workflow a ComfyUI | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +El sistema debe enviar workflows a ComfyUI para ejecuciΓ³n. + +**Criterios de aceptaciΓ³n:** +- [ ] Payload correcto enviado +- [ ] Respuesta de ComfyUI procesada +- [ ] Errores manejados correctamente + +--- + +### RF-PMC-004-024: Recibir Resultados de ComfyUI + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-024 | +| **Nombre** | Recibir Resultados de ComfyUI | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +El sistema debe procesar callbacks/webhooks de ComfyUI con resultados. + +**Criterios de aceptaciΓ³n:** +- [ ] ImΓ‘genes descargadas y almacenadas +- [ ] Assets creados automΓ‘ticamente +- [ ] Job actualizado a "completed" + +--- + +### RF-PMC-004-025: Monitorear Progreso en ComfyUI + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-025 | +| **Nombre** | Monitorear Progreso en ComfyUI | +| **Prioridad** | P2 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +Tracking de progreso durante ejecuciΓ³n del workflow. + +**Criterios de aceptaciΓ³n:** +- [ ] Websocket conectado a ComfyUI +- [ ] Progreso actualizado en tiempo real +- [ ] Propagado a frontend + +--- + +## Validaciones + +### RF-PMC-004-026: Validar Cuota Antes de GeneraciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-026 | +| **Nombre** | Validar Cuota Antes de GeneraciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +Verificar lΓ­mites del tenant antes de aceptar job. + +**Criterios de aceptaciΓ³n:** +- [ ] Generaciones mensuales verificadas +- [ ] Storage verificado para outputs +- [ ] Error claro si excede lΓ­mite + +--- + +### RF-PMC-004-027: Agregar Negative Prompts AutomΓ‘ticos + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-027 | +| **Nombre** | Agregar Negative Prompts AutomΓ‘ticos | +| **Prioridad** | P2 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +AΓ±adir negative prompts de calidad estΓ‘ndar. + +**Negative prompts por defecto:** +- "blurry, low quality, watermark, signature, bad anatomy, deformed..." + +**Criterios de aceptaciΓ³n:** +- [ ] Negativos agregados automΓ‘ticamente +- [ ] Usuario puede sobreescribir +- [ ] Configurables por tenant + +--- + +### RF-PMC-004-028: Cargar Identidad de Marca AutomΓ‘ticamente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-004-028 | +| **Nombre** | Cargar Identidad de Marca AutomΓ‘ticamente | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +Al generar para una campaΓ±a/marca, cargar automΓ‘ticamente: +- LoRAs asociados +- Colores de marca (para prompts) +- Forbidden words (para negative prompts) +- Tono de voz (para texto) + +**Criterios de aceptaciΓ³n:** +- [ ] LoRA se inyecta en workflow +- [ ] Colores incluidos en prompt si aplica +- [ ] Forbidden words en negative prompt + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 17 | +| P2 | 9 | +| P3 | 2 | +| **Total** | **28** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-005-AUTOMATION.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-005-AUTOMATION.md new file mode 100644 index 0000000..d1e394f --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-005-AUTOMATION.md @@ -0,0 +1,414 @@ +# Requerimientos Funcionales - PMC-005 Automation + +**MΓ³dulo:** Automation +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## GestiΓ³n de Flujos + +### RF-PMC-005-001: Listar Flujos de AutomatizaciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-001 | +| **Nombre** | Listar Flujos de AutomatizaciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de salida:** +- Lista de flujos disponibles +- Estado (activo/inactivo) +- Tipo (trigger_based, scheduled, manual) +- Última ejecuciΓ³n +- Conteo de ejecuciones + +**Criterios de aceptaciΓ³n:** +- [ ] Flujos de sistema y custom listados +- [ ] Filtro por tipo y estado +- [ ] Ordenamiento por nombre/ΓΊltima ejecuciΓ³n + +--- + +### RF-PMC-005-002: Ver Detalle de Flujo + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-002 | +| **Nombre** | Ver Detalle de Flujo | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de salida:** +- DescripciΓ³n completa +- Evento trigger +- ConfiguraciΓ³n +- Historial de ejecuciones recientes + +**Criterios de aceptaciΓ³n:** +- [ ] Toda la informaciΓ³n visible +- [ ] Link a workflow en n8n (admin) + +--- + +### RF-PMC-005-003: Activar Flujo + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-003 | +| **Nombre** | Activar Flujo | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +Habilitar un flujo para que procese eventos. + +**Criterios de aceptaciΓ³n:** +- [ ] is_active cambia a true +- [ ] Flujo comienza a procesar eventos +- [ ] Registro en audit log + +--- + +### RF-PMC-005-004: Desactivar Flujo + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-004 | +| **Nombre** | Desactivar Flujo | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +Deshabilitar un flujo sin eliminarlo. + +**Criterios de aceptaciΓ³n:** +- [ ] is_active cambia a false +- [ ] Eventos son ignorados +- [ ] ConfiguraciΓ³n preservada + +--- + +### RF-PMC-005-005: Configurar Flujo + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-005 | +| **Nombre** | Configurar Flujo | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- config: object + - retry_on_failure: boolean + - max_retries: number + - timeout_seconds: number + - custom_params: object + +**Criterios de aceptaciΓ³n:** +- [ ] ConfiguraciΓ³n se guarda +- [ ] Valores aplicados en ejecuciones +- [ ] ValidaciΓ³n de rangos + +--- + +### RF-PMC-005-006: Ejecutar Flujo Manualmente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-006 | +| **Nombre** | Ejecutar Flujo Manualmente | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +Disparar ejecuciΓ³n manual de un flujo con datos de prueba. + +**Datos de entrada:** +- flow_id: UUID +- test_data: object (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] EjecuciΓ³n inicia inmediatamente +- [ ] Datos de prueba inyectados +- [ ] Resultado visible al completar + +--- + +## Ejecuciones + +### RF-PMC-005-007: Ver Historial de Ejecuciones + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-007 | +| **Nombre** | Ver Historial de Ejecuciones | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Datos de salida:** +- Lista de ejecuciones con: + - Timestamp + - Status + - DuraciΓ³n + - Trigger data (resumen) + +**Criterios de aceptaciΓ³n:** +- [ ] PaginaciΓ³n implementada +- [ ] Filtro por status y fecha +- [ ] Click para ver detalle + +--- + +### RF-PMC-005-008: Ver Detalle de EjecuciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-008 | +| **Nombre** | Ver Detalle de EjecuciΓ³n | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Datos de salida:** +- Datos del trigger completos +- Output data +- Error message (si fallΓ³) +- DuraciΓ³n +- Timestamps + +**Criterios de aceptaciΓ³n:** +- [ ] JSON viewer para datos complejos +- [ ] Error stack visible en fallos + +--- + +### RF-PMC-005-009: Cancelar EjecuciΓ³n en Curso + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-009 | +| **Nombre** | Cancelar EjecuciΓ³n en Curso | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Precondiciones:** +- EjecuciΓ³n en status "running" + +**Criterios de aceptaciΓ³n:** +- [ ] EjecuciΓ³n marcada como "cancelled" +- [ ] n8n notificado para cancelar + +--- + +## Webhooks + +### RF-PMC-005-010: Crear Endpoint de Webhook + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-010 | +| **Nombre** | Crear Endpoint de Webhook | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- name: string +- target_flow_id: UUID + +**Datos de salida:** +- slug generado +- URL completa +- secret_key generado + +**Criterios de aceptaciΓ³n:** +- [ ] URL ΓΊnica generada +- [ ] Secret para validaciΓ³n +- [ ] Endpoint activo inmediatamente + +--- + +### RF-PMC-005-011: Listar Webhooks + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-011 | +| **Nombre** | Listar Webhooks | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Lista de endpoints del tenant +- [ ] URL copiable +- [ ] Estado y ΓΊltima llamada visible + +--- + +### RF-PMC-005-012: Eliminar Webhook + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-012 | +| **Nombre** | Eliminar Webhook | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] ConfirmaciΓ³n requerida +- [ ] Endpoint deja de funcionar +- [ ] Registro eliminado + +--- + +### RF-PMC-005-013: Regenerar Secret de Webhook + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-013 | +| **Nombre** | Regenerar Secret de Webhook | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +Generar nuevo secret invalidando el anterior. + +**Criterios de aceptaciΓ³n:** +- [ ] Nuevo secret generado +- [ ] Anterior invalidado +- [ ] Integradores deben actualizar + +--- + +### RF-PMC-005-014: Recibir Webhook Externo + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-014 | +| **Nombre** | Recibir Webhook Externo | +| **Prioridad** | P2 | +| **Actor** | Sistema Externo | + +**Flujo:** +1. Sistema externo hace POST a /hooks/{tenant_slug}/{webhook_slug} +2. Sistema valida firma HMAC +3. Sistema busca flujo asociado +4. Sistema crea ejecuciΓ³n +5. Sistema responde 202 Accepted + +**Criterios de aceptaciΓ³n:** +- [ ] ValidaciΓ³n HMAC funciona +- [ ] Payload parseado correctamente +- [ ] EjecuciΓ³n disparada + +--- + +## Eventos del Sistema + +### RF-PMC-005-015: Emitir Eventos Internos + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-015 | +| **Nombre** | Emitir Eventos Internos | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +El sistema debe emitir eventos cuando ocurren acciones relevantes. + +**Eventos a emitir:** +- CRM: client.created, brand.created, product.created +- Projects: campaign.created, campaign.status_changed, campaign.approved +- Generation: job.completed, job.failed +- Assets: asset.approved, all_assets.approved + +**Criterios de aceptaciΓ³n:** +- [ ] Eventos emitidos en cada acciΓ³n +- [ ] Payload incluye datos relevantes +- [ ] Flujos suscritos son notificados + +--- + +### RF-PMC-005-016: Suscribir Flujo a Evento + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-016 | +| **Nombre** | Suscribir Flujo a Evento | +| **Prioridad** | P1 | +| **Actor** | Sistema | + +**DescripciΓ³n:** +Asociar un flujo con un evento especΓ­fico. + +**Criterios de aceptaciΓ³n:** +- [ ] Flujo se activa cuando evento ocurre +- [ ] Datos del evento pasados al flujo +- [ ] MΓΊltiples flujos pueden suscribirse al mismo evento + +--- + +## Notificaciones + +### RF-PMC-005-017: Enviar NotificaciΓ³n por Email + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-017 | +| **Nombre** | Enviar NotificaciΓ³n por Email | +| **Prioridad** | P1 | +| **Actor** | Sistema (vΓ­a n8n) | + +**DescripciΓ³n:** +Enviar emails como parte de flujos automatizados. + +**Datos de entrada:** +- to: string (email) +- subject: string +- body: string (HTML) +- template_id: string (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Email enviado vΓ­a SMTP/SendGrid +- [ ] Templates soportados +- [ ] Variables interpoladas + +--- + +### RF-PMC-005-018: Enviar NotificaciΓ³n a Slack + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-005-018 | +| **Nombre** | Enviar NotificaciΓ³n a Slack | +| **Prioridad** | P3 | +| **Actor** | Sistema (vΓ­a n8n) | + +**DescripciΓ³n:** +Enviar mensajes a canales de Slack. + +**Datos de entrada:** +- channel: string +- message: string +- blocks: array (opcional, formato Slack) + +**Criterios de aceptaciΓ³n:** +- [ ] Mensaje enviado al canal +- [ ] Formato Slack soportado +- [ ] Webhook configurable por tenant + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 7 | +| P2 | 7 | +| P3 | 4 | +| **Total** | **18** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-006-ASSETS.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-006-ASSETS.md new file mode 100644 index 0000000..8beb65b --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-006-ASSETS.md @@ -0,0 +1,511 @@ +# Requerimientos Funcionales - PMC-006 Assets + +**MΓ³dulo:** Assets (DAM) +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## GestiΓ³n de Assets + +### RF-PMC-006-001: Subir Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-001 | +| **Nombre** | Subir Asset | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- file(s): array[file] (requerido) +- name: string (opcional, usa filename si vacΓ­o) +- description: text (opcional) +- tags: array[string] (opcional) +- campaign_id: UUID (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Upload mΓΊltiple funciona +- [ ] Drag & drop soportado +- [ ] Thumbnails generados automΓ‘ticamente +- [ ] Progreso visible durante upload + +--- + +### RF-PMC-006-002: Ver Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-002 | +| **Nombre** | Ver Asset | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Datos de salida:** +- Preview/visualizaciΓ³n del asset +- Metadata completa +- Historial de versiones +- Comentarios +- Estado de aprobaciΓ³n + +**Criterios de aceptaciΓ³n:** +- [ ] Lightbox para imΓ‘genes +- [ ] Player para videos +- [ ] Viewer para documentos +- [ ] Zoom disponible + +--- + +### RF-PMC-006-003: Editar Metadata de Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-003 | +| **Nombre** | Editar Metadata de Asset | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos editables:** +- name +- description +- tags +- visibility + +**Criterios de aceptaciΓ³n:** +- [ ] Cambios guardados correctamente +- [ ] Historial de cambios registrado + +--- + +### RF-PMC-006-004: Eliminar Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-004 | +| **Nombre** | Eliminar Asset | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Restricciones:** +- Assets aprobados no pueden eliminarse (solo admin) +- Soft delete con retenciΓ³n 30 dΓ­as + +**Criterios de aceptaciΓ³n:** +- [ ] Soft delete funciona +- [ ] Asset va a papelera +- [ ] ConfirmaciΓ³n requerida + +--- + +### RF-PMC-006-005: Restaurar Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-005 | +| **Nombre** | Restaurar Asset | +| **Prioridad** | P2 | +| **Actor** | Creative, Tenant Admin | + +**DescripciΓ³n:** +Recuperar asset de la papelera. + +**Criterios de aceptaciΓ³n:** +- [ ] Asset restaurado a su estado anterior +- [ ] deleted_at se limpia +- [ ] Disponible dentro de 30 dΓ­as + +--- + +### RF-PMC-006-006: Listar Assets + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-006 | +| **Nombre** | Listar Assets | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Vistas:** +- Grid (thumbnails) +- Lista (tabla con metadata) + +**Filtros:** +- type (image, video, document, copy, model) +- status (draft, pending_review, approved, rejected) +- campaign_id +- collection_id +- tags +- date_range +- source (generated, uploaded) + +**Criterios de aceptaciΓ³n:** +- [ ] Ambas vistas funcionan +- [ ] Filtros combinables +- [ ] PaginaciΓ³n con scroll infinito o pΓ‘ginas +- [ ] Ordenamiento mΓΊltiple + +--- + +### RF-PMC-006-007: BΓΊsqueda de Assets + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-007 | +| **Nombre** | BΓΊsqueda de Assets | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Campos buscables:** +- name +- description +- tags +- prompt (para generados) + +**Criterios de aceptaciΓ³n:** +- [ ] BΓΊsqueda de texto funciona +- [ ] Resultados relevantes primero +- [ ] Highlighting de matches + +--- + +## Colecciones + +### RF-PMC-006-008: Crear ColecciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-008 | +| **Nombre** | Crear ColecciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**Datos de entrada:** +- name: string (requerido) +- description: text (opcional) +- type: enum (manual, smart) +- smart_filters: object (si type=smart) + +**Criterios de aceptaciΓ³n:** +- [ ] ColecciΓ³n creada correctamente +- [ ] Smart collection ejecuta filtros + +--- + +### RF-PMC-006-009: Editar ColecciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-009 | +| **Nombre** | Editar ColecciΓ³n | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Criterios de aceptaciΓ³n:** +- [ ] Nombre y descripciΓ³n editables +- [ ] Filtros de smart collection editables +- [ ] Cover image seleccionable + +--- + +### RF-PMC-006-010: Agregar Assets a ColecciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-010 | +| **Nombre** | Agregar Assets a ColecciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Creative | + +**MΓ©todos:** +- Desde asset detail β†’ "Add to collection" +- Desde colecciΓ³n β†’ "Add assets" +- Bulk selection β†’ "Add to collection" + +**Criterios de aceptaciΓ³n:** +- [ ] MΓΊltiples mΓ©todos funcionan +- [ ] Asset puede estar en mΓΊltiples colecciones +- [ ] No duplicados en misma colecciΓ³n + +--- + +### RF-PMC-006-011: Quitar Assets de ColecciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-011 | +| **Nombre** | Quitar Assets de ColecciΓ³n | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Criterios de aceptaciΓ³n:** +- [ ] Asset se desvincula de colecciΓ³n +- [ ] Asset NO se elimina +- [ ] Bulk removal soportado + +--- + +### RF-PMC-006-012: Eliminar ColecciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-012 | +| **Nombre** | Eliminar ColecciΓ³n | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Criterios de aceptaciΓ³n:** +- [ ] ColecciΓ³n eliminada +- [ ] Assets NO se eliminan +- [ ] ConfirmaciΓ³n requerida + +--- + +## Versiones + +### RF-PMC-006-013: Subir Nueva VersiΓ³n de Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-013 | +| **Nombre** | Subir Nueva VersiΓ³n de Asset | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Datos de entrada:** +- asset_id: UUID +- new_file: file +- changes_description: text (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] Nueva versiΓ³n almacenada +- [ ] Version number incrementado +- [ ] VersiΓ³n anterior preservada + +--- + +### RF-PMC-006-014: Ver Historial de Versiones + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-014 | +| **Nombre** | Ver Historial de Versiones | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Datos de salida:** +- Lista de versiones con: + - NΓΊmero de versiΓ³n + - Fecha + - Usuario + - DescripciΓ³n de cambios + - Preview + +**Criterios de aceptaciΓ³n:** +- [ ] Historial completo visible +- [ ] Click para ver versiΓ³n especΓ­fica +- [ ] OpciΓ³n de restaurar versiΓ³n anterior + +--- + +### RF-PMC-006-015: Restaurar VersiΓ³n Anterior + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-015 | +| **Nombre** | Restaurar VersiΓ³n Anterior | +| **Prioridad** | P3 | +| **Actor** | Creative | + +**DescripciΓ³n:** +Hacer que una versiΓ³n anterior sea la actual. + +**Criterios de aceptaciΓ³n:** +- [ ] VersiΓ³n seleccionada se convierte en actual +- [ ] Nueva versiΓ³n creada (copia) +- [ ] Historial preservado + +--- + +## AprobaciΓ³n + +### RF-PMC-006-016: Aprobar Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-016 | +| **Nombre** | Aprobar Asset | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "approved" +- [ ] approved_by y approved_at registrados +- [ ] Asset no editable despuΓ©s (excepto metadata) + +--- + +### RF-PMC-006-017: Rechazar Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-017 | +| **Nombre** | Rechazar Asset | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- feedback: text (requerido) + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "rejected" +- [ ] Feedback almacenado +- [ ] Asset puede regenerarse/versionarse + +--- + +## Comentarios + +### RF-PMC-006-018: Agregar Comentario a Asset + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-018 | +| **Nombre** | Agregar Comentario a Asset | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- content: text (requerido) +- position: object (x, y) - opcional, para comentarios en imagen + +**Criterios de aceptaciΓ³n:** +- [ ] Comentario se crea +- [ ] PosiciΓ³n en imagen soportada +- [ ] NotificaciΓ³n a equipo + +--- + +### RF-PMC-006-019: Responder Comentario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-019 | +| **Nombre** | Responder Comentario | +| **Prioridad** | P2 | +| **Actor** | Creative, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Respuesta vinculada al comentario padre +- [ ] Thread visible +- [ ] NotificaciΓ³n a participantes + +--- + +### RF-PMC-006-020: Resolver Comentario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-020 | +| **Nombre** | Resolver Comentario | +| **Prioridad** | P2 | +| **Actor** | Creative | + +**Criterios de aceptaciΓ³n:** +- [ ] is_resolved cambia a true +- [ ] Comentario colapsado visualmente +- [ ] Puede des-resolverse + +--- + +## Descargas + +### RF-PMC-006-021: Descargar Asset Individual + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-021 | +| **Nombre** | Descargar Asset Individual | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Opciones:** +- Original +- Convertido (formato diferente) +- TamaΓ±o reducido + +**Criterios de aceptaciΓ³n:** +- [ ] Descarga inicia correctamente +- [ ] Registro de descarga creado +- [ ] ConversiΓ³n on-the-fly funciona + +--- + +### RF-PMC-006-022: Descargar MΓΊltiples Assets (ZIP) + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-022 | +| **Nombre** | Descargar MΓΊltiples Assets (ZIP) | +| **Prioridad** | P1 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- asset_ids: array[UUID] +- include_metadata: boolean (opcional) + +**Criterios de aceptaciΓ³n:** +- [ ] ZIP generado con estructura organizada +- [ ] Progreso visible para ZIPs grandes +- [ ] Metadata en JSON opcional + +--- + +### RF-PMC-006-023: Generar Enlace Temporal + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-023 | +| **Nombre** | Generar Enlace Temporal | +| **Prioridad** | P2 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- asset_id: UUID +- expiry_days: number (default: 7, max: 30) + +**Criterios de aceptaciΓ³n:** +- [ ] URL ΓΊnica generada +- [ ] Expira despuΓ©s del tiempo configurado +- [ ] No requiere autenticaciΓ³n para descargar + +--- + +### RF-PMC-006-024: Descargar ColecciΓ³n Completa + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-006-024 | +| **Nombre** | Descargar ColecciΓ³n Completa | +| **Prioridad** | P2 | +| **Actor** | Creative, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Todos los assets de colecciΓ³n en ZIP +- [ ] Estructura de carpetas preservada +- [ ] OpciΓ³n de incluir solo aprobados + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 13 | +| P2 | 9 | +| P3 | 2 | +| **Total** | **24** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-007-ADMIN.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-007-ADMIN.md new file mode 100644 index 0000000..7f3785a --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-007-ADMIN.md @@ -0,0 +1,438 @@ +# Requerimientos Funcionales - PMC-007 Admin + +**MΓ³dulo:** Admin +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## GestiΓ³n de Usuarios + +### RF-PMC-007-001: Listar Usuarios + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-001 | +| **Nombre** | Listar Usuarios | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos de salida:** +- Lista de usuarios del tenant +- Status, rol, ΓΊltimo login +- Filtros por status y rol + +**Criterios de aceptaciΓ³n:** +- [ ] Solo usuarios del tenant +- [ ] PaginaciΓ³n funciona +- [ ] BΓΊsqueda por nombre/email + +--- + +### RF-PMC-007-002: Invitar Usuario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-002 | +| **Nombre** | Invitar Usuario | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- email: string (requerido) +- role_id: UUID (requerido) +- message: text (opcional) + +**Flujo:** +1. Admin ingresa email y selecciona rol +2. Sistema verifica email no existe en tenant +3. Sistema crea invitaciΓ³n con token ΓΊnico +4. Sistema envΓ­a email con link +5. InvitaciΓ³n expira en 7 dΓ­as + +**Criterios de aceptaciΓ³n:** +- [ ] Email de invitaciΓ³n enviado +- [ ] Token ΓΊnico generado +- [ ] InvitaciΓ³n listada como pendiente + +--- + +### RF-PMC-007-003: Aceptar InvitaciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-003 | +| **Nombre** | Aceptar InvitaciΓ³n | +| **Prioridad** | P1 | +| **Actor** | Usuario invitado | + +**Datos de entrada:** +- token: string (del link) +- first_name: string +- last_name: string +- password: string + +**Criterios de aceptaciΓ³n:** +- [ ] Usuario creado con rol asignado +- [ ] Password hasheado +- [ ] InvitaciΓ³n marcada como aceptada +- [ ] Usuario puede hacer login + +--- + +### RF-PMC-007-004: Editar Usuario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-004 | +| **Nombre** | Editar Usuario | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos editables:** +- first_name, last_name +- role_id +- status + +**Criterios de aceptaciΓ³n:** +- [ ] Campos se actualizan +- [ ] Cambio de rol aplica inmediatamente +- [ ] Audit log registra cambios + +--- + +### RF-PMC-007-005: Suspender Usuario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-005 | +| **Nombre** | Suspender Usuario | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +Bloquear acceso de un usuario temporalmente. + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "suspended" +- [ ] Sesiones invalidadas +- [ ] Usuario no puede hacer login +- [ ] Admin no puede suspenderse a sΓ­ mismo + +--- + +### RF-PMC-007-006: Reactivar Usuario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-006 | +| **Nombre** | Reactivar Usuario | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "active" +- [ ] Usuario puede hacer login + +--- + +### RF-PMC-007-007: Eliminar Usuario + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-007 | +| **Nombre** | Eliminar Usuario | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Status cambia a "deactivated" +- [ ] Soft delete +- [ ] Datos preservados (para auditorΓ­a) +- [ ] No puede ser el ΓΊltimo admin + +--- + +### RF-PMC-007-008: Reenviar InvitaciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-008 | +| **Nombre** | Reenviar InvitaciΓ³n | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Nuevo email enviado +- [ ] Token regenerado +- [ ] Expiry extendido + +--- + +## GestiΓ³n de Roles + +### RF-PMC-007-009: Listar Roles + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-009 | +| **Nombre** | Listar Roles | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos de salida:** +- Roles de sistema +- Roles custom del tenant +- Usuarios por rol + +**Criterios de aceptaciΓ³n:** +- [ ] Todos los roles listados +- [ ] IdentificaciΓ³n clara de roles de sistema + +--- + +### RF-PMC-007-010: Ver Permisos de Rol + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-010 | +| **Nombre** | Ver Permisos de Rol | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos de salida:** +- Lista de permisos agrupados por mΓ³dulo +- Checkbox de cada permiso + +**Criterios de aceptaciΓ³n:** +- [ ] Permisos organizados por mΓ³dulo +- [ ] Visual claro de lo que puede/no puede hacer + +--- + +### RF-PMC-007-011: Crear Rol Custom + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-011 | +| **Nombre** | Crear Rol Custom | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Datos de entrada:** +- name: string +- description: text +- permissions: array[string] + +**Criterios de aceptaciΓ³n:** +- [ ] Rol creado con is_system=false +- [ ] Permisos asignados +- [ ] Disponible para asignar a usuarios + +--- + +### RF-PMC-007-012: Editar Rol Custom + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-012 | +| **Nombre** | Editar Rol Custom | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Restricciones:** +- Roles de sistema no editables + +**Criterios de aceptaciΓ³n:** +- [ ] Permisos actualizables +- [ ] Cambios aplican inmediatamente a usuarios + +--- + +### RF-PMC-007-013: Eliminar Rol Custom + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-013 | +| **Nombre** | Eliminar Rol Custom | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Restricciones:** +- No puede tener usuarios asignados +- Roles de sistema no eliminables + +**Criterios de aceptaciΓ³n:** +- [ ] ValidaciΓ³n de usuarios previo a eliminar +- [ ] Error si tiene usuarios + +--- + +## ConfiguraciΓ³n + +### RF-PMC-007-014: Ver ConfiguraciΓ³n del Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-014 | +| **Nombre** | Ver ConfiguraciΓ³n del Tenant | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Secciones:** +- General (nombre, timezone, idioma) +- Branding +- GeneraciΓ³n (defaults) +- Integraciones +- Notificaciones + +**Criterios de aceptaciΓ³n:** +- [ ] Todas las secciones accesibles +- [ ] Valores actuales mostrados + +--- + +### RF-PMC-007-015: Editar ConfiguraciΓ³n General + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-015 | +| **Nombre** | Editar ConfiguraciΓ³n General | +| **Prioridad** | P1 | +| **Actor** | Tenant Admin | + +**Datos editables:** +- Nombre del tenant +- Timezone +- Idioma por defecto +- Formato de fecha + +**Criterios de aceptaciΓ³n:** +- [ ] Cambios guardados +- [ ] Aplican a nuevos usuarios +- [ ] Usuarios existentes pueden tener preferencia propia + +--- + +### RF-PMC-007-016: Configurar Integraciones + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-016 | +| **Nombre** | Configurar Integraciones | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Integraciones configurables:** +- n8n webhook URL +- Slack webhook +- SMTP custom (opcional) +- CRM externo URL + +**Criterios de aceptaciΓ³n:** +- [ ] URLs validadas +- [ ] Test de conexiΓ³n disponible +- [ ] Secrets seguros + +--- + +## AuditorΓ­a + +### RF-PMC-007-017: Ver Logs de AuditorΓ­a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-017 | +| **Nombre** | Ver Logs de AuditorΓ­a | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Filtros:** +- Usuario +- AcciΓ³n +- Entidad +- Fecha + +**Criterios de aceptaciΓ³n:** +- [ ] Logs listados con paginaciΓ³n +- [ ] Filtros combinables +- [ ] Detalle expandible + +--- + +### RF-PMC-007-018: Exportar Logs de AuditorΓ­a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-018 | +| **Nombre** | Exportar Logs de AuditorΓ­a | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Formatos:** +- CSV +- JSON + +**Criterios de aceptaciΓ³n:** +- [ ] Filtros aplicados en export +- [ ] Archivo descargable generado + +--- + +## Sistema (Super Admin) + +### RF-PMC-007-019: Ver Estado del Sistema + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-019 | +| **Nombre** | Ver Estado del Sistema | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**MΓ©tricas:** +- Estado de servicios (API, ComfyUI, Redis, DB) +- Uso de GPU +- Cola de generaciΓ³n +- Storage total + +**Criterios de aceptaciΓ³n:** +- [ ] Dashboard de salud +- [ ] Alertas en problemas + +--- + +### RF-PMC-007-020: Ver Uso por Tenant + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-007-020 | +| **Nombre** | Ver Uso por Tenant | +| **Prioridad** | P2 | +| **Actor** | Super Admin | + +**MΓ©tricas por tenant:** +- Generaciones +- Storage +- Usuarios activos +- API calls + +**Criterios de aceptaciΓ³n:** +- [ ] Comparativa entre tenants +- [ ] Exportable + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 8 | +| P2 | 10 | +| P3 | 2 | +| **Total** | **20** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-008-ANALYTICS.md b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-008-ANALYTICS.md new file mode 100644 index 0000000..6069127 --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/RF-PMC-008-ANALYTICS.md @@ -0,0 +1,356 @@ +# Requerimientos Funcionales - PMC-008 Analytics + +**MΓ³dulo:** Analytics +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## Dashboards + +### RF-PMC-008-001: Ver Dashboard Principal + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-001 | +| **Nombre** | Ver Dashboard Principal | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Widgets:** +- Quick stats (campaΓ±as activas, assets mes, tasa aprobaciΓ³n) +- Actividad reciente +- Acciones pendientes + +**Criterios de aceptaciΓ³n:** +- [ ] Dashboard carga correctamente +- [ ] Datos actualizados +- [ ] Responsive en diferentes pantallas + +--- + +### RF-PMC-008-002: Ver Dashboard de ProducciΓ³n + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-002 | +| **Nombre** | Ver Dashboard de ProducciΓ³n | +| **Prioridad** | P2 | +| **Actor** | Creative, Tenant Admin | + +**Widgets:** +- Volumen de generaciΓ³n (grΓ‘fico de lΓ­neas) +- Estado de cola (gauge) +- Uso de modelos/workflows (pie chart) +- Tasa de error +- Tiempo promedio de procesamiento + +**Criterios de aceptaciΓ³n:** +- [ ] GrΓ‘ficos interactivos +- [ ] Filtro de perΓ­odo funciona +- [ ] Datos en tiempo real para cola + +--- + +### RF-PMC-008-003: Ver Dashboard de CampaΓ±as + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-003 | +| **Nombre** | Ver Dashboard de CampaΓ±as | +| **Prioridad** | P2 | +| **Actor** | Creative, Analyst, Tenant Admin | + +**Widgets:** +- Funnel de campaΓ±as por estado +- Tasa de aprobaciΓ³n primera iteraciΓ³n +- Tiempo promedio brief β†’ aprobaciΓ³n +- Assets por campaΓ±a +- Top clientes + +**Criterios de aceptaciΓ³n:** +- [ ] MΓ©tricas calculadas correctamente +- [ ] Drill-down en grΓ‘ficos +- [ ] Filtro por cliente/perΓ­odo + +--- + +### RF-PMC-008-004: Ver Dashboard de Recursos + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-004 | +| **Nombre** | Ver Dashboard de Recursos | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Widgets:** +- Storage usado vs cuota +- Generaciones mes vs lΓ­mite +- DistribuciΓ³n de storage por tipo +- ProyecciΓ³n de uso + +**Criterios de aceptaciΓ³n:** +- [ ] Progress bars claras +- [ ] Alertas en >80% uso +- [ ] Breakdown por tipo de asset + +--- + +### RF-PMC-008-005: Aplicar Filtros Globales + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-005 | +| **Nombre** | Aplicar Filtros Globales | +| **Prioridad** | P1 | +| **Actor** | Todos los roles | + +**Filtros:** +- PerΓ­odo (hoy, semana, mes, custom) +- Cliente +- Usuario + +**Criterios de aceptaciΓ³n:** +- [ ] Filtros aplican a todos los widgets +- [ ] Persistencia durante sesiΓ³n +- [ ] Reset disponible + +--- + +## Reportes + +### RF-PMC-008-006: Generar Reporte de Actividad Mensual + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-006 | +| **Nombre** | Generar Reporte de Actividad Mensual | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**Contenido:** +- Resumen ejecutivo +- CampaΓ±as del perΓ­odo +- Assets generados +- Uso de recursos +- Comparativa con perΓ­odo anterior + +**Formatos:** +- PDF +- Excel + +**Criterios de aceptaciΓ³n:** +- [ ] Reporte generado correctamente +- [ ] Datos precisos +- [ ] Formato profesional + +--- + +### RF-PMC-008-007: Generar Reporte de CampaΓ±a + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-007 | +| **Nombre** | Generar Reporte de CampaΓ±a | +| **Prioridad** | P2 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- campaign_id: UUID + +**Contenido:** +- Datos de campaΓ±a y brief +- Assets generados/aprobados +- Timeline de actividad +- Participantes + +**Criterios de aceptaciΓ³n:** +- [ ] Reporte especΓ­fico de campaΓ±a +- [ ] Incluye thumbnails de assets +- [ ] PDF descargable + +--- + +### RF-PMC-008-008: Generar Reporte de Cliente + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-008 | +| **Nombre** | Generar Reporte de Cliente | +| **Prioridad** | P3 | +| **Actor** | Analyst, Tenant Admin | + +**Datos de entrada:** +- client_id: UUID +- date_range: object + +**Contenido:** +- Proyectos y campaΓ±as +- Assets entregados +- HistΓ³rico de actividad + +**Criterios de aceptaciΓ³n:** +- [ ] Filtro de perΓ­odo funciona +- [ ] Exportable en PDF/Excel + +--- + +### RF-PMC-008-009: Programar Reporte AutomΓ‘tico + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-009 | +| **Nombre** | Programar Reporte AutomΓ‘tico | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Opciones:** +- Frecuencia (semanal, mensual) +- Destinatarios (emails) +- Tipo de reporte + +**Criterios de aceptaciΓ³n:** +- [ ] ProgramaciΓ³n guardada +- [ ] Email enviado automΓ‘ticamente +- [ ] PDF adjunto + +--- + +### RF-PMC-008-010: Ver Historial de Reportes + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-010 | +| **Nombre** | Ver Historial de Reportes | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Datos de salida:** +- Lista de reportes generados +- Fecha, tipo, generador +- Link de descarga + +**Criterios de aceptaciΓ³n:** +- [ ] Reportes listados +- [ ] Descarga disponible (30 dΓ­as) +- [ ] Filtro por tipo/fecha + +--- + +## MΓ©tricas + +### RF-PMC-008-011: Consultar MΓ©tricas Raw + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-011 | +| **Nombre** | Consultar MΓ©tricas Raw | +| **Prioridad** | P2 | +| **Actor** | Tenant Admin | + +**DescripciΓ³n:** +API para consultar mΓ©tricas agregadas. + +**ParΓ‘metros:** +- metric_type +- dimensions +- period +- filters + +**Criterios de aceptaciΓ³n:** +- [ ] API retorna datos correctos +- [ ] Agregaciones funcionan +- [ ] PaginaciΓ³n para grandes volΓΊmenes + +--- + +### RF-PMC-008-012: Exportar Datos de MΓ©tricas + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-012 | +| **Nombre** | Exportar Datos de MΓ©tricas | +| **Prioridad** | P3 | +| **Actor** | Tenant Admin | + +**Formatos:** +- CSV +- JSON + +**Criterios de aceptaciΓ³n:** +- [ ] Filtros aplicados +- [ ] Formato correcto +- [ ] Útil para BI externo + +--- + +## PersonalizaciΓ³n + +### RF-PMC-008-013: Guardar Vista Personalizada + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-013 | +| **Nombre** | Guardar Vista Personalizada | +| **Prioridad** | P3 | +| **Actor** | Creative, Tenant Admin | + +**Datos de entrada:** +- name: string +- dashboard: string +- config: object (filtros, widgets visibles) + +**Criterios de aceptaciΓ³n:** +- [ ] Vista guardada +- [ ] Cargable posteriormente +- [ ] Por usuario + +--- + +### RF-PMC-008-014: Establecer Vista por Defecto + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-014 | +| **Nombre** | Establecer Vista por Defecto | +| **Prioridad** | P3 | +| **Actor** | Creative, Tenant Admin | + +**DescripciΓ³n:** +Marcar una vista guardada como la que se carga al abrir dashboard. + +**Criterios de aceptaciΓ³n:** +- [ ] Vista se carga automΓ‘ticamente +- [ ] Una sola vista por defecto por dashboard + +--- + +### RF-PMC-008-015: Eliminar Vista Guardada + +| Campo | Valor | +|-------|-------| +| **ID** | RF-PMC-008-015 | +| **Nombre** | Eliminar Vista Guardada | +| **Prioridad** | P3 | +| **Actor** | Creative, Tenant Admin | + +**Criterios de aceptaciΓ³n:** +- [ ] Vista eliminada +- [ ] Si era default, se usa vista estΓ‘ndar + +--- + +## Resumen + +| Prioridad | Cantidad | +|-----------|----------| +| P1 | 2 | +| P2 | 6 | +| P3 | 7 | +| **Total** | **15** | + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/03-requerimientos/_INDEX.md b/projects/platform_marketing_content/docs/03-requerimientos/_INDEX.md new file mode 100644 index 0000000..fc9f3f1 --- /dev/null +++ b/projects/platform_marketing_content/docs/03-requerimientos/_INDEX.md @@ -0,0 +1,58 @@ +# Índice de Requerimientos Funcionales + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## Documentos de Requerimientos + +| ID | MΓ³dulo | Documento | RFs | Estado | +|----|--------|-----------|-----|--------| +| RF-001 | Tenants | [RF-PMC-001-TENANTS.md](./RF-PMC-001-TENANTS.md) | 15 | Definido | +| RF-002 | CRM | [RF-PMC-002-CRM.md](./RF-PMC-002-CRM.md) | 25 | Definido | +| RF-003 | Projects | [RF-PMC-003-PROJECTS.md](./RF-PMC-003-PROJECTS.md) | 22 | Definido | +| RF-004 | Generation | [RF-PMC-004-GENERATION.md](./RF-PMC-004-GENERATION.md) | 28 | Definido | +| RF-005 | Automation | [RF-PMC-005-AUTOMATION.md](./RF-PMC-005-AUTOMATION.md) | 18 | Definido | +| RF-006 | Assets | [RF-PMC-006-ASSETS.md](./RF-PMC-006-ASSETS.md) | 24 | Definido | +| RF-007 | Admin | [RF-PMC-007-ADMIN.md](./RF-PMC-007-ADMIN.md) | 20 | Definido | +| RF-008 | Analytics | [RF-PMC-008-ANALYTICS.md](./RF-PMC-008-ANALYTICS.md) | 15 | Definido | + +**Total de Requerimientos Funcionales:** 167 + +--- + +## Nomenclatura + +``` +RF-PMC-XXX-YYY + +Donde: +- RF: Requerimiento Funcional +- PMC: Platform Marketing Content +- XXX: ID del mΓ³dulo (001-008) +- YYY: NΓΊmero secuencial del requerimiento +``` + +--- + +## Prioridades + +| Prioridad | DescripciΓ³n | Criterio | +|-----------|-------------|----------| +| **P1** | CrΓ­tico | Bloquea el MVP, sin esto no funciona | +| **P2** | Alto | Necesario para MVP, funcionalidad core | +| **P3** | Medio | Deseable para MVP, mejora UX | +| **P4** | Bajo | Post-MVP, mejoras futuras | + +--- + +## Referencias + +- [DefiniciΓ³n de MΓ³dulos](../02-definicion-modulos/_INDEX.md) +- [Arquitectura TΓ©cnica](../00-vision-general/ARQUITECTURA-TECNICA.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/docs/04-modelado/MODELO-DOMINIO.md b/projects/platform_marketing_content/docs/04-modelado/MODELO-DOMINIO.md new file mode 100644 index 0000000..5cad5f7 --- /dev/null +++ b/projects/platform_marketing_content/docs/04-modelado/MODELO-DOMINIO.md @@ -0,0 +1,275 @@ +# Modelo de Dominio - Platform Marketing Content + +**VersiΓ³n:** 1.0.0 +**Fecha:** 2025-12-08 + +--- + +## Diagrama de Entidades + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CORE ENTITIES β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Tenant │◄────────│ Plan β”‚ β”‚ User β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ 1:N β”‚ N:1 β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Client β”‚ β”‚ Role β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ 1:N β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Contact β”‚ β”‚ Brand │◄────────┐ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ N:N β”‚ +β”‚ β”‚ 1:N β”‚ β”‚ +β”‚ β–Ό β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Product β”‚ β”‚CustomModelβ”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ PROJECT ENTITIES β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Project │◄──────────────────┐ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ N:1 (Client) β”‚ +β”‚ β”‚ 1:N β”‚ β”‚ +β”‚ β–Ό β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Campaign │─────────│Opportunityβ”‚ β”‚ BriefTpl β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ 1:N β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚CampaignAsset │──────────┐ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ N:1 β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Asset β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ GENERATION ENTITIES β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚GenerationJob │───────────────────│WorkflowTemplateβ”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ 1:N β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Asset β”‚ β”‚ TextGeneration β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ 1:N β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ AssetVersion β”‚ β”‚ AssetComment β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ AUTOMATION ENTITIES β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚AutomationFlow │───────────────────│ AutomationRun β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ N:1 β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚WebhookEndpoint β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ SUPPORT ENTITIES β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚Collectionβ”‚ β”‚Invitationβ”‚ β”‚ AuditLog β”‚ β”‚ Setting β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Download β”‚ β”‚ Metric β”‚ β”‚ Report β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Entidades por MΓ³dulo + +### PMC-001: Tenants + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **Tenant** | OrganizaciΓ³n que usa la plataforma | 1:N User, Client, Project, Asset | +| **Plan** | Plan de suscripciΓ³n con lΓ­mites | 1:N Tenant | + +### PMC-002: CRM + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **Client** | Empresa cliente de la agencia | N:1 Tenant, 1:N Contact, Brand, Project | +| **Contact** | Persona de contacto | N:1 Client | +| **Brand** | Marca con identidad visual | N:1 Client, 1:N Product, Campaign | +| **Product** | Producto o servicio | N:1 Brand | +| **Opportunity** | Oportunidad comercial | N:1 Client, Contact | + +### PMC-003: Projects + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **Project** | Contenedor de campaΓ±as | N:1 Client, Tenant, 1:N Campaign | +| **Campaign** | CampaΓ±a de marketing con brief | N:1 Project, Brand, 1:N CampaignAsset | +| **CampaignAsset** | RelaciΓ³n campaΓ±a-asset con estado | N:1 Campaign, Asset | + +### PMC-004: Generation + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **GenerationJob** | Tarea de generaciΓ³n | N:1 Tenant, Campaign, WorkflowTemplate | +| **WorkflowTemplate** | Plantilla de workflow ComfyUI | 1:N GenerationJob | +| **CustomModel** | LoRA/Checkpoint personalizado | N:1 Tenant, Brand | +| **TextGeneration** | GeneraciΓ³n de texto/copy | N:1 Tenant, GenerationJob | + +### PMC-005: Automation + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **AutomationFlow** | DefiniciΓ³n de flujo automatizado | N:1 Tenant, 1:N AutomationRun | +| **AutomationRun** | EjecuciΓ³n de un flujo | N:1 AutomationFlow | +| **WebhookEndpoint** | Endpoint para webhooks externos | N:1 Tenant, AutomationFlow | + +### PMC-006: Assets + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **Asset** | Recurso digital (imagen, video, etc.) | N:1 Tenant, GenerationJob | +| **AssetVersion** | VersiΓ³n histΓ³rica de asset | N:1 Asset | +| **Collection** | AgrupaciΓ³n de assets | N:1 Tenant, N:N Asset | +| **AssetComment** | Comentario sobre asset | N:1 Asset, User | +| **Download** | Registro de descarga | N:1 Asset, User | + +### PMC-007: Admin + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **User** | Usuario del sistema | N:1 Tenant, Role | +| **Role** | Rol con permisos | 1:N User | +| **Invitation** | InvitaciΓ³n pendiente | N:1 Tenant, Role | +| **AuditLog** | Registro de auditorΓ­a | N:1 Tenant, User | +| **Setting** | ConfiguraciΓ³n del sistema | N:1 Tenant (opcional) | + +### PMC-008: Analytics + +| Entidad | DescripciΓ³n | Relaciones Principales | +|---------|-------------|------------------------| +| **Metric** | Dato mΓ©trico agregado | N:1 Tenant | +| **Report** | Reporte generado | N:1 Tenant, User | +| **SavedView** | Vista personalizada guardada | N:1 Tenant, User | + +--- + +## Matriz de Relaciones + +``` + β”‚Tenβ”‚Plnβ”‚Usrβ”‚Rolβ”‚Cliβ”‚Conβ”‚Braβ”‚Proβ”‚Oppβ”‚Prjβ”‚Camβ”‚CAsβ”‚Jobβ”‚Wflβ”‚Modβ”‚Txtβ”‚Floβ”‚Runβ”‚Whkβ”‚Astβ”‚Verβ”‚Colβ”‚Comβ”‚Dwnβ”‚Invβ”‚Audβ”‚Setβ”‚Metβ”‚Repβ”‚Viwβ”‚ +─────────────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼──── +Tenant β”‚ β”‚N:1β”‚1:Nβ”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚1:Nβ”‚ β”‚1:Nβ”‚ β”‚1:Nβ”‚ β”‚1:Nβ”‚1:Nβ”‚ β”‚1:Nβ”‚ β”‚ β”‚1:Nβ”‚1:Nβ”‚1:Nβ”‚1:Nβ”‚1:Nβ”‚1:Nβ”‚ +Plan β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +User β”‚N:1β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚1:Nβ”‚1:Nβ”‚ β”‚1:Nβ”‚ β”‚ β”‚1:Nβ”‚1:Nβ”‚ +Role β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Client β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚1:Nβ”‚ β”‚1:Nβ”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Contact β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Brand β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚N:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Product β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Opportunity β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Project β”‚N:1β”‚ β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Campaign β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚N:1β”‚ β”‚1:Nβ”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +CampaignAssetβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +GenJob β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚N:1β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Workflow β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +CustomModel β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +TextGen β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +AutoFlow β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +AutoRun β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Webhook β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Asset β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚1:Nβ”‚N:Nβ”‚1:Nβ”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +AssetVer β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Collection β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +AssetComment β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚ β”‚1:Nβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Download β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Invitation β”‚N:1β”‚ β”‚N:1β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +AuditLog β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Setting β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Metric β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +Report β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +SavedView β”‚N:1β”‚ β”‚N:1β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +``` + +--- + +## Agregados (DDD) + +### Aggregate: Tenant +- **Root:** Tenant +- **Entities:** Plan (referencia) +- **Value Objects:** Settings, Branding, Limits + +### Aggregate: Client +- **Root:** Client +- **Entities:** Contact, Brand, Product +- **Value Objects:** Identity (en Brand) + +### Aggregate: Project +- **Root:** Project +- **Entities:** Campaign, CampaignAsset +- **Value Objects:** Brief (en Campaign) + +### Aggregate: Asset +- **Root:** Asset +- **Entities:** AssetVersion, AssetComment +- **Value Objects:** Metadata, Dimensions + +### Aggregate: GenerationJob +- **Root:** GenerationJob +- **Entities:** (outputs referenciados) +- **Value Objects:** InputParams, Progress + +### Aggregate: User +- **Root:** User +- **Entities:** (Role como referencia) +- **Value Objects:** Preferences + +--- + +## Referencias + +- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) +- [DefiniciΓ³n de MΓ³dulos](../02-definicion-modulos/_INDEX.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/orchestration/00-guidelines/CONTEXTO-PROYECTO.md b/projects/platform_marketing_content/orchestration/00-guidelines/CONTEXTO-PROYECTO.md new file mode 100644 index 0000000..a308700 --- /dev/null +++ b/projects/platform_marketing_content/orchestration/00-guidelines/CONTEXTO-PROYECTO.md @@ -0,0 +1,188 @@ +# Contexto de Proyecto: Platform Marketing Content + +**Versiθ΄Έn:** 1.0.0 +**Fecha:** 2025-12-08 +**Nivel SIMCO:** NIVEL_2B (Proyecto independiente) + +--- + +## Identificaciθ΄Έn del Proyecto + +```yaml +Proyecto: platform_marketing_content +Alias: PMC +Tipo: SaaS Platform +Dominio: Marketing Digital / Generaciθ΄Έn de Contenido IA +Estado: Anθ°©lisis y Documentaciθ΄Έn +``` + +--- + +## Descripciθ΄Έn + +**Platform Marketing Content (PMC)** es una plataforma SaaS para agencias de publicidad que combina: + +1. **Motor de Generaciθ΄Έn de Contenido con IA** - Imθ°©genes y copys automθ°©ticos +2. **CRM Integrado** - Gestiθ΄Έn de clientes, marcas y campaεΈ½as +3. **Automatizaciθ΄Έn Creativa** - Flujos desde brief hasta entrega +4. **DAM** - Biblioteca de activos digitales + +--- + +## Stack Tecnolθ΄Έgico + +```yaml +Backend: + - NestJS + TypeScript + - PostgreSQL 15+ + - Redis + - Bull/BullMQ + +Frontend: + - React 18 + Vite + - TailwindCSS + - Shadcn/UI + +Motor IA: + - ComfyUI + - Stable Diffusion XL + - ComfyDeploy + +Automatizaciθ΄Έn: + - n8n + +Almacenamiento: + - S3/MinIO +``` + +--- + +## Estructura de Documentaciθ΄Έn + +``` +projects/platform_marketing_content/ +鉁斺攒鉁? docs/ +鉁? 鉁斺攒鉁? 00-vision-general/ # Visiθ΄Έn, arquitectura, glosario +鉁? 鉁斺攒鉁? 01-analisis-referencias/ # Investigaciθ΄Έn, benchmarks +鉁? 鉁斺攒鉁? 02-definicion-modulos/ # Especificaciones por mθ΄Έdulo +鉁? 鉁斺攒鉁? 03-requerimientos/ # Requerimientos funcionales +鉁? 鉁斺攒鉁? 04-modelado/ # Modelos de dominio, DB design +鉁? 鉁斺攒鉁? 05-user-stories/ # Historias de usuario +鉁? 鉁斺攒鉁? 95-guias-desarrollo/ # Gu铆as y convenciones +鉁? 鉁斺攒鉁? 97-adr/ # Decisiones arquitectθ΄Έnicas +鉁? +鉁斺攒鉁? orchestration/ +鉁? 鉁斺攒鉁? 00-guidelines/ # Contexto, herencias +鉁? 鉁斺攒鉁? inventarios/ # Inventarios de implementaciθ΄Έn +鉁? 鉁斺攒鉁? trazas/ # Trazas de tareas +鉁? +鉁斺攒鉁? apps/ + 鉁斺攒鉁? backend/ # Cθ΄Έdigo NestJS + 鉁斺攒鉁? frontend/ # Cθ΄Έdigo React + 鉁斺攒鉁? comfyui/ # Workflows ComfyUI +``` + +--- + +## Mθ΄Έdulos Funcionales + +| ID | Mθ΄Έdulo | Descripciθ΄Έn | Prioridad | +|----|--------|-------------|-----------| +| PMC-001 | Tenants | Arquitectura multi-tenant | Alta | +| PMC-002 | CRM | Clientes, marcas, productos | Alta | +| PMC-003 | Projects | Proyectos y campaεΈ½as | Alta | +| PMC-004 | Generation | Motor de generaciθ΄Έn IA | Alta | +| PMC-005 | Automation | Flujos automatizados | Media | +| PMC-006 | Assets | DAM - biblioteca de activos | Alta | +| PMC-007 | Admin | Administraciθ΄Έn SaaS | Media | +| PMC-008 | Analytics | Reportes y dashboards | Baja | + +--- + +## Aliases del Proyecto + +```yaml +# Documentaciθ΄Έn +@PMC_DOCS: projects/platform_marketing_content/docs/ +@PMC_VISION: projects/platform_marketing_content/docs/00-vision-general/ +@PMC_MODULES: projects/platform_marketing_content/docs/02-definicion-modulos/ +@PMC_REQS: projects/platform_marketing_content/docs/03-requerimientos/ +@PMC_ADR: projects/platform_marketing_content/docs/97-adr/ + +# Orchestration +@PMC_ORCH: projects/platform_marketing_content/orchestration/ +@PMC_INVENTORY: projects/platform_marketing_content/orchestration/inventarios/ +@PMC_TRAZA: projects/platform_marketing_content/orchestration/trazas/ + +# Cθ΄Έdigo +@PMC_BACKEND: projects/platform_marketing_content/apps/backend/ +@PMC_FRONTEND: projects/platform_marketing_content/apps/frontend/ +``` + +--- + +## Dependencias del Catθ°©logo Core + +Funcionalidades reutilizables del catθ°©logo: + +```yaml +Requeridas: + - @CATALOG_AUTH: Autenticaciθ΄Έn JWT + OAuth + - @CATALOG_SESSION: Gestiθ΄Έn de sesiones + - @CATALOG_TENANT: Multi-tenancy (adaptar) + - @CATALOG_NOTIFY: Notificaciones + +Opcionales: + - @CATALOG_RATELIMIT: Rate limiting + - @CATALOG_FLAGS: Feature flags +``` + +--- + +## Roadmap de Fases + +```yaml +Fase 1 - MVP Core (Semanas 1-8): + - Arquitectura base + - CRM bθ°©sico + - Motor de generaciθ΄Έn (2-3 workflows) + - DAM bθ°©sico + - Admin usuarios + +Fase 2 - Personalizaciθ΄Έn (Semanas 9-14): + - LoRAs por marca + - Avatares consistentes + - Integraciθ΄Έn CRMιˆ«ζ‰œeneraciθ΄Έn + +Fase 3 - Contenido Enriquecido (Semanas 15-22): + - GIFs/cinemagraphs + - Video bθ°©sico + - Portal cliente + +Fase 4 - Multi-tenant Comercial (Semanas 23+): + - SaaS pη…€blico + - Planes de suscripciθ΄Έn +``` + +--- + +## Contactos y Responsables + +```yaml +Product Owner: [Por definir] +Tech Lead: [Por definir] +Requirements Analyst: Agente IA +``` + +--- + +## Referencias + +- [VISION-GENERAL.md](../../docs/00-vision-general/VISION-GENERAL.md) +- [ARQUITECTURA-TECNICA.md](../../docs/00-vision-general/ARQUITECTURA-TECNICA.md) +- [GLOSARIO.md](../../docs/00-vision-general/GLOSARIO.md) + +--- + +**Documento generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/orchestration/PROXIMA-ACCION.md b/projects/platform_marketing_content/orchestration/PROXIMA-ACCION.md new file mode 100644 index 0000000..1deab0c --- /dev/null +++ b/projects/platform_marketing_content/orchestration/PROXIMA-ACCION.md @@ -0,0 +1,161 @@ +# PrΓ³xima AcciΓ³n - Platform Marketing Content + +**Fecha:** 2025-12-08 +**Estado Actual:** DocumentaciΓ³n Completada + +--- + +## Resumen de Progreso + +### Completado + +- [x] VisiΓ³n general del proyecto consolidada +- [x] Glosario de tΓ©rminos del dominio +- [x] Arquitectura tΓ©cnica detallada +- [x] DefiniciΓ³n de 8 mΓ³dulos funcionales +- [x] Contexto de proyecto para orchestration +- [x] Inventario maestro (MASTER_INVENTORY.yml) + +### Estructura de DocumentaciΓ³n Creada + +``` +projects/platform_marketing_content/ +β”œβ”€β”€ docs/ +β”‚ β”œβ”€β”€ 00-vision-general/ +β”‚ β”‚ β”œβ”€β”€ VISION-GENERAL.md βœ… +β”‚ β”‚ β”œβ”€β”€ ARQUITECTURA-TECNICA.md βœ… +β”‚ β”‚ β”œβ”€β”€ GLOSARIO.md βœ… +β”‚ β”‚ └── MVP_Plataforma_SaaS...md (original) +β”‚ β”œβ”€β”€ 01-analisis-referencias/ (vacΓ­o) +β”‚ β”œβ”€β”€ 02-definicion-modulos/ +β”‚ β”‚ β”œβ”€β”€ _INDEX.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-001-TENANTS.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-002-CRM.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-003-PROJECTS.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-004-GENERATION.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-005-AUTOMATION.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-006-ASSETS.md βœ… +β”‚ β”‚ β”œβ”€β”€ PMC-007-ADMIN.md βœ… +β”‚ β”‚ └── PMC-008-ANALYTICS.md βœ… +β”‚ β”œβ”€β”€ 03-requerimientos/ (pendiente) +β”‚ β”œβ”€β”€ 04-modelado/ (pendiente) +β”‚ β”œβ”€β”€ 05-user-stories/ (pendiente) +β”‚ β”œβ”€β”€ 95-guias-desarrollo/ (pendiente) +β”‚ └── 97-adr/ (pendiente) +β”‚ +└── orchestration/ + β”œβ”€β”€ 00-guidelines/ + β”‚ └── CONTEXTO-PROYECTO.md βœ… + β”œβ”€β”€ inventarios/ + β”‚ └── MASTER_INVENTORY.yml βœ… + └── trazas/ (vacΓ­o) +``` + +--- + +## PrΓ³ximas Acciones Sugeridas + +### OpciΓ³n A: Continuar DocumentaciΓ³n (Requirements-Analyst) + +```yaml +Prioridad: Alta +Agente: Requirements-Analyst +Tareas: + 1. Crear requerimientos funcionales detallados: + - docs/03-requerimientos/RF-PMC-001-TENANTS.md + - docs/03-requerimientos/RF-PMC-002-CRM.md + - ... (por cada mΓ³dulo) + + 2. Crear modelo de datos consolidado: + - docs/04-modelado/MODELO-DOMINIO.md + - docs/04-modelado/ESQUEMA-BD.md + + 3. Crear user stories para MVP: + - docs/05-user-stories/EPIC-001-SETUP.md + - docs/05-user-stories/EPIC-002-CRM.md + - ... + +EstimaciΓ³n: 4-6 horas de trabajo de agente +``` + +### OpciΓ³n B: Iniciar ImplementaciΓ³n (Feature-Developer) + +```yaml +Prioridad: Alta +Agente: Feature-Developer +Prerequisitos: + - DocumentaciΓ³n actual es suficiente para MVP + - Usar docs/02-definicion-modulos/* como referencia + +Tareas: + 1. Setup del proyecto backend: + - Crear proyecto NestJS + - Configurar TypeORM + PostgreSQL + - Implementar estructura de mΓ³dulos + + 2. Implementar PMC-001-TENANTS: + - Entidades: Tenant, Plan + - RLS para multi-tenancy + - Endpoints bΓ‘sicos + + 3. Implementar PMC-007-ADMIN (parcial): + - User, Role, permisos + - AutenticaciΓ³n JWT + +EstimaciΓ³n: 16-24 horas para setup + 2 mΓ³dulos base +``` + +### OpciΓ³n C: Revisar y Validar (Documentation-Validator) + +```yaml +Prioridad: Media +Agente: Documentation-Validator +Tareas: + 1. Validar consistencia entre documentos + 2. Verificar que todas las entidades estΓ©n definidas + 3. Revisar endpoints duplicados o faltantes + 4. Generar checklist de validaciΓ³n + +EstimaciΓ³n: 2-3 horas +``` + +--- + +## RecomendaciΓ³n + +Para avanzar de manera eficiente, se sugiere: + +1. **Si se quiere documentaciΓ³n exhaustiva**: Continuar con OpciΓ³n A +2. **Si se quiere iniciar desarrollo pronto**: Ir con OpciΓ³n B usando la documentaciΓ³n actual +3. **Enfoque hΓ­brido**: Ejecutar OpciΓ³n B mientras otro agente avanza en OpciΓ³n A + +La documentaciΓ³n actual (8 mΓ³dulos definidos con entidades, funcionalidades, APIs) es suficiente para comenzar implementaciΓ³n del MVP. + +--- + +## Comandos de ActivaciΓ³n + +```bash +# Para continuar documentaciΓ³n +@Requirements-Analyst continuar con requerimientos funcionales para PMC + +# Para iniciar implementaciΓ³n +@Feature-Developer setup proyecto backend PMC con mΓ³dulos Tenants y Admin + +# Para validaciΓ³n +@Documentation-Validator validar documentaciΓ³n de PMC +``` + +--- + +## Notas Adicionales + +- El proyecto usa stack NestJS + React + ComfyUI +- Priorizar mΓ³dulos: PMC-001, PMC-007, PMC-002, PMC-006 (en ese orden) +- La integraciΓ³n con ComfyUI (PMC-004) requiere servidor GPU configurado +- n8n (PMC-005) puede ejecutarse en contenedor Docker local + +--- + +**Generado por:** Requirements-Analyst +**Fecha:** 2025-12-08 diff --git a/projects/platform_marketing_content/orchestration/inventarios/MASTER_INVENTORY.yml b/projects/platform_marketing_content/orchestration/inventarios/MASTER_INVENTORY.yml new file mode 100644 index 0000000..cfdeb31 --- /dev/null +++ b/projects/platform_marketing_content/orchestration/inventarios/MASTER_INVENTORY.yml @@ -0,0 +1,339 @@ +# MASTER_INVENTORY.yml - Platform Marketing Content +# Inventario maestro de implementaciΓ³n +# VersiΓ³n: 1.0.0 +# Fecha: 2025-12-08 + +project: + name: Platform Marketing Content + alias: PMC + nivel_simco: NIVEL_2B + status: documentacion + +# ============================================================================= +# MΓ“DULOS +# ============================================================================= +modules: + PMC-001-TENANTS: + name: Tenants + priority: alta + status: definido + doc_path: docs/02-definicion-modulos/PMC-001-TENANTS.md + dependencies: + catalog: + - "@CATALOG_TENANT" + entities: + - Tenant + - Plan + endpoints_count: 8 + features_count: 10 + + PMC-002-CRM: + name: CRM + priority: alta + status: definido + doc_path: docs/02-definicion-modulos/PMC-002-CRM.md + dependencies: + modules: + - PMC-001-TENANTS + - PMC-003-PROJECTS + - PMC-004-GENERATION + - PMC-006-ASSETS + entities: + - Client + - Contact + - Brand + - Product + - Opportunity + endpoints_count: 25 + features_count: 18 + + PMC-003-PROJECTS: + name: Projects + priority: alta + status: definido + doc_path: docs/02-definicion-modulos/PMC-003-PROJECTS.md + dependencies: + modules: + - PMC-001-TENANTS + - PMC-002-CRM + - PMC-004-GENERATION + - PMC-006-ASSETS + entities: + - Project + - Campaign + - CampaignAsset + endpoints_count: 20 + features_count: 16 + + PMC-004-GENERATION: + name: Generation (Motor IA) + priority: alta + status: definido + doc_path: docs/02-definicion-modulos/PMC-004-GENERATION.md + dependencies: + modules: + - PMC-001-TENANTS + - PMC-002-CRM + - PMC-003-PROJECTS + - PMC-006-ASSETS + catalog: + - "@CATALOG_RATELIMIT" + external: + - ComfyUI + - OpenAI/Claude API + - Redis + - S3/MinIO + entities: + - GenerationJob + - WorkflowTemplate + - CustomModel + - TextGeneration + endpoints_count: 18 + features_count: 20 + workflows_predefinidos: + - product_photo_synthetic + - social_media_post + - ad_variations + - virtual_avatar + + PMC-005-AUTOMATION: + name: Automation + priority: media + status: definido + doc_path: docs/02-definicion-modulos/PMC-005-AUTOMATION.md + dependencies: + modules: + - PMC-001-TENANTS + - PMC-002-CRM + - PMC-003-PROJECTS + - PMC-004-GENERATION + - PMC-006-ASSETS + external: + - n8n + - SMTP/SendGrid + entities: + - AutomationFlow + - AutomationRun + - WebhookEndpoint + endpoints_count: 15 + features_count: 12 + flows_predefinidos: + - product_asset_kit + - campaign_initial_batch + - campaign_delivery_prep + - job_failure_handler + + PMC-006-ASSETS: + name: Assets (DAM) + priority: alta + status: definido + doc_path: docs/02-definicion-modulos/PMC-006-ASSETS.md + dependencies: + modules: + - PMC-001-TENANTS + - PMC-003-PROJECTS + - PMC-004-GENERATION + external: + - S3/MinIO + - Sharp + entities: + - Asset + - AssetVersion + - Collection + - AssetComment + - Download + endpoints_count: 25 + features_count: 18 + + PMC-007-ADMIN: + name: Admin + priority: media + status: definido + doc_path: docs/02-definicion-modulos/PMC-007-ADMIN.md + dependencies: + modules: + - PMC-001-TENANTS + catalog: + - "@CATALOG_AUTH" + - "@CATALOG_SESSION" + entities: + - User + - Role + - Invitation + - AuditLog + - Setting + endpoints_count: 20 + features_count: 14 + roles_sistema: + - super_admin + - tenant_admin + - creative + - analyst + - viewer + - client_portal + + PMC-008-ANALYTICS: + name: Analytics + priority: baja + status: definido + doc_path: docs/02-definicion-modulos/PMC-008-ANALYTICS.md + dependencies: + modules: + - PMC-001-TENANTS + - PMC-003-PROJECTS + - PMC-004-GENERATION + - PMC-006-ASSETS + external: + - Redis + entities: + - Metric + - Report + - SavedView + endpoints_count: 12 + features_count: 10 + dashboards: + - home + - production + - campaigns + - resources + +# ============================================================================= +# STACK TECNOLΓ“GICO +# ============================================================================= +tech_stack: + backend: + framework: NestJS + language: TypeScript + database: PostgreSQL 15+ + cache: Redis + queue: Bull/BullMQ + orm: TypeORM + + frontend: + framework: React 18 + bundler: Vite + styling: TailwindCSS + components: Shadcn/UI + state: Zustand o React Query + + ia_engine: + image_generation: ComfyUI + SDXL + text_generation: OpenAI API / Claude API + deployment: ComfyDeploy + + automation: + orchestrator: n8n + + storage: + files: S3/MinIO + + infrastructure: + containers: Docker + Docker Compose + gpu: NVIDIA (12-24GB VRAM) + +# ============================================================================= +# CATÁLOGO DE DEPENDENCIAS +# ============================================================================= +catalog_dependencies: + required: + - id: "@CATALOG_AUTH" + description: AutenticaciΓ³n JWT + OAuth + module: PMC-007-ADMIN + + - id: "@CATALOG_SESSION" + description: GestiΓ³n de sesiones + module: PMC-007-ADMIN + + - id: "@CATALOG_TENANT" + description: Multi-tenancy (adaptar) + module: PMC-001-TENANTS + + optional: + - id: "@CATALOG_RATELIMIT" + description: Rate limiting + module: PMC-004-GENERATION + + - id: "@CATALOG_NOTIFY" + description: Notificaciones + module: PMC-005-AUTOMATION + +# ============================================================================= +# FASES DE IMPLEMENTACIΓ“N +# ============================================================================= +roadmap: + fase_1_mvp_core: + duration: "Semanas 1-8" + modules: + - PMC-001-TENANTS + - PMC-007-ADMIN + - PMC-002-CRM + - PMC-006-ASSETS + - PMC-003-PROJECTS + - PMC-004-GENERATION + deliverables: + - Arquitectura base multi-tenant + - AutenticaciΓ³n y usuarios + - CRM bΓ‘sico (clientes, marcas, productos) + - DAM bΓ‘sico + - CampaΓ±as con brief + - Motor de generaciΓ³n (2-3 workflows) + + fase_2_personalizacion: + duration: "Semanas 9-14" + modules: + - PMC-004-GENERATION (ampliaciΓ³n) + - PMC-005-AUTOMATION + deliverables: + - Entrenamiento de LoRAs + - Avatares consistentes + - Flujos automatizados CRM β†’ Generation + + fase_3_contenido_enriquecido: + duration: "Semanas 15-22" + modules: + - PMC-004-GENERATION (video) + - PMC-008-ANALYTICS + deliverables: + - GIFs/cinemagraphs + - Video bΓ‘sico + - Dashboards y reportes + - Portal cliente + + fase_4_saas_comercial: + duration: "Semanas 23+" + modules: + - PMC-001-TENANTS (planes) + - PMC-007-ADMIN (billing) + deliverables: + - SaaS pΓΊblico + - Planes de suscripciΓ³n + - Onboarding automΓ‘tico + +# ============================================================================= +# MΓ‰TRICAS +# ============================================================================= +metrics: + total_modules: 8 + total_entities: 28 + total_endpoints: ~143 + total_features: 118 + features_priority: + alta: 64 + media: 41 + baja: 13 + documentation_status: + vision_general: completado + glosario: completado + arquitectura: completado + modulos: completado + requerimientos: pendiente + user_stories: pendiente + +# ============================================================================= +# METADATOS +# ============================================================================= +metadata: + created_by: Requirements-Analyst + created_at: "2025-12-08" + last_updated: "2025-12-08" + version: "1.0.0"