Введение
Одна из тихих, но важных возможностей модели данных Odoo — это атрибут, который позволяет одному и тому же полю хранить разные значения для разных юридических лиц. На первый взгляд это мелочь, но в проектах с несколькими компаниями она реально экономит кучу времени и предотвращает дублирование данных.
В стандартной установке поля записывают одно значение для всех пользователей. Но в реальности часто встречаются ситуации: общий каталог товаров, но у каждой компании свои внутренние коды, свои счета по умолчанию или свои поставщики. Простая однозначная запись перестаёт работать в мультикомпанийной среде.
Именно для таких задач и предназначен атрибут company_dependent. Независимо от того, вы пишете модули, настраиваете систему или анализируете возможности платформы, понимание этой опции даёт преимущества при проектировании мультикомпанийных решений.
Что такое поле с зависимостью от компании в Odoo
Поле с зависимостью от компании — это обычное поле модели, но за ним скрывается особый механизм хранения: одна и та же запись может иметь разное значение поля в контексте разных компаний. Пользователь из одной компании видит своё значение, другой — своё, хотя формально это один и тот же объект в базе.
Для пользователя в интерфейсе поле выглядит как любое другое — ввод, просмотр, редактирование происходят привычно. Скрытая часть — логика ORM и способ хранения — обеспечивает нужную семантику данных.
Как это отражается в интерфейсе
В веб-интерфейсе Odoo пользователь не увидит каких-то заметных меток или флажков — поле визуально ничем не отличается от обычного. Это сделано намеренно: поведение прозрачно для конечного пользователя, чтобы не усложнять UX в повседневной работе.
С точки зрения разработчика, company_dependent можно применять к разным типам полей: Char, Boolean, Integer, Float, Many2one и т.д. Достаточно указать company_dependent=True в объявлении поля, и ORM возьмёт на себя организацию хранения и доступа.
В Odoo Studio часть таких полей уже доступна на стандартных моделях, особенно в области продуктов и аккаунтов. Однако возможности Studio в разных версиях различаются: для полного контроля часто удобнее создавать поля программно в модуле.
Как это поле работает
Под капотом поведение отличается от обычного поля, и понимание механизма хранения помогает предвидеть возможные трудности при отладке и миграции данных.
Хранение в ir.property
В версиях Odoo до 17 включительно значения company_dependent полей не лежат в таблице модели, а сохраняются в системной таблице ir.property — своеобразном «реестре» свойств, где одна запись связывает объект, поле и компанию с конкретным значением.
Каждая запись в ir.property привязывает несколько сущностей одновременно:
- Конкретную запись модели (например, product с id 42),
- Конкретное поле (например, property_account_income_id),
- Конкретную компанию,
- И само значение для этой связки.
Поэтому для пользователя всё выглядит прозрачно: ORM автоматически подставляет и сохраняет значение в ir.property в зависимости от текущего контекста компании.
Изменения в Odoo 17 и выше
С выходом Odoo 17 механизм хранения был переработан: значения стали сохраняться прямо в таблице модели в поле типа jsonb, где ключи — id компаний, а значения — соответствующие значения полей. Это ускорило выборки и упростило работу с большими объёмами данных.
Интерфейс для разработчиков и API остались привычными, но запросы и отчётность по таким полям теперь выполняются значительно быстрее при больших объёмах данных.
Значения по умолчанию
Company_dependent поля поддерживают значения по умолчанию для каждой компании. Если для компании значение не задано явно, используется дефолт, определённый в описании поля или через ir.property (в старых версиях) — в Odoo 17+ дефолты хранятся прямо в модели.
Взаимодействие с ORM
При доступе к company_dependent полю ORM всегда учитывает текущую компанию из окружения (self.env.company). Отсюда следуют ключевые правила:
- Чтение возвращает значение для активной компании,
- Запись меняет значение только для активной компании,
- С помощью record.with_company(company) можно читать или записывать значение в контексте конкретной компании.
Практические сценарии использования в бизнесе
Поле с зависимостью от компании — не теоретическая причуда, а практичный инструмент. Ниже — несколько типичных задач, где оно особенно полезно.
1) Бухгалтерия: отдельные счета доходов и расходов на компанию
Частый пример в стандартной конфигурации — поля property_account_income_id и property_account_expense_id у товара, которые различаются по компаниям.
На практике это значит, что один и тот же товар в общем каталоге может иметь разные бухгалтерские проводки в каждой компании, избегая необходимости дублировать карточки товара ради учёта.
2) Продажи и CRM: разные прайс-листы по компаниям
В группе компаний ценовая политика может отличаться: одна компания продаёт по фиксированным тарифам, другая — по дисконтным или по своим акциям. Company_dependent поле для прайс-листа позволяет одному клиенту «принадлежать» разным ценовым стратегиям в зависимости от того, какая компания оформляет заказ.
Это даёт централизованную CRM с возможностью локальных коммерческих правил.
3) Склад: метод оценки запасов по компании
В разных юрисдикциях группы могут требовать разные методы учёта себестоимости (FIFO, средняя и т.д.). Company_dependent поле на товаре или категории поможет задавать метод оценки отдельно для каждой компании, не размножая каталог товаров.
4) Производство: предпочитаемый поставщик на компанию
Если один и тот же товар закупается у разных поставщиков в разных компаниях, удобнее хранить ссылку на preferred supplier как company_dependent many2one на res.partner — каждая компания увидит своего поставщика.
5) Регуляторные данные: кастомные поля по юрисдикциям
Для международных групп часто нужно хранить специфику по стране — таможенные коды, налоговые классификации и пр. Company_dependent Char-поле позволяет держать эти значения прямо в карточке товара без создания отдельных версий модели.
Создание и настройка такого поля
Создать company_dependent поле можно двумя способами: через Odoo Studio или программно в модуле на Python.
Через Odoo Studio
Studio удобно для быстрого прототипирования без кода, но в нём не всегда доступна явная опция company_dependent во всех версиях. В Odoo 16–17 некоторые типы полей позволяют включить поведение прямо в Studio, но для гибкого управления лучше иметь доступ к техническим настройкам.
Если нужен полный контроль — лучше писать поле в модуле. Studio хорош для простых случаев и быстрого теста, но его возможности ограничены для серьёзных кастомизаций.
Технический подход: поля в Python
В модуле декларация такого поля делается обычным способом — к объявлению поля добавляют company_dependent=True. Это стандартный паттерн для разработки полей в Odoo.
Пример кода в модуле (контекст):
Достаточно добавить company_dependent=True при объявлении поля, и ORM выполнит всю необходимую работу по хранению и выдаче значений в нужном контексте.
Установка значений по умолчанию для каждой компании
В Odoo 16 и ранее дефолтные значения для компании задавались через ir.property, что удобно для массовой установки значения для всех записей в компании без ручного редактирования каждой карточки:
Пример использования API ir.property для задания дефолта программно показан выше.
В Odoo 17+ дефолты можно задавать непосредственно на модели и управлять ими более прозрачно через определение поля.
Особенности Odoo Studio и нюансы
При работе со Studio не забывайте про обязательный префикс x_ для пользовательских полей. Поведение company_dependent может быть невидимо в визуальном редакторе, но его можно настроить через техническое меню при включённом режиме разработчика.
Рекомендации по использованию
Простые правила и практики помогут избежать проблем при проектировании и сопровождении решения.
1) Используйте только там, где реально нужны разные значения для компаний
Если значение одинаково для всех юридических лиц — не усложняйте модель. Company_dependent добавляет уровень абстракции, который оправдан только при реальной вариативности данных между компаниями.
2) Всегда тестируйте в мультикомпанийном контексте
Разрабатывайте и проверяйте сценарии с минимум двумя активными компаниями. Многие ошибки проявляются только при переключении компании или при операциях между юнитами.
3) Для операций между компаниями используйте with_company()
Если нужно читать или записывать значение для другой компании, используйте record.with_company(target_company) — так вы не нарушите глобальный контекст окружения и не создадите побочных эффектов.
4) Будьте внимательны при экспортах/импортах
Экспорт покажет значения в контексте компании пользователя, который его выполняет; импорт под другой компанией запишет значения для неё. Учитывайте это при миграциях и сценариях массового обновления данных.
5) Документируйте, какие поля зависят от компании
Пользователи редко знают, какие поля показываются по-разному при смене компании. Короткая запись в документации или onboarding’е избавит от множества вопросов и недоразумений.
6) Для ссылочных данных предпочитайте Many2one вместо текста
Если значение — ссылка на другой объект (счёт, прайс-лист, партнёр), используйте company_dependent Many2one. Это сохраняет целостность данных и облегчает отчётность.
Типичные ошибки и подводные камни
Даже опытные разработчики иногда наступают на те же грабли. Зная распространённые ошибки, вы сэкономите время на отладке.
Ошибка 1: забыть про контекст компании в автоматических действиях
Планировщики, серверные действия и батч-задачи часто выполняются в контексте первой компании базы, а не той, которую вы ожидаете. Если автоматизация пишет или читает company_dependent поле — явно задавайте company через with_company().
Ошибка 2: путать с вычисляемым полем
Company_dependent не означает compute-поля. Различие — в способе получения значения: здесь разнообразие достигается через хранение, а не вычисление. Попытки комбинировать compute= с company_dependent=True могут привести к некорректной работе или исключениям.
Ошибка 3: поиск по всем компаниям
Обычные ORM-запросы возвращают значения в текущем контексте компании. Если вам нужно найти значения по всем компаниям, в старых версиях придётся работать с ir.property напрямую, в новых — аккуратно обрабатывать jsonb-колонку.
Ошибка 4: не задать дефолты для всех компаний
При внедрении нового company_dependent поля в рабочей системе существующие записи для компаний без явного значения будут пустыми. Если бизнес-логика требует значения по умолчанию — примените миграцию данных для всех компаний заранее.
Ошибка 5: путать с правами доступа
Это поле управляет тем, какое значение показывается, а не тем, видит ли пользователь само поле. Для скрытия поля в зависимости от компании или роли нужно использовать правила доступа или record rules, а не company_dependent.
Выводы
Поле с зависимостью от компании — такая функция, которую незаметно не замечаешь, пока она не понадобилась. Но как только требуется, оно становится незаменимым: совместный каталог, разные бухгалтерские настройки, локальные регуляторные требования — всё это решается аккуратно и без дублирования записей.
Разобраться, где и как данные хранятся, в каких версиях что изменилось и каких ошибок стоит избегать — значит существенно ускорить проект и избежать типичных проблем в мультикомпанийных внедрениях. Знание этой опции — признак профессионального подхода к Odoo.
Если ваша задача — корректно организовать данные по компаниям в Odoo, то company_dependent=True — именно тот инструмент, который вам нужен.
Нужна помощь с внедрением Odoo?
В компании Dasolo мы помогаем проектам любого масштаба проектировать и внедрять Odoo, включая сложные мультикомпанийные настройки. Нужна настройка модели данных, стратегия по кастомным полям или полный разворот системы — у нас есть опыт и экспертиза, чтобы сделать это правильно.
Если у вас остались вопросы по полям с зависимостью от компании или другим аспектам внедрения Odoo — мы готовы помочь. Свяжитесь с нами и обсудим ваш проект.