ODOO12 强制刷新计算字段

昨天在工作中遇到一个问题:

 由于这是odoo12的架构,所以新加的这个字段还是个计算字段。
逻辑是: 客户优先引用“出运要求”关联的客户,如果这个客户没有值,则取 “采购合同” 关联的客户字段。这张表已经有13000条数据了。
即使增加了这个客户的计算逻辑,也无法触发这个计算字段。

@api.depends('delivery_order_id', 'purchase_order')
    def _compute_customer_id(self):
        for record in self:
            if record.delivery_order_id and record.delivery_order_id.customer_id:
                # 如果出运要求存在并且有客户信息
                record.customer_id = record.delivery_order_id.customer_id
                # _logger.debug('出运要求的客户: %s', record.customer_id)
            elif record.purchase_order_id and record.purchase_order.customer_id:
                # 如果出运要求没有客户信息,则取采购订单的客户信息
                record.customer_id = record.purchase_order.customer_id
                # _logger.debug('采购订单: %s', record.purchase_order)
                # _logger.debug('采购订单的客户: %s', record.purchase_order.customer_id)
            else:
                # 如果两个字段都为空,设置 customer_id 为空
                record.customer_id = False
                # _logger.info('未找到客户信息')

 


所以下面有两个方式:

1、通过odoo的shell 来运行Py代码触发:

  

# 查找所有 purchase.account.invoice 记录
records = env['purchase.account.invoice'].search([])

# 批量触发 _compute_customer_id 方法来重新计算 customer_id 字段
records._compute_customer_id()

如果这个字段是可存储的,那么还要提交到数据库

env.cr.commit()

但是这个shell环境,我测试了好多次,也没有成功。所以就用了下面的方法

 

2、执行SQL来触发

UPDATE purchase_account_invoice AS pai
-- 更新 purchase_account_invoice 表,设置别名为 pai,以便在后续引用该表时简化代码书写。

SET customer_id = COALESCE(
    -- 设置 customer_id 字段的值,优先级按以下两种情况决定:
    -- 使用 COALESCE 函数在多个选项中选择第一个非空值。
    
    (SELECT delivery_order.customer_id
     FROM delivery_order
     WHERE delivery_order.id = pai.delivery_order_id),
    -- 如果 delivery_order_id 字段有值:
    -- 在 delivery_order 表中查找匹配的 delivery_order.id 值对应的 customer_id,
    -- 并将其作为 customer_id 的值。
    
    (SELECT purchase_order.customer_id
     FROM purchase_order
     WHERE purchase_order.id = pai.purchase_order)
    -- 如果 delivery_order_id 字段为空,但 purchase_order 字段有值:
    -- 在 purchase_order 表中查找匹配的 purchase_order.id 值对应的 customer_id,
    -- 并将其作为 customer_id 的值。
)

WHERE pai.delivery_order_id IS NOT NULL OR pai.purchase_order IS NOT NULL;
-- 仅当 delivery_order_id 或 purchase_order 字段存在有效值时才进行更新。

用SQL方法快速,缺点是:无法执行orm中的方法保持数据的一致性,所以要清缓存。最直接有效果的方法是重启odoo服务。

SQL 知识点外延

  1. COALESCE 函数

    • COALESCE 是 SQL 中常用的函数,用于从多个表达式中返回第一个非空值。例如,COALESCE(A, B, C) 会依次检查 ABC,并返回第一个非空的值。如果所有值都为空,则返回 NULL。
    • 这是简化条件判断的一种方式,适用于需要多层判断优先级的场景。
  2. JOIN 和子查询的对比

    • 在这段代码中,COALESCE 使用了子查询的方式来查找客户信息,分别从 delivery_orderpurchase_order 表中获取。
    • 另一种方式是使用 JOIN 来完成同样的操作,但由于此处使用的 COALESCE 需要优先级判断(即优先选择第一个非空值),JOIN 可能不够简洁或不易表达这种逻辑。
  3. 条件更新

    • WHERE 子句控制了 UPDATE 的执行条件,确保只有 delivery_order_idpurchase_order 不为空的记录才会被更新。这在数据表的批量更新操作中非常重要,因为能够有效避免对无关记录的更新,保证数据处理的准确性。
  4. 外键关联与冗余数据更新

    • 这种方式更新 customer_id 字段通常是为了优化查询性能。虽然 customer_id 存在于其他表中,但通过冗余存储在 purchase_account_invoice 表中,减少了频繁查询其他表的需求,适合高频访问数据的场景。
  5. 性能优化

    • 对大量数据进行批量更新时,SQL 的写法会影响性能。使用 COALESCE 和条件限制更新的方式可以显著减少更新的记录数量,这在大规模数据处理中尤为重要。

通过上述 SQL 查询, 可以将关联表中的信息冗余存储在当前表中以加速查询,同时可以灵活控制字段优先级和更新条件,实现数据优化。

posted @ 2024-10-31 10:35  *感悟人生*  阅读(5)  评论(0编辑  收藏  举报