先说结论
在 Odoo 里,工单计时不是“做个看板展示”这么浅。
mrp.workorder 的 duration 往后至少会影响:
- 工单进度和偏差百分比
- 工位 productivity / performance 指标
- 工序实际成本或理论成本
- MO 汇总时长
一句话记:
工单计时在 Odoo 里是执行事实、绩效信号,也是成本输入。
Expected Duration 和 Real Duration 为什么必须分开看
源码里 mrp.workorder 同时有:
duration_expecteddurationduration_unitduration_percent
这已经说明系统设计并不是只关心“实际花了多久”,而是要持续比较:
- 理论上应该多久
- 实际上做了多久
- 每单位耗时多少
- 偏差有多大
_compute_duration() 里会把:
- 总时长算出来
- 再除以
qty_produced得到单位耗时 - 再用 expected vs actual 算 deviation
所以你在界面上看到的 duration deviation,不是前端小计算,而是模型层正式字段。
Expected Duration 是怎么来的
很多人以为 expected duration 只是 operation 上手填一个分钟数。
但源码比这复杂。
在 mrp.routing.workcenter 里,官方会根据:
- 历史 workorder 数据
- work center capacity
- setup / cleanup
time_efficiency- 操作模式是 manual 还是按历史学习
去算 time_cycle 和 time_total。
然后到了工单层,_get_duration_expected() 又会继续结合:
- 当前要生产多少
- 所在工位容量
- setup / cleanup
- 替代工位效率
去得到这一次 workorder 的 duration_expected。
这意味着 expected duration 不是静态标签,而是带产量与工位语义的理论工时。
实际 duration 怎么记进去
Odoo 用的是 time_ids,也就是 mrp.workcenter.productivity 记录。
get_duration() 会把:
- 已结束的 productivity line 时长
- 还在进行中的 open time
一起累计成工单 duration。
而 _prepare_timeline_vals() 又会根据时长是否超过 expected,自动把时间归到不同 loss type:
productiveperformance
也就是说:
在 Odoo 里,时间不是只被记录成一个数字,而是被分类为“正常产出时间”还是“性能拖慢时间”。
这对后面的绩效统计非常关键。
为什么手工改 duration 也会影响时间线
_set_duration() 这段代码很有意思。
当你直接改工单 duration 时,Odoo 不是简单改字段值,而是会:
- 如果时长增加,就新建 productivity 记录
- 如果跨过 expected 边界,还会拆成 productive / performance 两段
- 如果时长减少,就回头删或缩短已有 timeline
这说明官方的真实模型是:
duration 只是时间线的汇总结果,不是脱离时间线独立存在的自由数字。
所以你手改 duration,本质上是在改底层的时间事实结构。
为什么工位 OEE / performance 会受它影响
在 mrp.workcenter 里,官方会按 time log 计算:
productive_timeblocked_timeoeeperformance
例如:
- OEE 会用 productive_time 和 blocked_time 算
- performance 会比较 done 工单的
duration_expected与duration
所以工单计时不是只服务工单自己。
它会向上汇总到工位层,变成:
- 这台设备是否经常被阻塞
- 实际表现比理论快还是慢
- 生产效率到底好不好
这也是为什么计时数据一旦乱录,后面整套分析都会失真。
它为什么还会影响成本
在 mrp.routing.workcenter 上有 cost_mode:
actualestimated
帮助文本写得很明确:
- actual time:按实际 tracked time 和真实成本算
- estimated time:按预计时间和成本算
工单层也有 _cal_cost() / _cal_real_cost() 一类逻辑,本质都是:
- duration ×
costs_hour
区别只是取:
duration_expected- 还是
get_duration()/ 实际时长
这意味着:
工单计时一旦进入 actual 模式,就不只是运营分析数据,而是会进入制造成本。
很多团队低估的正是这里。
为什么 MO 总时长也会跟着变
在 mrp.production 上,duration_expected 和 duration 会直接汇总 workorder_ids。
所以 MO 表头看到的总工时,并不是另一套单独计算,而是工单层时长的加总结果。
这也解释了一个常见现象:
- 明明 MO 没改
- 但下面某个工单补了时间
- 整张 MO 的 duration 就变了
因为它本来就是从工单层汇总上来的。
实战里最容易踩的 5 个坑
1. 以为计时只是车间 KPI 展示
它还会继续影响成本和工位分析。
2. 把 expected duration 当成静态手填值
它其实会受数量、容量、效率和历史数据影响。
3. 手工改 duration 时,以为只是改个数字
其实是在改 productivity timeline。
4. 只看工单总时长,不看 productive / performance 分类
你会看不懂慢在哪里。
5. 计时数据录得随意,却还想看准确 performance / OEE
后面的分析基础已经坏了。
一句话记忆法
Odoo 工单工时不是展示字段,而是从时间线、绩效到成本都在复用的核心执行数据。
DISCUSSION
评论区