工序绑定

Odoo 物料到底在哪道工序消耗:BOM Line 绑定 Operation、副产品回填与工单领料边界讲透

Odoo 不是所有原料都在整张 MO 上一起消耗。BOM line 和 by-product 可以绑定到具体 operation,系统会把 move 挂到对应 work order。本文把这层设计讲清楚。

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

先说结论

在 Odoo 里,原料消耗并不一定是“整张 MO 一次性扣完”。

如果 BOM line 或 by-product 绑定了 operation,系统会把对应 stock move 也挂到那道工序,再进一步挂到对应 work order。

一句话记:

BOM 上的 operation 绑定,决定的是某个组件或副产品应该在哪道工序被正式执行。


为什么很多人会忽略这层

因为从 MO 大视角看,大家更容易看到的是:

  • 原料 move 在 move_raw_ids
  • 成品 / 副产品 move 在 move_finished_ids

于是容易产生一个误解:

  • 这些 move 都只是挂在 MO 头上
  • 和具体工序关系不大

但源码其实给了明确的 operation 维度。

在生成原料 move 时,_get_moves_raw_values() 会优先取:

  • bom_line.operation_id
  • 如果当前行来自上级展开,也会看 parent_line.operation_id

然后把这个 operation_id 写进 move。

同样,_get_move_finished_values() 给副产品生成 move 时,也会把 byproduct.operation_id 写进去。

这说明 Odoo 从模型上就支持:

  • 某些料在某道工序领
  • 某些副产品在某道工序产

不是所有东西都在 MO 级别平均摊开。


move 是怎么进一步挂到 workorder 上的

这一步在 mrp.production._link_workorders_and_moves()

系统会先建立:

  • operation -> workorder

的映射。

然后遍历 move_raw_ids | move_finished_ids

  • 如果 move 上有 operation_id
  • 就把 workorder_id 写成对应 operation 实例化出来的那张工单

这意味着:

  1. BOM / byproduct 上定义工序归属
  2. MO 确认后生成具体工单
  3. move 再挂到具体工单

所以最后车间不是对着抽象 operation 操作,而是对着具体 workorder 上的领料 / 产出任务操作。


为什么这对原料消耗特别重要

mrp.workorder.button_finish() 里,Odoo 会找:

  • 当前待结束工单的 move_raw_ids
  • 以及 operation 属于当前工序的 byproduct move

然后给这些 move 补本次该 done 的数量,并标记 picked。

这个行为非常关键,因为它说明:

工单结束时,系统默认只推进属于这道工序的物料与副产品,而不是整张 MO 上所有 move 一起推进。

这就是为什么 operation 绑定在复杂制造里很值钱。

比如:

  • 某种辅料在最后装配工序才消耗
  • 某种边角料副产品在切割工序就产生

如果不做 operation 绑定,现场执行语义会明显变粗。


父子 BOM 展开后为什么还能保留工序语义

源码里 _get_moves_raw_values() 有个细节很妙:

  • 当前 BOM line 自己没有 operation_id
  • 但如果它来自展开结构,parent_line.operation_id 也会被继承进来

这表示 Odoo 在处理 exploded lines 时,并没有完全丢掉上层工序语义。

业务含义就是:

即使物料明细被展开,系统也尽量保留“它属于哪道工序”这件事。

对多层结构或带 phantom 展开思维的人来说,这点很重要。


副产品为什么也能挂工序

很多人只想到组件有工序归属,没意识到副产品也有。

_get_moves_finished_values() 明确会按 byproduct.operation_id 生成 finished move。

这就意味着你可以表达:

  • 主产品最终在整单完成后产出
  • 某个副产品其实在中间某道工序就已经产生

这对下面这些场景特别有用:

  • 切割产生边角余料
  • 熔炼产生副渣
  • 中间工序产生可回收副产物

如果全都压到 MO 完工时统一产出,现场和成本时点都会变粗糙。


为什么这和 routing 设计是一体的

很多团队做 routing 时,只想“步骤怎么排”。

但在 Odoo 里,routing / operation 设计还在回答一个更落地的问题:

  • 哪一步用掉哪种料
  • 哪一步生出哪类副产品

也就是说,operation 不是只负责排程。

它还承担了制造业务对象的执行归属

所以一个好的 routing,不只是顺序合理,还要能把:

  • 领料时点
  • 副产品时点
  • 工位执行时点

尽量对齐。


实战里最容易踩的 5 个坑

1. 以为所有原料都该挂在 MO 上统一消耗

复杂工艺下,很多料应该属于具体工序。

2. 只给 operation 排顺序,不给 BOM line 绑定工序

最后工单层执行会很粗。

3. 忽略副产品也能绑定 operation

会丢失很多真实现场语义。

4. 看到 move 在 MO 上,就以为和 workorder 没关系

_link_workorders_and_moves() 正是在做这层映射。

5. routing 设计只考虑时间,不考虑物料发生点

结果工序设计“看起来顺”,执行却很别扭。


一句话记忆法

在 Odoo 里,operation 不只是工序步骤,它还是组件消耗和副产品产出该落在哪张工单上的定位器。

DISCUSSION

评论区

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