Odoo16howto-6 多公司指引

Odoo16howto-6 多公司指引

从13.0版本开始,用户可以同时登录多个公司。这允许用户访问来自多个公司的信息,还可以在多公司环境中创建/编辑记录

如果管理不当,它可能是许多不一致的多公司行为的根源。例如,同时登录a公司和B公司的用户可以在a公司创建销售订单,并将属于B公司的产品添加到该订单中。只有当用户从公司B注销时,销售订单才会出现访问错误。

为了正确管理多公司行为,Odoo的ORM提供了多种功能:

1.公司依赖的字段

当一条记录来自多个公司时,我们必须期望将不同的值分配给给定的字段,这取决于设置该值的公司。

为了使同一记录的字段支持多个值,必须将属性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为主要公司登录到a公司和B公司,并为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

附:

odoo.api.depends_context(*args)

返回指定非存储“compute”方法的上下文依赖关系的装饰器。每个参数都是上下文字典中的一个键:

price = fields.Float(compute='_compute_product_price')

@api.depends_context('pricelist')
def _compute_product_price(self):
    for product in self:
        if product.env.context.get('pricelist'):
            pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
        else:
            pricelist = self.env['product.pricelist'].get_default_pricelist()
        product.price = pricelist._get_products_price(product).get(product.id, 0.0)

所有依赖项必须是可哈希的。以下键有特殊支持:

  • 公司(上下文中的值或当前公司id),
  • Uid(当前用户id和超级用户标志),
  • Active_test(在环境中的值)上下文或field.context中的值)。

不好意思,这一小节没怎么看懂

2.多公司一致性

当一条记录通过company_id字段在几个公司之间共享时,我们必须注意它不能通过关系字段链接到另一个公司的记录。例如,我们不希望销售订单及其发票属于不同的公司。

为了确保这种多公司一致性,您必须:

将类属性_check_company_auto设置为True。

如果模型有company_id字段,则将关系字段的属性check_company设置为True。

字段company_id不能定义为check_company=True。

在每次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)

Model._check_company(fnames=None)

检查给定字段名的值的公司

Parameters
fnames (list) – 要检查的关系字段的名称

Raises
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)]

fatux: form视图需要增加company_id的字段并且设置为invisible=“1”

在 Odoo 中,_check_company_auto = True 是一个类级别的属性,主要用于公司的多环境支持。当这个属性被设置为 True 的时候,Odoo 会自动检查所有带有 'company_id' 字段的模型,并确保这些模型中的 'company_id' 字段和它们相关联的记录在同一家公司中。
具体来说,Odoo 在创建或者写入一条记录的时候,会检查这条记录的 'company_id' 字段和它所关联的所有其他记录的 'company_id' 字段。如果这些 'company_id' 字段不一致,Odoo 会抛出一个警告。
所以,_check_company_auto = True 的作用就是启动这个自动检查公司一致性的功能。这个功能在多公司环境下尤其有用,因为它可以防止用户在一家公司中创建记录,但是这些记录关联的其他记录却在另一家公司中。


3.默认公司

当在模型上需要字段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)

4.视图

如上所述,如果用户没有访问多个公司的权限,则通常将公司隐藏在视图之外。这是用group base.group_multi_company进行评估的。

<record model="ir.ui.view" id="record_form_view">
    <field name="name">record.restricted.formfield>
    <field name="model">record.restrictedfield>
    <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>

5.安全规则

当处理跨公司共享的记录或仅限于单个公司的记录时,我们必须注意用户不能访问属于其他公司的记录。

这是通过基于company_ids的安全规则实现的,其中包含用户的当前公司(用户在多公司小部件中检查的公司)。


<record model="ir.rule" id="record_shared_company_rule">
    <field name="name">Shared Record: multi-companyfield>
    <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>

<record model="ir.rule" id="record_restricted_company_rule">
    <field name="name">Restricted Record: multi-companyfield>
    <field name="model_id" ref="model_record_restricted"/>
    <field name="global" eval="True"/>
    <field name="domain_force">
        [('company_id', 'in', company_ids)]
    field>
record>

6 实践经验

参考文档:

https://www.jianshu.com/p/c61910d57523

https://blog.csdn.net/u012739578/article/details/121670129

https://blog.csdn.net/sum1201/article/details/128380671

如果只是简单的多公司,不存在跨公司的情况,那么只需要按照第三和第五步定义记录规则就行了.

如果存在跨公司的情况: 二,三,五 都要设置

关于公司的环境变量:

print(self.env.user.company_id)            #用户的默认公司
print(self.env.user.company_ids)           #用户所在的所有公司
print(self.env.company)                    # 当前环境的默认公司, 界面右上方公司栏目,选中复选框并且底色比较深的公司
print(self.env.companies)				   # 当前环境选中的所有公司, 界面右上方所有勾选的公司

res.company(1,)
res.company(5, 4, 1)
res.company(1,)
res.company(1, 4)

``

你可能感兴趣的:(Odoo16,odoo)