What Multi-Company Means in Odoo#
Odoo's multi-company feature allows a single Odoo database to host multiple legal entities - each with its own chart of accounts, fiscal positions, bank accounts, and documents. Users can be members of multiple companies and switch between them in a single session.
The database is shared: all companies share the same PostgreSQL tables. Separation is enforced by company_id fields and record rules, not by physical isolation.
Which Records Are Shared, Which Are Per-Company#
Shared by default (no company_id)#
- Contacts (
res.partner): shared across all companies unless you enable the "Company-Specific" option per partner - Products (
product.template,product.product): shared by default; pricelists and costs are per-company - Product categories, units of measure, currencies
Per-company by default (have company_id)#
- Chart of accounts: each company has its own accounts, journals, and tax configuration
- Sale orders, purchase orders, invoices: always belong to a specific company
- Pricelists (when set as company-specific)
- Warehouses: a warehouse belongs to one company
Configurable#
Some records can be toggled between shared and per-company in Settings → Technical. The most common is Pricelists: you can set a pricelist as company-specific by giving it a company_id.
How Record Rules Enforce Company Separation#
Odoo uses ir.rule domain filters to restrict what a user sees. The default multi-company rule for sale orders looks roughly like:
[('company_id', 'child_of', user.company_ids.ids)]This means a user who is a member of companies A and B can see records from both companies simultaneously if both are active in their session. If you need strict separation (no cross-company visibility), remove users from the companies they should not access.
Important: Record rules apply at the ORM level, not at the SQL level. If you use raw SQL queries (via env.cr.execute), record rules are bypassed. Always use the ORM for company-sensitive queries.
Configuring Users for Multi-Company#
- Go to Settings → Users & Companies → Users → select a user
- In the Companies tab, add all companies the user should have access to
- The user's Current Company is the one active documents are created in
- Users can switch companies with the company switcher in the top menu
When a user activates multiple companies simultaneously (holding Ctrl when clicking), Odoo creates a multi-company context. Documents created in this context inherit the primary company.
Inter-Company Rules: Automatic Transactions#
Inter-company rules automate the creation of corresponding documents when a transaction occurs in one company that involves another.
Setting Up Inter-Company Rules#
Go to Settings → General Settings → Companies → enable Synchronize Operations.
For each company pair, configure:
- Sale Order → Purchase Order: when Company A creates a sale order to Company B, Odoo auto-creates a purchase order in Company B
- Purchase Order → Sale Order: the reverse
- Customer Invoice → Vendor Bill: when a posted invoice is sent to a related company, a draft vendor bill is created in the receiving company
Requirements#
- Both companies must be in the same Odoo database
- The partner record for Company B must have
company_idset to Company B'sres.companyrecord (i.e., the contact IS the company) - The user triggering the rule must have access to both companies
Common Mistakes#
Mistake 1: Shared users see each other's drafts#
If a user is a member of both Company A and Company B and activates both companies in the switcher, they see all records from both. This is by design - but it surprises teams who expect complete separation.
Fix: If you need strict isolation, keep users in only one company. Use separate login accounts for staff who genuinely work in both entities.
Mistake 2: Products have wrong costs per company#
Product cost (standard_price) is stored per-company using the property system. Setting it on the product form while logged into Company A does not affect Company B's cost.
Fix: Switch to Company B and update the standard price there explicitly.
Mistake 3: Journal entries on the wrong company's account#
When posting an inter-company invoice, Odoo uses the company on the invoice to determine which chart of accounts to use. If the invoice company_id was set incorrectly at creation, the journal entries will post to the wrong company's accounts.
Fix: Always verify company_id on draft documents before posting. Add a server action check if this is recurring.
Mistake 4: Fiscal position not found for inter-company invoice#
Inter-company invoices use the fiscal position of the receiving partner. If no fiscal position maps the inter-company partner, taxes may not be applied or removed as expected.
Fix: Define a dedicated fiscal position for inter-company transactions and assign it to the company partner record.
Multi-Company and Custom Modules#
If you are building a custom module that stores company-specific data:
- Add
company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company) - Add an
ir.rulethat filters bycompany_id in user.company_ids.ids - Add a
_sql_constraintsunique constraint that includescompany_idif the record should be unique per company but not globally
ERPeek can inspect whether your custom models have company_id fields and whether the corresponding record rules are correctly defined. See the contact page for details.

