Odoo开发:如何跨模型获取InvoiceLine的ans值赋值给主模型total字段
实现方案
你原有代码存在多处设计和逻辑错误,先修正模型结构,再采用Odoo标准的计算字段逻辑做金额同步,是最稳妥可落地的方案,不会出现数据不一致问题。
原有代码的问题点
- 模型继承逻辑完全错误:
myinvoice.invoice.line继承myinvoice.invoice会导致每新建一条明细就生成一条独立的发票主记录,完全违背发票头-明细行的一对多关系设计 - 关联字段定义错误:明细行关联主表的字段命名为
customer_id属于语义错误,且主表没有定义反向关联明细的字段,无法定位某张发票对应的所有明细 - 计算逻辑存在bug:合计变量
check定义在记录循环外,遍历结束后仅会给最后一条明细记录赋值,且跨发票遍历明细时会把不同发票的金额累加,结果完全错误 - 依赖项缺失:行金额计算方法仅依赖数量字段,产品单价变动时不会自动重算行金额
- 非法赋值:计算方法中直接给依赖字段
quantity赋值,会触发递归重算问题 - 字段拼写错误:数量字段
quanitity拼写错误,正确拼写为quantity
修正后可直接运行的实现代码
1. 发票主表(myinvoice.invoice)修正
主表增加反向关联明细的One2many字段,total字段改为依赖明细行金额的计算存储字段,自动汇总所有明细的合计值,不需要额外做赋值传递:
from odoo import models, fields, api class MyinvoiceInvoice(models.Model): _name = "myinvoice.invoice" _description = "发票主记录" # 反向关联所有发票明细行 line_ids = fields.One2many( comodel_name='myinvoice.invoice.line', inverse_name='invoice_id', string='发票明细' ) # 总金额:自动汇总明细行小计,开启数据库存储 total = fields.Integer(string="发票总金额", store=True, compute='_compute_invoice_total') @api.depends('line_ids.line_total') def _compute_invoice_total(self): for record in self: # 汇总当前发票下所有明细行的小计值 record.total = sum(record.line_ids.mapped('line_total'))
2. 发票明细表(myinvoice.invoice.line)修正
移除错误的主表继承,修正关联主表的字段,调整行金额计算逻辑:
class MyinvoiceInvoiceLine(models.Model): _name = "myinvoice.invoice.line" _description = "发票明细行" # 关联所属发票主记录,删除主记录时自动删除关联明细 invoice_id = fields.Many2one( comodel_name='myinvoice.invoice', string='所属发票', required=True, ondelete='cascade' ) product_id = fields.Many2one('myinvoice.product', string='关联产品') quantity = fields.Integer(string="数量", default=1) unit_price = fields.Integer(string="产品单价", related='product_id.price', readonly=False) line_total = fields.Integer(string="行小计", store=True, compute='_compute_line_total') @api.depends('quantity', 'unit_price') def _compute_line_total(self): for line in self: # 计算单行金额,空值时按0处理 line.line_total = line.quantity * line.unit_price if line.quantity and line.unit_price else 0
方案说明
- 该实现是Odoo官方标准的单据金额汇总方案,不需要额外定义中转字段
ans,也不需要编写额外的赋值传递逻辑 - 明细行新增、删除、数量/单价修改时,主表的
total字段会自动触发重算并持久化到数据库,查询效率和普通字段一致,不会出现数据不一致问题 - 如果你确实需要保留
ans字段做中转,只需要在明细行计算完ans后,通过line.invoice_id.total = ans的方式赋值即可,但这种方式需要额外处理明细删除、修改关联发票等边界场景,不推荐使用
内容的提问来源于stack exchange,提问作者Krishna Chavda
相关产品推荐
相关产品推荐

