Skip to main content
Odoo 20 Multi-Company: Products, Access & Intercompany Transactions
11 min read
Odoo

Odoo 20 Multi-Company: Products, Access & Intercompany Transactions

Learn how Odoo 20 multi-company works for shared products, company-specific data, user access, intercompany transactions, and safer customization.

Odoo 20 can run multiple companies inside one database, but “multi-company” does not mean every record is automatically isolated by legal entity.

Some records can be shared. Others belong to one company. Some fields on a shared record can even hold company-specific values. On top of that, Odoo can automate transactions between companies in the same database.

That flexibility is useful, but it is also where multi-company implementations become difficult. A product that should be shared, a user who can switch between several companies, and an invoice that must remain isolated are three different problems. Treating them as one access-control setting is how inconsistent data and confusing permissions appear later.

This guide explains the Odoo 20 model in practical terms: what is shared, what is company-specific, how product visibility behaves, how intercompany transactions work, and when custom rules are justified.

What Odoo 20 multi-company actually does

Odoo’s official Odoo 20 documentation describes multi-company as a way to configure several companies in a single database while allowing some data to be shared and other data to remain separated.

Users can be granted access to one or more companies. They can select several companies in the company switcher while one company remains the current active environment.

That distinction matters.

A user may be allowed to access Companies A, B, and C, while currently working in Company B. Code, default values, company-dependent fields, record rules, accounting configuration, and business logic can all care about that context.

Odoo also warns that enabling multi-company on a Standard subscription triggers an upsell to the Custom plan, except for One-App Free databases. Confirm the current commercial impact for the database before designing a rollout.

Official reference: Odoo 20 Multi-company documentation

Shared data and company-specific data are different concepts

A clean multi-company design starts by classifying records before configuring permissions.

Ask one question for every important model:

Should this record represent the same thing across the group, or a thing that belongs to one legal entity?

For example, a product called “Industrial Filter X200” may be the same commercial item for several companies. A posted invoice is not. It belongs to the accounting entity that issued it.

Odoo 20 supports this distinction through company-aware records and fields.

Products and contacts are shared by default

According to the Odoo 20 documentation, new products and contacts in a multi-company database are shared across companies by default.

For relevant records, leaving the Company field blank makes the record accessible across companies. Setting the Company field restricts the record to company context.

That default can be useful for a group that sells the same catalogue through several subsidiaries. The product name, reference, description, and other shared master data do not need to be recreated merely because another legal entity sells the item.

But “shared product” does not mean every value on the product is globally identical.

A shared product can still have company-specific values

The Odoo 20 documentation gives an important example: a product can share values such as Sales Price and Reference while its Cost remains company-specific.

This is the pattern to understand:

text
One shared product record
        │
        ├── shared commercial/master data
        │
        ├── Company A-specific property/value
        ├── Company B-specific property/value
        └── Company C-specific property/value

That architecture lets companies use one catalogue while retaining values that legitimately differ by company.

It also means integrations must carry the right company context. Reading a company-dependent value without the intended company can return a technically valid value for the wrong entity.

Product visibility should be designed before products are imported

Multi-company product problems are often discovered after thousands of products already exist.

Before importing or synchronizing a catalogue, classify products into at least two groups:

  1. Shared products — the same product should be available across the group.
  2. Company-restricted products — the product belongs to a specific company context.

Then test how those products behave in the workflows that actually consume them:

  • quotations and sales orders;
  • purchase orders;
  • warehouses and routes;
  • bills of materials;
  • manufacturing orders;
  • POS;
  • eCommerce;
  • price lists;
  • accounting properties;
  • API integrations.

A product appearing correctly in the Products menu is not enough. The real test is whether employees can use the correct product from the correct company without creating cross-company inconsistencies.

What if the native Company field is not granular enough?

Some organizations need rules that are more specific than a simple shared-versus-restricted model.

For example:

  • one brand can sell a product in Companies A and B but not C;
  • a regional catalogue depends on country rather than legal entity;
  • specific product categories should be hidden from selected operating companies;
  • an integration needs a separate catalogue policy from the Odoo UI.

