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

Odoo开发:如何实现crm.project双字段组合的重复值校验并弹出警告

原代码存在的问题
  • 取值键名错误:vals 是创建记录时传入的字段值字典,键名为字段本身的名称,原代码用crm.project.customer_id 作为键取值,永远返回空值,后续校验逻辑完全失效。
  • 校验逻辑拆分错误:原代码分别单独查询匹配客户的记录、匹配产品的记录,只要两个查询各自有结果就触发警告,会出现“库里存在一条客户A的记录、存在一条产品B的记录,但两条分属不同记录”的误触发场景,完全不符合“双字段组合完全匹配”的校验要求。
  • 执行顺序错误:原代码先调用父类create方法将记录写入数据库后才执行校验,此时搜索结果会把刚写入的新记录本身算进去,逻辑顺序颠倒。
  • 校验场景覆盖不全:仅重写create方法,用户在已有记录上修改客户、产品字段时,不会触发对应的重复组合校验,存在数据脏写的风险。
可直接运行的正确实现

校验核心逻辑:将客户、产品两个字段的条件放在同一个搜索域中,直接查询是否存在完全匹配该组合的存量记录,只要查到就触发警告。

from odoo.exceptions import UserError
from odoo import api, fields, models, _

class CrmProject(models.Model):
    _name = 'crm.project'
    customer_id = fields.Many2one('res.partner','Customer')
    project_product_id = fields.Many2one('crm.project.product','Project Product')

    @api.model
    def create(self, vals):
        # 按原逻辑生成项目编号序列
        vals['name'] = self.env['ir.sequence'].next_by_code('crm.project')
        
        # 执行真正的创建前先做重复组合校验
        customer_id = vals.get('customer_id')
        project_product_id = vals.get('project_product_id')
        # 两个字段都有值时才做组合校验,避免空值场景误触发
        if customer_id and project_product_id:
            # limit=1 只要查到一条匹配记录即判定重复,减少数据库查询开销
            duplicate_record = self.search([
                ('customer_id', '=', customer_id),
                ('project_product_id', '=', project_product_id)
            ], limit=1)
            if duplicate_record:
                raise UserError(_('The project has already been set before'))
        
        # 校验通过后执行创建动作
        return super(CrmProject, self).create(vals)

    def write(self, vals):
        # 覆盖编辑场景的校验:取修改后两个字段的最终值,vals无传入值时取原记录的存量值
        customer_id = vals.get('customer_id', self.customer_id.id)
        project_product_id = vals.get('project_product_id', self.project_product_id.id)
        
        if customer_id and project_product_id:
            # 搜索时排除当前正在编辑的记录本身,避免用户正常保存时被误判为重复
            duplicate_record = self.search([
                ('customer_id', '=', customer_id),
                ('project_product_id', '=', project_product_id),
                ('id', 'not in', self.ids)
            ], limit=1)
            if duplicate_record:
                raise UserError(_('The project has already been set before'))
        
        return super(CrmProject, self).write(vals)
实现效果说明
  • 新建记录时:只有当传入的客户+产品组合和库里任意一条已有记录的组合完全一致时,才会弹出警告,和要求的匹配逻辑完全一致。
  • 编辑记录时:如果修改两个字段后形成的组合和其他已有记录重复,也会被拦截,避免脏数据。
  • 只要两个字段有任意一个为空,就不会触发校验,符合空值场景的业务逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 11:06:10