Plan de Pruebas — Módulo de Contabilidad

---

Conceptos clave antes de empezar

┌─────────────────┬──────────────────────────────────────────────────────────────────────────────────┐
│ Término │ Qué es en la práctica │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ Ejercicio │ Un año fiscal (ej: "2026") — contiene períodos │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ Período │ Un mes dentro del ejercicio (ej: "Enero 2026") │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ Asiento │ Un registro contable. Siempre tiene dos lados: DEBE y HABER, y deben sumar igual │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ Plan de cuentas │ La lista de "categorías" contables (Caja, Ventas, IVA, etc.) │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ Mapeo │ Qué cuenta del plan corresponde a cada concepto del sistema (Caja → 1.1.1.001) │
└─────────────────┴──────────────────────────────────────────────────────────────────────────────────┘

---

Flujo obligatorio antes de cualquier prueba

1. Cargar Plan de Cuentas → 2. Crear Ejercicio → 3. El período se crea solo → 4. Configurar Mapeo

---

PRUEBA 1 — Cargar Plan de Cuentas Estándar

Dónde: Contabilidad → (banner amarillo)

Pasos:

1. Abrir la página de Contabilidad sin haber configurado nada
2. Verificar que aparece el banner "Plan de cuentas no configurado"
3. Hacer clic en "Cargar Plan Estándar"
4. Esperar respuesta

Resultado esperado:

- El botón muestra spinner mientras carga
- El banner desaparece al terminar
- El pill del header cambia a verde con el número de cuentas (ej: "87 cuentas")
- Tab Plan de Cuentas muestra un árbol con estructura jerárquica:

1. ACTIVO
   1.1 Activo Corriente
   1.1.1 Caja y Bancos
   1.1.1.001 Caja General
2. PASIVO
3. PATRIMONIO
4. INGRESO
5. EGRESO / GASTO

Resultado negativo (si falla):

- Toast rojo con mensaje de error
- El banner sigue visible

---

PRUEBA 2 — Crear Ejercicio y Períodos

Dónde: Contabilidad → tab Ejercicios

Pasos:

1. Hacer clic en el banner azul "Sin período contable" → botón "Crear Ejercicio"
   (debe navegar al tab Ejercicios y abrir el dialog automáticamente)
2. Completar:
   - Año: 2026
   - Marcar "Generar 12 períodos automáticamente"

3. Confirmar

Resultado esperado:

- Aparece la tarjeta del ejercicio con estado ABIERTO
- Al expandirla, muestra 12 períodos (Enero–Diciembre)
- El período que contiene hoy aparece como ABIERTO
- El banner azul desaparece
- El pill "Sin período activo" → cambia a "Período abierto"

Verificar en BD:
SELECT _ FROM cont_ejercicios WHERE empresa_id = 'tu-empresa-id';
SELECT _ FROM cont_periodos ORDER BY fecha_inicio;

---

PRUEBA 3 — Configurar Mapeo de Cuentas

Dónde: Contabilidad → tab Mapeo de Cuentas

Pasos:

1. Para cada concepto, seleccionar la cuenta correspondiente del plan:

┌───────────────────────────┬──────────────────────────┐
│ Concepto │ Cuenta sugerida │
├───────────────────────────┼──────────────────────────┤
│ Ventas gravadas 10% │ 4.1.1.001 Ventas │
├───────────────────────────┼──────────────────────────┤
│ IVA débito fiscal 10% │ 2.1.3.001 IVA Débito │
├───────────────────────────┼──────────────────────────┤
│ Ventas gravadas 5% │ 4.1.1.002 Ventas 5% │
├───────────────────────────┼──────────────────────────┤
│ IVA débito fiscal 5% │ 2.1.3.002 IVA Débito 5% │
├───────────────────────────┼──────────────────────────┤
│ Ventas exentas │ 4.1.1.003 Ventas Exentas │
├───────────────────────────┼──────────────────────────┤
│ Clientes │ 1.1.2.001 Clientes │
├───────────────────────────┼──────────────────────────┤
│ Caja general │ 1.1.1.001 Caja General │
├───────────────────────────┼──────────────────────────┤
│ Inventario │ 1.1.4.001 Inventario │
├───────────────────────────┼──────────────────────────┤
│ Proveedores │ 2.1.1.001 Proveedores │
├───────────────────────────┼──────────────────────────┤
│ IVA crédito 10% │ 1.1.3.001 IVA Crédito │
└───────────────────────────┴──────────────────────────┘

2. Hacer clic en Guardar cambios

⚠️ Los nombres exactos dependen de cómo quedó el seed. Buscá por código o por nombre aproximado.

Resultado esperado:

- Cada concepto muestra el dot verde a la derecha
- Toast: "Mapeo de cuentas actualizado correctamente"
- La barra flotante "cambios sin guardar" desaparece

---

PRUEBA 4 — Crear Asiento Manual

Dónde: Contabilidad → tab Asientos → botón "+ NUEVO ASIENTO"

Escenario: Registrar un pago en efectivo de Gs. 1.000.000 de un cliente.

Pasos:

1. Clic en "+ NUEVO ASIENTO"
2. Completar:
   - Descripción: Cobro en efectivo cliente Juan Pérez
   - Fecha: hoy
   - Período: seleccionar el período actual

3. Agregar líneas:

┌────────────────────────┬────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├────────────────────────┼────────────────┼───────────┼───────────┤
│ 1.1.1.001 Caja General │ Cobro efectivo │ 1.000.000 │ — │
├────────────────────────┼────────────────┼───────────┼───────────┤
│ 1.1.2.001 Clientes │ Juan Pérez │ — │ 1.000.000 │
└────────────────────────┴────────────────┴───────────┴───────────┘

4. Verificar que el indicador de balance muestra verde ("Balanceado ✓")
5. Guardar → el asiento queda en estado BORRADOR
6. Hacer clic en Confirmar

Resultado esperado:

- El asiento en borrador aparece en la lista
- Al confirmar → estado cambia a CONFIRMADO (no se puede editar más)
- Debe = Haber = Gs. 1.000.000

Prueba de validación (debe fallar):

- Intentar guardar con DEBE ≠ HABER → debe mostrar error "El asiento no está balanceado"

