ConTodo
Especialista Contable

ConTodo ERP — Modelo Contable, PCGE 2019 y Motor de Asientos Automáticos

Módulo Contable de ConTodo ERP

Alcance. Este documento define el modelo contable núcleo de ConTodo: catálogo de cuentas basado en el Plan Contable General Empresarial (PCGE 2019), el libro mayor (general ledger) multi-tenant y multimoneda, el motor de asientos automáticos desde transacciones operativas (compras, ventas, planilla, tesorería), la gestión de cuentas por cobrar/pagar, activos fijos y depreciación, y la generación de los cuatro estados financieros bajo NIIF (Estado de Situación Financiera, Estado de Resultados, Estado de Flujos de Efectivo y Estado de Cambios en el Patrimonio). Se incluyen supuestos explícitos, riesgos, alternativas y diagramas mermaid.


1. Principios de diseño y supuestos

#Supuesto / PrincipioJustificación
S1Partida doble inviolable: todo asiento debe cumplir Σ debe = Σ haber por moneda funcional. Validación a nivel de base de datos (constraint + trigger) y de aplicación.La integridad contable no puede depender solo del frontend. Un asiento descuadrado nunca se persiste.
S2Moneda funcional = PEN por defecto, con soporte multimoneda. Cada journal_entry_line guarda monto en moneda origen, tipo de cambio (TC) y monto en moneda funcional.NIC 21. Empresas importadoras textiles operan en USD; SUNAT exige libros en soles al TC SBS publicación/cierre.
S3Multi-tenant por company_id con aislamiento por Row Level Security (RLS) de PostgreSQL. El plan de cuentas se versiona: base PCGE compartida + cuentas personalizadas por empresa.Multiempresa es requisito. RLS evita fugas de datos entre tenants a nivel de motor, no solo de ORM.
S4Inmutabilidad del asiento contabilizado: una vez posted, no se edita; se corrige con asiento de extorno o de ajuste.Trazabilidad de auditoría (Big Four), exigencia de PLE/SIRE de SUNAT.
S5Plan de cuentas a 5 dígitos mínimo (PCGE) extensible a 7-9 dígitos para detalle analítico/sub-cuentas por empresa.El PCGE define dígitos 1-2 (cuenta), 3 (subcuenta), 4-5 (divisionaria); el ERP permite auxiliares adicionales.
S6Centro de costo y dimensión analítica opcionales por línea (sucursal, proyecto, línea de producto).BI y costeo por centro requieren etiquetas dimensionales sin multiplicar el catálogo.
S7Devengo (accrual) como base, no caja. El flujo de efectivo se deriva por método indirecto.NIC 1. La caja es una vista derivada del mayor de cuentas 10.

2. Catálogo de cuentas — PCGE 2019 (estructura por clases)

El PCGE organiza las cuentas en 9 elementos (clases). ConTodo precarga el catálogo oficial como seed del tenant y lo marca como system: true (no editable en su naturaleza, sí extensible en divisionarias).

ClaseElementoNaturalezaSaldo normalEstado financiero
1Activo disponible y exigibleActivoDeudorSituación Financiera
2Activo realizable (existencias)ActivoDeudorSituación Financiera
3Activo inmovilizadoActivoDeudorSituación Financiera
4PasivoPasivoAcreedorSituación Financiera
5Patrimonio netoPatrimonioAcreedorSituación Financiera
6Gastos por naturalezaResultadoDeudorResultados
7IngresosResultadoAcreedorResultados
8Saldos intermediarios de gestión / Determinación del resultadoResultadoMixtoCierre
9Cuentas analíticas de explotación (costos por función)Orden/CostosMixtoInterno / Costeo

2.1 Ejemplos de cuentas representativas (divisionarias)

