追溯算法

Odoo 追溯报表为什么能一路追到来处和去处:lot/serial traceability 的回溯规则讲透

很多人会用 Odoo 的追溯报表,但说不清它到底是怎么“顺藤摸瓜”的。本文不再只讲批次和序列号概念,而是直接拆源码里的 traceability 回溯规则。

Odoo 开发 库存
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 34 阅读

先说结论

Odoo 的 lot / serial traceability 报表,不是单纯按 stock.lot 把相关单据列表堆出来。

它更像一套“沿着 move line 关系继续追”的规则系统。

源码里 stock.traceability.report 真正做的事情是:

从一批已完成的 move line 出发,再根据 MTO 关系或 MTS 库位流向,继续往前或往后把相关 move line 递归找出来。

所以追溯报表之所以能“越点越深”,核心不在 lot 这个字段本身,而在:

  • 它把哪条 move line 当起点
  • 它如何判断下一跳应该去哪里找

为什么“批次存在”不等于“追溯链就完整”

很多人会误以为:

  • 只要产品开了 lot / serial
  • Odoo 就天然有完整追溯图

其实不是。

追溯报表真正依赖的是:

  • move line 有没有带上 lot
  • move line 是否已经 done
  • 上下游 move / location 关系是否还能连起来

也就是说,lot 只是索引入口,真正把图串起来的是已完成的库存流动事实

如果中间那条链没有 done move line,或者 lot 没被正确写进关键节点,追溯图就会断。


源码最值得看的地方:MTO 和 MTS 是两套回溯逻辑

stock.traceability.report._get_move_lines() 里有一个非常重要的分叉。

分支一:如果是 MTO

move_line.move_id.move_orig_ids 存在时,系统会去找:

  • 上游 origin move 的 move lines
  • lot 必须和当前 move line 相同
  • 状态必须是 done

也就是说,在 MTO / 链式供给里,追溯优先相信的是:

这条库存流有明确的上游 move 关系。

这种追法偏“业务链”。

分支二:如果不是 MTO,而是普通 MTS

当没有上游 move 关系时,系统转而按事实流向查:

  • 同产品
  • 同 lot
  • 某条 move line 的 location_dest_id 等于当前行的 location_id
  • 日期早于或等于当前行
  • 状态是 done

这一步的意思很直白:

既然没有明确上游业务链,那我就按“这批货以前是谁送到这个位置的”来回溯。

这种追法偏“物理流”。


这就是为什么 traceability 报表经常“既像业务图,又像物流图”

很多人第一次看追溯报表会有一种感觉:

  • 有时它像在沿着单据关系追
  • 有时它又像在沿着库位搬运历史追

这不是错觉,而是源码本来就这样设计。

因为 Odoo 在追溯时其实混合了两类线索:

  • 业务上的上游 / 下游 move 关系
  • 库存事实上的 location 流转关系

MTO 更依赖前者,MTS 更依赖后者。

所以 traceability 报表不是一张单纯的 lot 清单,而是一张混合了供应链关系和库内流转的图。


为什么 scrap 和 inventory adjustment 也能进追溯图

_get_reference() 里,Odoo 会识别 move line 背后的 reference 类型。

它不只识别普通 picking,还会识别:

  • is_inventory 对应 Inventory Adjustment
  • location_dest_usage == 'inventory' and scrap_id 对应 Scrap

这点非常关键。

它说明 Odoo 对 traceability 的理解不是“销售 / 采购 / 制造单据追踪”,而是:

凡是改变了这条 lot 实际位置与状态的库存事实,都应该有资格进入追溯链。

所以你在追溯图里看到盘点修正、报废节点,不是附赠信息,而是它们本来就是这批货生命周期的一部分。


为什么 done 状态这么重要

源码里基本反复要求:

  • state == 'done'

这背后的逻辑非常合理:

  • draft 是计划
  • assigned 是预留
  • waiting 是期待
  • 只有 done 才是已经发生的库存事实

而追溯报表要表达的是“这批货到底经历了什么”,那就只能建立在已发生事实上,而不能把未执行计划混进去。

这也是为什么很多人感觉:

  • 明明界面上看得到单据
  • traceability 却没串上

因为你看到的是业务对象存在,系统追的是库存事实已落地。


调试 traceability 断链时,最该查什么

如果追溯图不完整,优先查这 5 件事:

1. lot / serial 是否真的落到了关键 move line 上

不是单据上有,而是 move line 上有。

2. 中间节点是否已经 done

没 done 就还不能进事实链。

3. 这段流程是 MTO 还是 MTS

两套回溯逻辑完全不同。

4. location 流转是否连续

MTS 下断链最常见就是位置接不上。

5. 有没有 scrap / inventory adjustment 把链路改向了

这些动作本来就会成为追溯节点。


新手最容易误解的 4 件事

1. 以为 traceability 只是 lot 的相关单据列表

其实它是 move line 图。

2. 以为 lot 开启后追溯天然完整

中间若没有 done move line,图照样断。

3. 以为它只认业务单据关系

MTS 下它会按 location 流向回溯。

4. 以为 scrap / adjustment 不算追溯节点

它们恰恰是 lot 生命周期的重要节点。


一句话记忆法

Odoo 的 traceability 报表不是“批次相关单据列表”,而是从 done 的 move line 出发,按 MTO 业务链或 MTS 位置流递归追出来的一张库存事实图。

理解这句话,你以后看 lot / serial 追溯,就不会只盯着 stock.lot 那一张表了。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。