---

PRUEBA 5 — Asiento Desbalanceado (validación)

Pasos:

1. Crear nuevo asiento
2. Agregar solo una línea: Caja 500.000 en DEBE
3. Intentar guardar

Resultado esperado:

- El indicador de balance muestra rojo
- El botón de guardar está deshabilitado O muestra error: "DEBE y HABER deben ser iguales"
- El asiento NO se crea en BD

---

PRUEBA 6 — Revertir Asiento

Pasos:

1. Tomar el asiento confirmado de la Prueba 4
2. Buscar opción "Revertir"
3. Confirmar la reversión

Resultado esperado:

- El asiento original cambia a estado REVERTIDO
- Se crea automáticamente un nuevo asiento con las líneas invertidas (lo que era DEBE pasa a HABER y viceversa), en estado CONFIRMADO
- El nuevo asiento tiene descripción tipo: REVERSA: Cobro en efectivo cliente Juan Pérez

---

PRUEBA 7 — Integración Automática: Factura de Venta a CRÉDITO (SIFEN)

Dónde: Ventas → emitir una factura electrónica a crédito → esperar aprobación SIFEN

Escenario: Factura de Gs. 1.100.000 gravada al 10% (base Gs. 1.000.000 + IVA Gs. 100.000), condición de pago CRÉDITO.

Pasos:

1. Emitir la factura electrónica marcando condición CRÉDITO
2. Esperar a que SIFEN la apruebe (estado "Aprobado")
3. Ir a Contabilidad → tab Asientos y buscar el asiento generado

Resultado esperado — asiento generado automáticamente:

┌─────────────────────────┬──────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 1.1.2.001 Clientes │ Clientes │ 1.100.000 │ — │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 4.1.1.001 Ventas 10% │ Ventas 10% │ — │ 1.000.000 │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 2.1.3.001 IVA Débito 10%│ IVA Débito 10% │ — │ 100.000 │
└─────────────────────────┴──────────────────┴───────────┴───────────┘

- Tipo del documento contable: FACTURA_VENTA_CREDITO
- Glosa: "Factura venta (crédito) N° 001-001-0000001"
- Estado: CONFIRMADO (no requiere intervención manual)

Verificar en BD:
SELECT tipo, numero_documento, estado FROM cont_documentos WHERE origen_tipo = 'factura_cab' AND origen_id = '<id>';

---

PRUEBA 8 — Integración Automática: Factura de Venta al CONTADO (SIFEN)

Escenario: Misma factura pero con condición de pago CONTADO.

Resultado esperado — asiento generado automáticamente:

┌─────────────────────────┬──────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 1.1.1.001 Caja General │ Caja (contado) │ 1.100.000 │ — │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 4.1.1.001 Ventas 10% │ Ventas 10% │ — │ 1.000.000 │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 2.1.3.001 IVA Débito 10%│ IVA Débito 10% │ — │ 100.000 │
└─────────────────────────┴──────────────────┴───────────┴───────────┘

- Tipo del documento contable: FACTURA_VENTA_CONTADO
- Diferencia clave vs crédito: la contraparte es Caja, no Clientes

---

PRUEBA 9 — Integración Automática: Nota de Crédito Electrónica (SIFEN)

Dónde: Ventas → emitir nota de crédito electrónica sobre una factura aprobada

Escenario: Nota de crédito de Gs. 1.100.000 (misma factura de la Prueba 7).

Pasos:

1. Emitir la nota de crédito electrónica
2. Esperar aprobación SIFEN
3. Ir a Contabilidad → tab Asientos

Resultado esperado — asiento de NC (inverso a la venta):

┌─────────────────────────┬──────────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 4.1.1.001 Ventas 10% │ Devolución ventas 10%│ 1.000.000 │ — │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 2.1.3.001 IVA Débito 10%│ Reversión IVA 10% │ 100.000 │ — │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 1.1.2.001 Clientes │ Clientes │ — │ 1.100.000 │
└─────────────────────────┴──────────────────────┴───────────┴───────────┘

- Tipo: NOTA_CREDITO
- La NC reduce la deuda del cliente (HABER Clientes) y reversa ventas/IVA

---

PRUEBA 10 — Reversión Automática por Cancelación SIFEN (ECAN)

Escenario: Una factura aprobada (con asiento generado) es anulada mediante evento ECAN.

Pasos:

1. Verificar que la factura tiene asiento contable en estado CONFIRMADO
2. Anular la factura desde el panel SIFEN (evento ECAN)
3. Ir a Contabilidad → tab Asientos

Resultado esperado:

- El asiento original pasa a estado REVERTIDO
- Se crea automáticamente un asiento de reversión con líneas invertidas, en estado CONFIRMADO
- No requiere intervención manual del contador

Verificar en BD:
SELECT a.estado, a.es_reversa FROM cont_asientos a
JOIN cont_documentos d ON d.id = a.documento_id
WHERE d.origen_id = '<id-factura>';

---

PRUEBA 11 — Integración Automática: Factura de Compra

Dónde: Compras → registrar una compra

Escenario: Compra de Gs. 1.100.000 (base Gs. 1.000.000 + IVA 10% Gs. 100.000).

11A — Compra a CRÉDITO:

┌─────────────────────────┬──────────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 1.1.4.001 Inventario │ Inventario/Gasto │ 1.000.000 │ — │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 1.1.3.001 IVA Crédito │ IVA Crédito 10% │ 100.000 │ — │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 2.1.1.001 Proveedores │ Proveedor │ — │ 1.100.000 │
└─────────────────────────┴──────────────────────┴───────────┴───────────┘

- Tipo: FACTURA_COMPRA_CREDITO

11B — Compra al CONTADO:

┌─────────────────────────┬──────────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 1.1.4.001 Inventario │ Inventario/Gasto │ 1.000.000 │ — │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 1.1.3.001 IVA Crédito │ IVA Crédito 10% │ 100.000 │ — │
├─────────────────────────┼──────────────────────┼───────────┼───────────┤
│ 1.1.1.001 Caja General │ Caja (contado) │ — │ 1.100.000 │
└─────────────────────────┴──────────────────────┴───────────┴───────────┘

- Tipo: FACTURA_COMPRA_CONTADO
- Diferencia: Caja al HABER en vez de Proveedores

