如何在Odoo中让关联其他模型字段的store=True计算字段生效?
解决Odoo中store=True的计算字段在关联模型变更时不更新的问题
我之前也碰到过一模一样的问题,当把计算字段设置为store=True后,新增POS订单时伙伴的pos_order_total字段不会自动更新——这其实是Odoo的设计逻辑:存储字段默认只在当前模型(这里是res.partner)的记录本身变更时才会重新计算。而新增POS订单时,变动的是pos.order记录,不是res.partner本身,所以Odoo不会主动触发计算。
下面给你两种可行的解决方案,你可以根据业务场景选择:
方案一:通过@api.depends关联POS订单的字段
这种方法是让Odoo监听POS订单的关键字段变化,自动触发伙伴的计算字段更新。需要先确保伙伴模型和POS订单有反向关联(如果没有的话要加上):
from odoo import api, fields, models class ResPartner(models.Model): _inherit = 'res.partner' # 添加POS订单的反向关联(如果已有可以忽略) pos_order_ids = fields.One2many('pos.order', 'partner_id', string='POS Orders') pos_order_total = fields.Monetary( string='POS Order Total', compute='_compute_pos_order_total', store=True, currency_field='currency_id' # 必须指定货币字段,确保金额计算正确 ) # 用@api.depends监听POS订单的金额和伙伴关联变化 @api.depends('pos_order_ids.amount_total', 'pos_order_ids.partner_id') def _compute_pos_order_total(self): for partner in self: # 按需过滤订单状态(比如只计算已支付/完成的订单) valid_orders = partner.pos_order_ids.filtered(lambda o: o.state in ('paid', 'done')) partner.pos_order_total = sum(order.amount_total for order in valid_orders)
原理:
@api.depends('pos_order_ids.amount_total', 'pos_order_ids.partner_id')告诉Odoo:当任何一个关联的POS订单金额变化,或者订单的伙伴关联被修改时,自动重新计算对应伙伴的pos_order_total字段并更新存储值。
方案二:在POS订单的增删改操作中手动触发更新
如果不需要维护pos_order_ids这个反向关联字段,可以通过重写pos.order的核心方法,在订单变更后手动触发伙伴的计算更新:
第一步:修改伙伴模型的计算方法
from odoo import api, fields, models class ResPartner(models.Model): _inherit = 'res.partner' pos_order_total = fields.Monetary( string='POS Order Total', compute='_compute_pos_order_total', store=True, currency_field='currency_id' ) def _compute_pos_order_total(self): # 用read_group优化查询性能,避免循环遍历大量订单 order_summary = self.env['pos.order'].read_group( [('partner_id', 'in', self.ids), ('state', 'in', ('paid', 'done'))], fields=['partner_id', 'amount_total:sum'], groupby=['partner_id'] ) # 把结果转成字典方便查询 total_map = {item['partner_id'][0]: item['amount_total'] for item in order_summary} for partner in self: partner.pos_order_total = total_map.get(partner.id, 0.0)
第二步:继承POS订单模型,添加触发逻辑
class PosOrder(models.Model): _inherit = 'pos.order' @api.model def create(self, vals): order = super().create(vals) # 订单创建后,更新关联伙伴的总金额 if order.partner_id: order.partner_id._compute_pos_order_total() return order def write(self, vals): # 记录修改前的伙伴,防止订单被转移到其他伙伴 old_partners = self.mapped('partner_id') result = super().write(vals) # 更新旧伙伴和新伙伴的总金额 new_partners = self.mapped('partner_id') (old_partners | new_partners)._compute_pos_order_total() return result def unlink(self): # 删除订单前记录关联的伙伴 partners = self.mapped('partner_id') result = super().unlink() # 更新伙伴的总金额 partners._compute_pos_order_total() return result
原理:
通过重写pos.order的create、write、unlink方法,在订单发生增删改操作时,主动调用伙伴的计算方法,强制更新pos_order_total的存储值。这种方式更灵活,适合不需要反向关联的场景。
额外注意事项
- 订单状态过滤:根据你的业务需求调整
state的过滤条件(比如是否包含draft状态的订单)。 - 性能优化:如果伙伴的POS订单数量很大,建议使用
read_group来批量查询统计,避免循环遍历每个订单(方案二中已经用到)。 - 货币一致性:确保
Monetary字段指定了正确的currency_field,避免金额计算出现货币不匹配的问题。
内容的提问来源于stack exchange,提问作者Chaban33
相关产品推荐
相关产品推荐

