Odoo multi-company: one database, many entities, zero double entry
Running two or ten legal entities from one Odoo database sounds simple until inter-company invoicing, shared warehouses and per-company charts of accounts collide. The setup decisions we make on day one so consolidation stays painless.
The pattern is everywhere in Belgian SMEs: an operating company, a real estate entity that owns the building, maybe a management vennootschap on top, and — the moment business crosses the border — a French or Dutch subsidiary. Four legal entities, four sets of books. And in most of the intakes we see, four systems: the invoice from entity A to entity B gets typed twice, once outgoing, once incoming, and someone reconciles the mess in Excel at year-end.
So the question lands on our desk as: "can Odoo handle multiple companies?" Yes — natively, and well. But multi-company is not a checkbox, it's an architecture. Configured deliberately on day one it eliminates the double entry entirely; retrofitted in year two it's the most expensive cleanup job in ERP. Here's where the decisions actually live.
One database, many companies — what that means
In Odoo, companies are rows in one database, not separate installs. Every user has a set of allowed companies and one active company; every business document — quotation, delivery, journal entry — carries a company_id and is filtered by record rules so users only see what their current selection allows. One login, one product catalogue if you want it, and books that stay legally separate because the accounting layer is strictly per company.
That split is the part people underestimate. These are always per company, no exceptions:
- Chart of accounts — driven by localization:
l10n_befor the Belgian entity,l10n_frfor the French one, each with its own account plan, tax grids and statutory reports. - Journals and sequences — invoice numbering is a legal requirement per entity. Shared sequences across companies are an audit finding waiting to happen.
- Taxes and fiscal positions — Belgian 21% and French 20% are different records, mapped per company.
- Bank accounts and payment journals — one entity's IBAN never posts into another's books.
What can be shared is master data — and that's a choice, not a default.
Shared or separate: decide per object, on day one
Contacts and products in Odoo have an optional company field: leave it empty and the record is visible to every company; set it and the record belongs to one entity. Our default recommendation is boring and firm — share the catalogue and the address book, separate everything financial. One customer record for the client that buys from two of your entities beats three divergent copies with three different VAT numbers typed in.
The trap is how shared data gets created in practice. A user working with entity B active creates a product, Odoo quietly stamps it company_id = B, and three weeks later entity A's sales team swears the product doesn't exist. Nine out of ten multi-company "bugs" we're called in for are exactly this — records accidentally pinned to one company. The record rule behind the scenes is short enough to read:
['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]Empty means everyone, set means members only. The fix is process, not code: decide per model who may create shared records, default the company field explicitly, and audit company_id on products and partners before go-live — a one-line SQL check that saves weeks of confusion.
Inter-company transactions: the double-entry killer
This is the feature the holding structure actually buys the licence for. With inter-company rules enabled, entity A confirming a purchase order on entity B makes Odoo generate the mirrored sales order in B automatically — same products, same quantities, agreed prices. Invoice it, and the customer invoice in B produces the matching draft vendor bill in A. The numbers agree by construction, because they were never entered twice.
Two configuration decisions matter more than the checkbox:
- Draft or validated? Odoo can post the mirrored document automatically or leave it in draft for a human. Start with draft — let the accountant of the receiving entity confirm the first month of flows, then automate once the mappings prove out.
- Mapping completeness. The mirroring only works when both companies know the products, taxes and payment terms involved. A product visible only to entity B cannot appear on entity A's mirrored bill. This is where the shared-catalogue decision from the previous section pays off — or collects its debt.
Each entity also needs a partner record for its siblings (entity B is literally a customer of entity A), with the real inter-company pricing on it. Which brings up the part Odoo won't do for you: transfer pricing is a fiscal topic. Odoo executes the agreed price flawlessly; agreeing it is between you and your accountant.
Shared warehouses without shared books
The physical reality of most groups: one warehouse, owned by one entity, shipping for all of them. The tempting shortcut is letting every company sell straight from that stock. Don't — stock is an asset on someone's balance sheet, and goods leaving entity A's warehouse on entity B's delivery note is the kind of creativity auditors write paragraphs about.
Odoo's answer is inter-company resupply routes: entity B sells, the route triggers a resupply from entity A's warehouse, the goods move through an inter-company transfer with its own document trail, and the inter-company invoicing from the previous section prices the movement. Configured once, the whole chain — B's sale, A's internal transfer, the mirrored invoice pair — runs from a single order confirmation. The accountant gets a paper trail; the warehouse team picks one order like any other.
Consolidation is reporting, not bookkeeping
Statutory books stay per entity — that part Odoo enforces for you. The group-level view is a reporting exercise on top: eliminate the inter-company flows, translate currencies, present one P&L. Odoo Enterprise ships a consolidation module that handles ownership percentages and elimination entries; for groups that mostly need management consolidation rather than statutory, we as often point a BI layer at the database and build the eliminated view there — every inter-company transaction is already tagged with the sibling partner, so filtering it out is a query, not a quarter-end project.
Either way, the consolidation is only as clean as the discipline upstream. Groups that let inter-company flows happen outside the mirrored documents — a quick manual invoice here, a correction there — rediscover Excel reconciliation, just with better fonts.
When one database is the wrong answer
Multi-company is the right default for a group under common management, but we've talked clients out of it too:
- An entity that might be sold. Carving one company's data out of a shared database for due diligence is painful; if divestment is plausible, a separate database with API integration is cheaper insurance.
- Genuinely unrelated businesses. Shared master data between a construction firm and a restaurant chain shares nothing but risk.
- Different lifecycles. If one entity needs to stay on an old version while another moves, one database can't serve two masters — see our position on upgrade-proof customisation.
The common thread: multi-company optimises for shared operations. No shared operations, no benefit — only blast radius.
The cheap moment is now
Every decision above — what's shared, how inter-company flows are mirrored, who owns the stock — costs a workshop afternoon before go-live and a re-implementation after it. That's precisely why the entity structure is one of the first things we map in the fit-gap analysis of every Odoo implementation: which companies exist, which will exist in three years, and which flows cross the lines between them.
One database, many entities, zero double entry — but only if it's designed, not discovered.
Want us to publish something specific?
Tell us what you'd like to read and we'll add it to our writing queue.
Get the next one in your inbox
New articles, videos and the occasional engineering note — a short mail when there’s something worth reading, nothing else.