---

PRUEBA 11C — Factura de Venta/Compra en MONEDA EXTRANJERA

Escenario: Factura emitida en USD de $ 100 con cotización $ 1 = ₲ 7.850 (guardada en el documento).
Total en guaraníes = ₲ 785.000 (el sistema convierte automáticamente usando la cotización del documento).

⚠️ Diferencia importante entre dos cotizaciones del sistema:

┌─────────────────────────┬────────────────────────────────────────────────────────────────────────┐
│ cotizacion_moneda │ La tasa cargada en Configuración → Monedas. Se usa al EMITIR │
│ (tabla configuración) │ la factura para mostrar precios en moneda extranjera y calcular totales │
├─────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ cont_tipo_cambio │ La tasa del tab Contabilidad → Tipo de Cambio. La usa el módulo │
│ (tabla contabilidad) │ contable para convertir asientos en moneda extranjera a guaraníes │
└─────────────────────────┴────────────────────────────────────────────────────────────────────────┘

⚠️ Para facturas y compras: el sistema usa la cotización GUARDADA EN EL DOCUMENTO al momento de emisión
(campo dticam en factura_cab / campo cotizacion en compra_cab), NO la del tab Tipo de Cambio.
El tab Tipo de Cambio es para asientos manuales en moneda extranjera.

Pasos:

1. Ir a Configuración → Monedas, verificar que USD esté habilitado con cotización cargada
2. Emitir una factura de venta seleccionando moneda USD, con cotización ₲ 7.850
3. Esperar aprobación SIFEN
4. Ir a Contabilidad → Asientos y buscar el asiento generado

Resultado esperado — asiento con importes convertidos a ₲:

┌──────────────────────────┬──────────────────┬─────────┬─────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├──────────────────────────┼──────────────────┼─────────┼─────────┤
│ 1.1.2.001 Clientes │ Clientes │ 785.000 │ — │
├──────────────────────────┼──────────────────┼─────────┼─────────┤
│ 4.1.1.001 Ventas 10% │ Ventas 10% │ — │ 713.636 │
├──────────────────────────┼──────────────────┼─────────┼─────────┤
│ 2.1.3.001 IVA Débito 10% │ IVA Débito 10% │ — │ 71.364 │
└──────────────────────────┴──────────────────┴─────────┴─────────┘

- La glosa del asiento incluye la cotización aplicada: "Factura venta (crédito) N° 001-001-0000003 [USD x 7850]"
- Todos los importes en el asiento están en guaraníes (PYG)

Verificar en BD:
SELECT glosa FROM cont_asientos WHERE id = '<id>';
-- Debe mostrar el sufijo [USD x 7850]

---

PRUEBA 12 — Cobro de Cuota (Recibo)

Escenario: Se cobra una cuota de Gs. 500.000 de un cliente con deuda pendiente.

Resultado esperado — asiento automático:

┌─────────────────────────┬──────────────────┬─────────┬─────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────┼─────────┼─────────┤
│ 1.1.1.001 Caja General │ Caja cobranza │ 500.000 │ — │
├─────────────────────────┼──────────────────┼─────────┼─────────┤
│ 1.1.2.001 Clientes │ Clientes │ — │ 500.000 │
└─────────────────────────┴──────────────────┴─────────┴─────────┘

Nota: El cobro siempre usa Caja — no hay variante contado/crédito aquí.

---

PRUEBA 13 — Pago a Proveedor

Escenario: Se paga Gs. 1.100.000 al proveedor (cancela la deuda de la compra a crédito).

Resultado esperado — asiento automático:

┌─────────────────────────┬──────────────────┬───────────┬───────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 2.1.1.001 Proveedores │ Proveedor │ 1.100.000 │ — │
├─────────────────────────┼──────────────────┼───────────┼───────────┤
│ 1.1.1.001 Caja General │ Caja │ — │ 1.100.000 │
└─────────────────────────┴──────────────────┴───────────┴───────────┘

Nota: El pago siempre reduce la deuda con el proveedor (DEBE) y sale de Caja (HABER).

---

PRUEBA 4B — Asiento Manual en Moneda Extranjera (USD)

Dónde: Contabilidad → tab Asientos → Nuevo Asiento Manual

Prerrequisito: Tener registrada la tasa USD en el tab Tipo de Cambio (ej: 1 USD = ₲ 7.850).

Escenario: Registrar un gasto de $ 100 USD en concepto de suscripción de software.

Pasos:

1. Abrir "Nuevo Asiento Manual"
2. Cambiar el selector "Moneda" de PYG → USD
3. Verificar que aparece el banner azul: "Importes en USD. Tasa: 1 USD = ₲ 7.850,00"
4. Completar fecha y período
5. Agregar líneas (los importes se ingresan en USD):

┌──────────────────────────┬─────────────────────┬────────┬────────┐
│ Cuenta │ Descripción │ Debe │ Haber │
├──────────────────────────┼─────────────────────┼────────┼────────┤
│ 5.x.x.001 Gastos Softw. │ Suscripción mensual │ 100,00 │ — │
├──────────────────────────┼─────────────────────┼────────┼────────┤
│ 1.1.1.001 Caja General │ Pago en USD │ — │ 100,00 │
└──────────────────────────┴─────────────────────┴────────┴────────┘

6. Verificar que el BalanceBar muestra "USD 100,00 / USD 100,00 — Balanceado ✓"
7. Crear y Confirmar

Resultado esperado:

- El asiento aparece en la lista con badge "USD" junto a la glosa
- Al expandir, las columnas Debe/Haber muestran los valores convertidos a ₲:
  Debe: Gs. 785.000 / Haber: Gs. 785.000 (100 × 7.850)
- El total del asiento en la lista también muestra en ₲

Prueba sin tasa registrada (debe fallar):

1. Cambiar moneda a EUR sin tener tasa de EUR registrada
2. Verificar que aparece banner naranja: "Sin tasa registrada para EUR..."
3. Verificar que los botones "Guardar borrador" y "Crear y Confirmar" están deshabilitados

Verificar en BD:
SELECT moneda_origen, total_debe_pyg, total_haber_pyg FROM cont_asientos WHERE id = '<id>';
-- moneda_origen = 'USD', total_debe_pyg = 785000, total_haber_pyg = 785000

