成品追溯

Odoo 成品批次号为什么不是完工时随便填一个:lot_producing_ids、序列号生成与追溯绑定讲透

很多团队把制造完工时的批次/序列号输入当成前台录入动作,但在 Odoo 源码里,lot_producing_ids 会影响 qty_producing、校验逻辑、finished move 绑定,甚至后续追溯报表。

制造
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

在 Odoo 制造里,成品批次号 / 序列号不是“完工前填个文本框”这么简单。

lot_producing_ids 这组数据会同时影响:

  • 成品数量 qty_producing
  • 序列号合法性校验
  • finished move 上的 lot 归属
  • 原料 move line 与成品 move line 的追溯映射

一句话记:

制造中的 lot_producing_ids,不只是标签,而是成品身份与追溯链的核心锚点。


为什么 Odoo 要把“正在生产的 lot”单独建模

很多新手会问:

  • 原料 move line 已经有 lot 了
  • 成品 move line 完工后也会有 lot
  • 为什么制造单上还要有 lot_producing_ids

因为制造过程里,系统需要先知道:

  • 这次准备产出的成品是谁
  • 这次准备产出多少个序列号
  • 这些身份要不要在完工前就参与校验和联动

也就是说,lot_producing_ids 是“生产中的成品身份集合”,不是纯粹的结果回填字段。


它会怎么影响 qty_producing

addons/mrp/models/mrp_production.py 里,_change_producing() 有一段非常关键的逻辑:

  • 如果成品 tracking 是 serial,并且已经选了 lot_producing_ids
  • 那么 qty_producing 直接等于序列号个数

这意味着:

对序列号产品

你不是先说“我要做 10 个”,再随便补 10 个 SN。

而是你一旦录入了 10 个序列号,系统就会把“本次生产数量”理解成 10。

对 lot 管理产品

逻辑又不一样。

源码里还专门限制:如果 tracking 是 lotlot_producing_ids 不能超过 1 个。

也就是说:

  • lot 跟踪:一批产出对应 1 个成品 lot
  • serial 跟踪:每个产出单位对应 1 个序列号

Odoo 这里不是前台体验问题,而是在底层就把两种追踪粒度明确区分了。


自动生成序列号到底做了什么

action_generate_serial() 这段源码很值得看。

它不是简单“生成一个字符串”,而是按不同 tracking 模式走不同分支:

如果是 lot 跟踪

  • 只能有 1 个成品 lot
  • 如果已经存在,再生成会直接报错
  • 生成后会把 lot 放进 lot_producing_ids

如果是 serial 跟踪

  • 当数量为 1 且尚未生成时,可以直接创建一个序列号
  • 如果数量更大,系统会打开专门的序列号分配动作,让你按批量规则处理

这背后的设计很合理:

  • 批次号场景重在“一批身份”
  • 序列号场景重在“多单位唯一身份”

所以自动生成不是一个统一按钮,而是两种产品追踪策略的不同实现入口。


Odoo 为什么还要专门校验序列号

_can_produce_serial_numbers() 里,官方会对 lot_producing_ids 逐个检查。

它会调用 stock.quant 的序列号校验逻辑,确认这些 SN 对当前产品、当前公司是否可用。

这说明 Odoo 很明确地不允许“制造现场先随便写,事后再纠正”。

因为一旦 SN 冲突,你影响的不只是这张 MO,而是整条追溯链。

所以系统会尽量在录入阶段就把问题拦住。


成品 lot 是怎么落到 finished move 上的

源码里在制造单准备完工时,会遍历主成品 finished move:

  • 如果该 move 需要 tracking
  • 且 move 上还没有 lot
  • 就把 order.lot_producing_ids 赋给 move 的 lot_ids

这一步很关键。

它说明:

  • lot_producing_ids 不是停留在 MO 头上的临时字段
  • 它会真正下沉到 finished move / move line
  • 后续库存入库、追溯、报表都是基于这些实际 move 数据继续走

所以如果成品 lot 没绑对,不只是“单据看着别扭”,而是成品库存身份本身就歪了。


为什么它还会影响追溯报表

addons/mrp/models/stock_move_line.py 里,Odoo 对制造完成后的原料 move line 做了一步额外映射:

  • 先拿到本制造单的 lot_producing_ids
  • 再把对应的 finished move lines 找出来
  • 最后把这些 produced lines 反向挂到原料 move line 的 produce_line_ids

这一步的业务意义非常大:

原料批次和成品批次之间的追溯关系,不是凭空猜出来的,而是靠制造单上的 lot 身份明确建立起来的。

所以如果你觉得 traceability report 能“一路串起来”很神奇,关键锚点之一就是 lot_producing_ids


新手最容易误解的几个点

1)lot_producing_ids 不是备注字段

它会改 qty_producing、会触发校验、会参与完工与追溯。

2)lot 与 serial 的录入语义完全不同

lot 是一批一个身份,serial 是一件一个身份。不要用同一套习惯去理解这两个模式。

3)finished move 上后来能看到 lot,不代表前面的 lot_producing_ids 不重要

恰恰相反,后面的绑定很多时候就是从这里传下去的。


实战里该怎么用

如果你们做的是受监管、可追溯要求高的制造场景,比如食品、医疗、电子、精密零件,这套逻辑尤其重要。

建议关注三件事:

  1. 产品 tracking 策略先定清楚:是 lot 还是 serial
  2. 现场录入不要把 lot/SN 当“最后补资料”
  3. 出现追溯断链时,先回头查 MO 上的 lot_producing_ids 是否建立正确

最后总结

Odoo 对制造成品身份的设计非常一致:

  • 制造单先维护“本次将产出的批次 / 序列号”
  • 这些身份反过来约束 qty_producing 和合法性
  • 完工时再把身份落到 finished moves
  • 追溯报表继续基于这些 lot 关系把原料与成品串起来

所以成品批次号在 Odoo 里绝不是“最后录一下”的附件数据,而是:

制造执行、库存身份和追溯链路共同依赖的一根主线。

DISCUSSION

评论区

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