| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Sales (sale_management) • Purchase (purchase) • Discuss (mail) |
| Community Apps Dependencies | Show |
| Lines of code | 9375 |
| Technical Name |
eh_log_customs |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Versions | 16.0 17.0 18.0 19.0 |
Customs Broker for Odoo 16
A guarded customs declaration spine with HS classification, duty and VAT lines, a deferment ledger, and a regulator-of-record adapter that country packs plug into.
See it in action

The broker workspaceDeclarations keyed by broker reference and declaration type, with regulator-of-record routing and a clean open / queried / cleared lifecycle.

Declaration detailHS classification, duty and VAT, deferment account ledger and the regulator adapter all on one file.
Why this module
Customs Broker for Odoo 16
The spine ships, the country pack does the wire
This module carries the declaration lifecycle, the deferment ledger, and the HS model. The regulator protocol lives in a separately registered adapter, so the engine holds zero knowledge of any specific authority. Submit without a registered adapter and it raises with the list of providers it does know, never a silent no-op.
States move through buttons, not raw writes
Ten declaration states with a whitelisted transition table. A direct write to the state field is rejected outright. Marking a declaration ready blocks on missing HS lines, missing HS codes, zero customs value, or a missing regulator profile. Submission blocks when the deferment balance is below what is payable.
A deferment ledger that actually computes
The deferment account balance is computed from posted ledger entries, opening balance plus credits minus debits, with cancelled entries excluded. Paying an assessed declaration auto-posts the duty and VAT debit back to the account, linked to the declaration for traceability. A low-balance threshold flags accounts before they block a submission.
Day in the life
From confirmed order to cleared declaration
An operator opens a declaration, picks the type, and adds HS lines. Each line pulls a default duty and VAT rate from the HS code, then computes duty as value times rate and VAT on value plus duty. Marking it ready runs the preflight: no lines, no HS code, zero value, or no regulator profile each block with a specific message. Submit dispatches through the regulator adapter; with no country pack installed it raises cleanly, listing the providers it recognises. Once assessed, paying it debits the deferment account and the balance ticks down. Every transition writes an audit event and posts to the chatter.
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.
Writing the state field directly, outside the action buttons, is rejected with error EHL-CUSTOMS-DECL-001. State only moves through the guarded transition methods so the audit trail and preflight checks cannot be bypassed.
The transition table is a strict whitelist. Jumping from ready straight to cleared, or any move not in the allowed set, raises a state-conflict error naming the current state and the transitions that are legal from it.
Submitting when no adapter is registered for the profile's provider code raises a configuration-missing error that lists every registered provider. The engine never falls back to a no-op or a mock unless a mock-mode adapter is explicitly registered.
If the deferment account balance is below the declaration's payable amount, submission is blocked with the account label, current balance, and payable shown, so the broker tops up before filing rather than after a rejection.
HS codes are validated all-digit with length 2, 4, 6, 8, or 10. A non-numeric code or a five-digit code is rejected at write. The same code is allowed once per country (empty country is WCO scope), so national overlays do not collide.
A cancelled deferment entry is excluded from the live balance computation entirely, so reversing a top-up or a duty debit restores the balance without leaving a phantom amount.
What is inside
Built to do the job, end to end.
- Declaration spine and state machine. eh.log.customs.declaration carries parties, regulator-of-record, declaration number and date, HS lines, computed customs value, duty, VAT and total payable, broker reference, deferment account, and a ten-state lifecycle (draft, ready, submitted, queried, assessed, paid, cleared, closed, cancelled, rejected) with a whitelisted transition table and per-step preflight guards.
- HS classification model. eh.log.customs.hs.code is a hierarchical chapter, heading, subheading, and national-line model with automatic level inference from code length, all-digit length validation, per-country uniqueness, and default duty and VAT rates that flow onto declaration lines. A 16-chapter seed ships; country packs add the deeper national overlays.
- Deferment account ledger. eh.log.customs.deferment.account is the broker's prepaid float at a customs authority, with a live balance computed from eh.log.customs.deferment.entry rows (credits for top-ups, debits for duty), a configurable low-balance flag, and account-number uniqueness per regulator and company. Paying a declaration auto-posts the duty and VAT debit.
- Regulator-of-record adapter. Each declaration links to an eh.log.adapter.profile. The submit action builds a neutral payload dict and dispatches through the shared adapter registry with an idempotency key, so any country pack can map the payload to its wire format. Adapter exchanges are recorded with correlation id and redacted payloads in the suite's audit message log.
- Declaration types and sale-order linkage. eh.log.customs.declaration.type seeds the universal directions (Import, Export, Transit, Transfer, Re-export, Temporary Admission) with a requires-deferment flag, extensible per country. A declaration links back to its sale order, and the sale order shows a smart-button counter of its declarations.
- Multi-company, audit, and search. Record rules isolate declarations, deferment accounts, and entries by company. Every state transition logs an event and posts to the chatter. List, form, kanban, calendar, pivot, and graph views ship with a search view for filtering and grouping by state, type, regulator, and customer.
Honest about the edges
What this does not do, so nothing surprises you.
- Declarations are created and operated by hand. This module does not auto-spawn declarations when a sale order is confirmed; the sale order carries a smart-button counter only. Plan to create each declaration from the workspace.
- No regulator wire protocol ships in this module. Submission dispatches through an adapter that a country localisation pack must register. With no pack installed, submit raises a clear configuration error rather than transmitting anything.
- The HS seed is chapter-level only (16 chapters). Heading, subheading, and national tariff lines with country-specific duty and VAT rates come from country packs, not from this base module.
- Duty and VAT are computed from per-line rates you supply or that the HS code defaults provide. There is no live tariff-database lookup, no multi-currency declared-value conversion, and no customs-valuation engine beyond value times rate.
- There is no built-in document register, dangerous-goods classification guard, penalty or dispute workflow, pre-arrival notification, or period-end statement PDF in this module. Those are out of scope for the declaration spine.
- Deferment debits are posted on payment of an assessed declaration. The module does not reserve or ring-fence a balance at submission time; the submission guard checks the balance but does not hold it.
customs broker odoo, customs clearance odoo 19, customs declaration management, HS code classification, harmonised system tariff, duty and VAT calculation, deferment account ledger, regulator of record adapter, single window customs, freight forwarding customs, 3PL customs module, import export declaration, customs declaration lifecycle, multi company customs odoo, odoo 19 community logistics
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