Інструкції для мульти-компаній¶
Попередження
Цей посібник вимагає добрих знань Odoo. За потреби, будь ласка, спочатку ознайомтеся з посібником Server framework 101.
Починаючи з версії 13.0, користувач може одночасно входити до облікових записів кількох компаній. Це дозволяє користувачеві отримувати доступ до інформації з кількох компаній, а також створювати/редагувати записи в середовищі з кількома компаніями.
Якщо це не керувати належним чином, це може бути джерелом багатьох невідповідних дій у кількох компаніях. Наприклад, користувач, який увійшов до облікових записів обох компаній, A та B, може створити замовлення на продаж у компанії A та додати до нього продукти, що належать компанії B. Помилки доступу до замовлення на продаж виникнуть лише після виходу користувача з компанії B.
Щоб правильно керувати поведінкою кількох компаній, ORM Odoo надає кілька функцій:
Залежні від компанії поля¶
Коли запис доступний від кількох компаній, ми маємо очікувати, що певному полю будуть призначені різні значення залежно від компанії, від якої встановлено значення.
Щоб поле одного й того ж запису підтримувало кілька значень, його необхідно визначити з атрибутом company_dependent
, встановленим на True
.
from odoo import api, fields, models
class Record(models.Model):
_name = 'record.public'
info = fields.Text()
company_info = fields.Text(company_dependent=True)
display_info = fields.Text(string='Infos', compute='_compute_display_info')
@api.depends_context('company')
def _compute_display_info(self):
for record in self:
record.display_info = record.info + record.company_info
Примітка
Метод _compute_display_info
прикрашено depends_context('company')
(див. depends_context
), щоб забезпечити переобчислення обчисленого поля залежно від поточної компанії (self.env.company
).
Коли зчитується поле, залежне від компанії, для отримання його значення використовується поточна компанія. Іншими словами, якщо користувач увійшов до компаній A та B, де A є основною компанією, і створив запис для компанії B, значення полів, залежних від компанії, буде таким самим, як у компанії A.
Щоб прочитати значення полів, залежних від компанії, встановлених іншою компанією, ніж поточна, нам потрібно переконатися, що компанія, яку ми використовуємо, є правильною. Це можна зробити за допомогою with_company()
, який оновлює поточну компанію.
# Accessed as the main company (self.env.company)
val = record.company_dependent_field
# Accessed as the desired company (company_B)
val = record.with_company(company_B).company_dependent_field
# record.with_company(company_B).env.company == company_B
Попередження
Щоразу, коли ви обчислюєте/створюєте/… речі, які можуть працювати по-різному в різних компаніях, вам слід переконатися, що все, що ви робите, робиться в потрібній компанії. Завжди використовувати with_company
не коштує дорого, щоб уникнути проблем пізніше.
@api.onchange('field_name')
def _onchange_field_name(self):
self = self.with_company(self.company_id)
...
@api.depends('field_2')
def _compute_field_3(self):
for record in self:
record = record.with_company(record.company_id)
...
Відповідність мульти-компаній¶
Коли запис стає можливим для спільного використання кількома компаніями за допомогою поля company_id
, ми повинні подбати про те, щоб його не можна було пов’язати із записом іншої компанії через реляційне поле. Наприклад, ми не хочемо, щоб замовлення на продаж та його рахунок належали різним компаніям.
Щоб забезпечити узгодженість між мульти-компаніями, ви повинні:
Встановіть для атрибута класу
_check_company_auto
значенняTrue
.Визначте реляційні поля з атрибутом
check_company
, встановленим наTrue
, якщо їхня модель має полеcompany_id
.
Для кожного create()
і write()
запускатимуться автоматичні перевірки, щоб забезпечити узгодженість запису для кількох компаній.
from odoo import fields, models
class Record(models.Model):
_name = 'record.shareable'
_check_company_auto = True
company_id = fields.Many2one('res.company')
other_record_id = fields.Many2one('other.record', check_company=True)
Примітка
Поле company_id
не можна визначати за допомогою check_company=True
.
- Model._check_company(fnames=None)[source]¶
Перевірте компанії значень наведених імен полів.
- Параметри
fnames (list) – назви реляційних полів для перевірки
- Викликає
UserError – якщо
company_id
значення будь-якого поля не входить до[False, self.company_id]
(абоself
, якщоres_company
).
Для реляційних полів
res_users перевіряє, що звукозаписна компанія є в полях `company_ids
.Користувача з основною компанією A, який має доступ до компаній A і B, можна призначити або пов’язати із записами в компанії B.
Попередження
Функція check_company
виконує сувору перевірку! Це означає, що якщо запис не має company_id
(тобто поле не є обов’язковим), його не можна пов’язати із записом, у якого встановлено company_id
.
Примітка
Якщо в полі не визначено домен і check_company
має значення True
, додається домен за умовчанням: ['|', '('company_id', '=', False), ('company_id', ' =', company_id)]
Компанія за замовчуванням¶
Коли поле company_id
є обов’язковим у моделі, гарною практикою є встановлення компанії за замовчуванням. Це спрощує процес налаштування для користувача або навіть гарантує його дійсність, коли компанія прихована від перегляду. Дійсно, компанія зазвичай прихована, якщо користувач не має доступу до кількох компаній (тобто, коли користувач не має групи base.group_multi_company
).
from odoo import api, fields, models
class Record(models.Model):
_name = 'record.restricted'
_check_company_auto = True
company_id = fields.Many2one(
'res.company', required=True, default=lambda self: self.env.company
)
other_record_id = fields.Many2one('other.record', check_company=True)
Представлення¶
Як зазначено в вище, компанія зазвичай прихована від перегляду, якщо користувач не має доступу до кількох компаній. Це оцінюється за допомогою групи base.group_multi_company
.
<record model="ir.ui.view" id="record_form_view">
<field name="name">record.restricted.form</field>
<field name="model">record.restricted</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="company_id" groups="base.group_multi_company"/>
<field name="other_record_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
Правила безпеки¶
Працюючи із записами, які спільно використовуються між компаніями або обмежено однією компанією, ми повинні подбати про те, щоб користувач не мав доступу до записів, що належать іншим компаніям.
Це досягається за допомогою правил безпеки на основі company_ids
, які містять поточні компанії користувача (компанії, які користувач позначив у віджеті для кількох компаній).
<!-- Shareable Records -->
<record model="ir.rule" id="record_shared_company_rule">
<field name="name">Shared Record: multi-company</field>
<field name="model_id" ref="model_record_shared"/>
<field name="global" eval="True"/>
<field name="domain_force">
['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
</field>
</record>
<!-- Company-restricted Records -->
<record model="ir.rule" id="record_restricted_company_rule">
<field name="name">Restricted Record: multi-company</field>
<field name="model_id" ref="model_record_restricted"/>
<field name="global" eval="True"/>
<field name="domain_force">
[('company_id', 'in', company_ids)]
</field>
</record>