Files
inq-roi-simulador-web/src/persistence/db.ts

86 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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',
})
// Sprint 1: agrega campos de automatización a Activity y volumetría a Process.
// El upgrade popula datos existentes con defaults para garantizar invariante de tipo.
this.version(2)
.stores({
processes: 'id, name, updatedAt',
activities: 'id, processId, bpmnElementId',
gateways: 'id, processId, bpmnElementId',
resources: 'id, processId, name',
simulations: 'id, processId, executedAt',
})
.upgrade(async (tx) => {
await tx.table('activities').toCollection().modify((act) => {
if (act.automatable === undefined) act.automatable = false
if (act.automatedCostFixed === undefined) act.automatedCostFixed = 0
if (act.automatedTimeMinutes === undefined) act.automatedTimeMinutes = 0
})
await tx.table('processes').toCollection().modify((proc) => {
if (proc.annualFrequency === undefined) proc.annualFrequency = 1000
if (proc.analysisHorizonYears === undefined) proc.analysisHorizonYears = 3
if (proc.automationInvestment === undefined) proc.automationInvestment = 0
})
})
// Sprint 2: migra ActivityResourceAssignment.utilizationPercent → utilizationMinutes + units.
// Los stores no cambian — assignments están embebidos en Activity, no son tabla propia.
this.version(3)
.stores({
processes: 'id, name, updatedAt',
activities: 'id, processId, bpmnElementId',
gateways: 'id, processId, bpmnElementId',
resources: 'id, processId, name',
simulations: 'id, processId, executedAt',
})
.upgrade(async (tx) => {
await tx.table('activities').toCollection().modify((act) => {
if (!Array.isArray(act.assignedResources)) {
act.assignedResources = []
return
}
act.assignedResources = act.assignedResources.map((assignment: Record<string, unknown>) => {
if ('utilizationPercent' in assignment) {
// Heurística: minutos = round(executionTimeMinutes × utilizationPercent)
// Si executionTimeMinutes no está disponible o es 0, usar 0 (conservador)
const execMinutes = typeof act.executionTimeMinutes === 'number' ? act.executionTimeMinutes : 0
const utilizationMinutes = Math.round(execMinutes * (assignment.utilizationPercent as number))
return { resourceId: assignment.resourceId, utilizationMinutes, units: 1 }
}
if ('utilizationMinutes' in assignment) {
// Ya está en nuevo formato (idempotencia)
return {
resourceId: assignment.resourceId,
utilizationMinutes: assignment.utilizationMinutes ?? 0,
units: assignment.units ?? 1,
}
}
// Fallback defensivo
return { resourceId: assignment.resourceId, utilizationMinutes: 0, units: 1 }
})
})
})
}
}
export const db = new ProcessCostDb()