Odoo 8计算字段存储矛盾:store=True不更新,无则不存DB
问题描述
需要持久化存储sale.order.line模型中的cost_price_set、cost_price_currency和currency_rate_cost三个计算字段,但遇到以下问题:
- 给这三个字段设置
store=True后,字段无法正常更新; - 不设置
store=True时,字段能实时更新但保存后不会存入数据库。
原始Python代码
class sale_order_line(models.Model): _inherit='sale.order.line' @api.multi @api.depends('product_id') def _get_cost_price_currency(self): for lot in self: so_line_ids = self.env['product.product'].search([('id','=',lot.product_id.id)]) for rec in so_line_ids: if rec.date_hpp_start: converted_date = datetime.datetime.strptime(rec.date_hpp_start, '%Y-%m-%d').date() rec.days_difference = (datetime.date.today() - converted_date).days if rec.days_difference > 0: rec.days_difference = rec.days_difference else: rec.days_difference = 0 rec.cost_price_set = rec.cost_price_set rec.cost_price_currency = rec.cost_price_currency if rec.currency_rate_cost2: lot.currency_rate_cost = rec.currency_rate_cost2 else: lot.currency_rate_cost = rec.currency_rate_cost lot.hpp_non_interest = rec.hpp_non_interest lot.date_hpp_start = rec.date_hpp_start lot.days_difference = rec.days_difference lot.interest_per_year = rec.interest_per_year lot.interest_per_day = rec.interest_per_year/365 lot.interest_by_today = lot.days_difference*lot.interest_per_day if lot.hpp_non_interest and rec.currency_rate_cost2: lot.cost_price_currency = lot.hpp_non_interest + (rec.hpp_non_interest*rec.interest_by_today/100) lot.cost_price_set = lot.cost_price_currency * lot.currency_rate_cost elif lot.hpp_non_interest: lot.cost_price_currency = '0' lot.cost_price_set = rec.hpp_non_interest + (rec.hpp_non_interest*rec.interest_by_today/100) else: lot.cost_price_currency = rec.cost_price_currency lot.cost_price_set = rec.cost_price_set currency_rate_cost = fields.Float(string='Tax Rate',compute='_get_cost_price_currency', digits_compute=dp.get_precision('Custom1') ) hpp_non_interest = fields.Float(string='HPP Non Interest',compute='_get_cost_price_currency', digits_compute=dp.get_precision('Custom3')) date_hpp_start = fields.Date(string='HPP Date start',compute='_get_cost_price_currency') days_difference = fields.Integer(string='Interest Age (days)', compute=_get_cost_price_currency) interest_per_year = fields.Float(string='Interest(%) Per Year', compute=_get_cost_price_currency) interest_per_day = fields.Float(string='Interest(%) Per Day', compute=_get_cost_price_currency) interest_by_today = fields.Float(string='Today Interest', compute=_get_cost_price_currency) cost_price_currency = fields.Float(string='HPP USD',compute='_get_cost_price_currency', digits_compute=dp.get_precision('Custom3') ) cost_price_set = fields.Float(string='Cost Price Public',compute='_get_cost_price_currency', digits_compute=dp.get_precision('Custom1') )
原始XML代码
<record model="ir.ui.view" id="sale_cost_sale_order_line_form"> <field name="name">sale.order.line.tree.cost.view.form</field> <field name="model">sale.order</field> <field name="inherit_id" ref="sale.view_order_form"/> <field name="arch" type="xml"> <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="after"> <field name="cost_price_set" /> <field name="cost_price_currency" /> <field name="currency_rate_cost" /> </xpath> </field> </record>
解决方案
1. 修正计算字段的依赖关系
当前计算方法仅依赖product_id,但逻辑中用到了product.product的多个字段(如date_hpp_start、currency_rate_cost2等),这些字段变化时无法触发销售订单行的计算更新。需要将所有影响计算的产品字段添加到@api.depends中,确保字段值变化时自动重新计算并存储。
2. 优化计算逻辑,避免无效操作
原代码通过search获取产品对象完全多余,直接使用line.product_id即可;同时修复cost_price_currency赋值为字符串'0'的错误(Float字段需赋值数值类型)。
3. 正确设置store=True
给需要持久化的字段添加store=True,结合完善的依赖关系,确保字段能正常更新并保存到数据库。
修正后的Python代码
from odoo import models, fields, api import datetime class sale_order_line(models.Model): _inherit='sale.order.line' @api.multi @api.depends( 'product_id', 'product_id.date_hpp_start', 'product_id.currency_rate_cost2', 'product_id.hpp_non_interest', 'product_id.interest_per_year', 'product_id.cost_price_currency', 'product_id.cost_price_set' ) def _get_cost_price_currency(self): for line in self: product = line.product_id if not product: continue # 计算天数差 days_difference = 0 if product.date_hpp_start: converted_date = datetime.datetime.strptime(product.date_hpp_start, '%Y-%m-%d').date() days_diff = (datetime.date.today() - converted_date).days days_difference = days_diff if days_diff > 0 else 0 # 计算利息相关 interest_per_day = product.interest_per_year / 365 if product.interest_per_year else 0.0 interest_by_today = days_difference * interest_per_day # 赋值基础字段 line.hpp_non_interest = product.hpp_non_interest line.date_hpp_start = product.date_hpp_start line.days_difference = days_difference line.interest_per_year = product.interest_per_year line.interest_per_day = interest_per_day line.interest_by_today = interest_by_today line.currency_rate_cost = product.currency_rate_cost2 or product.currency_rate_cost # 计算成本价格 if product.hpp_non_interest and product.currency_rate_cost2: line.cost_price_currency = product.hpp_non_interest + (product.hpp_non_interest * interest_by_today / 100) line.cost_price_set = line.cost_price_currency * line.currency_rate_cost elif product.hpp_non_interest: line.cost_price_currency = 0.0 # 改为数值类型 line.cost_price_set = product.hpp_non_interest + (product.hpp_non_interest * interest_by_today / 100) else: line.cost_price_currency = product.cost_price_currency line.cost_price_set = product.cost_price_set currency_rate_cost = fields.Float( string='Tax Rate', compute='_get_cost_price_currency', digits=fields.Digits(precision_name='Custom1'), store=True ) hpp_non_interest = fields.Float( string='HPP Non Interest', compute='_get_cost_price_currency', digits=fields.Digits(precision_name='Custom3'), store=True ) date_hpp_start = fields.Date( string='HPP Date start', compute='_get_cost_price_currency', store=True ) days_difference = fields.Integer( string='Interest Age (days)', compute='_get_cost_price_currency', store=True ) interest_per_year = fields.Float( string='Interest(%) Per Year', compute='_get_cost_price_currency', store=True ) interest_per_day = fields.Float( string='Interest(%) Per Day', compute='_get_cost_price_currency', store=True ) interest_by_today = fields.Float( string='Today Interest', compute='_get_cost_price_currency', store=True ) cost_price_currency = fields.Float( string='HPP USD', compute='_get_cost_price_currency', digits=fields.Digits(precision_name='Custom3'), store=True ) cost_price_set = fields.Float( string='Cost Price Public', compute='_get_cost_price_currency', digits=fields.Digits(precision_name='Custom1'), store=True )
额外注意事项
- 若产品字段更新后,销售订单行的计算字段仍未自动更新,可在
product.product模型的write方法中添加逻辑,触发关联的sale.order.line记录重新计算。 - Odoo 12+版本中
digits_compute已被弃用,建议替换为fields.Digits(precision_name='xxx')。
内容的提问来源于stack exchange,提问作者Nur Faiz
相关产品推荐
相关产品推荐

