Plataforma técnica · Orchestrator
Chart Of Accounts Service
Orchestrator Administración Manual Cuentas
ChartOfAccountsService es el CRUD del plan de cuentas del tenant (administracion.plan_contable). Es la single source of truth contable: cada cuenta tiene código, padre, tipo, naturaleza y flags que determinan cómo se contabiliza.
Vive en domain/chart-of-accounts/ pero su UI y route están bajo /api/admin/chart-of-accounts — por eso se agrupa en docs con el resto de servicios de administración.
Distinción con otros servicios de plan
Section titled “Distinción con otros servicios de plan”| Servicio | Alcance |
|---|---|
ChartOfAccountsService (esta pág.) | CRUD per-tenant de administracion.plan_contable. |
PlanCuentasSyncService | Diff y sync del template accounting_template.plan_contable contra cada tenant. |
| Manual de Cuentas | Documentación contable (asientos tipo, NIC/IFRS) por código — vive en MongoDB. |
Este servicio opera dentro de la base del tenant. Los otros dos viven en el dominio Command y orquestan a través de todos los tenants.
Modelo
Section titled “Modelo”Account:
| Campo | Tipo | Notas |
|---|---|---|
codigo | string | PK, solo dígitos (^[0-9]+$). |
codigo_padre | string? | FK a otro codigo. NULL en raíces (nivel 1). |
nombre | string | Nombre local. |
nombre_ifrs | string? | Nombre canónico IFRS. |
tipo | enum ACTIVO|PASIVO|PATRIMONIO|INGRESO|GASTO | Clasificación contable mayor. |
naturaleza | enum D|C | Débito o Crédito (saldo natural). |
nivel | number | 1-6. Define profundidad jerárquica. |
es_imputable | boolean | Si se puede usar directamente en asientos. |
requiere_tercero | boolean | Si el asiento debe asignar RUT. |
requiere_cc | boolean | Si requiere centro de costo. |
requiere_proyecto | boolean | Si requiere proyecto. |
orden_presentacion | number | Para ordenar en estados financieros. |
categoria_ifrs | string? | |
notas_ifrs | string? | |
created_at / updated_at / created_by / updated_by | — |
Operaciones
Section titled “Operaciones”list(ctx)
Section titled “list(ctx)”SELECT * FROM plan_contable ORDER BY orden_presentacion, codigo. Sin paginación — el plan completo cabe en una sola respuesta (cientos de filas en el peor caso).
getByCode(ctx, code)
Section titled “getByCode(ctx, code)”Lookup directo. Lanza NotFoundError("Account", code) si no existe.
create(ctx, data)
Section titled “create(ctx, data)”flowchart TB IN["create(data)"] V1["code matches ^[0-9]+$"] V2["validateRequired(nombre, tipo, naturaleza)"] V3["nivel definido"] TX["withTransaction"] INS["INSERT plan_contable"] RET["ServiceResult(account)"] IN --> V1 V1 -- no --> ERR1["ValidationError 'must contain only numbers'"] V1 -- sí --> V2 --> V3 V3 -- no --> ERR2["ValidationError 'Missing required field: nivel'"] V3 -- sí --> TX --> INS --> RET
Validaciones explícitas (no delegadas a constraints PG):
codigosolo dígitos.nombre,tipo,naturalezarequeridos.nivelrequerido (chequeado aparte por ser numérico —validateRequiredno detectaundefined === 0).
El INSERT default-ea booleanos a false y orden_presentacion a 0. No valida que codigo_padre exista — confía en el FK de la DB para reportar.
update(ctx, code, updates)
Section titled “update(ctx, code, updates)”Permite cambiar todo menos codigo (la PK). Construye SET dinámico, retorna 404 si el código no existe.
No hay validación de jerarquía: cambiar codigo_padre puede crear ciclos si el operador se equivoca. La PK textual hace difícil garantizar acyclicity sin un CHECK trigger.
delete(ctx, code)
Section titled “delete(ctx, code)”Bloqueado si tiene hijos — hasChildren(code) cuenta WHERE codigo_padre = $1. Si hay aunque sea uno, lanza ValidationError("Cannot delete account: has associated sub-accounts"). Esto previene huérfanos al nivel del service (en vez de depender del FK de la DB).
No bloquea si hay movimientos contables que la referencian. Si el operador borra una cuenta con histórico, el FK desde asientos_detalle etc. fallará en runtime. Considerar agregar un check similar a PlanCuentasSyncService.getOrphanCheck si se vuelve un problema.
Consumidores
Section titled “Consumidores”Estos servicios validan códigos contra esta tabla (lectura) o referencian cuentas creadas aquí (FK):
| Consumidor | Uso |
|---|---|
CapitalService | Valida cuenta_contable_codigo y cuenta_contrapartida_codigo en create/update. |
ConfigContableService | Valida cuenta contra plan en cada create/update de wiring. |
LegalRepService | Crea sub-cuentas bajo 2204000 para cuenta corriente socio. |
AccountingService (asientos) | Cualquier asiento contable referencia códigos del plan. |
ReportesService | Agrupa por tipo y orden_presentacion para estados financieros. |
Por qué no hay hook
Section titled “Por qué no hay hook”Mutar el plan de cuentas es config estructural — no dispara cadenas reactivas. Los asientos posteriores usarán la nueva estructura; los previos referencian las cuentas que existían cuando se contabilizaron.
Si en el futuro se quiere notificar que se agregó una cuenta nueva (e.g. para invalidar caches de plan en otros servicios), agregar evento chart_of_accounts:created en DomainEventMap y encolarlo en withTransaction.
Endpoints
Section titled “Endpoints”Documentados en Administración API. Resumen:
| Método | Ruta | Service call |
|---|---|---|
GET | /api/admin/chart-of-accounts | list(ctx) |
GET | /api/admin/chart-of-accounts/:code | getByCode(ctx, code) |
POST | /api/admin/chart-of-accounts | create(ctx, data) |
PUT | /api/admin/chart-of-accounts/:code | update(ctx, code, updates) |
DELETE | /api/admin/chart-of-accounts/:code | delete(ctx, code) |