Saltar a contenido

ADR-011 · Contabilidad in-house · módulo cis-admin/contable, no SaaS

Fecha: 2026-04-27 Source: /srv/projects/cis/cis-plan/DECISIONS.md (do not edit here — re-split desde la fuente)


Contexto

VISION.md (línea 60) declaró desde el día cero: "❌ Construir nuestro propio ERP desde cero. Integramos contra Nubox/Defontana/Previred o hacemos puentes." La intuición era razonable — la regulación tributaria CL es ruidosa (F29 mensual IVA, F22 anual renta, libros DTE oficiales, CAFs timbrados, cesión de facturas, propuesta SII, etc.) y los SaaS chilenos cubren todo eso por $15-30 USD/mes.

Pero entre 2026-04-09 (cuando los datos tributarios reales migraron a cis_admin) y 2026-04-17 03:09 UTC, el camino terminó siendo el opuesto. Ya está construido y corriendo en producción:

  • Plan de cuentas 5 niveles (PlanCuenta model + CUENTAS_DEFAULT con 18 cuentas seed cubriendo Activo/Pasivo/Patrimonio/Ingreso/Gasto · cis-admin/backend/app/api/v1/contable.py:54-84).
  • Doble partida (Asiento + LineaAsiento con balance debe=haber enforced en código).
  • Estados financieros endpoints: GET /contable/{estado-resultados,balance,libro-diario,libro-mayor,libro-ingresos-egresos} con filtros por empresa_id + periodo. Régimen Pro-Pyme 14D soportado.
  • DTE bridge (POST /contable/recibir-dte + POST /contable/emit-dte) que delega al cis-sii-gateway (:8270) para emisión y registra Factura recibida + asiento automáticamente.
  • Poller intercambio@ (scripts/intercambio_poller.py · systemd timer cada 10 min) que lee buzón Gmail intercambio@innovacionsantiago.cl, extrae XMLs DTE adjuntos, y POST-ea al endpoint S2S /contable/poller/recibir-dte con dedup por Message-ID.
  • Multi-empresa desde el día uno (empresa_id en cada modelo).
  • Audit trail (log_action por cada operación contable).

Commit referencia: d89907b7 (2026-04-17). CHANNEL referencia: 2026-04-17 03:09 UTC. La decisión nunca tuvo ADR; se construyó porque era la salida más limpia para el caso concreto. Este ADR documenta esa decisión retroactivamente y la formaliza como dirección.

Alternativas consideradas

  1. (a) Nubox / Bsale / Toteat / Defontana (la posición original de VISION.md)
  2. Pro: cero mantenimiento del módulo contable, soporte SII oficial, soporte humano por chat, conformidad fiscal garantizada por el proveedor.
  3. Contra: $15-30 USD/mes recurrente por empresa (CIS hoy = 1 empresa, pero la plataforma debe escalar a N empresas multi-tenant — costo crece linealmente). Datos tributarios sensibles en infra de tercero. Integración con cis-inbox / poller intercambio@ requiere webhooks que esos SaaS NO ofrecen (los DTEs llegarían dos veces: a su sistema + al nuestro, sin convergencia automática). La definición de cuentas y plan contable está sujeta al UI del proveedor.
  4. Costo de exit: alto. Migrar de un SaaS contable después de 1+ años de asientos es no trivial.

  5. (b) Híbrido — usar Nubox para emisión DTE + asientos in-house para reporting

  6. Pro: emisión de factura electrónica oficialmente certificada via PPP (proveedor habilitado SII).
  7. Contra: dos fuentes de verdad para Factura, sincronización constante, doble costo (SaaS + dev). El emisor DTE in-house ya está parcialmente construido en cis-sii-gateway (vía cis-sign + maullin/palena SOAP) — abandonarlo desperdicia el trabajo.

  8. (c) In-house puroelegida (de facto desde 2026-04-17)

  9. Pro: control total sobre el modelo contable. Integración nativa: el poller intercambio@ → asiento + factura es 1 sola transacción atómica en el mismo Postgres. Cero recurring SaaS. Cuando hay multi-tenant (1 plataforma → N empresas), el costo marginal por empresa es ~0. El plan de cuentas es código + migración → versionable.
  10. Contra: nosotros somos responsables de mantener al día las reglas SII (cambios de F29, formatos DTE, CAFs, cesión, propuesta SII). Riesgo: regulación cambia y nuestro código no se entera hasta que hay un DTE rechazado. Mitigación: monitoreo del watcher SII (ADR pendiente) detecta cambios en la carpeta tributaria y alerta.

