You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Odoo中如何全局校验模型关联字段的公司ID一致性?

Odoo全局实现公司一致性校验方案

要实现你提出的「所有带自身company_id且关联模型也有company_id的模型,自动校验双方公司一致」的需求,最优雅的方式是用Mixin抽象类+自动字段检测,无需在每个模型重复编写校验逻辑,具体实现如下:

1. 编写通用校验Mixin

创建一个抽象模型,把校验逻辑封装为可复用的Mixin,所有需要该功能的模型都能直接继承:

from odoo import models, api, _
from odoo.exceptions import ValidationError

class CompanyConsistencyMixin(models.AbstractModel):
    _name = 'company.consistency.mixin'
    _description = '全局公司一致性校验Mixin'

    @api.model
    def _get_related_company_fields(self):
        # 自动识别当前模型中,关联带`company_id`的Many2one字段
        return [
            field_name for field_name, field in self._fields.items()
            if field.type == 'many2one' and 'company_id' in self.env[field.comodel_name]._fields
        ]

    @api.constrains('company_id')
    def _check_company_on_self_change(self):
        # 当自身`company_id`修改时,校验所有关联字段的公司一致性
        self._validate_company_matches()

    @api.constrains()
    def _check_company_on_related_change(self):
        # 当关联字段修改时,触发公司一致性校验
        fields_to_check = self._get_related_company_fields()
        if fields_to_check:
            self._validate_company_matches(fields_to_check)

    def _validate_company_matches(self, fields_to_check=None):
        fields_to_check = fields_to_check or self._get_related_company_fields()
        for field_name in fields_to_check:
            field = self._fields[field_name]
            for rec in self:
                # 仅当当前记录有公司、且关联记录存在时执行校验
                if rec.company_id and rec[field_name]:
                    if rec.company_id.id != rec[field_name].company_id.id:
                        raise ValidationError(_(
                            "字段「%(field)s」关联的%(model)s「%(rel_name)s」公司不匹配!\n"
                            "当前记录公司:%(curr_comp)s\n关联记录公司:%(rel_comp)s"
                        ) % {
                            'field': field.string or field_name,
                            'model': field.comodel_name,
                            'rel_name': rec[field_name].display_name,
                            'curr_comp': rec.company_id.name,
                            'rel_comp': rec[field_name].company_id.name
                        })

2. 让目标模型继承Mixin

以res.partner为例,只需继承这个Mixin就能自动生效校验:

class ResPartner(models.Model):
    _inherit = ['res.partner', 'company.consistency.mixin']

其他任何符合条件的模型(比如account.move、purchase.order这类自带company_id且关联模型也有company_id的),只要继承该Mixin,就会自动启用公司一致性校验,无需额外编写重复逻辑。

方案优势

  • 全局复用:一次编写,所有符合条件的模型都能直接套用,避免重复造轮子
  • 自动适配:Mixin会自动识别模型内的关联字段,无需手动指定要校验的字段
  • 精准触发:仅在company_id或关联字段修改时执行校验,不会额外消耗系统性能
  • 清晰提示:报错信息明确指出问题字段、关联记录及双方公司,用户可快速排查

内容的提问来源于stack exchange,提问作者Shoaib Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:57:07