Les sept règles, avec le texte du Schematron EN 16931 (validation-1.3.17). Toutes sont fatales :
| Règle | Catégorie | Texte |
|---|---|---|
| BR-E-10 | E, exonéré | A VAT breakdown (BG-23) with VAT Category code (BT-118) "Exempt from VAT" shall have a VAT exemption reason code (BT-121) or a VAT exemption reason text (BT-120). |
| BR-AE-10 | AE, autoliquidation | A VAT breakdown (BG-23) with VAT Category code (BT-118) "Reverse charge" shall have a VAT exemption reason code (BT-121), meaning "Reverse charge" or the VAT exemption reason text (BT-120) "Reverse charge" (or the equivalent standard text in another language). |
| BR-IC-10 | K, intracommunautaire | A VAT breakdown (BG-23) with the VAT Category code (BT-118) "Intra-community supply" shall have a VAT exemption reason code (BT-121), meaning "Intra-community supply" or the VAT exemption reason text (BT-120) "Intra-community supply" (or the equivalent standard text in another language). |
| BR-G-10 | G, exportation | A VAT breakdown (BG-23) with the VAT Category code (BT-118) "Export outside the EU" shall have a VAT exemption reason code (BT-121), meaning "Export outside the EU" or the VAT exemption reason text (BT-120) "Export outside the EU" (or the equivalent standard text in another language). |
| BR-O-10 | O, hors champ | A VAT breakdown (BG-23) with VAT Category code (BT-118) " Not subject to VAT" shall have a VAT exemption reason code (BT-121), meaning " Not subject to VAT" or a VAT exemption reason text (BT-120) " Not subject to VAT" (or the equivalent standard text in another language). |
| BR-S-10 | S, normal | A VAT breakdown (BG-23) with VAT Category code (BT-118) "Standard rate" shall not have a VAT exemption reason code (BT-121) or VAT exemption reason text (BT-120). |
| BR-Z-10 | Z, taux zéro | A VAT breakdown (BG-23) with VAT Category code (BT-118) "Zero rated" shall not have a VAT exemption reason code (BT-121) or VAT exemption reason text (BT-120). |
Le motif peut être donné sous forme de code (BT-121, issu de la liste VATEX) ou de texte (BT-120). Pour E, l'un ou l'autre suffit ; pour AE, K, G et O, le code ou le texte doit signifier exactement cela : « Reverse charge », « Intra-community supply »… Les autres règles de chaque famille (BR-E-08, BR-AE-08 et suivantes) portent sur les montants ; ici, seul le motif est concerné.

Comment Odoo détermine la catégorie
C'est ici que les versions divergent :
- Odoo 17 et 18 : par défaut, la taxe n'a pas de champ de catégorie et Odoo la déduit : pour un client espagnol dont le code postal commence par 35 ou 38 (îles Canaries), L, et par 51 ou 52 (Ceuta et Melilla), M ; E si la taxe est à 0 % et que vendeur et client sont dans le même pays ; AE pour l'autoliquidation d'un co-contractant belge ou pour l'autofacturation avec une taxe d'autoliquidation ; avec le numéro de TVA du vendeur et une taxe à 0 %, K si les deux sont dans l'EEE et G si un seul l'est ; sinon, S si la taxe a un taux et E si elle est à 0 %. Le module standard account_edi_ubl_cii_tax_extension (Tax extension for UBL/CII), qui ne s'installe pas automatiquement, ajoute à la taxe Tax Category Code et Tax Exemption Reason Code : une fois la catégorie renseignée, Odoo l'utilise au lieu de la déduire.
- Odoo 19 : chaque taxe dispose de Tax Category Code (AE, E, S, Z, G, O, K, L, M, B) et de Tax Exemption Reason Code, avec la liste VATEX.
- Odoo 20 : les mêmes deux champs et, en plus, Tax Exemption Reason, un texte libre.
- Dans les quatre versions : si une catégorie E se retrouve sans motif, Odoo écrit le texte « Exempt from tax », qui respecte BR-E-10.
Le piège habituel d'Odoo 17 et 18 sans ce module est une taxe à 0 % pour une prestation hors champ de la TVA, que la déduction ne marque jamais O, ou une vente nationale en autoliquidation : la catégorie obtenue diffère de celle qu'attend votre expert-comptable.
Avec notre module XRechnung et ZUGFeRD
Le générateur du module publié ne connaît que deux catégories, S et Z. En XRechnung UBL, il écrit S lorsque la taxe a un pourcentage et Z lorsqu'elle est à 0 %. En XRechnung CII, son format par défaut, chaque ligne sort en S, y compris avec une taxe à 0 %, et le validateur de KoSIT la rejette avec BR-S-05 (nous l'avons vérifié). Une facture en autoliquidation, intracommunautaire, d'exportation ou exonérée ne sort ni avec AE, ni K, ni G, ni E. Sous Odoo 18, 19 et 20, avec l'abonnement FlexigoTech Cloud, le module valide le résultat avec les règles de KoSIT et laisse toute règle en échec sous Validation Errors. Pour ces factures, aujourd'hui, c'est l'export natif d'Odoo qui connaît les catégories. Sous Odoo 17, la version publiée ne valide pas.

Comment le corriger
- Repérez la catégorie dans la ventilation de TVA du XML (BT-118) et comparez-la à l'opération réelle.
- Sous Odoo 19 et 20, ouvrez la taxe et renseignez son Tax Category Code et, si c'est E, AE, K, G ou O, son Tax Exemption Reason Code.
- Sous Odoo 17 et 18, installez account_edi_ubl_cii_tax_extension et renseignez sur chaque taxe sa catégorie et, si cette catégorie l'exige, son motif. Sans ce module, vérifiez le pays du client, son code postal, son numéro de TVA et la position fiscale : ce sont les données à partir desquelles Odoo déduit la catégorie.
- Un motif d'exonération sur une ligne au taux normal provoque BR-S-10 : retirez-le de la taxe.
- Générez de nouveau le fichier.
À lire aussi
Vérifié dans le code du module (version 17.0 et 20.0) et dans les sources citées
Sources
- github.com/odoo/odoo/blob/6f00fdadb875342de2d14a179f25431f93cd63c9/addons/account_edi_ubl_
- github.com/odoo/odoo/blob/2982b5f44af03fae6a9888f20632c1cc19f623ba/addons/account_edi_ubl_
- github.com/odoo/odoo/blob/6f00fdadb875342de2d14a179f25431f93cd63c9/addons/account_edi_ubl_
- Code du module : flexigo_germany_xrechnung 20.0 (446f2f68): lib/generators/cii_generator.py
- Code du module : flexigo_germany_xrechnung 20.0 (446f2f68): models/res_company.py
- github.com/odoo/odoo/blob/6f00fdadb875342de2d14a179f25431f93cd63c9/addons/account_edi_ubl_
- 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_
- 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_
- Code du module : flexigo_germany_xrechnung 20.0 (446f2f68): lib/generators/ubl_generator.py
- Code du module : flexigo_germany_xrechnung 20.0 (446f2f68): models/xrechnung_cloud.py
- Code du module : flexigo_germany_xrechnung 17.0 (ad05de8f): __manifest__.py
- github.com/ConnectingEurope/eInvoicing-EN16931/releases/tag/validation-1.3.17
