Plataforma técnica · Orchestrator
Reportes
Orchestrator Reportes Balance
El dominio Reportes es el motor que convierte líneas contables proyectadas por categorías en presentación financiera y tributaria. Cierra el ciclo del modelo por categorías: los documentos clasificados generan líneas en libro diario, este dominio las agrega por cuenta/nivel y las presenta como balance clasificado, estado de resultados y base imponible.
No genera líneas contables propias (eso vive en los dominios fuente: operaciones, inventario, payroll, activo-fijo, financieros). Lee, agrega y presenta. La única excepción es CierrePeriodoService.cerrarPeriodo, que persiste el saldo de cierre y emite ciclo:cierre.
Ubicación
Section titled “Ubicación”orchestrator/src/domain/reportes/├── ReportesService.ts # facade pública (re-exporta los 5 services)├── ReportesServiceSupport.ts # abstract base + el motor (build*)├── BalanceService.ts # calcular, lifecycle (BORRADOR→APROBADO)├── BalanceRepository.ts # fn_balance_lineas SQL + validación config├── CierrePeriodoService.ts # cerrarPeriodo, bootstrap, checkBlocker├── CierrePeriodoRepository.ts # persistencia de saldo_cuentas_cierre├── PpmService.ts # actualización por corrección monetaria├── PpmRepository.ts # list/upsert/reversar├── RentaService.ts # base imponible├── RentaRepository.ts # raw ingresos/deducciones del año├── ResultadosAcumuladosService.ts # generar/listar resultado acumulado├── ResultadosAcumuladosRepository.ts # persistencia de resultados_acumulados├── ReportesRepository.ts # facade que re-exporta los 5 repos├── BalanceHtmlGenerator.ts # render PDF/HTML del reporte├── nivel4Classification.ts # clasifica saldos por tipo+naturaleza└── types.ts (+ {balance,renta,cierre-periodo,ppm,resultados-acumulados}.types.ts)ReportesService es una facade delgada que re-exporta los 5 servicios especializados; los callers HTTP llaman svc.calcular o svc.contabilizarPpmActualizacionAnual sin conocer la división interna. ReportesRepository cumple el mismo rol con los repos.
Servicios
Section titled “Servicios”| Servicio | Responsabilidad | Doc |
|---|---|---|
BalanceService | Entry point del motor: calcular(anio, tipo, {mes}) retorna ReporteAnual (balance + EERR + renta). Lifecycle: guardar como BORRADOR, aprobar, reversar, eliminar. | → |
ReportesServiceSupport | Clase abstracta con el motor de presentación: buildBalanceClasificado, buildEstadoResultados, buildRenta, helpers PPM, mapearNombresIfrs. Todos los services del dominio extienden esta clase. | → |
CierrePeriodoService | cerrarPeriodo(anio, 12) persiste saldo de cierre + emite ciclo:cierre. bootstrapCierre para seed histórico. checkCierreBlocker valida si el período previo permite avanzar. | → |
PpmService | Actualiza PPM declarado mes a mes por factor de corrección monetaria al cierre anual; contabiliza o reversa el ajuste. | → |
RentaService | calcularRenta(anio, mes) retorna BalanceTributario (base imponible, total ingresos, deducciones, impuesto estimado). | → |
ResultadosAcumuladosService | Genera resultado acumulado FINANCIERO (desde balance) o TRIBUTARIO (desde renta); listar y transicionar estado (BORRADOR/CONTABILIZADO/APROBADO). | → |
Conexión con el modelo por categorías
Section titled “Conexión con el modelo por categorías”flowchart LR
subgraph SRC["Modelo por categorías"]
DOC["Documento operativo<br/>(factura, boleta, liquidación, mov. bancario, activo fijo)"]
CAT["Categoría"]
LIB["Línea contable<br/>(libro diario)"]
DOC --> CAT --> LIB
end
subgraph ENG["Motor balance (dominio reportes)"]
FN["fn_balance_lineas(anio, mes)<br/>PostgreSQL function"]
LIN["BalanceLinea[]<br/>(nivel 1-4, debe, haber, activo, pasivo,<br/>perdidas, ganancias)"]
BS["BalanceService.calcular"]
SUP["ReportesServiceSupport.build*"]
LIB --> FN --> LIN --> BS --> SUP
end
subgraph OUT["Presentación"]
BC["BalanceClasificado<br/>(activos cte/no-cte, pasivos, patrimonio, cuadra)"]
ER["EstadoResultados<br/>(margen bruto, op., antes impto., ejercicio)"]
RT["BalanceTributario<br/>(base imponible, impto. estimado)"]
SUP --> BC & ER & RT
end El motor no decide qué cuenta usar ni qué naturaleza tiene un saldo — esa información ya vive en el plan_contable y en las categorías que generaron las líneas. El motor solo agrega y proyecta:
- Agregación SQL —
fn_balance_lineas(anio, mes)agrupa líneas del libro diario por cuenta, calcula debe/haber acumulado del período y devuelve filas en 4 niveles del plan (1=tipo, 2=sección, 3=subsección, 4=cuenta). - Clasificación de saldo —
classifyNivel4Balancedecide si el saldo va aactivoopasivomirandotipo(ACTIVO/PASIVO/PATRIMONIO) ynaturaleza(D/C) de la cuenta. Maneja contra-cuentas (depreciación acumulada va contipo=ACTIVO + naturaleza=C→ suma apasivopara restar del activo bruto). - Presentación clasificada —
buildBalanceClasificadofiltra nivel-3 por código padre nivel-2 (anclas:1100000activos corrientes,1200000no corrientes,2100000pasivos corrientes,2200000no corrientes,2300000patrimonio). Suma resultado del ejercicio al patrimonio. Calculacuadraydiferencia. - Estado de resultados —
buildEstadoResultadosfiltra por anclas nivel-2 (4100000ingresos ordinarios,3100000costo de ventas,3200000gastos admin,3300000gastos ventas,3400000financieros,3600000impuesto a la renta). Calcula margen bruto, resultado operacional, antes de impuesto, del ejercicio (con tasa 27% si no hay impuesto contabilizado).
Endpoint principal
Section titled “Endpoint principal”GET /api/reportes/calcular?anio=2026&tipo=TRIBUTARIO&mes=12POST /api/reportes/guardar # snapshot del reporteGET /api/reportes/listar # balances guardados (resumen)GET /api/reportes/:id # detalle de balance guardadoPOST /api/reportes/:id/aprobar # BORRADOR → APROBADOPOST /api/reportes/:id/reversar # APROBADO → BORRADORDELETE /api/reportes/:id # solo BORRADORGET /api/reportes/:id/pdf # render vía BalanceHtmlGenerator + PdfService
POST /api/reportes/cierre-periodo # CierrePeriodoService.cerrarPeriodo (mes=12)POST /api/reportes/cierre-periodo/bootstrap
GET /api/reportes/ppm-actualizacion?anio=2026 # PpmService.getPpmActualizacionAnualPOST /api/reportes/ppm-actualizacion/contabilizarPOST /api/reportes/ppm-actualizacion/reversar
GET /api/reportes/resultados-acumuladosPOST /api/reportes/resultados-acumulados # generarPATCH /api/reportes/resultados-acumulados/:id/estado
GET /api/reportes/renta?anio=2026&mes=12 # RentaService.calcularRentaHooks emitidos
Section titled “Hooks emitidos”| Evento | Trigger | Payload |
|---|---|---|
ciclo:cierre | CierrePeriodoService.cerrarPeriodo post-COMMIT | { anio, mes, pasosCompletados: string[] } (replica desde CicloContableRepository.findCierreEventPayload) |
El resto del dominio no emite eventos — son lecturas o lifecycle administrativo (aprobar, reversar) sin consecuencia cross-dominio.
Persistencia
Section titled “Persistencia”| Tabla | Owner | Contenido |
|---|---|---|
reportes.balance_guardado | BalanceService.guardar | Snapshot completo del ReporteAnual en columna detalle JSONB + columnas indexables (total_activos, total_pasivos, base_imponible, resultado_ejercicio). Estado: BORRADOR/APROBADO. |
administracion.saldo_cuentas_cierre | CierrePeriodoService.cerrarPeriodo | Saldos finales por cuenta para período cerrado. Insumo del próximo balance que necesite arrastre. |
reportes.ppm_actualizaciones_anual | PpmService.contabilizar | Filas mes-a-mes con ppm_declarado, factor_aplicable, ppm_actualizado, ajuste_correccion. |
reportes.resultados_acumulados | ResultadosAcumuladosService.generar | Resultado acumulado por año/tipo (FINANCIERO o TRIBUTARIO). |
Dependencias
Section titled “Dependencias”fn_balance_lineas(anio, mes) exige que el concepto FACT-COMP-NET esté configurado en operaciones_sii.config_conceptos_contables con cuenta_debito_codigo y cuenta_credito_codigo. BalanceRepository lo valida antes de invocar la función — si falta, lanza ValidationError con mensaje accionable. Esto evita balances corruptos por configuración incompleta.
El motor delega corrección monetaria UF/UTM/factores a CommonDataService (PPM y arrastre). No replica esa lógica.