CódigoDenominaciónClaseTipoUso típico en ConTodo
10Efectivo y equivalentes de efectivo1ActivoCabecera tesorería
104.1Cuentas corrientes operativas BCP MN1ActivoConciliación bancaria
105.1Cuentas corrientes operativas USD1ActivoMultimoneda
12Cuentas por cobrar comerciales – terceros1ActivoSubmódulo CxC
121.1Facturas por cobrar1ActivoVenta a crédito
1212Detracciones por cobrar1ActivoSPOT SUNAT
19Estimación de cuentas de cobranza dudosa1Activo (regularizadora)Provisión incobrables
20Mercaderías2ActivoInventario reventa
21Productos terminados2ActivoProducción textil
24Materias primas2ActivoHilados, telas
33Inmuebles, maquinaria y equipo3ActivoActivo fijo
39Depreciación acumulada3Activo (regularizadora)Depreciación
40Tributos por pagar4PasivoIGV, Renta, ESSALUD
4011IGV – Cuenta propia4PasivoDébito/crédito fiscal
42Cuentas por pagar comerciales – terceros4PasivoSubmódulo CxP
41Remuneraciones y participaciones por pagar4PasivoPlanilla
45Obligaciones financieras4PasivoPréstamos/leasing
50Capital5PatrimonioAportes
59Resultados acumulados5PatrimonioCierre
60Compras6GastoCompra mercadería
62Gastos de personal, directores y gerentes6GastoPlanilla
63Gastos de servicios prestados por terceros6GastoFletes, servicios
68Valuación y deterioro de activos y provisiones6GastoDepreciación, deterioro
69Costo de ventas6GastoCOGS
70Ventas7IngresoFacturación
75Otros ingresos de gestión7IngresoDiferencia de cambio, etc.
77Ingresos financieros7IngresoIntereses ganados
CREATE TABLE chart_of_accounts (
  id            BIGSERIAL PRIMARY KEY,
  company_id    BIGINT NOT NULL REFERENCES companies(id),
  code          VARCHAR(12) NOT NULL,           -- '104.1'
  name          VARCHAR(200) NOT NULL,
  class_id      SMALLINT NOT NULL,              -- 1..9
  account_type  VARCHAR(20) NOT NULL,           -- asset|liability|equity|income|expense|order
  normal_side   CHAR(1) NOT NULL,               -- 'D' | 'H'
  is_postable   BOOLEAN NOT NULL DEFAULT false, -- solo hojas reciben asientos
  is_system     BOOLEAN NOT NULL DEFAULT false,
  parent_id     BIGINT REFERENCES chart_of_accounts(id),
  currency      VARCHAR(3),                     -- NULL = multimoneda
  requires_aux  BOOLEAN NOT NULL DEFAULT false, -- exige auxiliar (RUC) p.ej. 12, 42
  fs_caption    VARCHAR(60),                    -- mapeo a rubro de EEFF
  created_at    TIMESTAMPTZ DEFAULT now(),
  UNIQUE (company_id, code)
);

Regla clave: solo cuentas con is_postable = true (hojas del árbol) reciben movimientos. Las cuentas cabecera (10, 12, 42) son agregadoras de reporte.


3. Libro Diario y Libro Mayor (modelo de asiento)

El núcleo es el par journal_entries (cabecera) + journal_entry_lines (detalle). Todo evento contable, sin importar su origen, produce un asiento.

CREATE TABLE journal_entries (
  id            BIGSERIAL PRIMARY KEY,
  company_id    BIGINT NOT NULL,
  branch_id     BIGINT,                         -- multisucursal
  entry_number  VARCHAR(20) NOT NULL,           -- correlativo por libro/periodo
  entry_date    DATE NOT NULL,
  period        CHAR(6) NOT NULL,               -- '202606' (YYYYMM)
  book_type     VARCHAR(20) NOT NULL,           -- diario|compras|ventas|caja
  source_type   VARCHAR(30),                    -- Invoice|Purchase|Payroll|Manual
  source_id     BIGINT,                         -- polimórfico al doc origen
  description   TEXT,
  currency      VARCHAR(3) NOT NULL DEFAULT 'PEN',
  exchange_rate NUMERIC(12,6) NOT NULL DEFAULT 1,
  status        VARCHAR(12) NOT NULL DEFAULT 'draft', -- draft|posted|voided
  posted_at     TIMESTAMPTZ,
  posted_by     BIGINT,
  UNIQUE (company_id, book_type, period, entry_number)
);

