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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:40:39