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

Odoo中无法存储计算字段时,如何按月追踪对比计算字段值?

嘿,针对你遇到的这个计算字段历史值追踪的问题,我整理了几个实用的方案,你可以根据自己的需求来选~

可行的替代方案来追踪计算字段的历史值

1. 新建历史快照表(首推方案)

专门建一个模型来存储每个时间节点的计算字段快照,这样你能精准保留每月1号的b值,后续对比差异直接查这个表就行,逻辑清晰还容易维护。

具体实现步骤:

首先定义历史快照模型:

class ModelAHistory(models.Model):
    _name = 'model.a.history'
    _description = 'Model A Monthly Value Snapshot'

    model_a_id = fields.Many2one('model.a', string='Model A Record', required=True)
    snapshot_date = fields.Date(string='Snapshot Date', required=True)
    b_value = fields.Float(string='Calculated B Value', required=True)

然后写个方法来计算并存储当月的快照:

def _create_monthly_snapshot(self):
    today = fields.Date.today()
    # 取当月1号作为快照日期,你也可以根据需求调整成其他固定日期
    snapshot_date = today.replace(day=1)
    # 遍历所有Model A记录,计算当前b值并存入历史表
    for record in self.env['model.a'].search([]):
        # 手动触发计算(如果b没设置存储的话)
        record._compute_field()
        self.env['model.a.history'].create({
            'model_a_id': record.id,
            'snapshot_date': snapshot_date,
            'b_value': record.b
        })

最后在Odoo的后台配置一个每月1号执行的定时任务,调用上面的方法,就能自动生成当月的快照了。

之后要对比的时候,直接查历史表就行,比如拿4月和5月的数据对比:

april_snapshots = self.env['model.a.history'].search([('snapshot_date', '=', '2018-04-01')])
may_snapshots = self.env['model.a.history'].search([('snapshot_date', '=', '2018-05-01')])

for april, may in zip(april_snapshots, may_snapshots):
    difference = may.b_value - april.b_value
    # 这里写你处理差异的逻辑,比如打印、生成报表之类的

2. 先排查store=True失效的问题(如果想直接存储计算字段)

你说设置store=True后b一直显示0,大概率是计算方法的依赖声明或者逻辑出了问题,先试试排查这个:

  • 一定要给计算方法加上@api.depends装饰器,明确声明依赖的c和d字段,不然Odoo不知道什么时候触发计算:
from odoo import api, fields, models

class ModelA(models.Model):
    _name = 'model.a'

    c = fields.Float()
    d = fields.Float()
    b = fields.Float(compute='_compute_field', store=True)

    @api.depends('c', 'd')
    def _compute_field(self):
        for record in self:
            # 替换成你实际的计算逻辑
            record.b = record.c + record.d
  • 如果c或d是关联字段(比如partner_id.amount),要把完整的依赖路径写在depends里,比如@api.depends('partner_id.amount')。
  • 还要检查有没有其他继承的模型或者逻辑不小心覆盖了b的计算值。

不过要注意:就算store=True生效了,b字段存的是当前最新值,不会保留历史版本。如果要对比不同日期的数值,还是得结合上面的历史快照表,或者用Odoo的审计日志查变更记录,但审计日志更适合追踪变更时间点,不是固定日期的快照。

3. 临时计算+报表查询(适合一次性对比需求)

如果只是偶尔需要生成对比报表,不需要长期存历史值,可以试试动态计算指定日期的b值:

  • 前提是c和d的历史值能被追溯,比如你给这两个字段开了track_visibility,或者有专门的表存它们的变更记录。
  • 写个方法,传入目标日期,找到该日期时c和d的值,再计算对应的b,然后和其他日期的结果对比。

这个方案适合临时需求,但长期用的话还是快照表更靠谱。


内容的提问来源于stack exchange,提问作者fueggit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:03:52