Skip to content

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.

ServicioAlcance
ChartOfAccountsService (esta pág.)CRUD per-tenant de administracion.plan_contable.
PlanCuentasSyncServiceDiff y sync del template accounting_template.plan_contable contra cada tenant.
Manual de CuentasDocumentació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.

Account:

CampoTipoNotas
codigostringPK, solo dígitos (^[0-9]+$).
codigo_padrestring?FK a otro codigo. NULL en raíces (nivel 1).
nombrestringNombre local.
nombre_ifrsstring?Nombre canónico IFRS.
tipoenum ACTIVO|PASIVO|PATRIMONIO|INGRESO|GASTOClasificación contable mayor.
naturalezaenum D|CDébito o Crédito (saldo natural).
nivelnumber1-6. Define profundidad jerárquica.
es_imputablebooleanSi se puede usar directamente en asientos.
requiere_tercerobooleanSi el asiento debe asignar RUT.
requiere_ccbooleanSi requiere centro de costo.
requiere_proyectobooleanSi requiere proyecto.
orden_presentacionnumberPara ordenar en estados financieros.
categoria_ifrsstring?
notas_ifrsstring?
created_at / updated_at / created_by / updated_by

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).

Lookup directo. Lanza NotFoundError("Account", code) si no existe.

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):

  • codigo solo dígitos.
  • nombre, tipo, naturaleza requeridos.
  • nivel requerido (chequeado aparte por ser numérico — validateRequired no detecta undefined === 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.

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.

Bloqueado si tiene hijoshasChildren(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.

Estos servicios validan códigos contra esta tabla (lectura) o referencian cuentas creadas aquí (FK):

ConsumidorUso
CapitalServiceValida cuenta_contable_codigo y cuenta_contrapartida_codigo en create/update.
ConfigContableServiceValida cuenta contra plan en cada create/update de wiring.
LegalRepServiceCrea sub-cuentas bajo 2204000 para cuenta corriente socio.
AccountingService (asientos)Cualquier asiento contable referencia códigos del plan.
ReportesServiceAgrupa por tipo y orden_presentacion para estados financieros.

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.

Documentados en Administración API. Resumen:

MétodoRutaService call
GET/api/admin/chart-of-accountslist(ctx)
GET/api/admin/chart-of-accounts/:codegetByCode(ctx, code)
POST/api/admin/chart-of-accountscreate(ctx, data)
PUT/api/admin/chart-of-accounts/:codeupdate(ctx, code, updates)
DELETE/api/admin/chart-of-accounts/:codedelete(ctx, code)