Las fórmulas, tal como las escribe el Schematron
| Regla | Texto de EN 16931 (Schematron validation-1.3.17) |
|---|---|
| BR-CO-15 | Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110). |
| BR-CO-14 | Invoice total VAT amount (BT-110) = Σ VAT category tax amount (BT-117). |
| BR-CO-16 | Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) -Paid amount (BT-113) +Rounding amount (BT-114). |
| BR-CO-17 | VAT category tax amount (BT-117) = VAT category taxable amount (BT-116) x (VAT category rate (BT-119) / 100), rounded to two decimals. |
| BR-S-08 | For each different value of VAT category rate (BT-119) where the VAT category code (BT-118) is "Standard rated", the VAT category taxable amount (BT-116) in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts (BT-131) plus the sum of document level charge amounts (BT-99) minus the sum of document level allowance amounts (BT-92) where the VAT category code (BT-151, BT-102, BT-95) is "Standard rated" and the VAT rate (BT-152, BT-103, BT-96) equals the VAT category rate (BT-119). |
| BR-S-09 | The VAT category tax amount (BT-117) in a VAT breakdown (BG-23) where VAT category code (BT-118) is "Standard rated" shall equal the VAT category taxable amount (BT-116) multiplied by the VAT category rate (BT-119). |
Las seis son fatales. Léelas como una cadena: las líneas suman la base de cada tipo (BR-S-08), cada base por su tipo da el IVA de ese tipo (BR-CO-17 y BR-S-09), los IVA por tipo suman el IVA total (BR-CO-14), base más IVA da el total (BR-CO-15) y el total menos lo pagado más el redondeo da lo que queda por pagar (BR-CO-16).

Qué reglas notan un céntimo
No todas cuentan céntimos. BR-CO-17 y BR-S-09 comparan el IVA de cada tipo (BT-117) con la base por el tipo, pero el Schematron les deja un margen de 1 € arriba o abajo. BR-S-08 compara bases, así que el redondeo del IVA no le afecta. BR-CO-14, BR-CO-15 y BR-CO-16 comparan sumas redondeadas a dos decimales, sin margen: ahí un céntimo ya es un error.
El céntimo aparece cuando hay dos maneras de calcular el IVA. Odoo lo calcula según el ajuste Tax Calculation Rounding Method de la empresa:
| Versión de Odoo | Opciones | Por defecto |
|---|---|---|
| Odoo 17 y 18 | Round per Line o Round Globally | Por línea |
| Odoo 19 y 20 | Round per Tax o Round per Line | Por impuesto |
Con el redondeo por línea, Odoo redondea el IVA de cada línea y luego suma. En una factura con muchas líneas de importes pequeños, esa suma puede quedar a un céntimo del IVA calculado sobre la base de cada tipo. Si todas las cifras del fichero salen del mismo cálculo, las sumas cuadran. Si el fichero lleva el IVA total de Odoo junto a un desglose rehecho por tipo, falla BR-CO-14; si lleva el total con IVA de Odoo junto a un IVA rehecho, falla BR-CO-15. Para que salte BR-CO-17, la diferencia tiene que pasar de 1 €.
El método de redondeo es un ajuste de la empresa, no de cada factura: cambiarlo afecta a los impuestos que se calculen desde ese momento. Hazlo entre facturas, nunca con una a medias.
Lo que hace el Factur-X de Odoo
En el Factur-X (CII) de Odoo 18, 19 y 20, el total con IVA (BT-112) se escribe como la suma de la base (BT-109) y del IVA (BT-110) que ya van en el fichero, justo para cumplir BR-CO-15. Eso asegura la regla de la suma; el resto de la cadena sigue dependiendo de que el desglose cuadre.
Con nuestro módulo XRechnung y ZUGFeRD
El módulo genera el XML con su propio código y hoy mezcla los dos cálculos. El IVA de cada tipo (BT-117) lo calcula como base por tipo; el total con IVA (en UBL) y el IVA total (en CII) los copia de la factura de Odoo. Con el redondeo por línea, un céntimo de diferencia basta: el XML sale con BR-CO-15 en XRechnung UBL y con BR-CO-14 en XRechnung CII, el formato que el módulo usa por defecto. Lo hemos comprobado con el validador de KoSIT. En Odoo 17 y 18, el redondeo por línea es el valor por defecto.
Con un pago parcial falla BR-CO-16: el importe a pagar (BT-115) es lo que queda pendiente en Odoo, pero el fichero no lleva el importe ya pagado (BT-113).

En Odoo 18, 19 y 20, con la suscripción a FlexigoTech Cloud, cada XRechnung y cada ZUGFeRD EN 16931 que genera el módulo pasa por las reglas de KoSIT, que incluyen estas seis. Si una falla, queda escrita en la factura, en Validation Errors, y la factura no se marca como Ready to send. En Odoo 17 la versión publicada no valida: el fichero sale con el fallo y sin aviso.
Qué hacer
- Mira en el informe qué regla falla primero: BR-S-08 apunta a las bases, BR-CO-14 al desglose, BR-CO-15 al total y BR-CO-17 al IVA de un tipo.
- Revisa el método de redondeo de la empresa y, si emites facturas electrónicas con muchas líneas, valora el redondeo por impuesto con tu asesor.
- BR-CO-16 aparece con pagos parciales o con redondeo de caja: el importe pagado y el de redondeo tienen que ir en el fichero. Con nuestro módulo, genera la XRechnung antes de registrar ningún pago.
- Corrige y genera de nuevo; no edites el XML a mano.
Sigue leyendo
Comprobado en el código del módulo (versión 17.0 y 20.0) y en las fuentes enlazadas
Fuentes
- github.com/ConnectingEurope/eInvoicing-EN16931/releases/tag/validation-1.3.17
- Código del módulo: flexigo_germany_xrechnung 20.0 (446f2f68): lib/generators/ubl_generator.py
- Código del módulo: flexigo_germany_xrechnung 20.0 (446f2f68): lib/generators/cii_generator.py
- Código del módulo: flexigo_germany_xrechnung 20.0 (446f2f68): models/res_company.py
- github.com/odoo/odoo/blob/6f00fdadb875342de2d14a179f25431f93cd63c9/addons/account/models/c
- github.com/odoo/odoo/blob/2982b5f44af03fae6a9888f20632c1cc19f623ba/addons/account/models/c
- github.com/odoo/odoo/blob/4d2d4b5895db70596863df941d9a1f0beeb117f8/addons/account/models/c
- github.com/odoo/odoo/blob/2fec20391a8a61ea3a3bf15e9f24d59dba910a8d/addons/account/models/c
- github.com/odoo/odoo/blob/2982b5f44af03fae6a9888f20632c1cc19f623ba/addons/account_edi_ubl_
- github.com/odoo/odoo/blob/4d2d4b5895db70596863df941d9a1f0beeb117f8/addons/account_edi_ubl_
- github.com/odoo/odoo/blob/2fec20391a8a61ea3a3bf15e9f24d59dba910a8d/addons/account_edi_ubl_
- Código del módulo: flexigo_germany_xrechnung 20.0 (446f2f68): models/xrechnung_cloud.py
- Código del módulo: flexigo_germany_xrechnung 20.0 (446f2f68): models/account_move.py
- Código del módulo: flexigo_germany_xrechnung 17.0 (ad05de8f): __manifest__.py