CREATE TABLE journal_entry_lines (
  id              BIGSERIAL PRIMARY KEY,
  journal_entry_id BIGINT NOT NULL REFERENCES journal_entries(id),
  account_id      BIGINT NOT NULL REFERENCES chart_of_accounts(id),
  debit_fc        NUMERIC(16,2) NOT NULL DEFAULT 0, -- funcional (PEN)
  credit_fc       NUMERIC(16,2) NOT NULL DEFAULT 0,
  debit_oc        NUMERIC(16,2),                    -- moneda origen
  credit_oc       NUMERIC(16,2),
  cost_center_id  BIGINT,
  aux_party_id    BIGINT,                           -- cliente/proveedor (RUC)
  line_description TEXT
);

Constraint de cuadre (defensa en profundidad):

-- Trigger AFTER INSERT/UPDATE: por journal_entry_id, suma debe = haber en FC
CREATE FUNCTION assert_balanced() RETURNS trigger AS $$
DECLARE d NUMERIC; c NUMERIC;
BEGIN
  SELECT SUM(debit_fc), SUM(credit_fc) INTO d, c
  FROM journal_entry_lines WHERE journal_entry_id = NEW.journal_entry_id;
  IF round(d,2) <> round(c,2) THEN
    RAISE EXCEPTION 'Asiento descuadrado: debe=% haber=%', d, c;
  END IF;
  RETURN NEW;
END; $$ LANGUAGE plpgsql;

4. Motor de asientos automáticos (Accounting Templates)

En lugar de cablear lógica contable en cada módulo, ConTodo usa plantillas de asiento parametrizables por tipo de transacción y empresa. Cada plantilla describe qué cuentas mover y con qué fórmula. Esto desacopla la operación de la contabilidad y permite que un contador (no un dev) ajuste mapeos.

PlantillaDisparador (evento)Líneas generadas (debe / haber)
SALE_INVOICE_CREDITVenta a crédito emitidaD 12 Clientes / H 70 Ventas, H 4011 IGV
SALE_COGSSalida de inventario por ventaD 69 Costo de ventas / H 20/21 Existencias
PURCHASE_INVOICEFactura de compra (mercadería)D 60 Compras, D 4011 IGV crédito / H 42 Proveedores
PURCHASE_TO_INVDestino de la compra a almacénD 20/24 Existencias / H 61 Variación de existencias
CUSTOMER_PAYMENTCobro de clienteD 10 Caja/Bancos / H 12 Clientes
SUPPLIER_PAYMENTPago a proveedorD 42 Proveedores / H 10 Caja/Bancos
DETRACTIONDetracción retenida en cobroD 1212 Detracciones / H 12 Clientes (parcial)
PAYROLL_ACCRUALCierre de planillaD 62 Gastos personal / H 41 Remun., H 40 Tributos, H 41 AFP
DEPRECIATIONCorrida mensual de activosD 681 Depreciación / H 39 Deprec. acumulada
FX_DIFFERENCERevaluación de partidas MED/H 67/77 Dif. de cambio / H/D 12/42/10

4.1 Estructura de la plantilla

# AccountingTemplate (parametrizable por company_id)
{
  code: "SALE_INVOICE_CREDIT",
  lines: [
    { account_resolver: "customer_ar_account", side: :debit,  formula: "total_with_tax" },
    { account_resolver: "sales_revenue",        side: :credit, formula: "subtotal" },
    { account_resolver: "vat_payable",          side: :credit, formula: "igv_amount" }
  ]
}

Los account_resolver consultan reglas (por línea de producto, almacén, tipo de operación) para elegir la cuenta divisionaria correcta. El formula opera sobre el contexto del documento origen.

4.2 Ejemplo numérico — venta a crédito con IGV 18% y detracción 12% (servicio)

Venta de S/ 10,000 + IGV. Total S/ 11,800. Detracción 12% sobre total = S/ 1,416 retenida por el cliente y depositada al Banco de la Nación.