---

PRUEBA 4C — Asiento Manual con Centros de Costo

Dónde: Contabilidad → tab Asientos → Nuevo Asiento Manual

Prerrequisito: Tener al menos un centro de costo creado y activo (ej: ADMIN, VENTAS).

Escenario: Registrar un gasto de luz Gs. 500.000 y asignarlo al área de Administración.

Pasos:

1. Abrir "Nuevo Asiento Manual"
2. Agregar líneas y notar que ahora aparece la columna "C. Costo" en cada fila:

┌──────────────────────────┬───────────────┬─────────┬─────────┬─────────────┐
│ Cuenta │ Descripción │ Debe │ Haber │ C. Costo │
├──────────────────────────┼───────────────┼─────────┼─────────┼─────────────┤
│ 5.x.x.002 Gastos Luz │ Factura ANDE │ 500.000 │ — │ ADMIN │
├──────────────────────────┼───────────────┼─────────┼─────────┼─────────────┤
│ 1.1.1.001 Caja General │ Pago efectivo │ — │ 500.000 │ (ninguno) │
└──────────────────────────┴───────────────┴─────────┴─────────┴─────────────┘

3. En la línea del gasto, seleccionar "ADMIN — Administración y RRHH" en el selector C. Costo
4. En la línea de caja, dejar C. Costo en "Ninguno" (es opcional)
5. Crear y Confirmar

Resultado esperado:

- El asiento se crea correctamente
- Al expandir el asiento en la lista, la columna C. Costo muestra "ADMIN" en la primera línea y "—" en la segunda
- La columna C. Costo solo aparece en el formulario si hay centros creados; si no hay ninguno, el selector no se muestra

Nota: Si no hay centros de costo creados, el selector C. Costo no aparece en el formulario.
Creá al menos uno desde el tab Centros de Costo antes de probar esta funcionalidad.

Verificar en BD:
SELECT l.cuenta_id, l.centro_costo_id, l.debe_pyg, l.haber_pyg
FROM cont_lineas_asiento l WHERE l.asiento_id = '<id>';
-- La línea del gasto debe tener centro_costo_id != null

---

PRUEBA 13C — Centros de Costo: CRUD y aplicación en asientos

Dónde: Contabilidad → tab Centros de Costo

Contexto: Los centros de costo no afectan la mecánica contable (DEBE/HABER) — son una capa de
clasificación adicional para poder analizar los gastos e ingresos por área, proyecto o departamento.

13C.1 — CRUD básico

Pasos:

1. Crear un centro: código "ADMIN", descripción "Administración General"
2. Crear un centro: código "VENTAS", descripción "Fuerza de Ventas"
3. Verificar que aparecen en la tabla con código en naranja y dot verde (activo)
4. Editar "ADMIN" → cambiar descripción a "Administración y RRHH" → Guardar
5. Desactivar "VENTAS" con el toggle → verificar que el dot cambia a gris
6. Intentar eliminar "ADMIN" → si no tiene asientos asignados, debe eliminarse
7. Intentar eliminar un centro con asientos → debe retornar error del servidor

13C.2 — Dónde aplica (asiento manual con centro de costo)

Escenario: Registrar un gasto de luz de Gs. 500.000 y cargarlo al centro "ADMIN".

Pasos:

1. Ir a Asientos → Nuevo asiento manual
2. Completar el asiento:

┌──────────────────────────┬───────────────────┬─────────┬─────────┐
│ Cuenta │ Descripción │ DEBE │ HABER │
├──────────────────────────┼───────────────────┼─────────┼─────────┤
│ 5.1.1.001 Gastos Luz │ Factura ANDE │ 500.000 │ — │
├──────────────────────────┼───────────────────┼─────────┼─────────┤
│ 1.1.1.001 Caja General │ Pago en efectivo │ — │ 500.000 │
└──────────────────────────┴───────────────────┴─────────┴─────────┘

3. Seleccionar Centro de Costo: "ADMIN — Administración y RRHH"
4. Guardar y Confirmar

Resultado esperado:

- El asiento queda asociado al centro "ADMIN"
- En el Libro Diario, el asiento muestra el centro de costo asignado
- Los reportes futuros podrán filtrar por centro → permite saber cuánto gasta cada área

Nota: En la versión actual el filtro por centro de costo en reportes es una mejora pendiente.
El campo ya se guarda correctamente para uso futuro.

---

PRUEBA 13D — Tipo de Cambio: registro y verificación

Dónde: Contabilidad → tab Tipo de Cambio

Contexto importante — diferencia entre los dos sistemas de cotización:

┌──────────────────────────────┬───────────────────────────────────────────────────────────────┐
│ Configuración → Monedas │ Cotización operativa. Se usa al EMITIR una factura/compra │
│ (cotizacion_moneda) │ en moneda extranjera. Define el precio de venta en USD/BRL/etc │
├──────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ Contabilidad → Tipo de Cambio│ Cotización contable diaria. Se usa en asientos MANUALES en │
│ (cont_tipo_cambio) │ moneda extranjera para convertir a guaraníes al registrar │
└──────────────────────────────┴───────────────────────────────────────────────────────────────┘

En resumen: una factura en USD ya trae su cotización guardada (dticam/cotizacion en el documento).
El tab Tipo de Cambio es para asientos manuales donde el contador ingresa importes en moneda extranjera.

Pasos:

1. Ir al tab Tipo de Cambio
2. Verificar que aparecen las 4 cards (USD, BRL, ARS, EUR) — si no hay registros, muestran "Sin registro"
3. Hacer clic en "Registrar tasa"
4. Completar: Moneda: USD, Fecha: hoy, Tasa: 7.850
5. Guardar

Resultado esperado:

- La card de USD actualiza: "₲ 7.850,00 — [fecha de hoy]"
- El historial muestra la entrada con badge "Hoy"
- Registrar otra tasa con fecha distinta → aparece en el historial ordenado por fecha desc
- Registrar la misma moneda/fecha → debe actualizar (upsert, no duplicar)

Verificar en BD:
SELECT moneda, fecha, tasa FROM cont_tipo_cambio WHERE empresa_id = 'tu-id' ORDER BY fecha DESC;

