🧾 Módulo de Egresos y Proveedores (DDD)
Este módulo maneja el flujo de salida de capital del condominio. Bajo la filosofía de Monolito Modular y Domain-Driven Design (DDD), este sistema no es un CRUD monolítico, sino una orquestación de contextos delimitados (Bounded Contexts) que garantizan la integridad contable.
🏗️ Mapa de Contextos y Arquitectura
🏭 1. Dominio de Proveedores (Suppliers)
El Proveedor es un Aggregate Root independiente.
- Regla de Negocio: Un proveedor puede existir en el sistema sin tener gastos asociados (Ej. Se registró para un futuro contrato).
- Restricción: Un gasto jamás puede existir sin un proveedor asociado.
- Gestión: Se administra a través de su propio endpoint (
/v1/suppliers) y su propia interfaz en el Frontend. No se crean proveedores "a la fuerza" dentro del payload de un gasto.
🧾 2. Dominio de Egresos (Expenses)
El Gasto representa la factura física o recibo emitido por el proveedor. Se almacena su metadata y el soporte físico en la nube (Hetzner S3).
Máquina de Estados del Gasto
El flujo financiero requiere flexibilidad operativa, por lo que el Gasto muta a través de los siguientes estados:
DRAFT(Borrador): El gasto está registrado, el documento está en S3, pero no ha afectado la contabilidad de los residentes.DISTRIBUTED(Distribuido): El monto total del gasto ha sido fraccionado y asignado a las unidades correspondientes.CANCELLED(Anulado): Un gasto borrador que contenía un error y fue dado de baja.
⚙️ 3. Motor de Distribución (Accounting Engine)
Es el servicio orquestador encargado de convertir un gasto global en deudas individuales.
Reglas Transaccionales (ACID)
La distribución es una operación crítica de suma cero.
- Tipos de Alcance:
GLOBAL: Se divide el total utilizando la alícuota de todo el condominio.SECTORIZED: Se divide el total entre las alícuotas recalibradas de una Torre.INDIVIDUAL: Se cobra el monto exacto de forma directa a unidades seleccionadas.
- Atomicidad: La distribución se ejecuta bajo un
QueryRunner. Si el cálculo falla, toda la distribución hace rollback.