序列号生产

Odoo 序列号产品为什么一张 MO 能做多件却要一件件报工:qty_producing、lot_producing_ids 与校验边界讲透

很多团队看到序列号产品的制造单,既能做多数量,又总被要求逐件生成序列号。本文结合 mrp.production 源码,讲清 qty_producing、lot_producing_ids、自动生成序列号和完工校验之间的关系。

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

先说结论

序列号产品在 Odoo 里看起来最反直觉的一点是:

  • 制造单可以有总数量
  • 但执行时又总是被拉回到“一个序列号对应一个产出单位”

这不是界面故意找麻烦,而是 Odoo 在保护追溯语义。

一句话说透:

对 serial tracked 成品,制造单可以按批下达,但执行层必须回到逐件确认,因为每一件都要有自己独立的身份。

源码里这套逻辑主要围绕:

  • lot_producing_ids
  • qty_producing
  • _change_producing() / _set_qty_producing()
  • action_generate_serial()
  • pre_button_mark_done()

为什么序列号产品不能只靠 product_qty

对普通未追踪产品,product_qty = 100 大多数时候就足够表达生产目标。

但对序列号产品来说,数量只是“总任务”,还不是“可追溯结果”。

因为业务真正需要的是:

  • 做了几件
  • 每件叫什么序列号
  • 后续每件对应哪些原料、工序、售后记录

所以在 mrp.production.py 里,Odoo 给 serial 场景额外强调:

  • lot_producing_ids:本次要产出的成品序列号集合
  • serial_numbers_count:序列号数量
  • qty_producing 会和这些序列号数量发生强绑定

也就是说,在 serial 场景里,数量只是结果之一,序列号集合才是执行真相

qty_producing 为什么会被序列号数量“拉回去”

_change_producing() 里有个关键判断:

  • 如果产品追踪方式是 serial
  • 且存在 lot_producing_ids
  • 那么 qty_producing = len(lot_producing_ids)

这句非常重要。

它等于直接宣布:

对于序列号制造,当前准备产出的数量,不由你自由输入决定,而由你实际准备好的序列号数量决定。

这就是为什么现场经常出现这种感觉:

  • 我明明想先把 qty_producing 改成 10
  • 但系统还是要求我先准备 10 个序列号

不是 Odoo 啰嗦,而是如果没有 10 个独立 serial identity,系统就不认为你真的准备好了 10 件可追溯成品。

_set_qty_producing() 为什么还会再校正一次

_set_qty_producing() 里,serial 产品会再次检查:

  • qty_producing_uom
  • qty_production_uom
  • len(lot_producing_ids)

如果当前 qty_producing 和应有逻辑不一致,系统会把它重新换算回以序列号数量为准的值。

这说明 Odoo 的设计不是“前端 onchange 提醒一下”而已,而是:

  • onchange 会管一次
  • 真正重算生产数量时再管一次

也就是说,这是一条核心规则,不是 UX 建议。

自动生成序列号时,为什么有时直接生一个,有时弹向导

action_generate_serial() 里,serial 产品有两种路径:

情况一:product_qty == 1 且当前还没序列号

系统会直接创建一个 lot/serial,并把:

  • qty_producing = 1
  • 然后调用 set_qty_producing()

这适合典型的单件生产。

情况二:总数量不止 1

系统不会替你偷偷一次性全做完,而是打开 action_assign_serial_numbers 向导。

这背后的业务含义很清楚:

  • 单件生产,自动补一个序列号没什么歧义
  • 多件生产,必须让用户明确本次到底生成多少个、命名区间怎么走、是否真的要逐件落号

所以向导不是多余步骤,而是多件 serial 生产的责任确认界面。

完工前为什么一定盯 lot/serial

pre_button_mark_done() 里,Odoo 会先做一个关键判断:

  • 如果这张制造单按规则必须自动检查追踪信息
  • lot_producing_ids 还没有
  • 系统就不让你直接完工

并且会返回 action_generate_serial()

这条链路说明:

对 serial 成品来说,完工不是“数量够了就行”,而是“每一件的身份先落地,再谈完工”。

这和很多新手心里的模型正好相反。

他们以为序列号只是完工后的补充属性;但在 Odoo 这里,序列号是完工成立条件的一部分。

业务上为什么必须这样设计

因为序列号产品通常意味着更高追溯要求,例如:

  • 设备整机
  • 高价值单件产品
  • 售后保修依赖 SN
  • 质量问题要追到单体

如果允许用户先完工 10 件、后面再慢慢补序列号,就会出现严重歧义:

  • 哪 10 件先做完了
  • 每件用的是哪批组件
  • 哪件已经交付、哪件还在库

所以 Odoo 宁愿让执行界面更“麻烦”一点,也要把追溯语义锁死。

新手最容易误解的点

1)一张 MO 多数量,不代表可以不逐件落号

MO 的总数量是任务视角;serial number 是执行与追溯视角。

2)qty_producing 不是在 serial 场景下完全自由

只要 lot_producing_ids 已经存在,数量就会被这些序列号数牵着走。

3)自动生成序列号不等于系统会替你无脑生成整批

单件可以自动,多件通常要通过向导明确确认。

4)完工前缺序列号不是小问题

它不是单纯“资料还没补完”,而是这批产出在 Odoo 看来还没有形成可追溯成品。

实施与开发注意点

一,不要把 serial 生产按普通批量生产讲给现场

培训时要先讲清:

  • 计划可以按批
  • 追溯必须逐件

这一步不讲清,后面大家只会觉得系统“卡人”。

二,批量导码或自定义生码时,要尊重 lot_producing_ids -> qty_producing 的主从关系

很多二开喜欢先强塞 qty_producing,再补 lot。这样极易造成界面值和源码重算不一致。

更稳妥的做法通常是:

  • 先准备序列号集
  • 再让系统顺着 _change_producing() / _set_qty_producing() 去落数量

三,排错时优先看三件事

  1. 产品 tracking 是否为 serial
  2. lot_producing_ids 里到底有多少个序列号
  3. 完工前是不是被 pre_button_mark_done() 拉去补序列号

最后总结

Odoo 对序列号制造的核心立场非常稳定:

  • 制造任务可以批量下达
  • 但执行确认必须逐件可追溯
  • 数量不是唯一真相,序列号集合才是
  • 没有序列号,就不算真正完成可追溯成品

一句话记住:

Serial MO 可以批量计划,但只能逐件成立。

DISCUSSION

评论区

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