---

PRUEBA 14 — Reportes Contables

Dónde: Contabilidad → tab Reportes

14A — Libro Diario

Pasos:

1. Seleccionar ejercicio y período actual en el filtro superior
2. Hacer clic en PDF (abre en nueva pestaña) o Excel (descarga archivo)

Resultado esperado:

- El PDF/Excel muestra todos los asientos confirmados del período en orden cronológico
- Cada asiento tiene sus líneas con código de cuenta, descripción, debe y haber
- Total DEBE = Total HABER en cada asiento
- El encabezado muestra el nombre y RUC de la empresa

14B — Balance de Comprobación

Resultado esperado:

- Lista de todas las cuentas que tuvieron movimiento
- Columnas: Cuenta | Sumas Debe | Sumas Haber | Saldo Deudor | Saldo Acreedor
- La suma de Saldo Deudor = Suma de Saldo Acreedor (el sistema cuadra)

14C — Estado de Resultados

Resultado esperado:

- Sección Ingresos (cuentas tipo INGRESO)
- Sección Costos
- Sección Gastos
- Al fondo: Utilidad = Ingresos - Costos - Gastos

14D — Balance General

Resultado esperado:

- Sección Activos (lo que tiene la empresa)
- Sección Pasivos (lo que debe)
- Sección Patrimonio
- Debe cumplir: Activos = Pasivos + Patrimonio
- El sistema muestra indicador "✓ Cuadra" o "✗ No cuadra"

---

PRUEBA 15 — Plan de Cuentas (CRUD)

Dónde: Contabilidad → tab Plan de Cuentas

Buscar cuenta

- Escribir "caja" en el buscador
- Esperado: filtra el árbol mostrando solo las cuentas que contengan "caja"

Editar cuenta

1. Hacer clic sobre una cuenta hoja (que no tenga hijos)
2. Cambiar la descripción
3. Guardar

- Esperado: la descripción se actualiza en el árbol, toast de éxito

Intentar eliminar cuenta con hijos

1. Hacer clic en eliminar sobre una cuenta que tenga sub-cuentas

- Esperado: error "No se puede eliminar una cuenta con sub-cuentas"

Eliminar cuenta hoja

1. Eliminar una cuenta que no tenga sub-cuentas ni movimientos

- Esperado: la cuenta desaparece del árbol, toast de éxito

---

PRUEBA 16 — Cierre de Período

Dónde: Contabilidad → tab Ejercicios → expandir ejercicio

Pasos:

1. Localizar un período abierto
2. Hacer clic en "Cerrar período"
3. Confirmar

Resultado esperado:

- El período cambia a estado CERRADO
- Ya no aparece como "período activo"
- No se pueden crear asientos con fecha dentro de ese período
- El botón "Reabrir" aparece disponible

---

PRUEBA 17 — Permisos (control de acceso)

Escenario: Verificar que los botones de acción respetan los permisos asignados al perfil del usuario.

Pasos:

1. Iniciar sesión con un usuario que tenga solo el permiso CONT_VER
2. Ir a Contabilidad

Resultado esperado:

- El tab Plan de Cuentas NO muestra botones de edición/eliminación/seed
- El tab Asientos NO muestra el botón "+ Nuevo Asiento", ni "Confirmar" ni "Revertir"
- El tab Ejercicios NO muestra "Nuevo Ejercicio", ni botones de cerrar/reabrir/bloquear
- El tab Mapeo de Cuentas NO muestra el botón "Guardar cambios"
- El tab Reportes SÍ es visible (CONT_VER alcanza para ver reportes solo si tiene CONT_VER_REPORTES también)

3. Intentar llamar directamente al endpoint (ej: POST /contabilidad/plan-cuentas) sin el permiso → debe retornar 403 Forbidden.

---

---

ESTADO DE IMPLEMENTACIÓN CONSOLIDADO (actualizado 2026-04-19)

┌─────────────────────────────────────────────────────┬──────────────────┬────────────────────────────────────────────────────────┐
│ Funcionalidad │ Estado │ Detalle │
├─────────────────────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────┤
│ Plan de Cuentas (seed + CRUD) │ ✅ Implementado │ Frontend + backend completo │
│ Ejercicios y Períodos │ ✅ Implementado │ Crear/cerrar/reabrir/bloquear │
│ Mapeo de Cuentas │ ✅ Implementado │ 10 conceptos mapeables │
│ Asientos manuales (crear/confirmar/revertir) │ ✅ Implementado │ Con moneda, centros de costo │
│ Integración SIFEN — factura venta contado/crédito │ ✅ Implementado │ Usa condicion_operacion + dticam │
│ Integración SIFEN — factura compra contado/crédito │ ✅ Implementado │ Usa condicion_operacion + cotizacion │
│ Integración SIFEN — nota de crédito │ ✅ Implementado │ Asiento inverso a la venta │
│ Integración SIFEN — cancelación ECAN │ ✅ Implementado │ Reversión automática │
│ Integración — cobro de cuota (recibo) │ ✅ Implementado │ Caja DEBE / Clientes HABER │
│ Integración — pago a proveedor │ ✅ Implementado │ Proveedores DEBE / Caja HABER │
│ Multi-moneda en asientos manuales │ ✅ Implementado │ USD/BRL/ARS/EUR con tipo de cambio │
│ Multi-moneda en integración facturas/compras │ ✅ Implementado │ Usa dticam/cotizacion del documento │
│ Centros de Costo (CRUD) │ ✅ Implementado │ Frontend + backend │
│ Centros de Costo en asientos manuales │ ✅ Implementado │ Selector por línea, opcional │
│ Tipo de Cambio (tab contable diario) │ ✅ Implementado │ Frontend + backend, 4 monedas │
│ Reportes — Libro Diario (PDF + Excel) │ ✅ Implementado │ Filtro por ejercicio/período/rango │
│ Reportes — Balance de Comprobación (PDF + Excel) │ ✅ Implementado │ Con preview inline │
│ Reportes — Estado de Resultados (PDF) │ ✅ Implementado │ Con preview inline │
│ Reportes — Balance General (PDF) │ ✅ Implementado │ Con indicador de cuadre │
│ Reportes — Libro Mayor (UI) │ ✅ Implementado │ Card con Autocomplete en ReportesContablesTab │
│ Libro IVA Ventas │ ✅ Implementado │ Número SET, CDC, filtro estado_sifen Aprobado │
│ Libro IVA Compras │ ✅ Implementado │ GET /compras/libro-iva-compras + ReporteLibroIVACompras │
│ Liquidación de IVA │ ✅ Implementado │ GET /facturas/liquidacion-iva + ReporteLiquidacionIVA │
│ Reportes — Filtro por Centro de Costo │ ✅ Implementado │ Selector CC en ReportesContablesTab; filtra Libro Diario y Libro Mayor │
│ Link a Reportes Contables desde Centro de Reportes │ ✅ Implementado │ Sección "Contabilidad Financiera" en Reportes.jsx con permiso CONT_VER_REPORTES │
└─────────────────────────────────────────────────────┴──────────────────┴────────────────────────────────────────────────────────┘

