先说结论
很多人把 BOM 理解成“生产配方表”,这个方向没错,但还不够。
在 Odoo 里,BOM 不只是回答“需要哪些组件”,它还决定:
这东西是要真的生成制造单,还是只在物流上展开成组件;以及生产过程中会不会除了主成品之外还产出副产品。
所以 BOM 同时在表达结构、执行方式和产出语义。
normal 和 phantom 最大的区别是什么
在 mrp.bom 里,type 至少会区分:
normalphantom(Kit)
这两种的脑回路完全不同:
Normal BOM
更偏制造语义,通常会进入 MO / 生产流程。
Phantom BOM
更偏展开语义,系统会把上层产品在物流链里直接 explode 成组件,而不是单独做一张完整制造单。
所以 phantom 不是“简化版制造”,而是另一种处理路径。
explode() 为什么这么重要
源码里的 mrp.bom.explode() 是理解 BOM 的关键入口之一。
它不是简单列出材料,而是在做:
- 当前产品和数量下应该展开哪些 BOM
- 各层子项该怎么算数量
- 子 BOM 是否还要继续递归展开
这说明 Odoo 看 BOM 不是死表,而是可展开的结构树。
为什么 Kit 会直接影响库存动作
在 stock.move.action_explode() 的逻辑里,phantom BOM 会直接把上层 move 拆成底层组件 move。
这背后的意思很明确:
对 kit 来说,业务上卖的是一个组合品,但物流上真正动的是组件。
所以 kit 最大的特点,不是“界面长得像套装”,而是它在库存链路里会被真正展开。
By-product 为什么不是备注字段
在 mrp.bom 里,官方单独建了 mrp.bom.byproduct,并且在生产单、成品 move 里都有对应逻辑。
这说明副产品不是“顺便说明一下还有点边角料”,而是正式产出的一部分。
源码里还会校验:
- 副产品成本分摊不能乱来
- cost share 总和不能超过边界
这说明 Odoo 认为副产品会影响真实成本分配和产出记录。
为什么 BOM 不只是结构清单
因为它还同时影响:
- 是否制造还是展开
- 组件行与子 BOM 层级
- 关联 operation
- 副产品产出
- 成本分摊边界
所以 BOM 在 Odoo 里更像生产/履约结构规则,而不只是物料表。
一句话记忆法
BOM 不只定义“要什么料”,还定义“怎么展开、要不要制造、会不会产出副产品”。
DISCUSSION
评论区