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_idde 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
AmbienteaPruebas, el Estado de FE quedaba enErrorcon 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_ida la factura POS estaba dentro del bloque condicional de FE. - La marca
to_invoice = trueen 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_xmlintentaba decodificar el certificado.p12en base64 sin validar previamente su existencia. En compañías sin certificado cargado, recibía un valorFalseen lugar debytesy 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_idahora 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_xmlque 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 = truedel 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
- Sincronizar el código: hacer
git pullen el repositorioLogosoft-S-A/l10_crramaprod-modules. - 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 → Buscarcr_electronic_invoice_pos→ Actualizar. - Reiniciar el contenedor Odoo.
- Validar caso #1 (método de pago):
- Abrir una sesión POS y procesar una venta con el campo
Ambientede la compañía enDeshabilitado. - Cerrar la sesión y verificar la factura generada en Contabilidad → Clientes → Facturas: el campo
Métodos de pagodebe estar lleno.
- Abrir una sesión POS y procesar una venta con el campo
- Validar caso #2 (mensaje claro):
- Sin cargar certificado
.p12, cambiar el ambiente aPruebas. - Verificar que el mensaje recibido es el descriptivo (no el error de bytes/bool).
- Sin cargar certificado
- Validar caso #3 (facturación automática):
- Con la casilla
Factura Electrónicadesmarcada en la compañía, procesar una venta desde POS. - Verificar que la factura se generó automáticamente al cerrar la sesión.
- Con la casilla
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:
- Solicitar la renovación del certificado de firma electrónica al proveedor (Hacienda / Banco).
- Cargar el nuevo archivo
.p12en la configuración de la compañía: Ajustes → Compañías → [Compañía] → Pestaña Facturación Electrónica → Certificado. - Actualizar la contraseña del certificado y la fecha de expiración.
- Probar la firma con una factura de prueba en ambiente
Pruebasantes de operar enProducció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
.p12de cada compañía. - Sincronización de ramas: al aplicar fixes en
prod-modules, replicar también enmain/stagingpara evitar regresiones.
Referencias
- Módulo:
cr_electronic_invoice_pos(extensión decr_electronic_invoice) — repoLogosoft-S-A/l10_crramaprod-modules. - Instancia donde se reportó y validó:
https://polita.logosoftla.com/. - Ticket origen: #125 — Bug con clientes sin datos de FE.