Asiento de venta (devengo):

CuentaDebeHaber
12 Clientes11,800.00
70 Ventas10,000.00
4011 IGV por pagar1,800.00

Asiento de cobro con detracción:

CuentaDebeHaber
104 Bancos (neto recibido)10,384.00
1212 Detracciones por cobrar1,416.00
12 Clientes11,800.00

5. Diagrama del flujo de asientos


6. Cuentas por cobrar (CxC) y por pagar (CxP)

Ambos submódulos son subledgers sincronizados con el mayor (cuentas 12 y 42). Cada documento (factura, NC, ND, anticipo) genera partidas abiertas (open items) que se aplican contra cobros/pagos.

CaracterísticaCxC (cuenta 12)CxP (cuenta 42)
Auxiliar obligatorioCliente (RUC)Proveedor (RUC)
Aging buckets0-30 / 31-60 / 61-90 / +90igual
Provisión19 Cobranza dudosa (NIIF 9 — pérdida esperada)
RetencionesDetracción (1212), retención IGVDetracción a depositar, retención 4ta cat.
ReportesEstado de cuenta, antigüedad de saldos, DSOAntigüedad, programación de pagos, DPO

Conciliación subledger ↔ mayor: una tarea Sidekiq nocturna valida que Σ saldos abiertos CxC = saldo cuenta 12 y levanta alerta si difieren (control SOX-like).


7. Activos fijos y depreciación

CREATE TABLE fixed_assets (
  id, company_id, asset_code, name, account_id,    -- 33x
  acquisition_date, acquisition_cost, residual_value,
  useful_life_months, method,                       -- straight_line|declining
  depreciation_account_id,   -- 681
  accumulated_account_id,    -- 39x
  status                     -- active|disposed|fully_depreciated
);
CategoríaVida útil (tributaria SUNAT)Tasa anual máx.
Edificios y construcciones33 años3%
Maquinaria y equipo (industria textil)10 años10%
Vehículos de transporte5 años20%
Equipos de cómputo4 años25%
Muebles y enseres10 años10%

La corrida mensual (DepreciationRunJob) genera un asiento DEPRECIATION por categoría/centro de costo. Se distingue depreciación contable (NIIF, vida útil real) de la tributaria (tasas SUNAT), generando diferencias temporales que alimentan el impuesto diferido (cuenta 37/49).


8. Tesorería

  • Conciliación bancaria automática: importación de extractos (formato banco / Norma 43) y matching por monto+fecha+referencia contra movimientos de la cuenta 104/105.
  • Posición de caja consolidada multimoneda y multiempresa con proyección de flujos (CxC + CxP programadas).
  • Medios de pago Perú: Yape/Plin, transferencias interbancarias (CCI), detracciones (cuenta BN), cheques.
  • Cada movimiento de tesorería confirmado dispara CUSTOMER_PAYMENT o SUPPLIER_PAYMENT.

9. Estados financieros (NIIF)

Los EEFF se construyen mapeando el balance de comprobación a rubros (fs_caption). ConTodo genera los cuatro estados obligatorios:

EstadoNormaMétodo en ConTodo
Estado de Situación FinancieraNIC 1Saldos clases 1-5 a la fecha, clasificados corriente/no corriente
Estado de ResultadosNIC 1Clases 6-7 del periodo; presentación por función (usa clase 9) o naturaleza
Estado de Flujos de EfectivoNIC 7Método indirecto: utilidad + ajustes no monetarios ± variaciones capital de trabajo
Estado de Cambios en el PatrimonioNIC 1Movimientos de clase 5 (capital, reservas, resultados)

9.1 Cierre contable

Proceso mensual/anual: (1) corridas automáticas (depreciación, dif. cambio, provisiones), (2) balance de comprobación, (3) ajustes manuales, (4) asiento de destino de resultados (clase 8 → 59), (5) bloqueo del periodo (period_locked), (6) generación de PLE/SIRE.


10. Cumplimiento SUNAT

