| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Purchase (purchase) • Discuss (mail) |
| Community Apps Dependencies | Show |
| Lines of code | 6678 |
| Technical Name |
eh_account_einvoice_peppol |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Versions | 16.0 17.0 18.0 19.0 |
Peppol eInvoicing
Send and receive Peppol BIS Billing 3.0 invoices on Odoo 16 Community, with a real UBL 2.1 generator, an inbound bill workflow, and pre-flight validation that catches errors before the access point does.
Why this module
Peppol eInvoicing
A real generator and a real parser
Outbound emits the actual OASIS UBL 2.1 namespaces and the Invoice-2 and CreditNote-2 roots. Inbound is a parser plus a received to parsed to matched to posted state machine that creates the vendor bill. Not field names that sound like Peppol, the actual document mechanisms.
Caught before the access point
Every payload is checked against the high-frequency Peppol and EN 16931 invariants (mandatory elements, single currency, totals reconciled within 1 cent) before download, and a failure names the rule. Participant identifiers are checksum-validated so an invalid ABN or GLN bounces with a precise message, not a rejection hours later.
Yours to keep, yours to wire
LGPL-3 source on disk, no activation key, no phone-home. Transport is bring-your-own through a published adapter contract, and the account.move payload builder is split into override methods so a localisation can enrich party identification and per-line tax mapping without forking the module.
Day in the life
An AP clerk handles a cross-border invoice both ways.
A posted customer invoice gets one button: the generator produces the BIS Billing 3.0 XML, structurally validated for mandatory elements, single-currency consistency and total reconciliation before it is offered for download. Later the same day a supplier UBL arrives in the inbox. The poll cron parses it into header data but does not post anything. The clerk opens the record, the parser has already matched the supplier, and an accounting manager posts it as a vendor bill. When the access point retransmits the same file an hour later, the duplicate guard recognises the file hash and refuses it, so no second bill is created. None of it required an Enterprise subscription.
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.
Posting an inbound bill is gated to accounting managers, a distinct control from parse and match. The cron auto-parses on poll but never auto-posts, so no vendor bill is ever created without a human review and a manager action.
A re-submitted identical UBL (same SHA-256 file hash, same supplier, same company, not previously rejected) is flagged and posting is refused, so a retrying access point cannot create a duplicate vendor bill.
Any currencyID attribute that differs from the document currency code is rejected before transmission, catching mixed-currency drift that would otherwise be rejected downstream.
Line totals against the legal monetary total, and tax subtotals against the tax total, are each reconciled within a 1 cent tolerance that absorbs per-line half-up rounding residual, so a one-cent drift is named rather than shipped.
When more than one supplier candidate matches an inbound document, the partner is left empty and the record is routed to an exception state for manual review rather than guessing the wrong vendor.
Credit notes are not a relabelled invoice: they use the CreditNote root and namespace, CreditNoteTypeCode 381 and CreditedQuantity, and omit DueDate, the way a compliant BIS credit note must.
Export refuses any move that is not posted and any document type that is not a customer invoice or credit note, with an explicit message instead of producing an invalid payload.
What is inside
Built to do the job, end to end.
- Outbound UBL 2.1 generator. One button on a posted customer invoice or credit note renders a Peppol BIS Billing 3.0 document using the official OASIS UBL 2.1 namespaces and Invoice-2 / CreditNote-2 roots, with UN/ECE rec-20 unit codes in the unitCode attribute.
- Structural pre-flight validation. Before download, the payload is checked against the high-frequency Peppol and EN 16931 invariants: mandatory elements, single-currency consistency, and line and tax reconciliation within 1 cent. A failure names the offending rule. This is a structural check, not full XSD validation.
- Inbound parser and bill workflow. A complete UBL parser feeds a received to parsed to matched to posted to exception state machine that creates the vendor bill, with posting gated to accounting managers and ambiguous suppliers routed to exception for review.
- Participant-identifier validation. Real checksums validate participant identifiers before export: ABN weighted checksum, GS1 GLN mod-10, fixed-length numeric schemes, DE VAT, FR SIRET Luhn and MY TIN, so an invalid id bounces with a precise message instead of failing at the access point.
- Country-profile validators (opt-in). A-NZ, MY, DE and FR validators ship in tools as unit-tested, opt-in checks for jurisdiction identifiers and allowed tax categories against the BIS 3.0 payload. They do not generate national formats and are not run by the default Export button.
- Bring-your-own access point. An adapter registry and submit/poll contract ships in-module with a manual file-drop stub. The access-point key and inbox email are stored per company and read by the poll cron, so each company in a multi-company install can route to its own access point. Live AS4 transport is a separate adapter, not included.
- Localisation override hooks. The account.move payload builder is split into override methods for payload, party, and lines plus tax, so a localisation can enrich party identification and per-line tax mapping by inheritance.
Honest about the edges
What this does not do, so nothing surprises you.
- No live AS4 transmission is included. A real adapter registry, submit/poll contract and a manual file-drop stub ship in-module, but live access-point transport requires a separate ERP Heritage adapter module registered under the same key.
- Validation is structural, not full XSD. The pre-flight checker enforces the high-frequency Peppol and EN 16931 invariants (mandatory elements, single currency, total reconciliation), not the complete OASIS XSD schema; no .xsd files ship.
- The four country profiles validate, they do not generate national formats. A-NZ, MY, DE and FR validators check identifiers and tax categories only; they do not emit MyInvois submissions, XRechnung CII or Factur-X documents, and they are opt-in rather than run by the Export button.
- No dedicated Settings panel ships. Configuration lives on records: the Peppol endpoint id and scheme are set per partner, and the access-point key per company. There is no res.config.settings view or top-level menu in this module.
- The low-level UBL renderers are pure functions, not inheritance override points. Override seams exist on the account.move side (payload, party, lines plus tax); the renderers in tools are module-level functions and cannot be overridden via Odoo inheritance.
Odoo 16 Peppol e-invoicing, Peppol BIS Billing 3.0 Odoo Community, UBL 2.1 invoice generator Odoo, Peppol inbound vendor bill Odoo, UBL XML parser Odoo accounting, Peppol access point adapter Odoo, ABN GLN participant id validation Peppol, electronic invoicing EN 16931 Odoo, credit note UBL CreditNote Odoo, Peppol duplicate invoice detection
Languages
Available in 19 languages
The interface ships translated out of the box. Switch language in Odoo and the fields, menus, and messages follow.
Please log in to comment on this module