Resolución: Bugs con clientes sin Factura Electrónica en POS (métodos de pago, error de certificado, facturación automática) - Odoo 17
📋

Resolución: Bugs con clientes sin Factura Electrónica en POS (Odoo 17 - cr_electronic_invoice_pos)

Este artículo documenta tres comportamientos inesperados en compañías que no utilizan Factura Electrónica (régimen fiscal sin obligación de FE) cuando operan a través del Punto de Venta (POS) en Odoo 17, y la refactorización aplicada al módulo cr_electronic_invoice_pos para desacoplar la lógica administrativa de la lógica electrónica.

Problema

En la instancia polita.logosoftla.com (cliente con régimen fiscal que no requiere FE) se detectaron tres comportamientos al operar el POS con el campo Ambiente de la compañía en estado Deshabilitado:

  • Caso #1: el campo payment_methods_id de las facturas generadas desde POS quedaba vacío, afectando procesos posteriores como la generación de Notas de Crédito.
  • Caso #2: al cambiar el campo Ambiente a Pruebas, el Estado de FE quedaba en Error con un mensaje técnico de Python confuso para el usuario:
    Warning!. Error in generate_and_send_invoice:
    argument should be a bytes-like object or ASCII string, not 'bool'
    Adicionalmente aparecía el mensaje: "No podrá validar porque su llave criptográfica expiró hace 247 día(s)".
  • Caso #3: si la casilla Factura Electrónica (invoice_is_electronic) no estaba marcada en la compañía, las ventas procesadas desde POS no generaban factura automáticamente.

Causa Raíz

El módulo cr_electronic_invoice_pos está diseñado para no ejecutar lógica de FE cuando el ambiente está deshabilitado. Esto es correcto para la firma digital y el envío a Hacienda, pero el módulo tenía lógica administrativa acoplada al flujo de FE que también quedaba inactiva en compañías sin Factura Electrónica:

  • La asignación del payment_methods_id a la factura POS estaba dentro del bloque condicional de FE.
  • La marca to_invoice = true en el JS del POS (que ordena al sistema generar factura al validar la orden) también estaba dentro del condicional de FE.
  • La función sign_xml intentaba decodificar el certificado .p12 en base64 sin validar previamente su existencia. En compañías sin certificado cargado, recibía un valor False en lugar de bytes y generaba el error genérico de Python.

El segundo mensaje ("llave criptográfica expiró hace 247 días") no es un bug: es la notificación correcta del módulo cuando detecta un certificado expirado. Solo indica que el certificado debe renovarse.

Solución Aplicada

Se refactorizó el módulo cr_electronic_invoice_pos separando la lógica administrativa de la lógica electrónica. La firma digital, generación de número electrónico, tipo de documento (FE/TE/NC) y envío a Hacienda siguen ejecutándose únicamente cuando la FE está activa.

A. Caso #1 — Asignación del método de pago

  • El campo payment_methods_id ahora se asigna siempre al generar facturas o notas de crédito desde POS, sin importar el estado del ambiente FE.
  • Esto garantiza que las Notas de Crédito posteriores funcionen correctamente para clientes con o sin Facturación Electrónica.

B. Caso #2 — Mensaje de error claro al asignar "Pruebas" sin certificado

  • Se agregó una validación previa en la función sign_xml que verifica la existencia del certificado y la contraseña antes de intentar firmar.
  • En lugar del error técnico de Python, ahora el usuario recibe un mensaje claro:

    "No se ha cargado el certificado de firma electrónica (.p12) en la compañía. Configure el certificado antes de activar el ambiente de Facturación Electrónica."

C. Caso #3 — Facturación automática desde POS

  • Se separó la marca to_invoice = true del flujo de FE en el archivo JavaScript del POS.
  • Ahora toda orden POS marca la factura como automática, independientemente de si la compañía tiene o no Facturación Electrónica activa.

D. Repositorio GitHub

  • Repositorio: Logosoft-S-A/l10_cr
  • Rama: prod-modules (según solicitud explícita en el ticket)
  • Módulo afectado: cr_electronic_invoice_pos

Validación / Prueba Realizada

Las correcciones se desplegaron en la instancia polita.logosoftla.com y se validó cada caso. El cliente confirmó por escrito el correcto funcionamiento de los tres escenarios.

