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:
99
src/store/process-store.ts
Normal file
99
src/store/process-store.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { create } from 'zustand'
|
||||
import { processRepo, activityRepo, gatewayRepo, resourceRepo } from '@/persistence/repositories'
|
||||
import type { Process, Activity, GatewayConfig, Resource } from '@/domain/types'
|
||||
|
||||
interface ProcessState {
|
||||
currentProcess: Process | null
|
||||
activities: Activity[]
|
||||
gateways: GatewayConfig[]
|
||||
resources: Resource[]
|
||||
isLoading: boolean
|
||||
error: string | null
|
||||
|
||||
// Acciones
|
||||
loadProcess: (processId: string) => Promise<void>
|
||||
setCurrentProcess: (process: Process) => Promise<void>
|
||||
updateProcess: (updates: Partial<Process>) => Promise<void>
|
||||
updateActivity: (activity: Activity) => Promise<void>
|
||||
updateGateway: (gateway: GatewayConfig) => Promise<void>
|
||||
addResource: (resource: Resource) => Promise<void>
|
||||
updateResource: (resource: Resource) => Promise<void>
|
||||
deleteResource: (resourceId: string) => Promise<void>
|
||||
reset: () => void
|
||||
}
|
||||
|
||||
export const useProcessStore = create<ProcessState>((set, get) => ({
|
||||
currentProcess: null,
|
||||
activities: [],
|
||||
gateways: [],
|
||||
resources: [],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
|
||||
loadProcess: async (processId) => {
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
const [process, activities, gateways, resources] = await Promise.all([
|
||||
processRepo.getById(processId),
|
||||
activityRepo.getByProcess(processId),
|
||||
gatewayRepo.getByProcess(processId),
|
||||
resourceRepo.getByProcess(processId),
|
||||
])
|
||||
if (!process) throw new Error('Proceso no encontrado')
|
||||
set({ currentProcess: process, activities, gateways, resources, isLoading: false })
|
||||
} catch (err) {
|
||||
set({ error: err instanceof Error ? err.message : 'Error desconocido', isLoading: false })
|
||||
}
|
||||
},
|
||||
|
||||
setCurrentProcess: async (process) => {
|
||||
await processRepo.save(process)
|
||||
const [activities, gateways, resources] = await Promise.all([
|
||||
activityRepo.getByProcess(process.id),
|
||||
gatewayRepo.getByProcess(process.id),
|
||||
resourceRepo.getByProcess(process.id),
|
||||
])
|
||||
set({ currentProcess: process, activities, gateways, resources })
|
||||
},
|
||||
|
||||
updateProcess: async (updates) => {
|
||||
const current = get().currentProcess
|
||||
if (!current) return
|
||||
const updated: Process = { ...current, ...updates, updatedAt: Date.now() }
|
||||
await processRepo.save(updated)
|
||||
set({ currentProcess: updated })
|
||||
},
|
||||
|
||||
updateActivity: async (activity) => {
|
||||
await activityRepo.save(activity)
|
||||
set((state) => ({
|
||||
activities: state.activities.map((a) => (a.id === activity.id ? activity : a)),
|
||||
}))
|
||||
},
|
||||
|
||||
updateGateway: async (gateway) => {
|
||||
await gatewayRepo.save(gateway)
|
||||
set((state) => ({
|
||||
gateways: state.gateways.map((g) => (g.id === gateway.id ? gateway : g)),
|
||||
}))
|
||||
},
|
||||
|
||||
addResource: async (resource) => {
|
||||
await resourceRepo.save(resource)
|
||||
set((state) => ({ resources: [...state.resources, resource] }))
|
||||
},
|
||||
|
||||
updateResource: async (resource) => {
|
||||
await resourceRepo.save(resource)
|
||||
set((state) => ({
|
||||
resources: state.resources.map((r) => (r.id === resource.id ? resource : r)),
|
||||
}))
|
||||
},
|
||||
|
||||
deleteResource: async (resourceId) => {
|
||||
await resourceRepo.delete(resourceId)
|
||||
set((state) => ({ resources: state.resources.filter((r) => r.id !== resourceId) }))
|
||||
},
|
||||
|
||||
reset: () => set({ currentProcess: null, activities: [], gateways: [], resources: [], error: null }),
|
||||
}))
|
||||
Reference in New Issue
Block a user