Enable Dark Mode!
how-to-configure-multi-company-domains-in-odoo-19.jpg
By: Sayed Mahir Abdulla KK

How to Configure Multi-Company Domains in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

Multi-company functionality in Odoo 19 allows a single database to manage multiple legal entities while maintaining proper data segregation. One of the core mechanisms enabling this is the use of domains, which control record visibility and selection based on the active company or allowed companies.

This blog explains how multi-company domains work in Odoo 19, how they are implemented at both the UI and ORM levels, and how to correctly design them in custom modules.

Understanding Multi-Company Behavior in Odoo 19

In a multi-company environment:

  • Each record may belong to a specific company (company_id)
  • Some records are shared across companies (company_id = False)
  • Users can have access to multiple companies simultaneously

Odoo automatically filters records based on:

  • Current company (env.company)
  • Allowed companies (env.companies)

Domain:

A domain in Odoo is a filter expression used to restrict records. It is defined as a list of tuples:

[('field_name', 'operator', value)]

Example:

[('company_id', '=', env.company.id)]

Default Multi-Company Domain Behavior

Odoo internally applies a domain like:

['|', ('company_id', '=', False), ('company_id', 'in', allowed_company_ids)]

This ensures:

  • Shared records (no company) are visible
  • Records belonging to allowed companies are visible

Using Domains in Fields (UI Level)

Domains are often applied in field definitions to restrict selectable records.

Example: Restricting a Many2one Field

partner_id = fields.Many2one(
   'res.partner',
   domain="[('company_id', 'in', allowed_company_ids)]"
)

With Shared Records

partner_id = fields.Many2one(
   'res.partner',
   domain="['|', ('company_id', '=', False), ('company_id', 'in', allowed_company_ids)]"
)

Using Domains in XML Views

You can also define domains directly in views.

Example:

<field name="partner_id" domain="[('company_id', 'in', allowed_company_ids)]"/>

Using Domains in Python (ORM Level)

When writing backend logic, always ensure company-safe domains.

Example:

records = self.env['sale.order'].search([
   ('company_id', 'in', self.env.companies.ids)
])

Including Shared Records

records = self.env['sale.order'].search([
   '|',
   ('company_id', '=', False),
   ('company_id', 'in', self.env.companies.ids)
])

Special Variables for Multi-Company

Odoo provides useful variables:

VariableDescription
env.companyCurrent company
env.companiesSelected multiple companies
allowed_company_idsUsed in UI domains for allowed companies

Common Mistakes

1. Using Only env.company

('company_id', '=', env.company.id)

Problem: Blocks access to other allowed companies

2. Ignoring Shared Records

('company_id', 'in', env.companies.ids)

Problem: Excludes global records

3. Hardcoding Company IDs

('company_id', '=', 1)

Problem: Breaks portability

Best Practices

  • Always use env.companies.ids instead of env.company.id
  • Include shared records when needed
  • Avoid hardcoding company IDs
  • Use consistent domain patterns across modules

Real-World Example

Scenario: Multi-Company Product Selection

You want users to select products only from allowed companies.

Python Field

product_id = fields.Many2one(
   'product.product',
   domain="['|', ('company_id', '=', False), ('company_id', 'in', allowed_company_ids)]"
)

XML View

<field name="product_id"
      domain="['|', ('company_id', '=', False), ('company_id', 'in', allowed_company_ids)]"/>

Debugging Multi-Company Domains

  • Enable developer mode
  • Inspect applied domains in views
  • Use logs to check env.companies.ids

Example:

_logger.info(self.env.companies.ids)

Multi-company domains are essential for maintaining data isolation and integrity in Odoo 19. Understanding how Odoo applies implicit domains and how to correctly extend them ensures that your custom modules behave correctly in complex multi-company setups.

By following best practices and avoiding common pitfalls, you can build robust, scalable multi-company solutions.

To read more about How to Use Dynamic Domains in Odoo 19 Views, refer to our blog How to Use Dynamic Domains in Odoo 19 Views.


Frequently Asked Questions

Why do I need to include ('company_id', '=', False) in my domain — can't I just filter by company IDs?

In Odoo 19, some records are intentionally shared across all companies — products, countries, currencies, and certain master data records have company_id = False. If your domain only filters by company IDs like ('company_id', 'in', env.companies.ids), those shared records become invisible to the user, which breaks selection fields and search results.

Do I need to define multi-company domains in both the Python field definition and the XML view, or is one enough?

They serve different purposes, so both are often needed. The Python field domain (domain= on the fields.Many2one) acts as a default and is used when the field is accessed programmatically or via the ORM. The XML view domain (domain= on the tag) controls what the user sees in the UI dropdown when selecting a record on a form. If you only set it in Python, the UI may still show records from other companies in the dropdown.

If I hardcode a company ID in a domain like ('company_id', '=', 1), will it work and what problems can it cause?

It will technically work in the specific database where company ID 1 happens to be the right company, but it is one of the worst practices in Odoo development. The core problem is portability — when the module is installed on a different database, company IDs are assigned differently, so ID 1 may belong to a completely different company or may not even exist.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, KINFRA Techno Park
Kakkanchery, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message