feat: let other apps route e-invoices per business unit through hooks
Problem
Some companies invoice on behalf of several business units. A cooperative of activity and employment (CAE, served by the Ruche app) issues the invoices of each entrepreneur's activity, called an "enseigne". It registers one routing code per unit in the directory (SIREN_CODE).
- Outbound: eTransactions always sends from the company's own electronic address (BT-34).
- Inbound: nothing tells which unit a received invoice is addressed to. The buyer's electronic address (BT-49) is parsed but not used.
Root cause
The seller's identity is read only from the Company. The data passed from a received eInvoice to the Supplier Invoice has no extension point. The app declares no custom hooks (frappe.get_hooks isn't used anywhere).
Fix
Two generic hooks, documented in the new etransactions/utils/hooks.py. The module also has two helpers, first_hook_result and merged_hook_values.
etransactions_seller_electronic_address:fn(sales_invoice) -> str | Nonereturns the directory identifier the invoice is sent from, e.g."123456789_ATELIER"or"0225:123456789_ATELIER".- The first non-empty answer replaces the company's electronic address in
EInvoiceMapper.map_electronic_addresses. - The CII and UBL writers read it from the eInvoice, so both formats follow.
- Without an answer, nothing changes.
- The first non-empty answer replaces the company's electronic address in
etransactions_incoming_invoice_values:fn(einvoice) -> dict | Nonereturns extra header values merged intoIncomingInvoiceDataTransformer.get_data. These are the Supplier Invoice's values.SupplierInvoice.get_purchase_invoicealready copies header fields by fieldname, so a field that exists on both DocTypes (e.g. an accounting dimension) reaches the Purchase Invoice.
Ruche uses both hooks to send each enseigne's invoices from its own routing code, and to put received invoices on the addressed enseigne's accounting dimension.
Tests
- New
etransactions/tests/test_extension_hooks.py(unit tests, no database):- hook helper order and merging;
- the seller address comes from the hook, or falls back to the company's;
- hook values end up in the Supplier Invoice data.
test_incoming_flow,test_routingandtest_ubl_generatorstill pass.