Caso Verificación Resultado
#1 Factura POS con Ambiente Deshabilitado → revisar campo payment_methods_id Cargado correctamente ✓
#2 Cambiar Ambiente a Pruebas sin certificado .p12 Mensaje claro pidiendo configurar certificado ✓
#3 Venta POS con invoice_is_electronic desmarcado Factura generada automáticamente ✓
Confirmación del cliente (Logosoft) "Funcionando correctamente" ✓

Pasos para Aplicar la Solución en una Instancia

  1. Sincronizar el código: hacer git pull en el repositorio Logosoft-S-A/l10_cr rama prod-modules.
  2. Actualizar el módulo en Odoo:
    • Acceder al servidor de la instancia.
    • Ejecutar odoo -u cr_electronic_invoice_pos -d <base_de_datos> o, desde la interfaz, Aplicaciones → Buscar cr_electronic_invoice_pos → Actualizar.
    • Reiniciar el contenedor Odoo.
  3. Validar caso #1 (método de pago):
    • Abrir una sesión POS y procesar una venta con el campo Ambiente de la compañía en Deshabilitado.
    • Cerrar la sesión y verificar la factura generada en Contabilidad → Clientes → Facturas: el campo Métodos de pago debe estar lleno.
  4. Validar caso #2 (mensaje claro):
    • Sin cargar certificado .p12, cambiar el ambiente a Pruebas.
    • Verificar que el mensaje recibido es el descriptivo (no el error de bytes/bool).
  5. Validar caso #3 (facturación automática):
    • Con la casilla Factura Electrónica desmarcada en la compañía, procesar una venta desde POS.
    • Verificar que la factura se generó automáticamente al cerrar la sesión.

Comportamiento Esperado por Diseño

Tras la refactorización, el módulo cr_electronic_invoice_pos mantiene la siguiente separación de responsabilidades:

Lógica Cuándo se ejecuta
Asignación de payment_methods_id Siempre (con o sin FE)
Marca to_invoice = true en POS Siempre (con o sin FE)
Generación de número electrónico (clave/consecutivo) Solo si Ambiente ≠ Deshabilitado
Determinación de tipo de documento (FE/TE/NC) Solo si Ambiente ≠ Deshabilitado
Firma digital (sign_xml) y envío a Hacienda Solo si Ambiente ≠ Deshabilitado y certificado .p12 cargado y vigente

Sobre el mensaje "Llave criptográfica expiró"

El mensaje "No podrá validar porque su llave criptográfica expiró hace N día(s)" no es un bug; es el comportamiento correcto del módulo cuando detecta que la fecha de expiración del certificado .p12 ya pasó. Para resolverlo:

  1. Solicitar la renovación del certificado de firma electrónica al proveedor (Hacienda / Banco).
  2. Cargar el nuevo archivo .p12 en la configuración de la compañía: Ajustes → Compañías → [Compañía] → Pestaña Facturación Electrónica → Certificado.
  3. Actualizar la contraseña del certificado y la fecha de expiración.
  4. Probar la firma con una factura de prueba en ambiente Pruebas antes de operar en Producción.

Advertencia Importante

Antes de replicar el despliegue en otras instancias productivas, validar el funcionamiento en una instancia de pruebas con los tres escenarios descritos. Una vez confirmado el visto bueno del cliente, proceder con el despliegue al resto de instancias y verificar la primera venta POS posterior al despliegue.

Prevención

  • Separar lógica electrónica de lógica administrativa: al desarrollar nuevas funcionalidades en cr_electronic_invoice*, mantener la regla de que campos administrativos (métodos de pago, marcas internas del POS, etc.) no dependan del estado de FE.
  • Validar precondiciones antes de operaciones criptográficas: cualquier llamada a funciones que requieran certificado debe verificar primero su existencia y vigencia, devolviendo errores semánticos en lugar de errores técnicos de Python.
  • Pruebas con compañías sin FE: incluir en el plan de pruebas casos para compañías con régimen fiscal sin Facturación Electrónica (Ambiente Deshabilitado, sin certificado, invoice_is_electronic=False).
  • Renovación proactiva del certificado: configurar un recordatorio (cron o notificación) que avise con al menos 30 días de anticipación la expiración del certificado .p12 de cada compañía.
  • Sincronización de ramas: al aplicar fixes en prod-modules, replicar también en main / staging para evitar regresiones.

Referencias

  • Módulo: cr_electronic_invoice_pos (extensión de cr_electronic_invoice) — repo Logosoft-S-A/l10_cr rama prod-modules.
  • Instancia donde se reportó y validó: https://polita.logosoftla.com/.
  • Ticket origen: #125 — Bug con clientes sin datos de FE.