---

DECISIÓN ARQUITECTÓNICA — Reportes Contables

Los reportes contables (Libro Diario, Balance de Comprobación, Estado de Resultados, Balance General,
Libro Mayor) QUEDAN en el módulo de Contabilidad → tab Reportes.

Razón: dependen de ejercicios/períodos contables, estado de asientos y plan de cuentas. En todos
los ERPs profesionales estos reportes viven dentro del módulo contable.

Acción pendiente: agregar en Centro de Reportes una sección "Contabilidad Financiera" con shortcuts
que naveguen a Contabilidad → tab Reportes (sin mover el componente).

---

DECISIÓN ARQUITECTÓNICA — Reportes Fiscales vs. Reportes Contables

Los libros IVA y la liquidación IVA son REPORTES FISCALES, no contables:

- Se generan desde factura_cab y compra_cab (datos SIFEN), NO desde cont_asientos_det
- El SET pide el detalle factura por factura con CDC, RUC, montos desagregados
- Pertenecen en Centro de Reportes → Fiscal e Impuestos (ubicación actual correcta)

Control de consistencia: el IVA total del Libro IVA Ventas DEBE igualar el saldo de la cuenta
"IVA Débito Fiscal" en el Balance de Comprobación del mismo período. Si no cuadra, hay un
asiento mal registrado o una factura sin integrar.

---

PRUEBA 14E — Libro Mayor (PENDIENTE IMPLEMENTAR UI)

Dónde: Contabilidad → tab Reportes → card "Libro Mayor" (a agregar)

El Libro Mayor muestra todos los movimientos de UNA cuenta específica en un período,
con saldo acumulado. Es el complemento del Libro Diario: el Diario por asiento, el Mayor por cuenta.

Pasos:

1. En el tab Reportes, seleccionar cuenta (ej: 1.1.1.001 Caja General)
2. Seleccionar ejercicio/período o rango de fechas
3. Clic en PDF

Resultado esperado:

- Listado cronológico de todos los asientos que afectaron esa cuenta
- Columnas: Fecha | Asiento | Descripción | Debe | Haber | Saldo acumulado
- Saldo final = Saldo inicial + Σ Debe - Σ Haber (para cuentas de naturaleza deudora)

Nota técnica: el endpoint GET /contabilidad/reportes/libro-mayor/:cuentaId ya existe en el backend.
Solo falta la card con selector de cuenta en el frontend.

---

AUDITORÍA — Libro IVA Ventas (Reportes → Fiscal e Impuestos)

Estado actual: PARCIALMENTE CORRECTO — requiere correcciones antes de usar para declarar al SET.

Gaps identificados vs. requisitos SET Paraguay:

┌─────┬───────────────────────────────────────────┬──────────────────────────────────────────────────────────────────┐
│ # │ Gap │ Corrección │
├─────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ 1 │ Número de factura incompleto │ Cambiar dnumdoc → `${dest}-${dpunexp}-${dnumdoc}` en service │
│ │ Solo muestra "0000001" │ El SET exige formato "001-001-0000001" │
├─────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ 2 │ Notas de Débito NO incluidas (CRÍTICO) │ Consultar nota_debito_cab + nota_debito_subtotal │
│ │ Subestima el IVA débito si existen ND │ Los montos de ND SUMAN (no restan) al débito fiscal │
│ │ │ Fórmula correcta: IVA = Facturas - NC + ND │
├─────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ 3 │ Filtro estado SIFEN incorrecto │ Cambiar `estado: { not: 'Anulada' }` por `estado: 'APROBADO'` │
│ │ Puede incluir facturas rechazadas │ Solo documentos aprobados por SIFEN van al libro IVA │
├─────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ 4 │ CDC no expuesto en detalle │ Agregar campo `cdc` al detalle de cada comprobante │
│ │ │ Permite trazabilidad con consultas SIFEN │
└─────┴───────────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘

Lo que SÍ está correcto:

- Base gravada 10%/5%/Exentas: campos SIFEN correctos (dbasegrav10, dbasegrav5, dsubexe)
- IVA 10%/5%: campos correctos (dliqtotiva10, dliqtotiva5)
- Notas de crédito incluidas y restan correctamente
- Facturas anuladas excluidas
- Multimoneda soportado
- Export CSV disponible

---

PRUEBA 18 — Libro IVA Compras

Dónde: Reportes → Fiscal e Impuestos → Libro IVA Compras

Prerrequisito: Tener al menos una compra registrada y NO anulada en el período seleccionado.

Pasos:

1. Abrir Reportes → Fiscal e Impuestos → Libro IVA Compras
2. Seleccionar el mes y año del período con compras
3. Verificar que el resumen muestra:
   - Cantidad de compras del período
   - IVA Crédito 10% y 5% por separado
   - Total IVA Crédito (en verde)
4. Verificar la tabla de detalle con columnas: Fecha | Número | Timbrado | Proveedor | RUC | Grav. 10% | Grav. 5% | Exentas | IVA 10% | IVA 5% | Total
5. Clic en "Exportar" → descarga CSV
6. Abrir el CSV y verificar que los importes cuadran con los de pantalla

Resultado esperado:

