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>
216 lines
8.4 KiB
Markdown
216 lines
8.4 KiB
Markdown
# 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)
|