先说结论
Odoo 的替代工位不是一个“坏了就人工换一下”的备注功能。
在排程时,系统会把主工位和 alternative_workcenter_ids 一起拿来比较,然后按每个候选工位重新计算:
- 有没有可用时隙
- 换到该工位后
duration_expected会不会变化 - 这个工位的
capacity、setup/cleanup、time_efficiency会怎么影响总时长
所以它本质上是一个排程切换机制,不是静态主数据。
为什么旧文里讲“产能与替代工位”还不够
之前很多讨论会停在:
- 工位有产能
- 工位可配置替代关系
- 排程时可能会换工位
但真正容易踩坑的,是“系统到底什么时候切、切过去后重新算什么”。
这篇要补的是:
替代工位不是并排摆着给你选,而是 Odoo 在
_plan_workorder()里逐个试算出来的。
关键源码链路
主逻辑集中在两个文件:
mrp/models/mrp_workcenter.pymrp/models/mrp_workorder.py
排程时,_plan_workorder() 会拿到:
- 当前工位
self.workcenter_id - 它的
alternative_workcenter_ids
然后按候选工位逐个尝试:
- 如果还是原工位,沿用当前
duration_expected - 如果换成替代工位,调用
_get_duration_expected(alternative_workcenter=workcenter)重新计算 - 调用
workcenter._get_first_available_slot(date_start, duration_expected)找首个可排时隙 - 一旦找到更早可行的槽位,就生成新的
leave_id与workcenter_id
所以“切工位”不是单独动作,而是排程算法的一部分。
capacity 为什么会直接影响换工位结果
很多顾问知道工位有 capacity,但没意识到它直接参与换工位后的时长重算。
mrp.workcenter._get_capacity() 会综合:
- 产品专属 capacity
- UoM
- setup time
- cleanup time
而 mrp.workorder._get_duration_expected() 会基于 capacity 重新算 cycle 数,再乘上效率系数。
这意味着两个看起来都能做这个工序的工位,排程结果可能完全不同:
- A 工位空闲更早,但 capacity 小、效率低
- B 工位稍晚有空,但 capacity 大、效率高
最终谁被选中,不是看“谁是替代工位”,而是看谁能更早给出可执行的完整时间段。
planning switch 真正切换的不是名字,而是整套资源假设
一旦工单切到替代工位,变化的不只是字段 workcenter_id。
跟着一起变的还有:
resource_idresource_calendar_idleave_id绑定的日历资源- 基于该工位得出的
duration_expected - 后续 gantt / overlap / replan 判断
所以如果你在现场遇到“为什么切了替代工位后预计时长也变了”,答案不是系统算错了,而是它在按新工位的资源参数重新定义整个工单。
replan 时为什么经常出现“明明能做却没被切过去”
常见原因通常不是替代关系没配,而是下面几种:
1. 候选工位没有更早可用时隙
替代工位存在,不代表它更早有空。
2. 新工位重算后的时长更长
由于 capacity、效率、setup/cleanup 不同,切过去反而更慢。
3. 日历或停机 leaves 把时隙打碎了
源码找的是完整可用区间,不是零碎空档。
4. 工单已经进入 progress / done 等不适合重排的状态
不是所有状态都能自由切换。
最容易犯的 4 个配置错误
1. 只配了 alternative_workcenter_ids,却没维护产能和效率
这样切换逻辑就失真,因为时长重算缺真实参数。
2. 把替代工位当成手工调度备注
结果发现系统自动排程和人工认知不一致。
3. 忽略产品级 capacity
同一工位对不同产品可并行数量不同,忽略后预计时长会偏差很大。
4. 改了工位却没理解 leave_id 也会换资源
于是甘特图、冲突检测和工位负载看起来“突然变了”。
排错顺序
如果工单没切到你预期的替代工位,按这个顺序查:
- 原工位和替代工位关系是否双向理解正确
- 候选工位日历、停机、block time 是否可排
- 每个工位对该产品的
capacity、time_efficiency、setup/cleanup 是否合理 _get_duration_expected()在新工位上是否显著变长- replan 时工单状态是否允许
- 最后再看是不是自定义代码改写了选槽规则
一句话记忆法
Odoo 的替代工位不是“备胎名单”,而是排程器拿来逐个试算并动态切换的一组资源模型。
DISCUSSION
评论区