- Número de factura muestra formato proveedor: "001-001-0000001" (establecimiento-punto-número)
- Timbrado del proveedor visible
- RUC del proveedor con dígito verificador
- Total IVA Crédito en el encabezado coincide con la suma de la columna IVA 10% + IVA 5% en el detalle
- Compras anuladas NO aparecen en el listado

Verificar en BD:
SELECT SUM(total_iva_10), SUM(total_iva_5) FROM compra_cab
WHERE empresa_id = 'tu-id' AND EXTRACT(MONTH FROM fecha_emision) = <mes>
  AND EXTRACT(YEAR FROM fecha_emision) = <anio> AND anulado = false;
-- Debe coincidir con lo mostrado en pantalla

---

PRUEBA 19 — Liquidación de IVA

Dónde: Reportes → Fiscal e Impuestos → Liquidación de IVA

Contexto: La Liquidación consolida Libro IVA Ventas y Libro IVA Compras para determinar
si la empresa debe pagar IVA al SET o tiene crédito fiscal a favor.

Fórmula: IVA Débito (ventas netas) − IVA Crédito (compras) = Saldo IVA

Pasos:

1. Abrir Reportes → Fiscal e Impuestos → Liquidación de IVA
2. Seleccionar el mismo mes y año usado en Prueba 14A y Prueba 18
3. Verificar el panel superior "Resultado":
   - Si IVA Débito > IVA Crédito → muestra "IVA a Ingresar al SET" en rojo
   - Si IVA Débito < IVA Crédito → muestra "Crédito Fiscal a Favor" en verde
   - Si IVA Débito = IVA Crédito → muestra "IVA Compensado"
4. Expandir la ayuda (ícono ?) → verificar que la fórmula muestra valores reales del período
5. Verificar el cuadro de liquidación inferior:
   - Columna "Débito" muestra valores del Libro IVA Ventas
   - Columna "Crédito" muestra valores del Libro IVA Compras
   - Columna "Saldo" muestra la diferencia (entre paréntesis si es a favor)
6. Hacer clic en "Libro IVA Ventas" y "Libro IVA Compras" (botones de acceso rápido) → verifica navegación

Resultado esperado:

┌──────────────────────────────┬───────────────┐
│ Concepto                     │ Valor         │
├──────────────────────────────┼───────────────┤
│ IVA Débito 10%               │ Gs. X         │
│ IVA Débito 5%                │ Gs. Y         │
│ Total IVA Débito             │ Gs. X+Y       │
│ IVA Crédito 10%              │ (Gs. A)       │
│ IVA Crédito 5%               │ (Gs. B)       │
│ Total IVA Crédito            │ (Gs. A+B)     │
│ SALDO TOTAL IVA              │ Gs. X+Y-A-B   │
└──────────────────────────────┴───────────────┘

Prueba de consistencia (CRÍTICA):
- Anotar el "Saldo Total IVA" de la Liquidación
- Ir a Contabilidad → tab Reportes → Balance de Comprobación del mismo período
- Buscar la cuenta "IVA Débito Fiscal" o "IVA por Pagar"
- El saldo de esa cuenta DEBE coincidir con el Saldo IVA de la Liquidación
- Si no cuadra: hay facturas sin integrar contablemente o asientos manuales incorrectos

Verificar en BD:
-- IVA Débito (ventas)
SELECT SUM(dliqtotiva10), SUM(dliqtotiva5) FROM factura_cab
WHERE empresa_id = 'tu-id' AND estado_sifen = 'Aprobado'
  AND EXTRACT(MONTH FROM dfeemide) = <mes> AND EXTRACT(YEAR FROM dfeemide) = <anio>;

-- IVA Crédito (compras)
SELECT SUM(total_iva_10), SUM(total_iva_5) FROM compra_cab
WHERE empresa_id = 'tu-id' AND anulado = false
  AND EXTRACT(MONTH FROM fecha_emision) = <mes> AND EXTRACT(YEAR FROM fecha_emision) = <anio>;

---

Checklist de "todo funciona"

MÓDULO CONTABILIDAD

[ ] Banner desaparece tras cargar el plan de cuentas
[ ] Pill del header muestra verde con cantidad de cuentas
[ ] Ejercicio creado con 12 períodos
[ ] Período actual aparece como activo
[ ] Mapeo guardado sin errores (todos los conceptos con dot verde)
[ ] Asiento balanceado se crea en BORRADOR
[ ] Asiento desbalanceado es rechazado
[ ] Asiento confirmado no se puede editar
[ ] Asiento revertido genera contraasiento automático
[ ] Factura venta CRÉDITO → asiento con Clientes al DEBE (tipo FACTURA_VENTA_CREDITO)
[ ] Factura venta CONTADO → asiento con Caja al DEBE (tipo FACTURA_VENTA_CONTADO)
[ ] Factura compra CRÉDITO → asiento con Proveedores al HABER (tipo FACTURA_COMPRA_CREDITO)
[ ] Factura compra CONTADO → asiento con Caja al HABER (tipo FACTURA_COMPRA_CONTADO)
[ ] Nota de crédito aprobada → asiento inverso a la venta (Ventas/IVA al DEBE, Clientes al HABER)
[ ] Cancelación SIFEN (ECAN) → asiento original REVERTIDO + contraasiento automático
[ ] Cobro de cuota → asiento Caja DEBE / Clientes HABER
[ ] Pago proveedor → asiento Proveedores DEBE / Caja HABER
[ ] Balance de Comprobación: Saldo Deudor = Saldo Acreedor
[ ] Balance General: Activos = Pasivos + Patrimonio
[ ] PDF se abre en nueva pestaña con datos de la empresa
[ ] Excel se descarga correctamente
[ ] Búsqueda en Plan de Cuentas filtra el árbol
[ ] Usuario sin permiso no ve botones de acción (frontend)
[ ] Endpoint protegido retorna 403 sin el permiso correcto (backend)
[ ] Centro de costo: crear/editar/desactivar funciona correctamente
[ ] Centro de costo: no se puede eliminar uno con asientos asignados
[ ] Tipo de cambio USD: registrar tasa del día actualiza la card
[ ] Tipo de cambio: misma moneda/fecha registrada dos veces → upsert, no duplicado
[ ] Factura en USD → asiento generado con importes en ₲ (total × cotización del documento)
[ ] Glosa del asiento en moneda extranjera incluye "[USD x 7850]"
[ ] Asiento manual USD: banner azul muestra tasa vigente al seleccionar moneda
[ ] Asiento manual USD sin tasa registrada: botones guardar deshabilitados + banner naranja
[ ] Asiento manual USD: totales en BalanceBar muestran en USD, asiento guardado en ₲
[ ] Asiento manual USD: badge "USD" visible en la lista de asientos
[ ] Asiento con C. Costo: selector aparece solo si hay centros de costo creados
[ ] Asiento con C. Costo: línea guarda centro_costo_id correctamente en BD
[ ] Vista expandida de asiento: columna C. Costo muestra código o "—" por línea