Decisión

Opción (c): contabilidad in-house en el módulo cis-admin/backend/app/api/v1/contable.py. No usamos SaaS contable de terceros para CIS SpA ni para las empresas que la plataforma onboardee.

Para casos donde el cliente ya tiene una contabilidad histórica en Nubox/Bsale/Defontana, ofrecemos import (one-shot, vía CSV o API del proveedor) pero la fuente de verdad post-onboarding es nuestro módulo.

Razones canónicas

  1. Control fiscal CL completo — F29 mensual, F22 anual, libros DTE oficiales (diario, mayor, ingresos-egresos), todo armado contra el plan de cuentas que nosotros definimos. Sin "el campo X que el SaaS llama Y".
  2. Integración nativa con poller intercambio@ — el endpoint S2S POST /contable/poller/recibir-dte registra factura + asiento + dedup en una sola transacción. Con SaaS, el poller tendría que llamar a una API externa, manejar errores de red, reconciliar duplicados — fragilidad innecesaria.
  3. Sin SaaS recurrente — costo marginal ≈ 0 por empresa adicional. Cuando la plataforma escale, esto importa.
  4. Datos sensibles bajo nuestro control — tributario es categoría especial bajo la nueva ley de protección de datos personales chilena. Tener los asientos en cis_admin (vps-cis, controlado) elimina toda la superficie de tercero-procesador.
  5. Sinergia con cis-sii-gateway — el gateway ya hace login con cert, scrape de carpeta, emisión DTE SOAP. La contabilidad in-house es el otro extremo del mismo flujo.
  6. Ya construido y funcional — reescribir hacia un SaaS sería negar el trabajo del 2026-04-17.

Consecuencias

  • Positivo: stack contable es código nuestro, testeable (tests/api/test_contable.py), evolucionable. Cero pago mensual por empresa. Integración con poller intercambio@ + cis-sii-gateway + cis-mailer es 1 transacción.
  • Negativo: nosotros somos responsables de mantener compliance SII al día. Cuando el SII cambia el formato del F29 (sucede 1-2 veces al año), tenemos que actualizar el código. Cuando aparezca propuesta SII (2027 estimado), tenemos que implementar el flujo de aceptación.
  • Equipo: requiere consultoría con un contador para cierre anual hasta que tengamos confianza interna. Costo: ~$200K CLP/año por empresa para cierre + revisión F22. Aún así es < 12×$30USD = ~$340K/año por empresa de SaaS.
  • Multi-empresa: el modelo empresa_id ya está en cada tabla. Cada nueva empresa onboardeada se siembra automáticamente con _ensure_plan_cuentas(empresa_id) (contable.py:90).
  • Compliance certificación SII — emisor DTE oficial requiere certificación del proveedor en SII (ya en proceso vía cert MIV en cis-sign). Hasta certificarse, emisión DTE corre en SII_ENV=cert (maullin), no producción.
  • Riesgo regulatorio — mitigación parcial: el sii_watch (ADR pendiente, cis-sii-gateway watcher 08:00 daily, ya activo desde 2026-04-27) detecta cambios en la carpeta tributaria y notifica a cis-inbox; cualquier divergencia con nuestros asientos genera ticket.
  • Reversibilidad — alta. Si en 2-3 años decidimos migrar a Nubox, nuestros asientos están en Postgres; export a CSV es 1 query. La elección no cierra puertas.

Relaciones

  • Reemplaza la postura ❌ no construimos ERP declarada en VISION.md:60. Actualizar VISION.md acompaña este ADR (cambio de ❌ a "✅ construido in-house, módulo cis-admin/contable").
  • Depende de: cis-sii-gateway (emisión DTE + scrape carpeta) y cis-sign (firma cert). Ambos ya operativos.
  • Habilita: poller intercambio@ (corriendo cada 10 min), F29 prep automatizado (backlog), libros oficiales para SII (backlog), reporting financiero en /contabilidad del frontend nuevo (Fase D de ADR-010).
  • No alinea con: el item 1 del parking-lot original (que era sobre cis-admin Django vs rewrite, no sobre contabilidad). El user en la sesión 2026-04-27 pidió "reemplaza al punto 1 del parking-lot" — la mejor lectura de eso es que el parking-lot histórico no captura la decisión de contabilidad in-house, y este ADR lo formaliza como decisión arquitectural canónica independiente del parking-lot.

Implementación: aplicada de facto en sesión 2026-04-17 (commit d89907b7). Este ADR la formaliza retroactivamente. Pendiente: actualizar VISION.md:60 a la nueva postura.