Files
inq-roi-simulador-web/sprints/sprint-3/ETAPA_6_PROMPT.md
Marcos Benítez 67e259e6ed 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>
2026-05-27 11:49:43 -03:00

271 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sprint 3 — Etapa 6: PDF recursos automatizados + tests del sprint
## Contexto
Sos Claude Code trabajando en **InQ ROI**. 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:**
- Etapas 15 completadas. Motor de simulación usa `automatedAssignedResources` correctamente. ActivityPanel tiene sección "Recursos TO-BE". Reporte web muestra comparación AS-IS/TO-BE en filas expandibles.
- `Activity.automatedAssignedResources` sigue siendo `?` (opcional) en `types.ts` — pendiente de esta etapa.
- `drawResourcesSection` en `pdf-sections.ts` lee `activityRow?.assignedResources` para los campos `utilizationMinutes` y `units`, incluso cuando se exporta el tab "automatizado". Esto es un bug: para el escenario automatizado debería leer `automatedAssignedResources`.
- Los factories de Activity en tests (`makeAutoActivity`, `makeActivity`) no incluyen `automatedAssignedResources`. Cuando hagamos el campo requerido, TypeScript los marcará con error.
**Esta etapa cierra los tres pendientes del sprint: PDF correcto, campo promovido a requerido, tests del sprint.**
---
## Objetivo
**F.1 — PDF recursos automatizados**
Corregir `drawResourcesSection` para que cuando se exporta el escenario automatizado lea `automatedAssignedResources` (no `assignedResources`) al mostrar `utilizationMinutes` y `units` por fila.
**F.2 — Promover campo a requerido**
Cambiar `automatedAssignedResources?: ActivityResourceAssignment[]``automatedAssignedResources: ActivityResourceAssignment[]` en `types.ts`. Corregir todos los factories en tests que crean `Activity` sin ese campo.
**F.3 — Tests nuevos del sprint**
Tests unitarios del motor de simulación cubriendo los tres casos con `automatedAssignedResources`: solo fijo, solo recursos, mixto. Tests de `drawResourcesSection` para escenario automatizado.
---
## Cambios autorizados
### `src/domain/types.ts`
Remover el `?` del campo:
```typescript
// ANTES:
automatedAssignedResources?: ActivityResourceAssignment[] // 🆕 Sprint 3
// DESPUÉS:
automatedAssignedResources: ActivityResourceAssignment[] // requerido desde Etapa 6
```
Después de este cambio, TypeScript reportará errores en los factories de tests. Corregir todos los que aparezcan (ver sección de tests).
### `src/lib/export/pdf-sections.ts`
**Agregar parámetro `scenario` a `drawResourcesSection`:**
```typescript
export function drawResourcesSection(
doc: any,
autoTable: Function,
result: { perActivity: ActivitySimResult[] },
resources: Resource[],
activities: Activity[],
currency: string,
startY: number,
scenario: 'actual' | 'automatizado' = 'actual' // 🆕 default 'actual' = retrocompatible
): void
```
**Corregir el lookup de asignación** (línea ~547 del archivo actual):
```typescript
// ANTES (siempre usa AS-IS):
const assignment = activityRow?.assignedResources.find((a) => a.resourceId === br.resourceId)
// DESPUÉS (usa el array del escenario correcto):
const assignment = scenario === 'automatizado'
? activityRow?.automatedAssignedResources?.find((a) => a.resourceId === br.resourceId)
: activityRow?.assignedResources.find((a) => a.resourceId === br.resourceId)
```
**Nota:** `automatedAssignedResources` puede ser `undefined` en actividades antiguas migradas sin pasar por ImportPage (aunque la migración Dexie v4 debería poblarlas con `[]`). El optional chaining `?.find` ya cubre ese caso.
El resto del cuerpo de `drawResourcesSection` no cambia.
### `src/lib/export/pdf-export.ts`
En `exportScenarioPdf`, actualizar la llamada a `drawResourcesSection` para pasar el `tab`:
```typescript
// Antes:
drawResourcesSection(docAny, autoTable, result, resources, activities, currency, y)
// Después:
drawResourcesSection(docAny, autoTable, result, resources, activities, currency, y, tab)
```
Esta es la única línea que cambia en este archivo.
---
## Tests — correcciones de factories
Cuando se promueva `automatedAssignedResources` a requerido, TypeScript reportará error en los siguientes archivos. Agregar `automatedAssignedResources: []` a cada factory que construye un `Activity`:
### `tests/domain/simulation.test.ts`
**Factory `makeAutoActivity`** (~línea 218): agregar campo:
```typescript
automatedCostFixed: opts.automatedCost ?? 0,
automatedTimeMinutes: opts.automatedTime ?? 0,
automatedAssignedResources: opts.automatedAssignedResources ?? [], // 🆕
```
Si la interfaz de `opts` no incluye el campo, agregar:
```typescript
automatedAssignedResources?: ActivityResourceAssignment[]
```
**Factory genérico** (~línea 77): agregar `automatedAssignedResources: []`.
**Factory `makeActivity` para recursos** (~línea 410): agregar `automatedAssignedResources: []`.
### `tests/integration/indexeddb-persistence.test.ts`
**`makeActivity`** (~línea 40): agregar `automatedAssignedResources: []` al objeto retornado.
### `tests/integration/sprint1-report-roi.test.ts`
**Factories inline** (~líneas 51, 311): agregar `automatedAssignedResources: []` a cada construcción de Activity.
### `tests/lib/export/pdf-resources-section.test.ts`
**`mockActivity`** (~línea 34): agregar `automatedAssignedResources: []`.
### `tests/integration/dexie-migration.test.ts`
**`makeLegacyActivity`** (~línea 19): usa `Omit<Activity, 'automatable' | 'automatedCostFixed' | 'automatedTimeMinutes'>`. Verificar si el tipo resultante cubre `automatedAssignedResources`. Si TypeScript reporta error, agregar `'automatedAssignedResources'` al Omit O cambiar la función para retornar directamente el campo con `[]`.
---
## Tests — nuevos
### `tests/domain/simulation-sprint3.test.ts` (NUEVO)
Cubrir los tres casos de recursos en escenario automatizado. Usar el mismo BPMN lineal simple de un nodo que ya existe en otros tests del dominio.
#### Caso 1: solo costo fijo, sin recursos TO-BE
```
Actividad automatable, automatedCostFixed=100, automatedTimeMinutes=60, automatedAssignedResources=[]
→ scenario=automated: costo esperado = 100 * execProb (sin costo de recursos)
→ resourceCostBreakdown vacío
```
#### Caso 2: solo recursos TO-BE, sin costo fijo
```
Actividad automatable, automatedCostFixed=0, automatedTimeMinutes=30
automatedAssignedResources=[{ resourceId: 'r1', utilizationMinutes: 60, units: 2 }]
Resource r1: costPerHour=30
→ scenario=automated: resourceCost = 30 * (60/60) * 2 * execProb = 60 * execProb
→ resourceCostBreakdown: [{ resourceId: 'r1', resourceName: 'Bot', cost: 60 * execProb }]
```
#### Caso 3: mixto — costo fijo + recurso TO-BE
```
Actividad automatable, automatedCostFixed=50, automatedTimeMinutes=30
automatedAssignedResources=[{ resourceId: 'r1', utilizationMinutes: 30, units: 1 }]
Resource r1: costPerHour=60
→ scenario=automated: totalCost = (50 + 60*(30/60)*1) * execProb = (50+30) * execProb = 80 * execProb
```
#### Caso 4: actividad NO automatable → usa assignedResources (regresión)
```
Actividad automatable=false, con assignedResources=[r1] y automatedAssignedResources=[r2]
→ scenario=automated: usa r1 (assignedResources), NO r2
```
**Nota de arquitectura:** para los tests de dominio puro, usar un grafo BPMN de un solo nodo secuencial (sin gateways), igual que en el `describe('scenario=automated')` ya existente en `simulation.test.ts`. Los inputs del motor (`activities`, `resources`, `gateways`, `graph`) se construyen inline.
### `tests/lib/export/pdf-resources-section.test.ts` — tests nuevos (agregar al archivo existente)
Agregar un `describe` nuevo: `drawResourcesSection — escenario automatizado`:
#### Test 1: escenario automatizado usa automatedAssignedResources para min/unidades
```
mockActivity con assignedResources=[{ utilMin: 30, units: 1 }] y automatedAssignedResources=[{ utilMin: 5, units: 3 }]
Llamar drawResourcesSection(..., scenario='automatizado')
→ autoTable debe recibir min='5' y units='3' (no '30' y '1')
```
#### Test 2: escenario actual usa assignedResources (regresión)
```
Mismo mockActivity
Llamar drawResourcesSection(..., scenario='actual') [o sin el param]
→ autoTable recibe min='30' y units='1'
```
---
## ❌ Lo que NO entra en esta etapa
- Tests E2E de la biblioteca (Playwright) — diferido a Etapa 7 o post-sprint si hay tiempo
- PDF de ROI — no modificar `pdf-sections-roi.ts`
- Cambios en `simulation.ts`, `ActivityPanel.tsx`, `ActivitiesTable.tsx` — ya cerrados en Etapa 5
- Cambios en `WorkspacePage.tsx`, `BpmnCanvas.tsx`, stores — ya cerrados en Etapas anteriores
- Nuevas features de UI
---
## Verificación antes de entregar
```bash
# 1. Build limpio (verifica que el campo requerido no deja ningún any suelto)
npm run build
# 2. Tests — el count debe subir respecto a 555
npm run test
# 3. Control de scope
git diff --name-only HEAD
```
El diff debe mostrar únicamente:
- `src/domain/types.ts`
- `src/lib/export/pdf-sections.ts`
- `src/lib/export/pdf-export.ts`
- `tests/domain/simulation.test.ts`
- `tests/domain/simulation-sprint3.test.ts` (nuevo)
- `tests/lib/export/pdf-resources-section.test.ts`
- `tests/integration/indexeddb-persistence.test.ts`
- `tests/integration/sprint1-report-roi.test.ts`
- `tests/integration/dexie-migration.test.ts`
Si aparece cualquier archivo de `src/features/`, `src/store/`, o `src/persistence/`: **revertir y reportar**.
### Verificación funcional mandatoria
Antes de reportar, verificar manualmente:
1. **PDF automatizado muestra min/unidades correctas:** asignar un recurso TO-BE con `utilizationMinutes=5, units=3` → exportar PDF desde el tab Automatizado → verificar que la tabla de recursos muestra `5` y `3` (no los valores del AS-IS).
2. **PDF actual no regresiona:** exportar PDF desde tab Actual → tabla de recursos muestra los valores de `assignedResources` sin cambio.
3. **TypeScript limpio:** `npm run build` sin errores — el campo promovido a requerido no deja `any` ni errores de tipo.
---
## Criterios de aceptación
- [ ] `automatedAssignedResources` requerido en `types.ts` sin errores TypeScript en build.
- [ ] PDF tab "Automatizado": tabla de recursos muestra `utilizationMinutes` y `units` de `automatedAssignedResources`.
- [ ] PDF tab "Actual": sin regresión, tabla sin cambio.
- [ ] Todos los tests previos siguen verdes (555+).
- [ ] 4 nuevos tests en `simulation-sprint3.test.ts` (casos 14) verdes.
- [ ] 2 nuevos tests en `pdf-resources-section.test.ts` verdes.
- [ ] Validación visual del director aprobada (PDF tab Automatizado con datos correctos).
---
## Reporte esperado al terminar
1. Resultado de `git diff --name-only HEAD`.
2. Resultado de `npm run build` y `npm run test` (incluir count final de tests).
3. Confirmación de los 3 casos de verificación funcional.
4. Lista de factories de tests corregidos (archivo + línea aproximada).
5. Cualquier decisión de iniciativa (Nivel 1/2/3).
6. Si algún archivo de test tuvo más cambios de los esperados: declararlo.
---
## Referencias
- `sprints/sprint-3/BRIEF.md` — sección 4, Feature F
- `src/lib/export/pdf-sections.ts``drawResourcesSection` (~línea 479), lookup de `assignedResources` (~línea 547)
- `src/lib/export/pdf-export.ts``exportScenarioPdf` (~línea 54), llamada a `drawResourcesSection` (~línea 147)
- `tests/domain/simulation.test.ts` — factories `makeAutoActivity` (~línea 218) y genérico (~línea 77)
- `tests/lib/export/pdf-resources-section.test.ts``mockActivity` fixture (~línea 34)
- `methodology/ANTI_PATTERNS.md` — AP.8 (adelanto silencioso), AP.9 (restricciones contradictorias)
- `methodology/PATTERNS.md` — C.7 (git diff como control preventivo)