| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Discuss (mail) |
| Community Apps Dependencies | Show |
| Lines of code | 4742 |
| Technical Name |
eh_account_sepa_ct |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Discuss (mail) |
| Community Apps Dependencies | Show |
| Lines of code | 4742 |
| Technical Name |
eh_account_sepa_ct |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
SEPA Credit Transfer
Turn a batch of posted vendor payments into a bank ready ISO 20022 SEPA credit transfer file, with IBAN and BIC checked before the bank ever sees it.
Why this module
SEPA Credit Transfer
Caught before the bank
IBAN passes a pure Python mod-97 check, country in the SEPA zone with the exact per country length, and BIC against ISO 9362 structure. No external library. A bad account never reaches the file.
The file your bank actually wants
Pick PAIN.001.001.03 (legacy SEPA rulebook) or PAIN.001.001.09 (current EU Implementation Guidelines, 2024 onward) per originator. The .09 path renames BIC to BICFI automatically so the same batch serves either bank.
Every file accounted for
Each export records user, timestamp, message ID, transaction count, control sum and a SHA-256 hash. Regenerating supersedes the old file instead of deleting it, so the audit trail shows which one the bank received.
Day in the life
An AP clerk pays thirty European suppliers before the bank cut off.
The clerk posts the supplier payments, drops them into a batch, and hits generate. One supplier was entered with a French branch IBAN that is one digit short; generation stops and names that line rather than producing a file the bank would silently reject. The clerk fixes the IBAN, regenerates, and the prior draft is marked superseded so only the live file remains. A supplier name carries an accented character, which the SEPA Latin pass transliterates so the gateway accepts it. The originator is set to PAIN.001.001.09, so the file carries BICFI as this bank now requires. The export record shows the message ID, thirty transactions, the control sum and a SHA-256 hash. The clerk downloads the XML, uploads it to the bank portal, and the export flips to downloaded. One pay run, one file, no surprises at the gateway.
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.
A batch that mixes currencies is refused before any file is written, with the offending currency names listed, rather than silently truncating to one currency.
Creditor bank account resolution falls back from the payment bank account to the first partner bank whose IBAN actually validates mod-97, and raises a named error if the partner has no valid IBAN account at all. No silent fallthrough to a non IBAN account.
Two exports in the same UTC second still get distinct 35 character message IDs via a uuid fragment, with the name part capped so the uuid can never be truncated away.
The IBAN country must be in the embedded SEPA zone registry and match the exact per country length before mod-97 runs, so an out of zone or wrong length IBAN is rejected with a specific message instead of a generic failure.
Supplier names and remittance text are transliterated and stripped to the SEPA Latin character set, so a name with diacritics clears the bank gateway instead of bouncing.
Downloading an export whose attachment was deleted raises a clear remediation error instead of a 404, and only flips state to downloaded on success.
What is inside
Built to do the job, end to end.
- Dual PAIN.001 output per originator. Generate PAIN.001.001.03 or PAIN.001.001.09 selected on the journal originator, with the BIC element renamed to BICFI automatically for the .09 version. Output targets the published namespace and structure and carries the ISO 20022 schemaLocation hint.
- Pure Python IBAN and BIC validation. Dependency free IBAN mod-97 (ISO 13616) and BIC (ISO 9362) checks, enforced when you save the originator and again when the export is built. IBAN and BIC are canonicalised, spaces stripped, upper cased, 8 character BIC padded to 11, before they are stored.
- Single currency enforcement. Mixed currency batches are blocked before generation with the currency names shown, because SEPA requires one currency per file and a single control sum.
- Per export audit record. Each generated file gets an export record with the SHA-256 hash, user, timestamp, transaction count and control sum. Regenerating supersedes prior exports so the trail stays clear, and state tracks from generated to downloaded.
- SEPA Latin sanitisation. Names and remittance information are transliterated and filtered to the characters the SEPA scheme allows, so accented or non Latin text does not break the file at the bank gateway.
- Verified by parse-back tests. The test suite renders an inline payload, parses the XML back with lxml, and asserts the namespace, message ID, transaction count, control sum, per transaction amounts and currency, service level (SEPA) and charge bearer (SLEV), element by element.
Honest about the edges
What this does not do, so nothing surprises you.
- Currency is EUR only, fixed by the SEPA scheme. Non EUR transfers are out of scope, use a different transfer instruction.
- The file targets the published PAIN.001.001.03 and .09 namespace and structure and carries the schemaLocation hint. It does not bundle an XSD or run xmllint or XSD validation; the tests assert structure by parsing the XML back, not by validating against a schema.
- The SHA-256 hash and supersession let an auditor detect a duplicate generation, but the module does not hard block a second export of the same batch.
- One message (CstmrCdtTrfInitn) per export, SEPA service level only, charges allocated SLEV, and no batch booking. Each transaction renders as its own entry.
- This is a file generator. It does not connect to the bank or transmit the file; you download the XML and upload it through your bank portal.
SEPA credit transfer Odoo 19, PAIN.001.001.03 generator Odoo, PAIN.001.001.09 ISO 20022 Odoo, SEPA XML batch vendor payment Odoo Community, IBAN BIC validation Odoo, ISO 20022 credit transfer file Odoo, SEPA pay run bank upload Odoo, EUR vendor payment file generator
Please log in to comment on this module