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>
8.4 KiB
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:
- Nuevas interfaces TypeScript:
ProcessGroupyAppSettings - Nuevos campos en
Process:groupIdytags - Nuevo campo en
Activity:automatedAssignedResources - Versión 4 de Dexie con función de upgrade que preserva todos los datos existentes
- 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):
// ─── 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):
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:
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:
import type { Process, Activity, GatewayConfig, Resource, Simulation, ProcessGroup, AppSettings } from '@/domain/types'
Agregar las dos tablas nuevas a la clase:
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:
// 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
# 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.tssrc/persistence/db.tstests/persistence/migration-v4.test.ts(nuevo)
Si aparece cualquier otro archivo: revertirlo y documentarlo como conflicto de scope.
Criterios de aceptación
ProcessGroupyAppSettingsexportados desdesrc/domain/types.tsProcess.groupIdyProcess.tagspresentes en la interfazActivity.automatedAssignedResourcespresente en la interfazdb.tsversión 4 con tablasgroupsysettingsregistradas- Migración v3→v4: procesos existentes reciben
groupId: nullytags: [] - 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 HEADmuestra solo los 3 archivos autorizados
Reporte esperado al terminar
Incluir en el reporte:
- Resultado de
git diff --name-only HEAD - Cantidad de tests nuevos y resultado
- Resultado del build (
npm run build) - Confirmación de que ningún archivo fuera del scope fue modificado
- 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 estilosrc/domain/types.ts— estado actual del dominiomethodology/ANTI_PATTERNS.md— AP.9 (restricciones contradictorias)methodology/PATTERNS.md— C.7 (git diff como control preventivo)