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:
24
src/persistence/db.ts
Normal file
24
src/persistence/db.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import Dexie, { type Table } from 'dexie'
|
||||
import type { Process, Activity, GatewayConfig, Resource, Simulation } from '@/domain/types'
|
||||
|
||||
export class ProcessCostDb extends Dexie {
|
||||
processes!: Table<Process>
|
||||
activities!: Table<Activity>
|
||||
gateways!: Table<GatewayConfig>
|
||||
resources!: Table<Resource>
|
||||
simulations!: Table<Simulation>
|
||||
|
||||
constructor() {
|
||||
super('ProcessCostPlatform')
|
||||
|
||||
this.version(1).stores({
|
||||
processes: 'id, name, updatedAt',
|
||||
activities: 'id, processId, bpmnElementId',
|
||||
gateways: 'id, processId, bpmnElementId',
|
||||
resources: 'id, processId, name',
|
||||
simulations: 'id, processId, executedAt',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const db = new ProcessCostDb()
|
||||
114
src/persistence/repositories.ts
Normal file
114
src/persistence/repositories.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { db } from './db'
|
||||
import type { Process, Activity, GatewayConfig, Resource, Simulation } from '@/domain/types'
|
||||
|
||||
// ─── Process ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export const processRepo = {
|
||||
async save(process: Process): Promise<void> {
|
||||
await db.processes.put(process)
|
||||
},
|
||||
|
||||
async getById(id: string): Promise<Process | undefined> {
|
||||
return db.processes.get(id)
|
||||
},
|
||||
|
||||
async getAll(): Promise<Process[]> {
|
||||
return db.processes.orderBy('updatedAt').reverse().toArray()
|
||||
},
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await db.transaction('rw', [db.processes, db.activities, db.gateways, db.resources, db.simulations], async () => {
|
||||
await db.processes.delete(id)
|
||||
await db.activities.where('processId').equals(id).delete()
|
||||
await db.gateways.where('processId').equals(id).delete()
|
||||
await db.resources.where('processId').equals(id).delete()
|
||||
await db.simulations.where('processId').equals(id).delete()
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
// ─── Activity ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export const activityRepo = {
|
||||
async save(activity: Activity): Promise<void> {
|
||||
await db.activities.put(activity)
|
||||
},
|
||||
|
||||
async saveMany(activities: Activity[]): Promise<void> {
|
||||
await db.activities.bulkPut(activities)
|
||||
},
|
||||
|
||||
async getByProcess(processId: string): Promise<Activity[]> {
|
||||
return db.activities.where('processId').equals(processId).toArray()
|
||||
},
|
||||
|
||||
async getByBpmnElementId(processId: string, bpmnElementId: string): Promise<Activity | undefined> {
|
||||
return db.activities
|
||||
.where('[processId+bpmnElementId]')
|
||||
.equals([processId, bpmnElementId])
|
||||
.first()
|
||||
},
|
||||
|
||||
async deleteByProcess(processId: string): Promise<void> {
|
||||
await db.activities.where('processId').equals(processId).delete()
|
||||
},
|
||||
}
|
||||
|
||||
// ─── GatewayConfig ────────────────────────────────────────────────────────────
|
||||
|
||||
export const gatewayRepo = {
|
||||
async save(gateway: GatewayConfig): Promise<void> {
|
||||
await db.gateways.put(gateway)
|
||||
},
|
||||
|
||||
async saveMany(gateways: GatewayConfig[]): Promise<void> {
|
||||
await db.gateways.bulkPut(gateways)
|
||||
},
|
||||
|
||||
async getByProcess(processId: string): Promise<GatewayConfig[]> {
|
||||
return db.gateways.where('processId').equals(processId).toArray()
|
||||
},
|
||||
|
||||
async deleteByProcess(processId: string): Promise<void> {
|
||||
await db.gateways.where('processId').equals(processId).delete()
|
||||
},
|
||||
}
|
||||
|
||||
// ─── Resource ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export const resourceRepo = {
|
||||
async save(resource: Resource): Promise<void> {
|
||||
await db.resources.put(resource)
|
||||
},
|
||||
|
||||
async getByProcess(processId: string): Promise<Resource[]> {
|
||||
return db.resources.where('processId').equals(processId).toArray()
|
||||
},
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await db.resources.delete(id)
|
||||
},
|
||||
|
||||
async deleteByProcess(processId: string): Promise<void> {
|
||||
await db.resources.where('processId').equals(processId).delete()
|
||||
},
|
||||
}
|
||||
|
||||
// ─── Simulation ───────────────────────────────────────────────────────────────
|
||||
|
||||
export const simulationRepo = {
|
||||
async save(simulation: Simulation): Promise<void> {
|
||||
await db.simulations.put(simulation)
|
||||
},
|
||||
|
||||
async getLatestByProcess(processId: string): Promise<Simulation | undefined> {
|
||||
return db.simulations
|
||||
.where('processId')
|
||||
.equals(processId)
|
||||
.last()
|
||||
},
|
||||
|
||||
async getByProcess(processId: string): Promise<Simulation[]> {
|
||||
return db.simulations.where('processId').equals(processId).toArray()
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user