Do not solve that by adding a visual filter and calling it security.

If the requirement goes beyond Odoo’s native company behavior, design it as an access model: explicit company relationships, record rules, consistency checks, integration tests, and migration behavior. The correct implementation depends on the model and the business rule.

Octivex’s Odoo customization and custom-module services cover this type of fit-gap work when standard behavior is not enough.

User access and the active company are not the same thing

A common implementation mistake is assuming:

“The user has access to Company B, therefore every operation will happen in Company B.”

Not necessarily.

Odoo distinguishes the companies a user can access from the current company context.

The official Odoo 20 developer tutorial explains the two concepts used by multi-company security rules:

  • company_ids: the companies available to the user in the current multi-company context;
  • company_id: the currently active company.

This matters when creating defaults, filtering records, computing fields, or building custom security.

Official reference: Odoo 20 — Restrict access to data: Multi-company security

Why cross-company access errors appear

Consider this simplified situation:

text
User can access:
- Company A
- Company B

Current company:
- Company A

Custom process creates:
- Sales Order in Company A
- Related custom record in Company B

The records may be individually accessible to the user, but the relationship can still violate company consistency.

The correct solution is not “give the user more permissions.”

The data model must respect which records are allowed to relate across company boundaries.

This is especially important for custom modules that connect sales, accounting, stock, HR, projects, or integrations.

Record rules are part of the data model, not just the UI

Odoo’s developer documentation shows multi-company rules as record rules based on company context.

A common shareable-record domain follows the idea:

python
[
    "|",
    ("company_id", "=", False),
    ("company_id", "in", company_ids),
]

Conceptually, this means:

  • records with no company can be shared;
  • company-specific records are available only when they match an allowed company context.

That example is useful for understanding the architecture, but it should not be copied blindly into every custom model.

Security rules must match the intended data ownership.

For a custom model, decide:

  • Can a record be global?
  • Must every record belong to a company?
  • Which relational records can it reference?
  • Should a user see records from all selected companies or only the active one?
  • What happens in automated jobs where there is no interactive company switcher?
  • What should external integrations see?

Those decisions should be made before writing the XML rule.

Multi-company consistency matters as much as visibility

Visibility rules answer “Can the user see this?”

Consistency rules answer “Can these records legally belong together?”

A secure implementation needs both.

For example, preventing a user from opening a Company B invoice while working only in Company A is useful. But it is even better to prevent a Company A transaction from being linked incorrectly to Company B accounting data in the first place.

When custom modules introduce company-aware records, test create and write operations under several company combinations. Do not test only as Administrator with every company selected.

A useful test matrix looks like this:

ScenarioExpected result
User has only Company ACannot access B-only records
User has A and B, A activeA defaults are used where appropriate
User has A and B, B activeB defaults are used where appropriate
Shared product used in ACompany A-specific values resolve correctly
Shared product used in BCompany B-specific values resolve correctly
A record references incompatible B recordOperation is blocked
Scheduled integration runs for BExplicit B context is applied

This catches problems that a normal single-company development database never exposes.

Intercompany transactions remove duplicate entry—but require configuration

Odoo 20 includes inter-company transaction automation for companies inside the same database.

Depending on the configuration, Odoo can create counterpart documents when one company trades with another.

The Odoo 20 documentation lists options including:

  • creating vendor bills from invoices/credit notes;
  • creating sales orders from confirmed purchase orders;
  • creating purchase orders from confirmed sales orders;
  • synchronizing stock moves between companies.

The counterpart records can also be automatically validated depending on configuration.

This is useful when, for example, a distribution company buys from a manufacturing company inside the same group.

Instead of employees re-entering both sides manually:

text
Company A confirms document
        ↓
Configured intercompany rule
        ↓
Company B counterpart is created

That reduces duplicate entry, but it does not remove accounting responsibility.

Odoo specifically warns that fiscal positions, localizations, and related configuration must be correct for inter-company transactions.

