Plataforma técnica · Orchestrator
Inventario
Orchestrator Inventarios Existencias
El dominio Inventario convierte compras del SII en existencias contabilizadas, mantiene el stock por movimiento, calcula el costo de ventas mensual con prorrateo por categoría y registra provisiones de cierre. Es uno de los dominios más grandes del Orchestrator: 8 servicios y ~5200 LOC entre service + repository.
InventarioService es una fachada delgada: re-exporta métodos de 7 services especializados para que las rutas HTTP existentes sigan funcionando sin cambios. Cada subservicio mantiene su propia responsabilidad y se documenta por separado.
Servicios
Section titled “Servicios”| Servicio | Responsabilidad | Doc |
|---|---|---|
InventarioService | Fachada que re-exporta operaciones de los 7 servicios especializados. | → |
ExistenciasService | CRUD de productos/existencias. Autogeneración de código por categoría+tipo. | → |
StockService | Stock actual, movimientos (entrada/salida), ajuste de saldo (emite hook), procesar/reversar saldo mensual por categoría. | → |
ComprasInventarioService | Pipeline compra SII → existencia: clasificación, procesamiento por producto, ingreso por categoría, devolución de NC, contabilización. Emite hook. | → |
CostoVentasService | Cálculo y registro de costo de ventas mensual con factor de prorrateo por categoría. Emite hook por cada detalle. | — |
CategoriasExistenciaService | CRUD de categorías. Restringe cuenta_existencia_codigo al grupo 1109 (Existencias del manual). | — |
ProveedoresClasificacionService | Clasificación proveedor → genera_existencias. Lista pendientes desde compras no clasificadas. | — |
ProvisionesInventarioService | Provisiones de cierre por compras no procesadas + ajustes de cierre por movimientos sin asiento. | — |
Las páginas dedicadas cubren los 4 servicios principales. Los 4 menores (CostoVentas, Categorias, Proveedores, Provisiones) se describen abajo y en sus secciones específicas de la fachada.
Hooks emitidos
Section titled “Hooks emitidos”| Evento | Trigger | Payload |
|---|---|---|
compra_inv:contabilizada | ComprasInventarioService.procesarCompraExistencia y procesarCompraIngresoCategoria (1 evento por movimiento) | { movimientoCostoId, compraDetalleId, categoriaId, monto } |
costo:egreso_calculado | CostoVentasService.calcularCostoVentas (1 evento por cada detalle de categoría) | { movimientoCostoId, categoriaId, periodo: { anio, mes }, monto, factorProrrateo } |
existencia:castigada | StockService.ajustarSaldoInventario cuando el ajuste es de tipo SALIDA | { movimientoCostoId, categoriaId, monto, motivo } |
Catálogo completo en Domain Events › Inventario / Costos.
Mapa de dependencias
Section titled “Mapa de dependencias”flowchart LR
subgraph SRC["Fuentes externas"]
SII[("operaciones_sii.compras<br/>+ compras_detalle")]
PROV[("administracion.proveedores")]
PLN[("administracion.plan_contable<br/>(grupo 1109)")]
end
subgraph SVC["domain/inventario/"]
PRV["ProveedoresClasificacionService"]
CAT["CategoriasExistenciaService"]
EXI["ExistenciasService"]
STK["StockService"]
COM["ComprasInventarioService"]
COS["CostoVentasService"]
PRO["ProvisionesInventarioService"]
INV["InventarioService<br/>(facade)"]
end
subgraph OUT["Tablas inventario"]
EXT[("existencias")]
CTG[("categorias_existencia")]
MOV[("movimientos_inventario")]
SAL[("saldo_stock_mensual")]
CV[("costo_ventas_cierre")]
PRC[("provisiones_existencias_cierre")]
PAJ[("provisiones_ajustes_cierre")]
PCL[("proveedores_clasificacion")]
end
EVT["DomainEventBus<br/>compra_inv:* · costo:* · existencia:*"]
PROV --> PRV --> PCL
PLN --> CAT --> CTG
CAT --> EXI --> EXT
EXI --> STK --> MOV
STK --> SAL
SII --> COM --> MOV
COM --> COS --> CV
SII --> PRO --> PRC & PAJ
COM & COS & STK -. post-COMMIT .-> EVT
INV -. delega .-> CAT & EXI & STK & COM & COS & PRO & PRV Servicios menores (no tienen doc dedicada)
Section titled “Servicios menores (no tienen doc dedicada)”CategoriasExistenciaService
Section titled “CategoriasExistenciaService”CRUD de categorias_existencia. Cada categoría tiene una cuenta_existencia_codigo (cuenta contable del activo) que debe pertenecer al grupo 1109 (Existencias) — el servicio rechaza códigos fuera de ese rango con ValidationError. Los services downstream (ExistenciasService, ComprasInventarioService) validan que el categoria_id exista al usarlo.
Operaciones: getCategorias(activas?), createCategoria(data), updateCategoria(id, data), deleteCategoria(id).
ProveedoresClasificacionService
Section titled “ProveedoresClasificacionService”Clasificación operacional de proveedores. Antes de procesar una compra como existencia, el proveedor debe estar en proveedores_clasificacion con genera_existencias = true. Si no, ComprasInventarioService rechaza el procesamiento.
Operaciones clave:
getProveedoresExistencias(giroCodes?)— lista de proveedores ya clasificados como existencias.getProveedoresPendientesDesdeCompras({ año, mes })— lista de RUTs que aparecen en compras pero aún no están clasificados.create/update/delete ProveedorClasificacion.
Sirve de bandeja de clasificación: el operador ve los pendientes, los clasifica una vez, y a partir de ahí sus compras se vuelven procesables como inventario.
CostoVentasService
Section titled “CostoVentasService”Calcula el costo de ventas mensual usando movimientos de inventario y un factor de prorrateo por categoría. Métodos clave:
getCostoVentas(filtros)— query agrupada por proveedor / categoría / cuenta, con resumen y metadata.calcularCostoVentas({ año, mes, categoria_id? })— calcula y persiste; emitecosto:egreso_calculadopor cada detalle (categoría) con sufactorProrrateo.reversarCostoVentas({ año, mes, categoria_id? })— borra los registros del período.crearCostoVentasCierre,actualizarEstadoCostoVentasCierre,eliminarCostoVentasCierre— gestión de la fila de cierre (BORRADOR → CONTABILIZADO → APROBADO).
El algoritmo de prorrateo vive en CostoVentasRepository.calcularYregistrarCostoVentas (~390 LOC) y no se documenta acá — es lógica SQL densa que merece su propia página si se requiere profundizar.
ProvisionesInventarioService
Section titled “ProvisionesInventarioService”Dos conceptos distintos:
-
provisiones_existencias_cierre— provisión por compras pendientes de procesar al cierre del período.crearProvisionExistenciaCierre(compra_id)valida el proveedor, la compra y crea/upserta el row concuenta_pasivo_codigo(default2105003). -
provisiones_ajustes_cierre— ajustes de provisión sobre movimientos del libro mensual.contabilizarProvisionAjustesCierre({ año_documento, mes_documento?, año_libro?, mes_libro?, referencia_tipo? })itera los candidatos y los persiste;reversarProvisionAjustesCierre({ año_libro, mes_libro })revierte el período.
Estados:
- Provisión existencia cierre:
BORRADOR | CONTABILIZADO | REVERSADO. - Provisión ajuste cierre:
BORRADOR | CONTABILIZADO.
Flujo operacional típico
Section titled “Flujo operacional típico”sequenceDiagram autonumber participant SII as SII (compras sincronizadas) participant Adm as Admin (Sevastopol) participant PRV as ProveedoresClasificacion participant COM as ComprasInventario participant STK as Stock participant COS as CostoVentas participant PRO as Provisiones SII->>Adm: compras pendientes Adm->>PRV: clasificar proveedor (genera_existencias) Adm->>COM: procesarCompraExistencia o procesarCompraIngresoCategoria COM->>STK: ENTRADA en movimientos_inventario COM-->>Adm: compra_inv:contabilizada (hook) Note over STK,COS: cierre de mes Adm->>COS: calcularCostoVentas(año, mes) COS->>STK: lee saldos + movimientos del período COS-->>Adm: costo:egreso_calculado (× N detalles) Adm->>PRO: crear provisiones de cierre para compras no procesadas