ObligaciónCómo lo resuelve ConTodo
PLE (Programa de Libros Electrónicos)Exportador de Libro Diario, Mayor, Registro de Compras y Ventas en formato TXT con estructura/encabezados oficiales
SIRE (Sistema Integrado de Registros Electrónicos)Generación de propuestas RVIE/RCE y conciliación con comprobantes
PCGE 2019Catálogo base obligatorio, mapeo a casillas
Detracciones (SPOT)Cálculo automático por tipo de bien/servicio y cuenta puente 1212
Tipo de cambio SBSJob que ingesta TC compra/venta diario para multimoneda y ajuste de cierre

11. Riesgos y oportunidades

Riesgos

IDRiesgoImpactoMitigación
R1Cambios normativos SUNAT (estructura PLE/SIRE)AltoCapa de exportadores versionada y desacoplada; tests de formato contra esquemas oficiales
R2Descuadre por concurrencia en correlativos de asientoAltoSecuencias por periodo con lock advisory de PostgreSQL; nunca correlativos en aplicación
R3Fuga de datos entre tenants en el mayorCríticoRLS a nivel de motor + company_id en todo índice
R4Diferencias entre depreciación contable y tributaria mal gestionadasMedioModelo de impuesto diferido explícito (NIC 12), doble libro de activos
R5Rendimiento de reportes sobre millones de líneasMedioTablas de saldos agregados (account_balances por periodo) actualizadas por trigger/job, no SUM en caliente
R6Errores de mapeo en plantillas por empresaMedioPlantillas con versión, simulación (dry-run) antes de activar, auditoría de cambios

Oportunidades

IDOportunidadValor
O1Asientos sugeridos por IA: clasificación automática de gastos y predicción de cuenta a partir del históricoReduce trabajo del contador, diferenciador vs. CONCAR/SISCONT
O2Cierre contable asistido: checklist guiado + detección de anomalías (saldos atípicos, partidas antiguas)Acelera cierre de 5 días a horas
O3Conciliación bancaria con ML de matching difusoReduce trabajo manual de tesorería
O4EEFF en tiempo real (drill-down de rubro → cuenta → asiento → documento)Ventaja BI frente a Defontana/StarSoft
O5Multi-GAAP (NIIF + tributario peruano simultáneo) con un solo set de transaccionesHabilita medianas empresas y filiales de multinacionales

12. Alternativas de arquitectura evaluadas

DecisiónOpción elegidaAlternativa descartadaRazón
Generación de asientosPlantillas parametrizables en datosLógica contable hardcodeada por móduloFlexibilidad por empresa, mantenibilidad, configurable por contador
Cuadre de partida dobleConstraint + trigger en BDValidación solo en appDefensa en profundidad; ningún path puede saltarse la regla
Saldos para reportesTabla agregada account_balancesSUM on-the-fly sobre el mayorRendimiento a escala SaaS
Aislamiento tenantRLS de PostgreSQLFiltro solo por scope de ActiveRecordSeguridad a nivel de motor, no confiar solo en el ORM
MultimonedaMonto en origen + funcional por líneaConversión al vuelo en reportesCumple NIC 21 y evita re-cálculos inconsistentes

13. Conclusión

El módulo contable de ConTodo se cimienta en tres pilares: PCGE 2019 como catálogo base extensible, un motor de asientos automáticos basado en plantillas que desacopla la operación de la contabilidad, y un libro mayor con partida doble garantizada por la base de datos. Sobre ese núcleo se construyen CxC/CxP como subledgers conciliados, activos fijos con doble tratamiento (contable/tributario), tesorería con conciliación bancaria, y los cuatro estados financieros NIIF derivados del balance de comprobación. El cumplimiento SUNAT (PLE, SIRE, detracciones, multimoneda SBS) se aísla en una capa de exportadores versionada para resistir cambios normativos. Las oportunidades de IA (asientos sugeridos, cierre asistido, conciliación con ML) y los EEFF en tiempo real con drill-down constituyen el principal diferenciador frente a CONCAR, SISCONT, Defontana y StarSoft en el mercado peruano y LATAM.