feat: MVP Fase 0 — Process Cost Platform v0.1.0

Plataforma completa de análisis de costos operativos basada en BPMN 2.0.

Funcionalidades incluidas:
- Import de archivos BPMN 2.0 por drag & drop + 3 procesos de ejemplo
- Visualización read-only del diagrama (bpmn-js)
- Configuración de actividades (costo, tiempo, recursos asignados)
- CRUD de recursos (rol, persona, sistema, equipo, insumo)
- Configuración global (moneda, overhead %, nombre, cliente)
- Motor de simulación determinístico agregado con propagación de gateways XOR/AND
- Reporte visual con mapa de calor en dos modos (relativo/absoluto)
- Gráficos: KPIs, top actividades, composición, costo por recurso
- Export PDF (jsPDF + html2canvas) y CSV (papaparse)
- Persistencia en IndexedDB (Dexie)
- 268 tests unitarios/integración + 6 E2E con Playwright
- Deploy: https://process-cost-platform.pages.dev

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-14 01:58:40 -03:00
commit bed161c92a
97 changed files with 19638 additions and 0 deletions

54
src/domain/schemas.ts Normal file
View File

@@ -0,0 +1,54 @@
import { z } from 'zod'
export const ResourceSchema = z.object({
id: z.string().uuid(),
processId: z.string().uuid(),
name: z.string().min(1, 'El nombre es requerido'),
type: z.enum(['role', 'person', 'system', 'equipment', 'supply']),
costPerHour: z.number().min(0, 'El costo no puede ser negativo'),
})
export const ActivityResourceAssignmentSchema = z.object({
resourceId: z.string().uuid(),
utilizationPercent: z.number().min(0).max(1),
})
export const ActivitySchema = z.object({
id: z.string().uuid(),
processId: z.string().uuid(),
bpmnElementId: z.string().min(1),
name: z.string(),
type: z.enum(['task', 'subprocess']),
directCostFixed: z.number().min(0),
executionTimeMinutes: z.number().min(0),
assignedResources: z.array(ActivityResourceAssignmentSchema),
})
export const GatewayBranchSchema = z.object({
flowId: z.string(),
targetElementId: z.string(),
probability: z.number().min(0).max(1),
})
export const GatewayConfigSchema = z.object({
id: z.string().uuid(),
processId: z.string().uuid(),
bpmnElementId: z.string().min(1),
gatewayType: z.enum(['exclusive', 'parallel', 'inclusive', 'event-based']),
branches: z.array(GatewayBranchSchema),
})
export const ProcessSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1, 'El nombre del proceso es requerido'),
clientName: z.string(),
bpmnXml: z.string().min(1),
currency: z.string().length(3, 'Código ISO de 3 letras'),
overheadPercentage: z.number().min(0).max(1),
createdAt: z.number(),
updatedAt: z.number(),
})
export type ResourceInput = z.infer<typeof ResourceSchema>
export type ActivityInput = z.infer<typeof ActivitySchema>
export type ProcessInput = z.infer<typeof ProcessSchema>