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>
11 KiB
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 1–5 completadas. Motor de simulación usa
automatedAssignedResourcescorrectamente. ActivityPanel tiene sección "Recursos TO-BE". Reporte web muestra comparación AS-IS/TO-BE en filas expandibles. Activity.automatedAssignedResourcessigue siendo?(opcional) entypes.ts— pendiente de esta etapa.drawResourcesSectionenpdf-sections.tsleeactivityRow?.assignedResourcespara los camposutilizationMinutesyunits, incluso cuando se exporta el tab "automatizado". Esto es un bug: para el escenario automatizado debería leerautomatedAssignedResources.- Los factories de Activity en tests (
makeAutoActivity,makeActivity) no incluyenautomatedAssignedResources. 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:
// 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:
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):
// 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:
// 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:
automatedCostFixed: opts.automatedCost ?? 0,
automatedTimeMinutes: opts.automatedTime ?? 0,
automatedAssignedResources: opts.automatedAssignedResources ?? [], // 🆕
Si la interfaz de opts no incluye el campo, agregar:
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
# 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.tssrc/lib/export/pdf-sections.tssrc/lib/export/pdf-export.tstests/domain/simulation.test.tstests/domain/simulation-sprint3.test.ts(nuevo)tests/lib/export/pdf-resources-section.test.tstests/integration/indexeddb-persistence.test.tstests/integration/sprint1-report-roi.test.tstests/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:
- 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 muestra5y3(no los valores del AS-IS). - PDF actual no regresiona: exportar PDF desde tab Actual → tabla de recursos muestra los valores de
assignedResourcessin cambio. - TypeScript limpio:
npm run buildsin errores — el campo promovido a requerido no dejaanyni errores de tipo.
Criterios de aceptación
automatedAssignedResourcesrequerido entypes.tssin errores TypeScript en build.- PDF tab "Automatizado": tabla de recursos muestra
utilizationMinutesyunitsdeautomatedAssignedResources. - 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 1–4) verdes. - 2 nuevos tests en
pdf-resources-section.test.tsverdes. - Validación visual del director aprobada (PDF tab Automatizado con datos correctos).
Reporte esperado al terminar
- Resultado de
git diff --name-only HEAD. - Resultado de
npm run buildynpm run test(incluir count final de tests). - Confirmación de los 3 casos de verificación funcional.
- Lista de factories de tests corregidos (archivo + línea aproximada).
- Cualquier decisión de iniciativa (Nivel 1/2/3).
- Si algún archivo de test tuvo más cambios de los esperados: declararlo.
Referencias
sprints/sprint-3/BRIEF.md— sección 4, Feature Fsrc/lib/export/pdf-sections.ts—drawResourcesSection(~línea 479), lookup deassignedResources(~línea 547)src/lib/export/pdf-export.ts—exportScenarioPdf(~línea 54), llamada adrawResourcesSection(~línea 147)tests/domain/simulation.test.ts— factoriesmakeAutoActivity(~línea 218) y genérico (~línea 77)tests/lib/export/pdf-resources-section.test.ts—mockActivityfixture (~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)