---

PRUEBA 20 — Filtro por Centro de Costo en Reportes Contables

Dónde: Contabilidad → tab Reportes

Prerrequisito: Tener al menos un Centro de Costo creado y activado (tab Centros de Costo).
Tener asientos con líneas asignadas a ese centro.

Pasos:

1. Ir a Contabilidad → tab Reportes
2. Verificar que el selector "Centro de Costo" aparece en los filtros (solo si hay centros activos)
3. En Libro Diario: seleccionar un centro de costo → verificar que solo aparecen asientos con al menos una línea de ese CC
4. Cambiar a "Todos los centros" → verificar que vuelven todos los asientos
5. Descargar PDF/Excel con filtro CC activo → verificar que el encabezado del documento indica el CC
6. En Libro Mayor: seleccionar cuenta + CC → verificar que los movimientos son solo de ese CC
7. En Balance de Comprobación: verificar que el selector CC NO aparece (no aplica a ese reporte)

Resultado esperado:
- El selector aparece automáticamente al detectar centros activos — no requiere configuración
- Libro Diario filtra a nivel asiento: si una línea del asiento pertenece al CC, el asiento completo aparece
- Libro Mayor filtra a nivel línea: solo las líneas con ese centro_costo_id
- Excel de Libro Diario incluye columna "Centro de Costo" con "código — descripción" o vacío

Verificar en BD:
-- Asientos que tienen al menos una línea del CC
SELECT a.numero, a.fecha FROM cont_asientos a
WHERE a.empresa_id = 'tu-id'
  AND EXISTS (
    SELECT 1 FROM cont_asientos_det d
    WHERE d.asiento_id = a.id AND d.centro_costo_id = 'tu-cc-id'
  );

---

MEJORAS IMPLEMENTADAS ✅
[x] Filtro por Centro de Costo: selector en ReportesContablesTab — filtra Libro Diario y Libro Mayor
[x] Centro de Reportes: sección "Contabilidad Financiera" en Reportes.jsx con 5 links y permiso CONT_VER_REPORTES

CENTRO DE COSTO — VALIDACIONES PENDIENTES (Prueba 20)
[ ] Filtro CC en Libro Diario: solo asientos con ≥1 línea del CC seleccionado (Prueba 20)
[ ] Filtro CC en Libro Mayor: solo líneas con el CC, saldo acumulado correcto (Prueba 20)
[ ] Excel Libro Diario con CC activo: columna "Centro de Costo" con datos (Prueba 20)
[ ] Selector CC no aparece en Balance de Comprobación (Prueba 20)
[ ] "Todos los centros" restaura el reporte completo (Prueba 20)

FISCAL E IMPUESTOS — YA IMPLEMENTADO ✅
[x] Libro IVA Ventas: número formato SET (001-001-0000001), filtro estado_sifen Aprobado, CDC expuesto
[x] Libro IVA Compras: endpoint GET /compras/libro-iva-compras, página ReporteLibroIVACompras
[x] Liquidación de IVA: endpoint GET /facturas/liquidacion-iva, página ReporteLiquidacionIVA
[x] Libro Mayor: card con selector de cuenta en ReportesContablesTab

FISCAL E IMPUESTOS — VALIDACIONES PENDIENTES (Prueba 18 y 19)
[ ] Libro IVA Compras: datos reales coinciden con compra_cab en BD (Prueba 18)
[ ] Liquidación IVA: Saldo IVA coincide con cuenta "IVA por Pagar" en Balance de Comprobación (Prueba 19)
[ ] Liquidación IVA: indicador "A_PAGAR" se muestra en rojo cuando IVA Débito > IVA Crédito
[ ] Liquidación IVA: indicador "A_FAVOR" se muestra en verde cuando IVA Crédito > IVA Débito
[ ] Libro IVA Ventas: verificar con datos reales mes en curso (Prueba 14E actualizada)

---

⚠️ Nota: Si el Balance General no cuadra o el Estado de Resultados muestra cifras raras, probablemente el mapeo de cuentas está mal configurado (una cuenta de Activo mapeada donde debería ir Ingreso, por ejemplo). Revisar el tab Mapeo de Cuentas primero.

⚠️ Nota contado vs crédito: Si los asientos de ventas/compras siempre muestran Clientes/Proveedores aunque la factura sea al contado, verificar que `condicion_operacion_id` esté cargado en la factura y que el mapeo de `CAJA_GENERAL` esté configurado.

⚠️ Nota moneda extranjera: El sistema usa la cotización GUARDADA EN EL DOCUMENTO (dticam / cotizacion), no la del tab Tipo de Cambio. Si el asiento muestra importes en moneda extranjera sin convertir, verificar que moneda_id y dticam/cotizacion estén cargados en la factura o compra.

⚠️ Nota centro de costos: Los centros de costo no afectan el cuadre contable (DEBE = HABER siempre). Son clasificadores analíticos que permiten filtrar gastos/ingresos por área. El filtro por CC está disponible en Libro Diario y Libro Mayor (selector aparece solo si hay centros activos). Balance de Comprobación, Estado de Resultados y Balance General no se filtran por CC ya que son agregaciones a nivel cuenta.

⚠️ Nota IVA: La Liquidación de IVA DEBE cuadrar con el Balance de Comprobación. Si el IVA Débito del Libro IVA Ventas no coincide con el saldo de la cuenta "IVA Débito Fiscal" en el Balance, hay facturas sin integrar o asientos manuales incorrectos. Este cruce es el primer control que hace un contador al cierre del mes.
