Los archivos de claude code modificados

This commit is contained in:
2026-05-14 20:50:12 -03:00
parent e95cfc42ac
commit f8f33a65c7
4 changed files with 753 additions and 112 deletions

View File

@@ -5,11 +5,12 @@
| Atributo | Valor | | Atributo | Valor |
|---|---| |---|---|
| Versión del documento | 0.1.0 | | Versión del documento | 0.2.0 |
| Fecha | Mayo 2026 | | Fecha | Mayo 2026 |
| Estado | Draft — Fase 0 (MVP "Noche Cero") en construcción | | Estado | Fase 0 completada · Sprint 1 (ROI) en construcción |
| Autor | Equipo fundador + Claude (arquitectura) | | Autor | Equipo fundador + Claude (arquitectura) |
| Alcance | MVP de esta noche + Norte V1.0 (1218 meses) | | Alcance | MVP completado + Sprint 1 + Norte V1.0 (1218 meses) |
| Deploy actual | https://process-cost-platform.pages.dev (v0.1.0-mvp) |
--- ---
@@ -18,14 +19,15 @@
1. [Contexto y Propuesta de Valor](#1-contexto-y-propuesta-de-valor) 1. [Contexto y Propuesta de Valor](#1-contexto-y-propuesta-de-valor)
2. [Glosario y Convenciones](#2-glosario-y-convenciones) 2. [Glosario y Convenciones](#2-glosario-y-convenciones)
3. [Norte Estratégico — Visión V1.0](#3-norte-estratégico--visión-v10) 3. [Norte Estratégico — Visión V1.0](#3-norte-estratégico--visión-v10)
4. [Fase 0 — MVP "Noche Cero"](#4-fase-0--mvp-noche-cero) 4. [Fase 0 — MVP "Noche Cero" (COMPLETADO)](#4-fase-0--mvp-noche-cero)
5. [Roadmap de Evolución](#5-roadmap-de-evolución) 5. [Fase 1 — Sprint 1: ROI y Escenarios de Automatización](#5-fase-1--sprint-1-roi-y-escenarios-de-automatización)
6. [Arquitectura Técnica](#6-arquitectura-técnica) 6. [Roadmap de Evolución](#6-roadmap-de-evolución)
7. [Modelo de Dominio](#7-modelo-de-dominio) 7. [Arquitectura Técnica](#7-arquitectura-técnica)
8. [Decisiones Arquitectónicas (ADRs)](#8-decisiones-arquitectónicas-adrs) 8. [Modelo de Dominio](#8-modelo-de-dominio)
9. [Atributos de Calidad](#9-atributos-de-calidad) 9. [Decisiones Arquitectónicas (ADRs)](#9-decisiones-arquitectónicas-adrs)
10. [Riesgos y Mitigaciones](#10-riesgos-y-mitigaciones) 10. [Atributos de Calidad](#10-atributos-de-calidad)
11. [Anexos](#11-anexos) 11. [Riesgos y Mitigaciones](#11-riesgos-y-mitigaciones)
12. [Anexos](#12-anexos)
--- ---
@@ -55,12 +57,20 @@ Las consultoras, gerentes de operaciones y profesionales de eficiencia operativa
### 1.4 Audiencia objetivo ### 1.4 Audiencia objetivo
**MVP (Fase 0)**: el propio fundador como consultor de automatización de procesos. **MVP (Fase 0 - COMPLETADO)**: el propio fundador como consultor de automatización de procesos.
**Sprint 1 (en curso)**: el **equipo de InQuality** como herramienta interna de consultoría y **pre-venta de proyectos de automatización con cálculo de ROI**.
**V1.0**: consultores independientes y boutique de procesos, gerentes de operaciones de pymes LATAM, equipos de Project/Process Office. **V1.0**: consultores independientes y boutique de procesos, gerentes de operaciones de pymes LATAM, equipos de Project/Process Office.
**V2+**: estudiantes y entusiastas de eficiencia operativa (tier educativo gratuito). **V2+**: estudiantes y entusiastas de eficiencia operativa (tier educativo gratuito).
### 1.4.1 Casos de uso confirmados (Sprint 1)
1. **Análisis de costos operativos**: el consultor de InQuality releva el proceso del cliente, lo modela en BPMN, configura costos/tiempos/recursos y entrega un reporte cuantitativo del costo operativo.
2. **Pre-venta de automatización con ROI**: el consultor identifica actividades automatizables, define costos automatizados estimados y el costo de inversión del proyecto. El sistema calcula payback, ahorro anual y ROI %, generando un reporte ejecutivo que sirve como propuesta comercial cuantificada.
### 1.5 Lo que NO somos ### 1.5 Lo que NO somos
- ❌ NO somos un BPMS (motor de ejecución de procesos). - ❌ NO somos un BPMS (motor de ejecución de procesos).
@@ -164,9 +174,11 @@ Las consultoras, gerentes de operaciones y profesionales de eficiencia operativa
--- ---
## 4. Fase 0 — MVP "Noche Cero" ## 4. Fase 0 — MVP "Noche Cero" ✅ COMPLETADA
### 4.1 Hipótesis a validar > **Estado**: ✅ Entregada el 13 de mayo de 2026. Tag `v0.1.0-mvp`. Deployada en https://process-cost-platform.pages.dev. **268 tests unit/integration + 5 E2E + 4/4 validación con gradiente real**. Bundle inicial 59.75 KB gzip. 0 vulnerabilidades.
### 4.1 Hipótesis validada
> Un consultor de procesos puede transformar un archivo `.bpmn` en un reporte visualmente deslumbrante de costos operativos en menos de 15 minutos, y usarlo al día siguiente en una reunión real con un cliente. > Un consultor de procesos puede transformar un archivo `.bpmn` en un reporte visualmente deslumbrante de costos operativos en menos de 15 minutos, y usarlo al día siguiente en una reunión real con un cliente.
@@ -264,43 +276,193 @@ Las consultoras, gerentes de operaciones y profesionales de eficiencia operativa
--- ---
## 5. Roadmap de Evolución ## 5. Fase 1 — Sprint 1: ROI y Escenarios de Automatización
> **Estado**: en construcción.
> **Audiencia primaria**: equipo de InQuality (consultora de procesos).
> **Caso de uso estrella**: pre-venta de proyectos de automatización con ROI cuantificado.
### 5.1 Hipótesis a validar
> Un consultor de InQuality puede modelar un proceso, identificar las actividades automatizables, configurar costos del escenario actual vs automatizado, y obtener en minutos un reporte ejecutivo de ROI (payback, ahorro anual, ROI %) que sirve como propuesta comercial cuantificada para vender un proyecto de automatización.
### 5.2 Alcance del Sprint 1
| # | Capacidad | Detalle |
|---|---|---|
| S1.1 | **Volumetría del proceso** | Frecuencia anual de ejecución + horizonte de análisis (años) configurables por proceso |
| S1.2 | **Marcado de actividades automatizables** | Toggle por actividad + campos de costo y tiempo automatizados |
| S1.3 | **Inversión en automatización** | Campo único agregado a nivel proceso (sin desglose) |
| S1.4 | **Motor dual de simulación** | Mismo motor recibe `scenario: 'actual' \| 'automated'` y aplica los campos correspondientes |
| S1.5 | **Sección de ROI en reporte** | Tabs en el reporte: Actual / Automatizado / Comparación + ROI |
| S1.6 | **5 KPIs de ROI** | Ahorro por ejecución · Ahorro anual · Payback (meses) · Ahorro acumulado a N años · ROI % anualizado |
| S1.7 | **Tabla comparativa** | Actividad por actividad: costos actual vs automatizado, ahorro $ y % |
| S1.8 | **Gráficos de ROI** | Ahorro acumulado en el tiempo + Top 5 actividades con mayor ahorro |
| S1.9 | **Mecanismo de transparencia** | Detecta valores cero/inversión cero y los expone en sección visible pero discreta |
| S1.10 | **Migración Dexie v1 → v2** | Preserva datos existentes, agrega los nuevos campos con defaults |
| S1.11 | **Export PDF/CSV ampliado** | El PDF incluye páginas de ROI; el CSV de ROI exporta comparación completa |
| S1.12 | **Documento metodológico** | Anexo en el repo: cómo calcular correctamente el costo automatizado por ejecución |
### 5.3 Decisiones arquitectónicas del Sprint 1
#### Modelo de escenarios — Modelo A (dos campos por actividad)
`Activity` gana 3 campos:
- `automatable: boolean` (default false)
- `automatedCostFixed: number` (default 0)
- `automatedTimeMinutes: number` (default 0)
`Process` gana 3 campos:
- `annualFrequency: number` (default 1000)
- `analysisHorizonYears: number` (default 3)
- `automationInvestment: number` (default 0)
**Justificación de Modelo A**:
- Trazabilidad actividad-por-actividad sin sincronización entre diagramas
- Un solo BPMN simplifica el flujo del consultor
- Migración a Modelo B (escenarios como entidad) queda pendiente para Sprint 3-4 si InQuality lo demanda
#### Volumetría — Multiplicador en el reporte
El motor sigue siendo determinístico ("costo de una ejecución"). La volumetría se aplica en el reporte:
```
costoAnual = costoUnitario × annualFrequency
costoHorizonte = costoAnual × analysisHorizonYears
```
No se introduce VPN, TIR ni Monte Carlo en este sprint. **Razón estratégica**: el cliente promedio de InQuality entiende payback nominal; el VPN abre discusiones sobre la tasa que distraen.
#### Fórmulas de ROI (en `domain/roi.ts`, función pura testeable)
```typescript
savingsPerExecution = costPerExecutionActual - costPerExecutionAutomated
savingsPerExecutionPercent = (savingsPerExecution / costPerExecutionActual) * 100
annualSavings = savingsPerExecution × annualFrequency
paybackMonths = (automationInvestment / annualSavings) × 12
paybackYears = paybackMonths / 12
cumulativeSavingsHorizon = (annualSavings × horizonYears) - automationInvestment
breaksEvenInHorizon = paybackYears <= horizonYears
roiAnnualPercent = (annualSavings / automationInvestment) * 100
```
**Edge cases manejados explícitamente**:
- `annualSavings <= 0`: `paybackMonths = Infinity`, `breaksEvenInHorizon = false`
- `automationInvestment === 0 && annualSavings > 0`: `paybackMonths = 0`, `roiAnnualPercent = Infinity` (display "N/A" o "∞")
- `costPerExecutionActual === 0`: `savingsPerExecutionPercent = 0` (evitar div/0)
#### Transparencia metodológica
Si el reporte detecta:
- Actividades marcadas como automatizables pero con `automatedCostFixed = 0` Y `automatedTimeMinutes = 0`
- `automationInvestment = 0` con payback < 1 mes
- Otros valores sospechosos
Muestra una sección **"Transparencia metodológica"** con:
- Lista de valores no informados
- Texto introductorio explicando el motivo del listado
- Fondo gris claro, no rojo/alarmante
- Aparece en pantalla y en PDF
**Filosofía**: convierte una posible debilidad en señal de seriedad profesional. El cliente final entiende que el consultor fue transparente sobre los supuestos.
### 5.4 Lo que NO entra en el Sprint 1
❌ Múltiples escenarios (más de 2) — viene en Sprint 3-4 si se demanda
❌ Escenarios como entidad separada (Modelo B)
❌ VPN, TIR, tasa de descuento
❌ Desglose de la inversión (licencias, dev, infra) — un único campo por ahora
❌ Análisis de sensibilidad
❌ Distribuciones probabilísticas
❌ Bots como recursos con capacidad finita
❌ Multi-tenant, login, colaboración, versionado, IA, modo oscuro, i18n, PWA
### 5.5 Definition of Done — Sprint 1
- [ ] Migración Dexie v1 → v2 con preservación de datos existentes
- [ ] Workspace permite marcar actividades como automatizables y configurar costos automatizados
- [ ] Workspace permite configurar volumetría e inversión a nivel proceso
- [ ] Motor de simulación acepta `scenario` y devuelve resultados correctos para ambos casos
- [ ] Reporte tiene 3 tabs (Actual / Automatizado / Comparación + ROI)
- [ ] Sección "Comparación + ROI" muestra 5 KPIs grandes correctamente formateados
- [ ] Tabla comparativa funcional con ordenamiento
- [ ] Gráfico de ahorro acumulado con marcador de payback
- [ ] Gráfico Top 5 actividades con mayor ahorro
- [ ] Sección "Transparencia metodológica" aparece cuando corresponde
- [ ] Cálculos de `domain/roi.ts` cubiertos por tests (≥ 10 casos incluyendo edge cases)
- [ ] Test E2E del flujo completo de ROI con Playwright
- [ ] PDF de ROI incluye las páginas adicionales con KPIs y gráficos
- [ ] CSV de ROI exporta comparación completa
- [ ] Documento `METHODOLOGY_AUTOMATED_COST.md` en raíz del repo
- [ ] Bundle no crece más de 20 KB gzip respecto al MVP
- [ ] Todos los tests previos (268 unit + 5 E2E) siguen verdes
- [ ] Deploy a producción exitoso
- [ ] Smoke test post-deploy verde
---
## 6. Roadmap de Evolución
``` ```
┌────────────┬──────────────────────────────────────────────────────┐ ┌──────────────┬──────────────────────────────────────────────────────┐
│ FASE │ CAPACIDADES │ │ FASE │ CAPACIDADES │
├────────────┼──────────────────────────────────────────────────────┤ ├──────────────┼──────────────────────────────────────────────────────┤
│ Fase 0 │ MVP client-side: importar, configurar, simular, │ │ Fase 0 │ MVP client-side: importar, configurar, simular, │
│ (1 noche) │ reportear, exportar PDF/CSV │ (completa) │ reportear, exportar PDF/CSV. v0.1.0-mvp en prod.
├────────────┼──────────────────────────────────────────────────────┤ ├──────────────┼──────────────────────────────────────────────────────┤
Fase 1 + Backend mínimo + Auth + Persistencia en la nube Sprint 1 🔄ROI + escenarios de automatización:
│ (1-2 sem) │ + i18n (es/en/pt-BR) + PWA installable │ (en curso) │ · Volumetría del proceso
├────────────┼──────────────────────────────────────────────────────┤ │ │ · Marcado de actividades automatizables │
Fase 2 │ + Editor BPMN (no solo lectura) + Validador │ · Inversión de automatización
(1 mes) │ + Glosario integrado + Recursos avanzados │ · Motor dual: actual vs automatizado
├────────────┼──────────────────────────────────────────────────────┤ │ │ · 5 KPIs de ROI + tabla comparativa + gráficos │
Fase 3 │ + Estructura organizacional + Multi-tenant │ · Transparencia metodológica
(1 mes) │ + RBAC + Versionado lineal │ · Migración Dexie v1 → v2
├────────────┼──────────────────────────────────────────────────────┤ ├──────────────┼──────────────────────────────────────────────────────┤
Fase 4 │ + Colaboración en tiempo real (Yjs/CRDT) Sprint 2 │ Productividad de carga:
(1-2 mes) │ + Presencia + Comentarios │ · Grilla de edición masiva (TanStack Table)
├────────────┼──────────────────────────────────────────────────────┤ │ │ · Pegado desde Excel │
Fase 5 │ + Distribuciones probabilísticas + Riesgos │ · Recursos con costo/hora + asignación múltiple
(1 mes) │ + Costeo ABC completo + Gobernanza RACI │ · Cálculo de costo esperado en vivo
├────────────┼──────────────────────────────────────────────────────┤ │ │ · Edición inline de nombre proceso/cliente │
│ Fase 6 │ + IA: detección de cuellos de botella │ ├──────────────┼──────────────────────────────────────────────────────┤
(1-2 mes) │ + Elementos RPA/Agente IA en paleta Sprint 3-4 │ Multi-escenario y reportes ejecutivos:
├────────────┼──────────────────────────────────────────────────────┤ │ │ · Escenarios como entidad (modelo B) si demandado │
Fase 7 │ + Marketplace comunitario de plantillas │ · Reporte ejecutivo (PDF 1-2 páginas) separado
(continuo) │ + Tutoriales interactivos + Modo educativo │ · Branding InQuality
└────────────┴──────────────────────────────────────────────────────┘ │ │ · Export Excel multi-hoja │
│ │ · Comparación de simulaciones (historial) │
├──────────────┼──────────────────────────────────────────────────────┤
│ Fase 2 │ Backend + colaboración básica: │
│ (1-2 meses) │ · Backend NestJS + Postgres + Auth │
│ │ · Multi-tenant + RBAC │
│ │ · Versionado lineal │
│ │ · Editor BPMN (no solo lectura) │
│ │ · Validador + Glosario │
│ │ · i18n (es/en/pt-BR) │
│ │ · PWA installable │
├──────────────┼──────────────────────────────────────────────────────┤
│ Fase 3 │ Colaboración avanzada y modelado fino: │
│ (1-2 meses) │ · Colaboración en tiempo real (Yjs/CRDT) │
│ │ · Presencia + Comentarios │
│ │ · Distribuciones probabilísticas │
│ │ · Riesgos │
│ │ · Costeo ABC completo │
│ │ · Gobernanza RACI │
├──────────────┼──────────────────────────────────────────────────────┤
│ Fase 4 │ Inteligencia y comunidad: │
│ (1-2 meses) │ · IA: detección de cuellos de botella │
│ │ · Elementos RPA/Agente IA en paleta │
│ │ · Marketplace comunitario de plantillas │
│ │ · Tutoriales interactivos │
│ │ · Modo educativo │
└──────────────┴──────────────────────────────────────────────────────┘
``` ```
--- ---
## 6. Arquitectura Técnica ## 7. Arquitectura Técnica
### 6.1 Vista de alto nivel — MVP (Fase 0) ### 7.1 Vista de alto nivel — MVP (Fase 0)
``` ```
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
@@ -340,7 +502,7 @@ Las consultoras, gerentes de operaciones y profesionales de eficiencia operativa
(estático, gratis, global) (estático, gratis, global)
``` ```
### 6.2 Vista de alto nivel — V1.0 ### 7.2 Vista de alto nivel — V1.0
``` ```
┌──────────────────┐ ┌──────────────────────────────┐ ┌──────────────────┐ ┌──────────────────────────────┐
@@ -381,7 +543,7 @@ Las consultoras, gerentes de operaciones y profesionales de eficiencia operativa
vía Docker Compose vía Docker Compose
``` ```
### 6.3 Stack tecnológico ### 7.3 Stack tecnológico
#### 6.3.1 Stack MVP (Fase 0) #### 6.3.1 Stack MVP (Fase 0)
@@ -423,7 +585,7 @@ Las consultoras, gerentes de operaciones y profesionales de eficiencia operativa
| i18n | i18next + react-i18next | Estándar de facto | | i18n | i18next + react-i18next | Estándar de facto |
| E2E testing | Playwright | Estándar moderno | | E2E testing | Playwright | Estándar moderno |
### 6.4 Arquitectura de carpetas (MVP) ### 7.4 Arquitectura de carpetas (MVP)
``` ```
process-cost-platform/ process-cost-platform/
@@ -496,7 +658,7 @@ process-cost-platform/
└── e2e/ ← post-MVP └── e2e/ ← post-MVP
``` ```
### 6.5 Modelo conceptual del motor de simulación (MVP) ### 7.5 Modelo conceptual del motor de simulación (MVP + Sprint 1)
El motor de simulación del MVP es **determinístico y agregado**. NO es discrete event simulation. Su contrato: El motor de simulación del MVP es **determinístico y agregado**. NO es discrete event simulation. Su contrato:
@@ -556,7 +718,7 @@ interface SimulationResult {
5. Costo indirecto = `costoDirectoTotal × overheadPercentage`. 5. Costo indirecto = `costoDirectoTotal × overheadPercentage`.
6. Agregar totales y rankings. 6. Agregar totales y rankings.
### 6.6 Integración bpmn-js + heatmap ### 7.6 Integración bpmn-js + heatmap
`bpmn-js` expone: `bpmn-js` expone:
- Un `viewer` (read-only) ideal para MVP. - Un `viewer` (read-only) ideal para MVP.
@@ -571,7 +733,7 @@ El heatmap se implementa así:
3. Registrar handler `element.click` para drill-down. 3. Registrar handler `element.click` para drill-down.
4. Mostrar tooltip con detalle al hover. 4. Mostrar tooltip con detalle al hover.
### 6.7 Deployment del MVP ### 7.7 Deployment
**Esta noche**: **Esta noche**:
1. `npm run build` → genera `dist/` estático. 1. `npm run build` → genera `dist/` estático.
@@ -582,9 +744,9 @@ El heatmap se implementa así:
--- ---
## 7. Modelo de Dominio ## 8. Modelo de Dominio
### 7.1 Entidades núcleo (MVP) ### 8.1 Entidades núcleo (estado al Sprint 1)
**Distinción fundamental de capas:** **Distinción fundamental de capas:**
- `ProcessGraph` (en memoria, reconstruido del XML cada vez): TODOS los nodos del diagrama incluidos gateways, eventos, flujos. Vive solo en el parser/motor, no se persiste. - `ProcessGraph` (en memoria, reconstruido del XML cada vez): TODOS los nodos del diagrama incluidos gateways, eventos, flujos. Vive solo en el parser/motor, no se persiste.
@@ -592,6 +754,8 @@ El heatmap se implementa así:
- `GatewayConfig` (persistido en IndexedDB): probabilidades por flujo saliente de gateways divergentes (XOR/OR). Los gateways convergentes (merge) no tienen config — el motor suma probabilidades entrantes. - `GatewayConfig` (persistido en IndexedDB): probabilidades por flujo saliente de gateways divergentes (XOR/OR). Los gateways convergentes (merge) no tienen config — el motor suma probabilidades entrantes.
- El heatmap **solo colorea nodos con Activity**. Los gateways conservan estilo BPMN neutro. - El heatmap **solo colorea nodos con Activity**. Los gateways conservan estilo BPMN neutro.
**Campos añadidos en Sprint 1** marcados con 🆕.
``` ```
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ Process │ │ Process │
@@ -602,6 +766,9 @@ El heatmap se implementa así:
│ + bpmnXml: string (raw XML) │ │ + bpmnXml: string (raw XML) │
│ + currency: string (ISO 4217) │ │ + currency: string (ISO 4217) │
│ + overheadPercentage: number (0..1) │ │ + overheadPercentage: number (0..1) │
│ + annualFrequency: number 🆕 default 1000 │
│ + analysisHorizonYears: number 🆕 default 3 │
│ + automationInvestment: number 🆕 default 0 │
│ + createdAt, updatedAt │ │ + createdAt, updatedAt │
└─────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────┘
│ 1 │ 1 │ 1 │ 1
@@ -622,8 +789,13 @@ El heatmap se implementa así:
│ number │ │ probability: number │ │ number │ │ probability: number │
│ + executionTimeMinutes: │ │ }> │ │ + executionTimeMinutes: │ │ }> │
│ number │ │ (paralelo: todas 1.0, │ │ number │ │ (paralelo: todas 1.0, │
└─────────────────────────┘ │ exclusivo: suma = 1.0) │ │ + automatable: boolean │🆕 │ exclusivo: suma = 1.0) │
│ N └──────────────────────────────┘ │ + automatedCostFixed: │🆕 └──────────────────────────────┘
│ number │
│ + automatedTimeMinutes: │🆕
│ number │
└─────────────────────────┘
│ N
│ M │ M
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
@@ -657,13 +829,13 @@ El heatmap se implementa así:
└─────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────┘
``` ```
### 7.2 Modelo extendido (V1.0) ### 8.2 Modelo extendido (V1.0)
Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `ProcessOwnership` (RACI), `Risk`, `RiskProcessLink`, `ProcessVersion`, `Comment`, `Notification`, `Template`. Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `ProcessOwnership` (RACI), `Risk`, `RiskProcessLink`, `ProcessVersion`, `Comment`, `Notification`, `Template`.
--- ---
## 8. Decisiones Arquitectónicas (ADRs) ## 9. Decisiones Arquitectónicas (ADRs)
### ADR-001 — MVP client-side sin backend ### ADR-001 — MVP client-side sin backend
- **Contexto**: tiempo de entrega = una noche, presupuesto cero. - **Contexto**: tiempo de entrega = una noche, presupuesto cero.
@@ -716,11 +888,48 @@ Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `P
- **Decisión**: Cloudflare Pages mientras sea estático; migración a VPS al introducir backend. - **Decisión**: Cloudflare Pages mientras sea estático; migración a VPS al introducir backend.
- **Justificación**: $0 al inicio, latencia global, sin operación. Migrar cuando haya backend. - **Justificación**: $0 al inicio, latencia global, sin operación. Migrar cuando haya backend.
### ADR-012 — Escenarios como dos pares de campos por actividad (Modelo A), no entidad separada
- **Contexto Sprint 1**: necesidad de modelar costo "actual" vs "automatizado" por actividad.
- **Decisión**: Modelo A — agregar `automatable`, `automatedCostFixed`, `automatedTimeMinutes` a `Activity`. El motor recibe un parámetro `scenario` y elige qué campos usar.
- **Alternativa descartada**: Modelo B (entidad `Scenario` con N configuraciones independientes) — más complejo, no necesario hasta que haya demanda real de >2 escenarios.
- **Justificación**:
- Trazabilidad actividad-a-actividad para la tabla comparativa (pieza más persuasiva del reporte).
- Un solo diagrama → consultor no mantiene 2 BPMNs sincronizados.
- Migración A→B es directa cuando llegue el momento.
- **Cuándo revisar**: Sprint 3-4 si InQuality necesita >2 escenarios o flujos distintos post-automatización.
### ADR-013 — Volumetría aplicada en el reporte, no en el motor
- **Contexto Sprint 1**: necesidad de anualizar costos para calcular ROI.
- **Decisión**: el motor sigue siendo determinístico ("costo de una ejecución"). La volumetría (frecuencia anual + horizonte) es metadata del proceso y se aplica como multiplicador en la capa de reporte.
- **Alternativa descartada**: correr Monte Carlo o múltiples instancias en el motor.
- **Justificación**:
- El motor es determinístico → correrlo N veces da el mismo resultado × N (perder ciclos).
- Mantiene separación de concerns: motor calcula costo unitario, reporte hace análisis temporal.
- Cuando lleguen distribuciones probabilísticas (Fase 3), ahí tiene sentido Monte Carlo.
### ADR-014 — ROI nominal sin VPN ni tasa de descuento en Sprint 1
- **Contexto Sprint 1**: cálculo de payback y ahorro acumulado para pre-venta.
- **Decisión**: usar fórmulas nominales simples (payback = inversión / ahorro anual × 12, acumulado = ahorro × años - inversión). NO incluir VPN, TIR ni tasa de descuento.
- **Justificación**:
- El cliente promedio de InQuality entiende payback nominal.
- VPN abre discusiones sobre la tasa que distraen del mensaje principal.
- Si en el futuro un cliente sofisticado lo pide, se agrega como opción.
- **Cuándo revisar**: cuando un cliente concreto pida VPN/TIR.
### ADR-015 — Transparencia metodológica como feature, no bug
- **Contexto Sprint 1**: riesgo de que consultores carguen valores incompletos (costos automatizados en 0, inversión en 0) generando ROIs irreales.
- **Decisión**: detectar estos casos y exponerlos en sección visible pero discreta del reporte ("Transparencia metodológica").
- **Justificación**:
- Anticipar limitaciones es señal de seriedad profesional.
- El cliente final confía más en consultores transparentes sobre supuestos que en cifras "perfectas".
- Protege la credibilidad de InQuality y la herramienta.
- **Mecanismo**: banner amarillo informativo (no rojo de error) + lista de valores no informados.
--- ---
## 9. Atributos de Calidad ## 10. Atributos de Calidad
### 9.1 Performance ### 10.1 Performance
| Métrica | MVP | V1.0 | | Métrica | MVP | V1.0 |
|---|---|---| |---|---|---|
@@ -730,7 +939,7 @@ Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `P
| Render mapa de calor | < 200ms | < 200ms | | Render mapa de calor | < 200ms | < 200ms |
| Export PDF | < 5s | < 5s | | Export PDF | < 5s | < 5s |
### 9.2 Mantenibilidad ### 10.2 Mantenibilidad
- **TypeScript strict** activado. - **TypeScript strict** activado.
- **ESLint + Prettier** configurados. - **ESLint + Prettier** configurados.
@@ -738,7 +947,7 @@ Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `P
- **Dominio puro separado** de UI (en `/src/domain`) — testeable sin React. - **Dominio puro separado** de UI (en `/src/domain`) — testeable sin React.
- **Sin lógica de negocio en componentes** — siempre en hooks o domain. - **Sin lógica de negocio en componentes** — siempre en hooks o domain.
### 9.3 Seguridad (V1.0) ### 10.3 Seguridad (V1.0)
- TLS obligatorio (Cloudflare en MVP, Caddy en VPS). - TLS obligatorio (Cloudflare en MVP, Caddy en VPS).
- Auth con tokens cortos + refresh. - Auth con tokens cortos + refresh.
@@ -747,7 +956,7 @@ Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `P
- CSP estricto en producción. - CSP estricto en producción.
- Backups cifrados (V1.0). - Backups cifrados (V1.0).
### 9.4 Accesibilidad ### 10.4 Accesibilidad
- WCAG 2.1 AA como objetivo V1.0. - WCAG 2.1 AA como objetivo V1.0.
- Contraste mínimo 4.5:1 en texto. - Contraste mínimo 4.5:1 en texto.
@@ -756,7 +965,7 @@ Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `P
--- ---
## 10. Riesgos y Mitigaciones ## 11. Riesgos y Mitigaciones
| # | Riesgo | Probabilidad | Impacto | Mitigación | | # | Riesgo | Probabilidad | Impacto | Mitigación |
|---|---|---|---|---| |---|---|---|---|---|
@@ -772,9 +981,9 @@ Añade: `Tenant`, `User`, `Role`, `OrganizationUnit` (jerárquica recursiva), `P
--- ---
## 11. Anexos ## 12. Anexos
### 11.1 Comandos de arranque para Claude Code (MVP) ### 12.1 Comandos de arranque para Claude Code (MVP)
```bash ```bash
# Inicialización # Inicialización
@@ -798,11 +1007,11 @@ npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom
npm install -D eslint prettier npm install -D eslint prettier
``` ```
### 11.2 BPMN XML de prueba sugerido ### 12.2 BPMN XML de prueba sugerido
Para testing inicial, usar el BPMN público de ejemplo de bpmn.io: https://github.com/bpmn-io/bpmn-js-examples Para testing inicial, usar el BPMN público de ejemplo de bpmn.io: https://github.com/bpmn-io/bpmn-js-examples
### 11.3 Recursos de referencia ### 12.3 Recursos de referencia
- **bpmn-js docs**: https://bpmn.io/toolkit/bpmn-js/ - **bpmn-js docs**: https://bpmn.io/toolkit/bpmn-js/
- **BPMN 2.0 spec**: https://www.omg.org/spec/BPMN/2.0/ - **BPMN 2.0 spec**: https://www.omg.org/spec/BPMN/2.0/
@@ -811,7 +1020,7 @@ Para testing inicial, usar el BPMN público de ejemplo de bpmn.io: https://githu
- **Zustand**: https://zustand-demo.pmnd.rs/ - **Zustand**: https://zustand-demo.pmnd.rs/
- **Dexie.js**: https://dexie.org/ - **Dexie.js**: https://dexie.org/
### 11.4 Definition of Done — MVP "Noche Cero" ### 12.4 Definition of Done — MVP "Noche Cero"
- [ ] El usuario puede importar un archivo `.bpmn` por drag & drop - [ ] El usuario puede importar un archivo `.bpmn` por drag & drop
- [ ] El diagrama se renderiza correctamente en el canvas - [ ] El diagrama se renderiza correctamente en el canvas

147
CLAUDE.md
View File

@@ -9,7 +9,7 @@
**Nombre de trabajo**: Process Cost Platform (nombre comercial por definir) **Nombre de trabajo**: Process Cost Platform (nombre comercial por definir)
**Una frase**: Plataforma web para que consultores de procesos transformen un archivo BPMN 2.0 en un reporte visual deslumbrante de costos operativos en minutos. **Una frase**: Plataforma web para que consultores de procesos cuantifiquen costos operativos y calculen ROI de automatización a partir de archivos BPMN 2.0.
**Mantra**: *Los procesos de negocio son activos estratégicos de las empresas y un diferencial competitivo.* **Mantra**: *Los procesos de negocio son activos estratégicos de las empresas y un diferencial competitivo.*
@@ -17,37 +17,83 @@
## Estado Actual ## Estado Actual
- **Fase**: 0MVP "Noche Cero" - **Fase**: 1Sprint 1 (ROI y escenarios de automatización)
- **Fase anterior completada**: 0 — MVP "Noche Cero" (v0.1.0-mvp, deployado en https://process-cost-platform.pages.dev)
- **Documento maestro**: `ARCHITECTURE.md` (raíz del repo) - **Documento maestro**: `ARCHITECTURE.md` (raíz del repo)
- **Fecha objetivo MVP**: una noche - **Audiencia primaria del Sprint 1**: equipo de InQuality (consultora de procesos)
- **Deploy objetivo**: Cloudflare Pages (estático, gratis) - **Caso de uso primario**: pre-venta de proyectos de automatización con cálculo de ROI
- **Deploy**: Cloudflare Pages (estático, gratis)
--- ---
## Reglas No Negociables del MVP ## Reglas No Negociables — Sprint 1
### ✅ Lo que SÍ hacemos esta noche ### ✅ Lo que SÍ entra en Sprint 1
1. Importar archivo `.bpmn` por drag & drop 1. **Volumetría del proceso**: frecuencia anual de ejecución + horizonte de análisis (años)
2. Renderizar el diagrama en read-only con bpmn-js 2. **Marcado de actividades automatizables** con costos automatizados (tiempo + costo fijo)
3. Editar atributos de actividades (costo, tiempo, recursos asignados) 3. **Inversión en automatización** como dato del proceso (un único valor agregado)
4. CRUD de recursos (rol/persona/sistema/equipo/insumo + costo/hora) 4. **Motor de simulación dual**: corre escenarios "actual" y "automatizado" sobre el mismo BPMN
5. Configuración global (moneda, overhead %, nombre proceso, cliente) 5. **Sección de ROI en el reporte**: KPIs grandes, tabla comparativa, gráficos de payback y ahorros
6. Motor de simulación determinístico agregado 6. **5 KPIs de ROI**: Ahorro por ejecución, Ahorro anual, Payback (meses), Ahorro acumulado a N años, ROI % anualizado
7. Reporte visual con mapa de calor sobre el diagrama 7. **Mecanismo de transparencia**: detecta valores cero o inversión cero y los expone en el reporte
8. Gráficos: KPIs, top actividades, costo por actividad, composición, costo por recurso 8. **Migración Dexie v1 → v2** con datos existentes preservados
9. Export a PDF (presentable a cliente) y CSV 9. **Export PDF/CSV ampliado** para incluir páginas/datos de ROI
10. Persistencia en IndexedDB (Dexie) 10. **Documento metodológico anexo** sobre cómo calcular el costo automatizado por ejecución
### ❌ Lo que NO hacemos esta noche ### ❌ Lo que NO entra en Sprint 1
Login · Multi-tenant · Backend · Colaboración · Edición del BPMN · Versionado · Distribuciones probabilísticas · Riesgos · Gobernanza/RACI · Jerarquía organizacional · IA · Elementos RPA/Agente custom · Tutoriales · Marketplace · i18n · PWA installable · Modo oscuro - Múltiples escenarios (más de 2)
- Escenarios como entidad separada (modelo B) — sigue siendo modelo A: dos pares de campos por actividad
- VPN, TIR, tasa de descuento (cálculos financieros sofisticados)
- Captura desglosada del costo de automatización (licencias, desarrollo, infra) — un único campo
- Análisis de sensibilidad ("¿qué pasa si la frecuencia cae 30%?")
- Distribuciones probabilísticas
- Modelar bots como recursos con capacidad
- Multi-tenant, login, colaboración, versionado, IA, modo oscuro, i18n, PWA
**Si dudás si una feature entra: NO ENTRA.** Defendé el alcance. **Si dudás si una feature entra: NO ENTRA.** Defendé el alcance. Anotala en `TODO.md`.
--- ---
## Stack Obligatorio (MVP) ## Decisiones Arquitectónicas Adoptadas (Sprint 1)
### Modelo de escenarios: Modelo A (dos campos por actividad)
Cada actividad tiene:
- `directCostFixed` y `executionTimeMinutes` (escenario actual, ya existían)
- `automatedCostFixed` y `automatedTimeMinutes` (nuevos, escenario automatizado)
- `automatable: boolean` (default false)
**NO se modela con dos diagramas distintos.** Un BPMN, dos pares de campos por actividad. El motor recibe un parámetro `scenario: 'actual' | 'automated'` y aplica los campos correspondientes.
Migración a "escenarios como entidad" se evaluará en Sprint 3-4 si InQuality lo demanda.
### Volumetría: multiplicador en el reporte, no en el motor
El motor sigue siendo **determinístico** y calcula "una ejecución". La volumetría (frecuencia anual + horizonte) es un parámetro del proceso que el reporte usa para extrapolar:
- `costoAnual = costoUnitario × frecuenciaAnual`
- `costoHorizonte = costoAnual × horizonteAños`
No se introduce VPN ni Monte Carlo en Sprint 1.
### ROI: cálculos nominales simples
- `savingsPerExecution = costActual - costAutomated`
- `annualSavings = savingsPerExecution × annualFrequency`
- `paybackMonths = (automationInvestment / annualSavings) × 12`
- `cumulativeSavingsHorizon = (annualSavings × horizonYears) - automationInvestment`
- `roiAnnualPercent = (annualSavings / automationInvestment) × 100`
Edge cases manejados explícitamente: inversión cero, ahorro negativo, división por cero.
### Transparencia metodológica
Si se detectan valores cero (costo automatizado en cero, inversión en cero, etc.), el reporte muestra una **sección visible pero discreta** ("Transparencia metodológica") con la lista de valores no informados. **Es feature, no bug**: convierte una posible debilidad en señal de seriedad profesional para el cliente.
---
## Stack Tecnológico (sin cambios respecto al MVP)
| Capa | Tecnología | | Capa | Tecnología |
|---|---| |---|---|
@@ -61,16 +107,16 @@ Login · Multi-tenant · Backend · Colaboración · Edición del BPMN · Versio
| Gráficos | Apache ECharts (vía echarts-for-react) | | Gráficos | Apache ECharts (vía echarts-for-react) |
| Persistencia | IndexedDB vía Dexie | | Persistencia | IndexedDB vía Dexie |
| Validación | Zod | | Validación | Zod |
| Export PDF | jsPDF + html2canvas | | Export PDF | jsPDF + jsPDF-autotable + html2canvas |
| Export CSV | papaparse | | Export CSV | papaparse |
| Testing | Vitest | | Testing | Vitest + Playwright |
| Deploy | Cloudflare Pages | | Deploy | Cloudflare Pages |
**No introduzcas librerías fuera de esta lista sin justificación explícita.** **No introduzcas librerías fuera de esta lista sin justificación explícita.**
--- ---
## Arquitectura de Carpetas (obligatoria) ## Arquitectura de Carpetas
``` ```
src/ src/
@@ -79,22 +125,23 @@ src/
├── router.tsx ├── router.tsx
├── domain/ ← lógica de negocio pura, sin React, testeable ├── domain/ ← lógica de negocio pura, sin React, testeable
│ ├── types.ts │ ├── types.ts
│ ├── simulation.ts ← motor de simulación │ ├── simulation.ts ← motor de simulación (acepta scenario)
│ ├── roi.ts ← NUEVO en Sprint 1: cálculos puros de ROI
│ ├── bpmn-parser.ts │ ├── bpmn-parser.ts
│ └── schemas.ts ← Zod schemas │ └── schemas.ts ← Zod schemas
├── store/ ← Zustand stores ├── store/ ← Zustand stores
├── persistence/ ← Dexie / IndexedDB ├── persistence/ ← Dexie / IndexedDB (v2 en Sprint 1)
├── features/ ← organizado por feature, no por tipo ├── features/ ← organizado por feature, no por tipo
│ ├── import/ │ ├── import/
│ ├── workspace/ │ ├── workspace/ ← ampliado en Sprint 1 (panel de automatización)
│ ├── simulation/ │ ├── simulation/ ← ampliado (dispara dual scenario)
│ └── report/ │ └── report/ ← ampliado (tab Comparación + ROI)
├── components/ui/ ← shadcn copy-pastes ├── components/ui/ ← shadcn copy-pastes
├── lib/ ← utilidades transversales (format, colors, pdf, csv) ├── lib/ ← utilidades transversales (format, colors, pdf, csv)
└── styles/ └── styles/
``` ```
**Reglas de dependencia**: **Reglas de dependencia (sin cambios)**:
- `domain/` NO importa de React, ni de `store/`, ni de `features/`. Es puro. - `domain/` NO importa de React, ni de `store/`, ni de `features/`. Es puro.
- `features/` puede importar de `domain/`, `store/`, `persistence/`, `lib/`, `components/`. - `features/` puede importar de `domain/`, `store/`, `persistence/`, `lib/`, `components/`.
- `store/` puede importar de `domain/` y `persistence/`. Nada más. - `store/` puede importar de `domain/` y `persistence/`. Nada más.
@@ -104,7 +151,7 @@ src/
## Principios de Código ## Principios de Código
1. **TypeScript strict** activado. Nada de `any` salvo en bordes con librerías sin tipos. 1. **TypeScript strict** activado. Nada de `any` salvo en bordes con librerías sin tipos.
2. **Dominio puro**: el motor de simulación es una función pura testeable sin DOM. 2. **Dominio puro**: motor y cálculos de ROI son funciones puras testeables sin DOM.
3. **Componentes tontos, hooks inteligentes**: lógica en custom hooks, JSX limpio. 3. **Componentes tontos, hooks inteligentes**: lógica en custom hooks, JSX limpio.
4. **Sin lógica de negocio en componentes**. 4. **Sin lógica de negocio en componentes**.
5. **Convenciones de naming**: 5. **Convenciones de naming**:
@@ -114,18 +161,24 @@ src/
- Tipos: `PascalCase`, interfaces con prefijo `I` PROHIBIDO - Tipos: `PascalCase`, interfaces con prefijo `I` PROHIBIDO
6. **Comentarios en español**, código (variables, funciones) en inglés. 6. **Comentarios en español**, código (variables, funciones) en inglés.
7. **Errores con mensajes accionables** para el usuario, nunca traces crudos en UI. 7. **Errores con mensajes accionables** para el usuario, nunca traces crudos en UI.
8. **Migraciones de schema**: SIEMPRE incrementar versión en Dexie, escribir función de upgrade y test que valide preservación de datos.
--- ---
## Diferencial Visual (CRÍTICO) ## Diferencial Visual (sigue siendo CRÍTICO)
El 60% del valor del MVP está en **el reporte final**. Si el reporte se ve mediocre, el MVP fracasa aunque el resto funcione. Reglas: El reporte sigue siendo el corazón. En Sprint 1 se le agregan páginas. Reglas:
- Tipografía: **Inter** para UI, **JetBrains Mono** para números/datos - Tipografía: **Inter** para UI, **JetBrains Mono** para números/datos
- Paleta heatmap: verde `#10b981` → amarillo `#f59e0b` → rojo `#ef4444` - Paleta heatmap: verde `#10b981` → amarillo `#f59e0b` → rojo `#ef4444`
- Paleta ROI:
- Ahorro positivo: verde `#10b981`
- Ahorro marginal o neutro: gris `#64748b`
- Ahorro negativo o payback fuera de horizonte: rojo `#ef4444`
- Advertencias de transparencia: amarillo `#f59e0b` (no rojo: es informativo, no error)
- Cifras de dinero siempre formateadas con separadores y símbolo de moneda - Cifras de dinero siempre formateadas con separadores y símbolo de moneda
- KPIs de ROI **más grandes** que los KPIs del reporte de costos (es la sección que vende)
- El export PDF debe verse igual o mejor que la pantalla - El export PDF debe verse igual o mejor que la pantalla
- Cada gráfico tiene título, leyenda clara y formato de moneda apropiado
- Densidad de información media-alta (audiencia: consultor profesional) - Densidad de información media-alta (audiencia: consultor profesional)
--- ---
@@ -136,20 +189,23 @@ Antes de marcar una tarea como terminada:
- [ ] Funciona en el happy path - [ ] Funciona en el happy path
- [ ] Maneja el caso de datos vacíos sin crashear - [ ] Maneja el caso de datos vacíos sin crashear
- [ ] Persiste en IndexedDB cuando corresponde - [ ] Maneja edge cases definidos (división por cero, valores negativos, valores cero)
- [ ] Persiste en IndexedDB cuando corresponde (con migración si cambió schema)
- [ ] Tiene estilo consistente con el resto de la app - [ ] Tiene estilo consistente con el resto de la app
- [ ] Si toca dominio: tiene al menos un test en Vitest - [ ] Si toca dominio: tiene al menos un test en Vitest
- [ ] Si toca el flujo end-to-end: tiene cobertura en Playwright
--- ---
## Comandos del Proyecto ## Comandos del Proyecto
```bash ```bash
npm run dev # desarrollo npm run dev # desarrollo
npm run build # producción npm run build # producción
npm run test # tests con Vitest npm run test # tests unitarios con Vitest
npm run lint # eslint npm run lint # eslint
npm run preview # previsualizar build npm run preview # previsualizar build de producción
npx playwright test # tests E2E (Playwright headless)
``` ```
--- ---
@@ -161,13 +217,18 @@ npm run preview # previsualizar build
- Si encontrás que algo del documento de arquitectura está mal o falta, **avisame antes de improvisar**. - Si encontrás que algo del documento de arquitectura está mal o falta, **avisame antes de improvisar**.
- No agregues features no pedidas. Si algo se te ocurre, anotalo en `TODO.md`. - No agregues features no pedidas. Si algo se te ocurre, anotalo en `TODO.md`.
- Cuando completes algo, **mostrame los archivos creados/modificados**, no los pegues completos en el chat salvo que te lo pida. - Cuando completes algo, **mostrame los archivos creados/modificados**, no los pegues completos en el chat salvo que te lo pida.
- **Validá programáticamente** lo que yo no puedo ver visualmente (uso Mac + VS Code + Claude Code sin browser interactivo). Para flujos críticos: Playwright + extracción de datos del PDF/CSV generado.
- Si un test revela algo raro: **NO racionalices el problema, investigá la causa raíz**. Los tests no mienten.
--- ---
## Contexto del Fundador ## Contexto del Fundador y Equipo
- Consultor de automatización de procesos basado en Paraguay - Consultor de automatización de procesos basado en Paraguay
- Construye esto como herramienta consultiva propia + para vender a colegas LATAM - Construye esto como herramienta consultiva propia + del equipo de InQuality + para vender a colegas LATAM
- Usa Claude Code Pro como único "equipo de desarrollo" - Usa Claude Code Pro como único "equipo de desarrollo"
- Lo va a presentar a clientes reales en días, no meses - Sprint 1 es para uso interno de InQuality (no para mostrar a cliente todavía)
- Valora: claridad, robustez, pulido visual, mantenibilidad - Casos de uso confirmados:
- Análisis de costos operativos en consultoría de procesos
- **Pre-venta de proyectos de automatización con cálculo de ROI** (caso estrella del Sprint 1)
- Valora: claridad, robustez, pulido visual, mantenibilidad, validación rigurosa

View File

@@ -122,7 +122,7 @@ export function ActivityPanel({ selectedElementId }: ActivityPanelProps) {
type="number" type="number"
min={0} min={0}
step={10} step={10}
value={localActivity.directCostFixed} value={localActivity.directCostFixed === 0 ? '' : localActivity.directCostFixed}
onChange={(e) => handleChange('directCostFixed', Math.max(0, parseFloat(e.target.value) || 0))} onChange={(e) => handleChange('directCostFixed', Math.max(0, parseFloat(e.target.value) || 0))}
className="font-mono h-8 text-sm" className="font-mono h-8 text-sm"
placeholder="0" placeholder="0"
@@ -147,7 +147,7 @@ export function ActivityPanel({ selectedElementId }: ActivityPanelProps) {
type="number" type="number"
min={0} min={0}
step={5} step={5}
value={localActivity.executionTimeMinutes} value={localActivity.executionTimeMinutes === 0 ? '' : localActivity.executionTimeMinutes}
onChange={(e) => handleChange('executionTimeMinutes', Math.max(0, parseFloat(e.target.value) || 0))} onChange={(e) => handleChange('executionTimeMinutes', Math.max(0, parseFloat(e.target.value) || 0))}
className="font-mono h-8 text-sm" className="font-mono h-8 text-sm"
placeholder="0" placeholder="0"

View File

@@ -0,0 +1,371 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="Definitions_CargaFacturasSAP"
targetNamespace="http://inquality.com/bpmn/cargafacturas">
<bpmn:collaboration id="Collaboration_1">
<bpmn:participant id="Participant_IKData" name="IKData (OCR)" processRef="Process_IKData"/>
<bpmn:participant id="Participant_Robot" name="Robot RPA (RocketBot)" processRef="Process_Robot"/>
<bpmn:participant id="Participant_SAP" name="SAP Business One" processRef="Process_SAP"/>
<bpmn:participant id="Participant_Excepcion" name="Bandeja manual / Operador humano" processRef="Process_Excepcion"/>
<bpmn:messageFlow id="MF_1" sourceRef="Task_GenerarPayload" targetRef="StartEvent_Robot"/>
<bpmn:messageFlow id="MF_2" sourceRef="Task_GuardarFactura" targetRef="Task_RecibirFactura"/>
<bpmn:messageFlow id="MF_3" sourceRef="Task_DerivarBandeja" targetRef="Task_RevisionManual"/>
</bpmn:collaboration>
<bpmn:process id="Process_IKData" name="IKData (OCR)" isExecutable="false">
<bpmn:startEvent id="StartEvent_IKData" name="Factura escaneada">
<bpmn:outgoing>Flow_IK_1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task_OCR" name="Procesar OCR sobre factura">
<bpmn:incoming>Flow_IK_1</bpmn:incoming>
<bpmn:outgoing>Flow_IK_2</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_GenerarPayload" name="Generar payload JSON estructurado">
<bpmn:incoming>Flow_IK_2</bpmn:incoming>
<bpmn:outgoing>Flow_IK_3</bpmn:outgoing>
</bpmn:task>
<bpmn:endEvent id="EndEvent_IKData" name="Payload disponible">
<bpmn:incoming>Flow_IK_3</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_IK_1" sourceRef="StartEvent_IKData" targetRef="Task_OCR"/>
<bpmn:sequenceFlow id="Flow_IK_2" sourceRef="Task_OCR" targetRef="Task_GenerarPayload"/>
<bpmn:sequenceFlow id="Flow_IK_3" sourceRef="Task_GenerarPayload" targetRef="EndEvent_IKData"/>
</bpmn:process>
<bpmn:process id="Process_Robot" name="Robot RPA (RocketBot)" isExecutable="true">
<bpmn:startEvent id="StartEvent_Robot" name="Recibe payload">
<bpmn:outgoing>Flow_R_1</bpmn:outgoing>
<bpmn:messageEventDefinition id="MED_1"/>
</bpmn:startEvent>
<bpmn:serviceTask id="Task_LeerPayload" name="Leer y validar payload (RPA-001 a RPA-003)">
<bpmn:incoming>Flow_R_1</bpmn:incoming>
<bpmn:outgoing>Flow_R_2</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="Gateway_PayloadValido" name="¿Payload válido?">
<bpmn:incoming>Flow_R_2</bpmn:incoming>
<bpmn:outgoing>Flow_R_3_Si</bpmn:outgoing>
<bpmn:outgoing>Flow_R_3_No</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:serviceTask id="Task_AbrirSAP" name="Abrir y navegar SAP B1 a Factura proveedores (RPA-004, RPA-005)">
<bpmn:incoming>Flow_R_3_Si</bpmn:incoming>
<bpmn:outgoing>Flow_R_4</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask id="Task_CargarCabecera" name="Cargar cabecera: proveedor, fechas, folio (RPA-006 a RPA-009)">
<bpmn:incoming>Flow_R_4</bpmn:incoming>
<bpmn:outgoing>Flow_R_5</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="Gateway_ProveedorExiste" name="¿Proveedor existe en SAP?">
<bpmn:incoming>Flow_R_5</bpmn:incoming>
<bpmn:outgoing>Flow_R_6_Si</bpmn:outgoing>
<bpmn:outgoing>Flow_R_6_No</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:serviceTask id="Task_CargarLinea" name="Cargar línea de servicio: cuenta, descripción, sucursal, depto, U.negocio, región, IVA, monto (RPA-010 a RPA-018)">
<bpmn:incoming>Flow_R_6_Si</bpmn:incoming>
<bpmn:outgoing>Flow_R_7</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="Gateway_CalculoOK" name="¿SAP recalculó totales OK?">
<bpmn:incoming>Flow_R_7</bpmn:incoming>
<bpmn:outgoing>Flow_R_8_Si</bpmn:outgoing>
<bpmn:outgoing>Flow_R_8_No</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:exclusiveGateway id="Gateway_TimbradoExiste" name="¿Timbrado vigente cargado?">
<bpmn:incoming>Flow_R_8_Si</bpmn:incoming>
<bpmn:outgoing>Flow_R_9_Si</bpmn:outgoing>
<bpmn:outgoing>Flow_R_9_No</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:subProcess id="SubProcess_Timbrado" name="Sub-proceso: Crear timbrado nuevo (RPA-021 a RPA-025)">
<bpmn:incoming>Flow_R_9_No</bpmn:incoming>
<bpmn:outgoing>Flow_R_10</bpmn:outgoing>
<bpmn:startEvent id="SubStart_Timbrado">
<bpmn:outgoing>SubFlow_T_1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:serviceTask id="SubTask_NavegarTimbrado" name="Navegar a Creación de Timbrado y añadir línea">
<bpmn:incoming>SubFlow_T_1</bpmn:incoming>
<bpmn:outgoing>SubFlow_T_2</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask id="SubTask_CompletarTimbrado" name="Completar campos del timbrado y guardar">
<bpmn:incoming>SubFlow_T_2</bpmn:incoming>
<bpmn:outgoing>SubFlow_T_3</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="SubEnd_Timbrado">
<bpmn:incoming>SubFlow_T_3</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SubFlow_T_1" sourceRef="SubStart_Timbrado" targetRef="SubTask_NavegarTimbrado"/>
<bpmn:sequenceFlow id="SubFlow_T_2" sourceRef="SubTask_NavegarTimbrado" targetRef="SubTask_CompletarTimbrado"/>
<bpmn:sequenceFlow id="SubFlow_T_3" sourceRef="SubTask_CompletarTimbrado" targetRef="SubEnd_Timbrado"/>
</bpmn:subProcess>
<bpmn:serviceTask id="Task_CargarCtrlTimbrado" name="Ingresar control de timbrado y autocompletar (RPA-026, RPA-028)">
<bpmn:incoming>Flow_R_9_Si</bpmn:incoming>
<bpmn:incoming>Flow_R_10</bpmn:incoming>
<bpmn:outgoing>Flow_R_11</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask id="Task_ValidacionFinal" name="Validar coincidencia IVA, número y monto (RPA-029)">
<bpmn:incoming>Flow_R_11</bpmn:incoming>
<bpmn:outgoing>Flow_R_12</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="Gateway_ValidacionFinal" name="¿Datos coinciden?">
<bpmn:incoming>Flow_R_12</bpmn:incoming>
<bpmn:outgoing>Flow_R_13_Si</bpmn:outgoing>
<bpmn:outgoing>Flow_R_13_No</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:serviceTask id="Task_GuardarFactura" name="Guardar factura: Agregar y nuevo (RPA-030, RPA-031)">
<bpmn:incoming>Flow_R_13_Si</bpmn:incoming>
<bpmn:outgoing>Flow_R_14</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="Gateway_GuardadoOK" name="¿Guardado confirmado?">
<bpmn:incoming>Flow_R_14</bpmn:incoming>
<bpmn:outgoing>Flow_R_15_Si</bpmn:outgoing>
<bpmn:outgoing>Flow_R_15_No</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:serviceTask id="Task_LogYNotificar" name="Registrar log + mover archivo + notificar (RPA-032 a RPA-034)">
<bpmn:incoming>Flow_R_15_Si</bpmn:incoming>
<bpmn:outgoing>Flow_R_16</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="EndEvent_OK" name="Factura cargada exitosamente">
<bpmn:incoming>Flow_R_16</bpmn:incoming>
</bpmn:endEvent>
<bpmn:serviceTask id="Task_DerivarBandeja" name="Derivar a bandeja manual con motivo (RPA-035, RPA-036)">
<bpmn:incoming>Flow_R_3_No</bpmn:incoming>
<bpmn:incoming>Flow_R_6_No</bpmn:incoming>
<bpmn:incoming>Flow_R_8_No</bpmn:incoming>
<bpmn:incoming>Flow_R_13_No</bpmn:incoming>
<bpmn:incoming>Flow_R_15_No</bpmn:incoming>
<bpmn:outgoing>Flow_R_17</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="EndEvent_Excepcion" name="Derivado a operador humano">
<bpmn:incoming>Flow_R_17</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_R_1" sourceRef="StartEvent_Robot" targetRef="Task_LeerPayload"/>
<bpmn:sequenceFlow id="Flow_R_2" sourceRef="Task_LeerPayload" targetRef="Gateway_PayloadValido"/>
<bpmn:sequenceFlow id="Flow_R_3_Si" name="Sí" sourceRef="Gateway_PayloadValido" targetRef="Task_AbrirSAP"/>
<bpmn:sequenceFlow id="Flow_R_3_No" name="No" sourceRef="Gateway_PayloadValido" targetRef="Task_DerivarBandeja"/>
<bpmn:sequenceFlow id="Flow_R_4" sourceRef="Task_AbrirSAP" targetRef="Task_CargarCabecera"/>
<bpmn:sequenceFlow id="Flow_R_5" sourceRef="Task_CargarCabecera" targetRef="Gateway_ProveedorExiste"/>
<bpmn:sequenceFlow id="Flow_R_6_Si" name="Sí" sourceRef="Gateway_ProveedorExiste" targetRef="Task_CargarLinea"/>
<bpmn:sequenceFlow id="Flow_R_6_No" name="No" sourceRef="Gateway_ProveedorExiste" targetRef="Task_DerivarBandeja"/>
<bpmn:sequenceFlow id="Flow_R_7" sourceRef="Task_CargarLinea" targetRef="Gateway_CalculoOK"/>
<bpmn:sequenceFlow id="Flow_R_8_Si" name="Sí" sourceRef="Gateway_CalculoOK" targetRef="Gateway_TimbradoExiste"/>
<bpmn:sequenceFlow id="Flow_R_8_No" name="No" sourceRef="Gateway_CalculoOK" targetRef="Task_DerivarBandeja"/>
<bpmn:sequenceFlow id="Flow_R_9_Si" name="Sí" sourceRef="Gateway_TimbradoExiste" targetRef="Task_CargarCtrlTimbrado"/>
<bpmn:sequenceFlow id="Flow_R_9_No" name="No" sourceRef="Gateway_TimbradoExiste" targetRef="SubProcess_Timbrado"/>
<bpmn:sequenceFlow id="Flow_R_10" sourceRef="SubProcess_Timbrado" targetRef="Task_CargarCtrlTimbrado"/>
<bpmn:sequenceFlow id="Flow_R_11" sourceRef="Task_CargarCtrlTimbrado" targetRef="Task_ValidacionFinal"/>
<bpmn:sequenceFlow id="Flow_R_12" sourceRef="Task_ValidacionFinal" targetRef="Gateway_ValidacionFinal"/>
<bpmn:sequenceFlow id="Flow_R_13_Si" name="Sí" sourceRef="Gateway_ValidacionFinal" targetRef="Task_GuardarFactura"/>
<bpmn:sequenceFlow id="Flow_R_13_No" name="No" sourceRef="Gateway_ValidacionFinal" targetRef="Task_DerivarBandeja"/>
<bpmn:sequenceFlow id="Flow_R_14" sourceRef="Task_GuardarFactura" targetRef="Gateway_GuardadoOK"/>
<bpmn:sequenceFlow id="Flow_R_15_Si" name="Sí" sourceRef="Gateway_GuardadoOK" targetRef="Task_LogYNotificar"/>
<bpmn:sequenceFlow id="Flow_R_15_No" name="No" sourceRef="Gateway_GuardadoOK" targetRef="Task_DerivarBandeja"/>
<bpmn:sequenceFlow id="Flow_R_16" sourceRef="Task_LogYNotificar" targetRef="EndEvent_OK"/>
<bpmn:sequenceFlow id="Flow_R_17" sourceRef="Task_DerivarBandeja" targetRef="EndEvent_Excepcion"/>
</bpmn:process>
<bpmn:process id="Process_SAP" name="SAP Business One" isExecutable="false">
<bpmn:task id="Task_RecibirFactura" name="Persistir factura en módulo de Compras"/>
</bpmn:process>
<bpmn:process id="Process_Excepcion" name="Bandeja manual" isExecutable="false">
<bpmn:userTask id="Task_RevisionManual" name="Operador humano revisa y completa caso"/>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
<bpmndi:BPMNShape id="Participant_IKData_di" bpmnElement="Participant_IKData" isHorizontal="true">
<dc:Bounds x="100" y="40" width="900" height="120"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="StartEvent_IKData_di" bpmnElement="StartEvent_IKData">
<dc:Bounds x="160" y="82" width="36" height="36"/>
<bpmndi:BPMNLabel><dc:Bounds x="145" y="125" width="70" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_OCR_di" bpmnElement="Task_OCR">
<dc:Bounds x="260" y="60" width="120" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_GenerarPayload_di" bpmnElement="Task_GenerarPayload">
<dc:Bounds x="440" y="60" width="140" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_IKData_di" bpmnElement="EndEvent_IKData">
<dc:Bounds x="640" y="82" width="36" height="36"/>
<bpmndi:BPMNLabel><dc:Bounds x="620" y="125" width="80" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_IK_1_di" bpmnElement="Flow_IK_1">
<di:waypoint x="196" y="100"/><di:waypoint x="260" y="100"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_IK_2_di" bpmnElement="Flow_IK_2">
<di:waypoint x="380" y="100"/><di:waypoint x="440" y="100"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_IK_3_di" bpmnElement="Flow_IK_3">
<di:waypoint x="580" y="100"/><di:waypoint x="640" y="100"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Participant_Robot_di" bpmnElement="Participant_Robot" isHorizontal="true">
<dc:Bounds x="100" y="180" width="2400" height="320"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="StartEvent_Robot_di" bpmnElement="StartEvent_Robot">
<dc:Bounds x="160" y="322" width="36" height="36"/>
<bpmndi:BPMNLabel><dc:Bounds x="145" y="365" width="70" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_LeerPayload_di" bpmnElement="Task_LeerPayload">
<dc:Bounds x="260" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_PayloadValido_di" bpmnElement="Gateway_PayloadValido" isMarkerVisible="true">
<dc:Bounds x="475" y="315" width="50" height="50"/>
<bpmndi:BPMNLabel><dc:Bounds x="465" y="280" width="70" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_AbrirSAP_di" bpmnElement="Task_AbrirSAP">
<dc:Bounds x="580" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_CargarCabecera_di" bpmnElement="Task_CargarCabecera">
<dc:Bounds x="780" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_ProveedorExiste_di" bpmnElement="Gateway_ProveedorExiste" isMarkerVisible="true">
<dc:Bounds x="990" y="315" width="50" height="50"/>
<bpmndi:BPMNLabel><dc:Bounds x="975" y="280" width="80" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_CargarLinea_di" bpmnElement="Task_CargarLinea">
<dc:Bounds x="1090" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_CalculoOK_di" bpmnElement="Gateway_CalculoOK" isMarkerVisible="true">
<dc:Bounds x="1295" y="315" width="50" height="50"/>
<bpmndi:BPMNLabel><dc:Bounds x="1280" y="280" width="80" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_TimbradoExiste_di" bpmnElement="Gateway_TimbradoExiste" isMarkerVisible="true">
<dc:Bounds x="1395" y="315" width="50" height="50"/>
<bpmndi:BPMNLabel><dc:Bounds x="1380" y="280" width="80" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="SubProcess_Timbrado_di" bpmnElement="SubProcess_Timbrado" isExpanded="false">
<dc:Bounds x="1390" y="200" width="180" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_CargarCtrlTimbrado_di" bpmnElement="Task_CargarCtrlTimbrado">
<dc:Bounds x="1500" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_ValidacionFinal_di" bpmnElement="Task_ValidacionFinal">
<dc:Bounds x="1700" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_ValidacionFinal_di" bpmnElement="Gateway_ValidacionFinal" isMarkerVisible="true">
<dc:Bounds x="1915" y="315" width="50" height="50"/>
<bpmndi:BPMNLabel><dc:Bounds x="1900" y="280" width="80" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_GuardarFactura_di" bpmnElement="Task_GuardarFactura">
<dc:Bounds x="2020" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_GuardadoOK_di" bpmnElement="Gateway_GuardadoOK" isMarkerVisible="true">
<dc:Bounds x="2225" y="315" width="50" height="50"/>
<bpmndi:BPMNLabel><dc:Bounds x="2210" y="280" width="80" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_LogYNotificar_di" bpmnElement="Task_LogYNotificar">
<dc:Bounds x="2310" y="300" width="160" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_OK_di" bpmnElement="EndEvent_OK">
<dc:Bounds x="2440" y="220" width="36" height="36"/>
<bpmndi:BPMNLabel><dc:Bounds x="2410" y="200" width="100" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_DerivarBandeja_di" bpmnElement="Task_DerivarBandeja">
<dc:Bounds x="1090" y="430" width="160" height="60"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_Excepcion_di" bpmnElement="EndEvent_Excepcion">
<dc:Bounds x="1310" y="442" width="36" height="36"/>
<bpmndi:BPMNLabel><dc:Bounds x="1280" y="485" width="100" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_R_1_di" bpmnElement="Flow_R_1">
<di:waypoint x="196" y="340"/><di:waypoint x="260" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_2_di" bpmnElement="Flow_R_2">
<di:waypoint x="420" y="340"/><di:waypoint x="475" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_3_Si_di" bpmnElement="Flow_R_3_Si">
<di:waypoint x="525" y="340"/><di:waypoint x="580" y="340"/>
<bpmndi:BPMNLabel><dc:Bounds x="540" y="320" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_3_No_di" bpmnElement="Flow_R_3_No">
<di:waypoint x="500" y="365"/><di:waypoint x="500" y="460"/><di:waypoint x="1090" y="460"/>
<bpmndi:BPMNLabel><dc:Bounds x="510" y="380" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_4_di" bpmnElement="Flow_R_4">
<di:waypoint x="740" y="340"/><di:waypoint x="780" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_5_di" bpmnElement="Flow_R_5">
<di:waypoint x="940" y="340"/><di:waypoint x="990" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_6_Si_di" bpmnElement="Flow_R_6_Si">
<di:waypoint x="1040" y="340"/><di:waypoint x="1090" y="340"/>
<bpmndi:BPMNLabel><dc:Bounds x="1055" y="320" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_6_No_di" bpmnElement="Flow_R_6_No">
<di:waypoint x="1015" y="365"/><di:waypoint x="1015" y="460"/><di:waypoint x="1090" y="460"/>
<bpmndi:BPMNLabel><dc:Bounds x="1025" y="380" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_7_di" bpmnElement="Flow_R_7">
<di:waypoint x="1250" y="340"/><di:waypoint x="1295" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_8_Si_di" bpmnElement="Flow_R_8_Si">
<di:waypoint x="1345" y="340"/><di:waypoint x="1395" y="340"/>
<bpmndi:BPMNLabel><dc:Bounds x="1360" y="320" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_8_No_di" bpmnElement="Flow_R_8_No">
<di:waypoint x="1320" y="365"/><di:waypoint x="1320" y="460"/><di:waypoint x="1250" y="460"/>
<bpmndi:BPMNLabel><dc:Bounds x="1330" y="380" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_9_Si_di" bpmnElement="Flow_R_9_Si">
<di:waypoint x="1445" y="340"/><di:waypoint x="1500" y="340"/>
<bpmndi:BPMNLabel><dc:Bounds x="1460" y="320" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_9_No_di" bpmnElement="Flow_R_9_No">
<di:waypoint x="1420" y="315"/><di:waypoint x="1420" y="280"/><di:waypoint x="1480" y="280"/>
<bpmndi:BPMNLabel><dc:Bounds x="1430" y="290" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_10_di" bpmnElement="Flow_R_10">
<di:waypoint x="1480" y="240"/><di:waypoint x="1580" y="240"/><di:waypoint x="1580" y="300"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_11_di" bpmnElement="Flow_R_11">
<di:waypoint x="1660" y="340"/><di:waypoint x="1700" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_12_di" bpmnElement="Flow_R_12">
<di:waypoint x="1860" y="340"/><di:waypoint x="1915" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_13_Si_di" bpmnElement="Flow_R_13_Si">
<di:waypoint x="1965" y="340"/><di:waypoint x="2020" y="340"/>
<bpmndi:BPMNLabel><dc:Bounds x="1980" y="320" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_13_No_di" bpmnElement="Flow_R_13_No">
<di:waypoint x="1940" y="365"/><di:waypoint x="1940" y="460"/><di:waypoint x="1250" y="460"/>
<bpmndi:BPMNLabel><dc:Bounds x="1950" y="380" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_14_di" bpmnElement="Flow_R_14">
<di:waypoint x="2180" y="340"/><di:waypoint x="2225" y="340"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_15_Si_di" bpmnElement="Flow_R_15_Si">
<di:waypoint x="2275" y="340"/><di:waypoint x="2310" y="340"/>
<bpmndi:BPMNLabel><dc:Bounds x="2285" y="320" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_15_No_di" bpmnElement="Flow_R_15_No">
<di:waypoint x="2250" y="365"/><di:waypoint x="2250" y="460"/><di:waypoint x="1250" y="460"/>
<bpmndi:BPMNLabel><dc:Bounds x="2260" y="380" width="20" height="14"/></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_16_di" bpmnElement="Flow_R_16">
<di:waypoint x="2390" y="300"/><di:waypoint x="2390" y="240"/><di:waypoint x="2440" y="240"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_R_17_di" bpmnElement="Flow_R_17">
<di:waypoint x="1250" y="460"/><di:waypoint x="1310" y="460"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Participant_SAP_di" bpmnElement="Participant_SAP" isHorizontal="true">
<dc:Bounds x="100" y="520" width="2400" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_RecibirFactura_di" bpmnElement="Task_RecibirFactura">
<dc:Bounds x="2310" y="535" width="160" height="50"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_Excepcion_di" bpmnElement="Participant_Excepcion" isHorizontal="true">
<dc:Bounds x="100" y="620" width="2400" height="80"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_RevisionManual_di" bpmnElement="Task_RevisionManual">
<dc:Bounds x="1110" y="635" width="160" height="50"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="MF_1_di" bpmnElement="MF_1">
<di:waypoint x="510" y="140"/><di:waypoint x="510" y="200"/><di:waypoint x="178" y="200"/><di:waypoint x="178" y="322"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="MF_2_di" bpmnElement="MF_2">
<di:waypoint x="2390" y="380"/><di:waypoint x="2390" y="535"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="MF_3_di" bpmnElement="MF_3">
<di:waypoint x="1170" y="490"/><di:waypoint x="1170" y="635"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>