Caso de Estudio: Cómo resolvimos el bug de "Pago Automático en $0"

EGP - Ticket #2026/03794 - Guía para el equipo de soporte
19 de marzo de 2026 por
Caso de Estudio: Cómo resolvimos el bug de "Pago Automático en $0"
Jinzo

🎯 El Problema

Un cliente de EGP reportó:

"Cuando confirmo una factura con el diario de pago directo en 'Mostrador', la factura queda sin pagar. Antes funcionaba."

🔍 Paso 1: Entender qué dejó de funcionar

Preguntas clave:

  • ¿Cuándo dejó de funcionar? → El 18/03 (funcionaba hasta el 17/03)
  • ¿Qué debería pasar? → Al confirmar factura con "Diario de pago directo", se crea un pago automático
  • ¿Qué está pasando? → El pago se crea pero con monto $0

Lección: Siempre preguntar cuándo dejó de funcionar. Nos da pistas de qué pudo haber cambiado.


🔍 Paso 2: Verificar el problema en los datos

Conectamos a producción (solo lectura) y buscamos facturas afectadas:

Facturas con "Diario de pago directo" seteado:
- 17/03: FA-A 00011-00001708 → PAGADA ✅
- 17/03: FA-A 00011-00001706 → PAGADA ✅
- 18/03: FA-A 00011-00001729 → NO PAGADA ❌
- 19/03: FA-A 00011-00001733 → NO PAGADA ❌

Confirmado: El problema empezó el 18/03. Algo cambió entre esas fechas.


🔍 Paso 3: Encontrar la causa en el código

Revisamos el método pay_now() del módulo account_payment_pro:

# El código hacía esto:
payment = crear_pago()
monto = payment.payment_difference  # ← AQUÍ ESTABA EL PROBLEMA
payment.amount = monto              # ← Quedaba en $0

¿Por qué fallaba?

El campo payment_difference es "computado" (se calcula automáticamente). Pero cuando el pago recién se crea, Odoo no calcula ese campo inmediatamente (esto se llama lazy evaluation). Entonces devolvía $0.

Analogía simple: Es como preguntar "¿cuánto es el total?" antes de que la calculadora termine de sumar.


🔍 Paso 4: Diseñar la solución

En lugar de confiar en un campo que se calcula "después", calculamos el monto directamente desde la factura:

# Solución: calcular el monto ANTES de crear el pago
monto = sum(factura.lineas_abiertas.mapped('saldo_pendiente'))
payment = crear_pago(monto=monto)  # ← Monto correcto desde el inicio

🧪 Paso 5: Probar en staging (NUNCA en producción)

  1. Replicamos el bug en staging → Confirmamos que fallaba igual
  2. Aplicamos el fix → Creamos un módulo nuevo (no modificamos el original)
  3. Testeamos → Nahiara creó facturas y verificó que se pagaban correctamente

Regla de oro: Todo fix se prueba en staging primero. Producción es sagrada.


🚀 Paso 6: Deploy con supervisión

Alejandro guió el proceso de deploy paso a paso:

  1. "Armá un módulo para el fix" → No modificar código de terceros, crear módulo propio
  2. "Subilo al repo de custom" → Cada cliente tiene su repo de personalizaciones
  3. "Actualizá el submodule en staging" → El repo principal "apunta" a los repos de módulos

¿Por qué un módulo separado?

  • Si actualizamos account_payment_pro (módulo de ingadhoc), perderíamos nuestro fix
  • Con módulo propio, el fix sobrevive a actualizaciones
  • Podemos activar/desactivar el fix fácilmente

📝 Resumen del Camino

REPORTE → VERIFICAR DATOS → ENCONTRAR CAUSA → DISEÑAR FIX → PROBAR EN STAGING → DEPLOY
   ↓            ↓                 ↓               ↓              ↓              ↓
"No paga"   "Desde 18/03"    "Lazy eval"    "Calcular      "Nahiara      "Módulo en
                                             directo"       testeó"       cl-egp-custom"

💡 Lecciones para el Equipo

SituaciónQué hacer
Cliente dice "dejó de funcionar"Preguntar cuándo exactamente
Necesitás verificar datosConectar vía SSH, solo SELECT en producción
Encontraste el bugReplicar en staging primero
Querés hacer un fixCrear módulo propio, no modificar módulos de terceros
Fix listoTestear en staging, documentar, luego deploy

👥 Créditos

  • Nahiara: Recepción del caso, testing y validación
  • Jinzo: Análisis técnico y desarrollo del fix
  • Alejandro: Supervisión y dirección del deploy

¿Dudas? Pregunten en el grupo de soporte. 🙌