feat(sprint-3): biblioteca, recursos TO-BE, ROI mejorado e identidad de marca

Sprint 3 completo — 7 etapas:

- Etapa 1-2: biblioteca de procesos con agrupación por cliente (Dexie v4,
  LibraryPage, library-store, groupId/tags en Process)
- Etapa 3: modal de configuración global por proceso (horizonte, frecuencia,
  inversión, moneda) con validación y persistencia
- Etapa 4: panel de recursos rediseñado con soporte de unidades y minutos
  de utilización (utilizationMinutes + units)
- Etapa 5: recursos en escenario automatizado — motor de simulación,
  UI de edición en ActivityPanel, comparación AS-IS/TO-BE en reporte
- Etapa 6: PDF recursos automatizados, automatedAssignedResources requerido,
  561 tests pasando
- Etapa 7: identidad de marca — AppHeader gradiente naranja/magenta con logo
  InQuality en 5 páginas, favicon con logo real, logo/marca navegan a home

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 11:49:43 -03:00
parent d2746f07d1
commit 67e259e6ed
57 changed files with 4372 additions and 82 deletions

View File

@@ -0,0 +1,215 @@
# Sprint 3 — Etapa 1: Dexie v4 — fundación del modelo de biblioteca
## Contexto
Sos Claude Code trabajando en **InQ ROI**, una herramienta web para análisis de costos de procesos BPMN y cálculo de ROI de automatización. El proyecto está en `simulador-web/`. Las reglas de implementación están en `simulador-web/CLAUDE.md`. El brief del sprint está en `sprints/sprint-3/BRIEF.md`.
**Estado al iniciar esta etapa:**
- Dexie v3 en producción. Schema actual: `processes`, `activities`, `gateways`, `resources`, `simulations`.
- 548 tests verdes (Vitest + Playwright).
- Deploy activo: https://process-cost-platform.pages.dev
**Esta etapa es data layer puro. Sin cambios de UI. Sin cambios de lógica de simulación.**
---
## Objetivo
Migrar la base de datos local a Dexie v4 agregando las estructuras necesarias para la Process Library del Sprint 3:
1. Nuevas interfaces TypeScript: `ProcessGroup` y `AppSettings`
2. Nuevos campos en `Process`: `groupId` y `tags`
3. Nuevo campo en `Activity`: `automatedAssignedResources`
4. Versión 4 de Dexie con función de upgrade que preserva todos los datos existentes
5. Tests de migración que verifican preservación de datos y correctos defaults
---
## Cambios autorizados
### 1. `src/domain/types.ts`
Agregar al final de la sección de entidades del dominio (antes de los tipos del motor de simulación):
```typescript
// ─── Process Library ─────────────────────────────────────────────────────────
export interface ProcessGroup {
id: UUID // generado con crypto.randomUUID()
name: string
createdAt: number // timestamp Unix ms
updatedAt: number // timestamp Unix ms
}
export interface AppSettings {
id: 'singleton' // siempre un único registro por instalación
groupLabel: string // etiqueta configurable para el nivel de agrupación. Default: 'Cliente'
}
```
Actualizar `Process` agregando los dos campos nuevos **al final de la interfaz** (para no romper destructuring existente):
```typescript
export interface Process {
// ... campos existentes sin tocar ...
groupId: UUID | null // 🆕 Sprint 3 — null = proceso sin grupo asignado ("Sin clasificar")
tags: string[] // 🆕 Sprint 3 — tags libres para clasificación y búsqueda
}
```
Actualizar `Activity` agregando el campo nuevo **al final de la interfaz**:
```typescript
export interface Activity {
// ... campos existentes sin tocar ...
automatedAssignedResources: ActivityResourceAssignment[] // 🆕 Sprint 3 — recursos del escenario automatizado
}
```
### 2. `src/persistence/db.ts`
Agregar imports de los nuevos tipos:
```typescript
import type { Process, Activity, GatewayConfig, Resource, Simulation, ProcessGroup, AppSettings } from '@/domain/types'
```
Agregar las dos tablas nuevas a la clase:
```typescript
export class ProcessCostDb extends Dexie {
processes!: Table<Process>
activities!: Table<Activity>
gateways!: Table<GatewayConfig>
resources!: Table<Resource>
simulations!: Table<Simulation>
groups!: Table<ProcessGroup> // 🆕 Sprint 3
settings!: Table<AppSettings> // 🆕 Sprint 3
// ...
}
```
Agregar versión 4 **después** de la versión 3 existente:
```typescript
// Sprint 3: agrega tabla de grupos (Process Library), tabla de settings,
// campos groupId/tags en Process, y automatedAssignedResources en Activity.
this.version(4)
.stores({
processes: 'id, name, updatedAt, groupId', // groupId indexado para queries por grupo
activities: 'id, processId, bpmnElementId',
gateways: 'id, processId, bpmnElementId',
resources: 'id, processId, name',
simulations: 'id, processId, executedAt',
groups: 'id, name, updatedAt', // nueva tabla
settings: 'id', // nueva tabla (singleton)
})
.upgrade(async (tx) => {
// Process: agregar groupId (null) y tags ([])
await tx.table('processes').toCollection().modify((proc) => {
if (proc.groupId === undefined) proc.groupId = null
if (!Array.isArray(proc.tags)) proc.tags = []
})
// Activity: agregar automatedAssignedResources ([])
await tx.table('activities').toCollection().modify((act) => {
if (!Array.isArray(act.automatedAssignedResources)) {
act.automatedAssignedResources = []
}
})
// Settings: crear singleton con defaults si no existe
const existing = await tx.table('settings').get('singleton')
if (!existing) {
await tx.table('settings').put({ id: 'singleton', groupLabel: 'Cliente' })
}
})
```
### 3. Tests de migración
Crear `tests/persistence/migration-v4.test.ts` con los siguientes casos:
**Test 1 — Proceso existente conserva todos sus campos**
Crear un proceso con el schema v3 (sin `groupId` ni `tags`), ejecutar la migración, verificar que todos los campos originales siguen intactos y que `groupId === null` y `tags` es un array vacío.
**Test 2 — Activity existente conserva todos sus campos y recibe array vacío**
Crear una activity con `assignedResources` poblado (al menos un assignment), ejecutar migración, verificar que `assignedResources` no se alteró y que `automatedAssignedResources` es `[]`.
**Test 3 — Settings singleton creado con defaults**
Después de la migración, leer `settings.get('singleton')`, verificar que existe con `groupLabel === 'Cliente'`.
**Test 4 — Idempotencia: upgrade no corrompe datos ya migrados**
Crear un proceso ya en formato v4 (con `groupId: null`, `tags: []`), ejecutar upgrade, verificar que los valores no cambian.
**Test 5 — groupId puede ser un UUID válido**
Crear un grupo, asignar su `id` como `groupId` de un proceso, verificar que el campo persiste correctamente y que se puede hacer query `processes.where('groupId').equals(groupId)`.
---
## ❌ Lo que NO entra en esta etapa
- Cambios en ningún componente de UI (`features/`, `components/`)
- Cambios en el motor de simulación (`domain/simulation.ts`)
- Cambios en `domain/schemas.ts` (los schemas Zod se actualizan en la etapa correspondiente)
- Cambios en lógica de exportación de PDF o CSV
- Cualquier otro archivo fuera de `src/domain/types.ts`, `src/persistence/db.ts`, y los tests nuevos
Si algún cambio en `types.ts` genera errores TypeScript en otros archivos por los nuevos campos opcionales/requeridos: **DETENER y reportar el conflicto al director antes de modificar esos archivos**. No resolver unilateralmente. Ver `methodology/ANTI_PATTERNS.md` AP.9.
---
## Verificación antes de entregar
```bash
# 1. Build limpio
npm run build
# 2. Tests unitarios
npm run test
# 3. Control de scope — solo deben aparecer archivos autorizados
git diff --name-only HEAD
```
El `git diff` debe mostrar únicamente:
- `src/domain/types.ts`
- `src/persistence/db.ts`
- `tests/persistence/migration-v4.test.ts` (nuevo)
Si aparece cualquier otro archivo: **revertirlo y documentarlo como conflicto de scope**.
---
## Criterios de aceptación
- [ ] `ProcessGroup` y `AppSettings` exportados desde `src/domain/types.ts`
- [ ] `Process.groupId` y `Process.tags` presentes en la interfaz
- [ ] `Activity.automatedAssignedResources` presente en la interfaz
- [ ] `db.ts` versión 4 con tablas `groups` y `settings` registradas
- [ ] Migración v3→v4: procesos existentes reciben `groupId: null` y `tags: []`
- [ ] Migración v3→v4: activities existentes reciben `automatedAssignedResources: []`
- [ ] Singleton de settings creado con `groupLabel: 'Cliente'`
- [ ] Los 5 tests de migración verdes
- [ ] Todos los tests previos del proyecto siguen verdes (548+)
- [ ] Build limpio sin errores TypeScript
- [ ] `git diff --name-only HEAD` muestra solo los 3 archivos autorizados
---
## Reporte esperado al terminar
Incluir en el reporte:
1. Resultado de `git diff --name-only HEAD`
2. Cantidad de tests nuevos y resultado
3. Resultado del build (`npm run build`)
4. Confirmación de que ningún archivo fuera del scope fue modificado
5. Si hubo alguna decisión de iniciativa (Nivel 1/2/3) tomada durante la etapa, declararla explícitamente
---
## Referencias
- `sprints/sprint-3/BRIEF.md` — scope completo del sprint, sección 3 (decisiones arquitectónicas)
- `src/persistence/db.ts` — versiones anteriores como referencia de estilo
- `src/domain/types.ts` — estado actual del dominio
- `methodology/ANTI_PATTERNS.md` — AP.9 (restricciones contradictorias)
- `methodology/PATTERNS.md` — C.7 (git diff como control preventivo)