Skip to content

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.

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.

ServicioResponsabilidadDoc
BalanceServiceEntry point del motor: calcular(anio, tipo, {mes}) retorna ReporteAnual (balance + EERR + renta). Lifecycle: guardar como BORRADOR, aprobar, reversar, eliminar.
ReportesServiceSupportClase abstracta con el motor de presentación: buildBalanceClasificado, buildEstadoResultados, buildRenta, helpers PPM, mapearNombresIfrs. Todos los services del dominio extienden esta clase.
CierrePeriodoServicecerrarPeriodo(anio, 12) persiste saldo de cierre + emite ciclo:cierre. bootstrapCierre para seed histórico. checkCierreBlocker valida si el período previo permite avanzar.
PpmServiceActualiza PPM declarado mes a mes por factor de corrección monetaria al cierre anual; contabiliza o reversa el ajuste.
RentaServicecalcularRenta(anio, mes) retorna BalanceTributario (base imponible, total ingresos, deducciones, impuesto estimado).
ResultadosAcumuladosServiceGenera resultado acumulado FINANCIERO (desde balance) o TRIBUTARIO (desde renta); listar y transicionar estado (BORRADOR/CONTABILIZADO/APROBADO).
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:

  1. Agregación SQLfn_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).
  2. Clasificación de saldoclassifyNivel4Balance decide si el saldo va a activo o pasivo mirando tipo (ACTIVO/PASIVO/PATRIMONIO) y naturaleza (D/C) de la cuenta. Maneja contra-cuentas (depreciación acumulada va con tipo=ACTIVO + naturaleza=C → suma a pasivo para restar del activo bruto).
  3. Presentación clasificadabuildBalanceClasificado filtra nivel-3 por código padre nivel-2 (anclas: 1100000 activos corrientes, 1200000 no corrientes, 2100000 pasivos corrientes, 2200000 no corrientes, 2300000 patrimonio). Suma resultado del ejercicio al patrimonio. Calcula cuadra y diferencia.
  4. Estado de resultadosbuildEstadoResultados filtra por anclas nivel-2 (4100000 ingresos ordinarios, 3100000 costo de ventas, 3200000 gastos admin, 3300000 gastos ventas, 3400000 financieros, 3600000 impuesto a la renta). Calcula margen bruto, resultado operacional, antes de impuesto, del ejercicio (con tasa 27% si no hay impuesto contabilizado).
GET /api/reportes/calcular?anio=2026&tipo=TRIBUTARIO&mes=12
POST /api/reportes/guardar # snapshot del reporte
GET /api/reportes/listar # balances guardados (resumen)
GET /api/reportes/:id # detalle de balance guardado
POST /api/reportes/:id/aprobar # BORRADOR → APROBADO
POST /api/reportes/:id/reversar # APROBADO → BORRADOR
DELETE /api/reportes/:id # solo BORRADOR
GET /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.getPpmActualizacionAnual
POST /api/reportes/ppm-actualizacion/contabilizar
POST /api/reportes/ppm-actualizacion/reversar
GET /api/reportes/resultados-acumulados
POST /api/reportes/resultados-acumulados # generar
PATCH /api/reportes/resultados-acumulados/:id/estado
GET /api/reportes/renta?anio=2026&mes=12 # RentaService.calcularRenta
EventoTriggerPayload
ciclo:cierreCierrePeriodoService.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.

TablaOwnerContenido
reportes.balance_guardadoBalanceService.guardarSnapshot completo del ReporteAnual en columna detalle JSONB + columnas indexables (total_activos, total_pasivos, base_imponible, resultado_ejercicio). Estado: BORRADOR/APROBADO.
administracion.saldo_cuentas_cierreCierrePeriodoService.cerrarPeriodoSaldos finales por cuenta para período cerrado. Insumo del próximo balance que necesite arrastre.
reportes.ppm_actualizaciones_anualPpmService.contabilizarFilas mes-a-mes con ppm_declarado, factor_aplicable, ppm_actualizado, ajuste_correccion.
reportes.resultados_acumuladosResultadosAcumuladosService.generarResultado acumulado por año/tipo (FINANCIERO o TRIBUTARIO).

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.