| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Lines of code | 396 |
| Technical Name |
eh_edi_core |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Lines of code | 396 |
| Technical Name |
eh_edi_core |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
EH EDI Core
One audited credential vault and one canonical EN16931 invoice model, shared by every ERP Heritage e-invoicing module.
Why this module
EH EDI Core
Crypto and mapping, written once
The security-critical vault and the standards-critical EN16931 mapping live in a single audited place, not duplicated per format module. A fix lands once and every e-invoicing module that depends on it benefits. No copy of the AES-256-GCM code per module, no second reader of the move.
Authenticated encryption, no plaintext credentials
API secrets for each tax authority or access point are sealed with AES-256-GCM, the master key resolved from environment, a 0600 key file, or a system parameter. The vault refuses to run without a master key and raises on tampered or wrong-key ciphertext rather than handing back garbage.
Read the invoice once, serialise many ways
A single mapper reads account.move into one BT-code-annotated EN16931 model. The to_cii_input and to_ubl_inputs adapters feed the Factur-X CII and Peppol UBL serializers, so each format module serialises the same shared model instead of re-reading the move and drifting apart.
Day in the life
A developer adds a second e-invoicing country without touching the crypto.
A new tax authority needs encrypted API credentials and a structured invoice. Rather than writing fresh encryption, the format module asks the shared vault for its own key namespace; the master key resolves from the environment, a 0600 key file (rejected if its permissions are loose), or a system parameter (which logs a least-secure warning). For the document, the module calls the one EN16931 mapper, which reads the account.move into a single semantic model with parties, deterministic multi-rate tax buckets, the correct credit-note document type, and UNTDID 5305 categories. The module then calls to_cii_input or to_ubl_inputs and serialises that shared model to its target syntax. No new crypto, no second reader of the move.
Edge cases
The cases most modules quietly ignore.
In the shipped code today, each one a place where a cheaper module silently does the wrong thing.
The vault refuses to read a master-key file that is group or world readable and demands chmod 0600 first, so a loose-permission key can never be used silently.
Tampered, truncated, wrong-key, or non-base64 ciphertext raises a vault error from the authenticated decryption rather than returning corrupt or partial plaintext.
When the master key is read from the config parameter (key co-located with the ciphertext), the vault emits a loud security warning instead of accepting that source quietly.
Product-line detection handles section and note rows and the v16 versus v17+ display_type difference, so non-product lines are excluded from the EN16931 line set across Odoo versions.
Tax lines bucket by rate and category in first-seen order, so a multi-rate invoice produces one stable, deterministic subtotal per rate.
Out-refund and in-refund moves map to the credit-note document type rather than being serialised as plain invoices.
Cross-module fields such as SIRET, Peppol endpoint id and scheme, and PO reference are read defensively, so the mapper runs whether or not those modules are installed.
What is inside
Built to do the job, end to end.
- AES-256-GCM credential vault. Authenticated-encryption vault parametrised per module by a key namespace, with three-tier master-key resolution (environment, 0600 key file, config parameter) and refusal to operate when no key resolves. Backward-compatible on-disk ciphertext layout.
- Canonical EN16931 invoice model. One BT-code-annotated semantic model carrying parties, lines, multi-rate tax breakdown, totals, references, and UNTDID 5305 tax categories, shared live by the France, Peppol, and Mauritius modules.
- account.move EN16931 mapper. The sole reader of the move for outbound e-invoicing, with cross-version product-line detection, deterministic multi-rate tax bucketing, and correct credit-note document typing.
- CII and UBL adapters. to_cii_input and to_ubl_inputs build the input each serializer consumes, so the Factur-X CII and Peppol UBL modules serialise the one shared model to their syntax without re-reading the move.
- Output-shape unit tests. Pure shape-equality tests in this module pin the mapping output, and the vault is proven against raw AES-GCM blobs, tamper, short and non-base64 ciphertext, and key-file permission hardening.
Honest about the edges
What this does not do, so nothing surprises you.
- This is a technical dependency, not an end-user application. It has no user interface, no menu, and no configuration of its own, and is installed automatically with the e-invoicing modules that need it.
- EH EDI Core emits no XML itself. The to_cii_input and to_ubl_inputs adapters build the input the serializers consume; the actual CII and UBL serialization lives in the consuming format modules (France CII, Peppol UBL).
- The mapping is pinned by output-shape unit tests in this module. Byte-for-byte golden XML regression tests live in the consuming e-invoicing modules and lock their serialized output; a mapping change that alters a generated document surfaces in those modules' tests.
- No silent fallback applies to credentials: a missing or invalid master key surfaces an explicit error. The mapper itself reads invoice fields defensively with safe defaults; the pre-flight that rejects unmappable EN16931 fields is enforced by the e-invoicing format modules' validators, not here.
- Requires the Python cryptography library as an external dependency.
EN16931 invoice model Odoo, AES-256-GCM credential vault Odoo, encrypt API secrets Odoo e-invoicing, Factur-X CII mapper, Peppol BIS Billing UBL Odoo, UNTDID 5305 tax category, e-invoicing shared library Odoo 19, account.move to EN16931 mapper, authenticated encryption secrets at rest Odoo
Please log in to comment on this module