先说结论
Odoo 的 BOM Structure & Cost 报表,不是一棵好看的料件树。
它真正解决的是三个经常被混在一起的问题:
- 这套 BOM 理论上要花多少钱
- 现在手上组件够不够,最多能做多少
- 如果缺料或工序排不开,大概要什么时候能做出来
一句话记:
这张报表本质上是“制造可行性 + 理论成本 + 预计提前期”的综合模拟器。
如果你把它只当“BOM 展开表”,就会低估它对制造规划和成本理解的价值。
这套机制到底在解决什么问题
实施里最常见的三个误区是:
- 成本人员以为 BOM 报表只看组件标准价
- 计划人员以为可制造数量只看最短板组件库存
- 开发人员以为 lead time 只是
produce_delay
但 Odoo 官方在 addons/mrp/report/mrp_report_bom_structure.py 里,把这三件事揉在了一张报告模型里:
- 递归展开组件与子 BOM
- 汇总组件成本
- 叠加工序成本
- 扣除副产品 cost share
- 估算当前可制造数量
- 结合路线和可用性给出预计日期
这也是为什么它看似只是报表,实际却是理解 MRP 决策逻辑的入口。
成本是怎么滚上来的
1. 组件成本:先按展开后的实际数量累计
对普通组件,系统会按:
- BOM 行数量
- 当前查询数量
- 产品标准成本
standard_price
算出当前层的理论组件成本。
也就是说,这里不是看历史入库估值,而是看“按当前主数据,如果现在要做这一套,理论料成本是多少”。
2. 工序成本:不是附注,而是正式叠加
很多团队忽略了工序成本。
但源码里 _get_operation_line() 会对每道 operation 计算:
- 预计时长
- 对应成本
op.cost
最后把所有 operation cost 累加进 bom_cost。
这说明在 Odoo 的官方视角里:
BOM 成本不是纯物料成本,而是组件成本 + 工序成本。
3. 副产品成本:通过 cost_share 从主成本里切出去
_get_byproducts_lines() 会把副产品的 cost_share 变成成本分摊比例。
随后系统会:
- 先拿到组件+工序形成的总成本
- 再按副产品
cost_share分出一部分给副产品 - 剩余部分才留给主成品
所以副产品不是“顺便列一下”,而是直接改变主成品理论成本。
这和很多实施里“副产品只是数量副作用”的理解完全不同。
可制造数量为什么不是只看 on hand
报表里的 _compute_current_production_capacity() 会按每个组件的:
- 需求数量
free_to_manufacture_qty
算出当前最多能做多少。
注意它看的不是简单 qty_available,而是更接近“当前可用于制造的自由数量”。
这意味着:
- 你看着库存有货
- 但如果已被其他需求占用,报表可制造数量可能没你想的那么大
所以这张报表对计划层真正有用的,不是“总库存多少”,而是:
以当前这张 BOM 为准,系统认为你现在真能开出多少。
提前期是怎么估出来的
1. 路线信息不是装饰
_format_route_info() 在制造路线下会计算:
manufacture_delaylead_time
其中 lead time 不只是 bom.produce_delay,还会叠加:
- 相关规则的 delay
days_to_prepare_mo- 多步制造下 pre-production 规则带来的额外延迟
所以如果你只盯 produce_delay,几乎一定低估计划日期。
2. 缺料时,系统会看最慢组件
_get_resupply_availability() 会取组件里最大的可得性延迟。
这很符合真实制造:
- 不是平均一下所有组件
- 而是最慢那个决定你什么时候能开工
3. 有工序时,报表甚至会模拟排程
如果 BOM 有 operation,_simulate_bom_planning() 会进一步模拟:
- 前后工序依赖
- 工位及替代工位
- 日历空档
- 理论开完工时间
这也是为什么 BOM 结构报告里有时会出现 Estimated 日期,而不是简单 Available / Not Available。
这张报表最容易被误读的地方
误区 1:把它当实际成本报表
不是。
它主要基于:
- 当前标准价
- 当前工序成本
- 当前 BOM 结构
所以它更像理论 / 规划成本,不是财务意义上的实际结算成本。
误区 2:以为副产品不影响主品成本
会影响,而且是直接切成本份额。
如果 cost_share 配错,主产品理论成本马上失真。
误区 3:忽略 warehouse context
报表会受 warehouse_id、路线和 forecast 语义影响。
换个仓库看,路线、可用量和预计日期都可能不同。
误区 4:以为报表不涉及排程
只要有 operation、依赖和工位可用性,报表就不只是“材料树”,而是会部分模拟制造计划。
开发时最该注意什么
1. 区分“理论成本”与“实际估值”
如果你要做实施解释或开发扩展,必须把:
- BOM 结构报告成本
- 库存估值 / 会计实际成本
分开讲。
两者都重要,但不是一回事。
2. 自定义成本字段前,先确认它属于哪一层
你的扩展到底是想影响:
- 组件理论成本
- 工序理论成本
- 副产品分摊
- 实际完工估值
这四层混在一起最容易把报表和会计都搞乱。
3. Lead time 调试要同时看 route 和 BOM
如果预计日期不对,至少同时检查:
- BOM 的
produce_delay days_to_prepare_mo- 相关 rule delay
- operation 依赖和 workcenter calendar
4. 关注 minimized、warehouse_id、from_date 这些上下文
这张报表模型很依赖上下文。
很多“同一张 BOM 为什么两次结果不一样”的问题,其实是上下文不同,而不是算法不稳定。
最后总结
BOM Structure & Cost 报表之所以值得认真看,是因为它把制造里最容易分裂理解的三件事放到了一张图里:
- 理论成本
- 可制造数量
- 预计提前期
在 Odoo 的设计里,它不是单纯给你看结构,而是在回答:
如果我现在按这张 BOM、这个仓库、这组路线和工序去做,成本大概多少、能做多少、什么时候可能做出来。
这才是它对制造实施、计划和开发都非常有价值的原因。
DISCUSSION
评论区