先说结论
Odoo 的一/二/三步制造,差别绝不只是“多几张调拨单”。
它真正解决的是一个现场问题:
制造不是凭空从 Stock 直接变成成品,而是先备料到生产前区,再在生产区消耗,最后把成品从生产后区回到可用库存。
所以当你把仓库的 manufacture_steps 从单步切到两步或三步时,系统改变的不是界面,而是整条库存链。
这个机制在解决什么问题
单步制造适合很简单的场景:
- 原料直接从库存扣
- 成品直接入库存
- 不强调线边库、生产前区、生产后区
但很多工厂不是这样运作的。
真实现场经常需要:
- 先把组件从主库拉到线边 / 备料区
- 生产进行中,物料已经不该再算作“普通库存可直接拿用”
- 成品完工后先落到产出区,再由仓库回库
如果系统还只用单步模型,计划、可用量和责任边界就会混在一起。
所以 Odoo 用:
mrp_one_steppbm(pick before manufacturing)pbm_sam(pick before + store after manufacturing)
来表达不同制造仓流。
核心链路:仓库设置如何把 MO 变成一条库存链
test_warehouse_multistep_manufacturing.py 把这条链测得很清楚。
单步:直接制造
当 manufacture_steps = 'mrp_one_step' 时:
- 没有真正启用的 pre-production 取料链
- 制造 pull rule 直接把目的地指向主库存位
- 生产更像是在同一库存语义里完成领料和入库
适合流程短、边界弱的小场景。
两步:先备料,再制造
当 manufacture_steps = 'pbm' 时:
- 系统会创建 Picking Before Manufacturing 路线
- 原料先从
lot_stock_id移到pbm_loc_id - MO 的 raw move 再从 pre-production 位置进入制造消耗
这一步的意义不是好看,而是让“已备到线边”和“仍在总库存”在系统里变成两个不同状态。
三步:先备料,完工后再回库
当 manufacture_steps = 'pbm_sam' 时,链路最完整:
- 组件从 Stock → Pre-Production
- 生产在制造区消耗组件并产生成品 / 副产品
- 成品从 Post-Production → Stock
官方测试里还能看到:
- raw move 的
move_orig_ids指向前置备料 move - finished move 的
move_dest_ids指向完工回库 move
也就是说,三步制造不是三个孤立动作,而是一条首尾相接的 move 链。
为什么 operation type 和默认库位特别关键
很多新手会以为,多步制造只要开仓库参数就够了。
其实 picking_type_id 的默认源/目标库位非常关键。
在测试里,官方专门覆盖了:
- 不同 pre-production 子库位
- 自定义 manufacturing picking type
- merge 后 source location 是否还能保持正确
这说明 Odoo 的真实心智模型是:
制造单不是独立对象,而是嵌在仓库 operation type 语义里的。
如果你的 operation type 默认库位配置错了,就算 MO 看上去能确认,后续生成的 picking 也会串错位置。
多步制造下,MTO / 补货链会怎么接进来
官方测试还展示了一个非常重要的点:
- 客户需求触发 MTO
- MTO 生成 MO
- MO 再长出前置备料 picking
- 完工后再长出回库 picking
- 最终客户出库 move 接到这条后置链上
这说明在多步制造里,MO 不是终点,而是中间节点。
前面可能挂着:
- 销售需求
- 补货规则
- 上游子件补货
后面可能挂着:
- 回库 move
- 客户交付 move
- 其他下游 move_dest_ids
所以看多步制造,不能只盯 MO 表单,要看整条库存和补货链。
新手最容易误解的 4 个点
误区 1:以为 pre-production 是可有可无的中转位
不是。
一旦启用两步或三步制造,pre-production 的业务意义就是:
- 这些组件已经被制造流程占用
- 但还没真正消耗完
它让线边备料和总库存分家。
误区 2:以为成品一完工就天然在 Stock
三步制造下不成立。
完工后,成品先在 post-production 语义里,再通过后置 move 回到可销售/可调拨库存。
误区 3:以为后加组件/副产品不会影响调拨
官方测试覆盖了确认后新增 component 和 byproduct 的情况,并确保前置 / 后置 picking 会同步反映这些变化。
这说明多步制造下,MO 内容变更不是只改 MO 本身,相关 transfer 也要跟着更新。
误区 4:以为取消某个 picking 只是局部动作
不是。
在多步制造链里,取消前置备料 move 可能直接影响 MO 的可执行性和取消传播逻辑。
开发时最该注意什么
1. 涉及 location 的定制必须全链路验证
不要只测 move_raw_ids.location_id。
至少要看:
- 备料 picking 的源/目的位
- MO raw move 的源位
- finished move 的目标位
- 后置回库 move 的源/目的位
2. 不要把多步制造当作单步制造 + 两张附属单
这是最常见的错误心智模型。
正确理解应该是:
- 仓库路线决定补货和搬运
- MO 是中间生产节点
- picking 是这条节点前后的库存实现
3. 加字段时要考虑 pickings 是否也要继承
如果你在 MO、raw move 或 byproduct move 上挂自定义字段,而业务又依赖前置 / 后置 transfer,那就要检查这些字段是否需要同步到 picking move。
4. 站在“库存可用性”而不是“表单便利性”看设计
多步制造存在的最大价值,是把:
- 已备料
- 在制
- 已完工待回库
- 已回可用库存
这些状态从一个模糊概念,拆成系统可追踪的库存位置与 move 链。
最后总结
多步制造真正改变的,不是单据数量,而是 Odoo 对“生产发生在哪里、库存什么时候算可用”的建模方式。
你可以把它理解成:
- 单步:制造是一个点
- 两步:制造前有备料链
- 三步:制造前后都有库存链
所以如果你在实施或开发时只把它看成“多几张拣货单”,就会低估它对:
- 可用量
- 路线决策
- 下游交付
- move 追溯
的影响。
真正理解 Pick Components → Produce → Store Finished 这条链,才算真正理解了 Odoo 多步制造。
DISCUSSION
评论区