Official reference: Odoo 20 Multi-company — Inter-company transactions

Odoo 20 also documents intercompany clearing

Odoo 20 documents an Intercompany clearing feature for a different problem: one company receives payment for an invoice issued by another company in the same database.

With the required module and configuration, Odoo can create the balancing entries that represent what one company owes the other.

This is not the same thing as sharing a customer or product record.

It is an accounting workflow.

The official documentation requires the account_payment_interco module and inter-company transactions to be enabled for the relevant companies. It also requires company-specific clearing configuration in Accounting.

Treat this setup as accounting configuration, not merely automation. The payable and receivable clearing accounts, journals, payment method behavior, and reconciliation result should be reviewed with the finance team before production use.

Not every branch or business unit should become a company

Another common mistake is using multi-company to solve every organizational separation problem.

Odoo’s own use-case guidance for Odoo 20 makes the opposite point: creating an additional company can add unnecessary complexity when the requirement is simply to separate a product line or operating process.

Sometimes the better tool is:

  • multiple warehouses;
  • analytic accounting;
  • departments;
  • branches;
  • separate sales teams;
  • projects;
  • operating units implemented through a justified customization.

A new company affects much more than menu visibility. It can influence accounting, taxes, users, warehouses, security rules, intercompany flows, subscriptions, reporting, and integrations.

Create another company when the business boundary genuinely behaves like a company—not because a team wants a separate dashboard.

Multi-company integrations need explicit company context

External applications create another source of ambiguity.

Imagine a mobile app sends:

json
{
  "customer_id": 842,
  "product_id": 115,
  "quantity": 4
}

Which company owns the transaction?

If the API authenticates a user who can access several companies and the integration does not explicitly define the intended company, the payload may be incomplete even though every individual ID is valid.

For multi-company APIs and middleware, define:

  • the company that owns the transaction;
  • the companies the service account may access;
  • how the company is validated against referenced records;
  • which values are company-dependent;
  • whether shared products/contacts are allowed;
  • how retries preserve the original company;
  • how logs expose the company context.

This applies whether the client is a Flutter mobile app, eCommerce connector, payment service, warehouse scanner, or another backend.

If you are planning a connected app, Octivex also documents the broader architecture in Odoo Mobile App Development That Stays Connected.

A practical Odoo 20 multi-company checklist

Before enabling or expanding multi-company, verify the following.

Company structure

  • Each company represents a justified operational/legal boundary.
  • Branches or warehouses have not been modeled as companies without a reason.
  • Subscription impact has been confirmed.

Master data

  • Shared versus company-specific products are defined.
  • Shared versus company-specific contacts are defined.
  • Company-dependent values are identified.
  • Product/import defaults have been tested before bulk migration.

Security

  • Users have only the companies they need.
  • Custom record rules are tested with non-admin users.
  • Cross-company relational consistency is tested.
  • Scheduled jobs run in an explicit intended company context.

Operations

  • Sales and purchasing are tested per company.
  • Warehouses, routes, and stock movements are validated.
  • Accounting and tax configuration are validated separately per entity.
  • Intercompany documents are reconciled against the expected business flow.

Integrations

  • Every write operation identifies the intended company.
  • Service accounts follow least privilege.
  • Shared records do not cause company-dependent values to be read from the wrong context.
  • Retry behavior preserves company ownership.
  • Logs record enough context to investigate cross-company failures.

The right question is not “Does Odoo support multi-company?”

It does.

The more useful question is:

Which data should be shared, which data should belong to one company, and which business events should cross company boundaries?

Odoo 20 gives you the building blocks: shared records, company-aware records, company-specific values, company access controls, and intercompany automation.

A reliable implementation comes from defining those boundaries before importing data or writing custom rules.

If your database already has several companies and users are seeing the wrong products, inconsistent values, cross-company access errors, or duplicated intercompany work, Octivex Tech can audit the current model and separate configuration problems from cases that genuinely need custom development.

Official references