工位产能

Odoo 工位产能为什么不是“每小时几件”:capacity、setup/cleanup 与替代工位排程讲透

很多团队给工位填了一个产能,结果计划时间还是不准。问题通常不在按钮,而在 Odoo 用 capacity、time_efficiency、setup/cleanup 和 alternative workcenter 共同算时长。

制造
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

Odoo 里的工位产能,不是单独一个“每小时做几件”的数字。

系统在算工单预计时长和排程时,至少会同时考虑:

  • 工位或产品级的 capacity
  • 开机/收尾时间 time_starttime_stop
  • 工位效率 time_efficiency
  • 工艺本身的 time_cycle
  • 是否存在 alternative_workcenter_ids

所以如果你觉得“我明明填了产能,为什么排程还是怪”,往往不是 Odoo 没用这个字段,而是你把整套模型只理解成了一个数字。

一句话记:

Odoo 排工单看的是“每批要跑几轮、每轮多长、能不能换工位”,不是只看一条产能参数。


capacity 在源码里到底是什么意思

关键逻辑在 addons/mrp/models/mrp_workcenter.py_get_capacity()

这段实现不是简单返回一个工位默认值,而是先在 capacity_ids 里找最合适的记录:

  • 优先匹配当前产品 + 当前产品主 UoM
  • 其次匹配通用容量 + 当前单位
  • 再其次匹配通用容量 + 产品主单位

如果找到了产品级容量,就优先用它;找不到,才退回工位默认的 setup/cleanup 和默认 capacity。

这说明 Odoo 的心智模型是:

  • 同一个工位,对不同产品可以有不同并行产能
  • 产能还可以和单位绑定
  • 工位默认值只是兜底,不是唯一真相

这和很多工厂现场非常接近:同一条线做 A 产品和 B 产品,节拍本来就可能完全不同。


setup / cleanup 为什么会经常被忽略

很多人只盯 time_cycle,但 Odoo 在 _get_capacity() 和工单时长计算里,都会把:

  • time_start
  • time_stop

一起带入。

这两个字段的业务含义很直白:

  • setup:开工准备、换模、预热
  • cleanup:收尾、清场、换线整理

于是总时长不是单纯:

数量 × 单件时间

而更接近:

准备时间 + 收尾时间 + 批次数 × 每轮工作时间

这也是为什么小批量生产特别容易“感觉系统算多了”。

不是系统算多,而是你脑子里只算了节拍,没有把每次开工的固定成本算进去。


Odoo 怎么把产能变成工单时长

核心逻辑在 addons/mrp/models/mrp_workorder.py_get_duration_expected()

这段代码会先拿到:

  • 当前工位 capacity
  • setup / cleanup
  • time_efficiency
  • operation 的 time_cycle

然后做一个关键动作:

先算要跑多少轮 cycle

如果这次要做的数量是 qty_producing,工位 capacity 是每轮可并行做 5 件,那么系统不会算 20 件就跑 20 次,而是:

  • cycle_number = ceil(qty / capacity)

也就是:

capacity 在 Odoo 里更像“每轮能并行吞多少数量”,不是“每小时产量”。

再把效率折进去

最终时长里还会乘除 time_efficiency

这意味着:

  • 工位效率低,预计时长会拉长
  • 同一个 operation 放到不同工位,预计时长会变

所以 capacity 解决的是“要跑几轮”,而 efficiency 解决的是“每轮实际要多久”。

这两个不是一回事。


替代工位到底怎么介入排程

另一个经常被低估的字段是 alternative_workcenter_ids

mrp.workorder 里,Odoo 规划工单时不会只看原工位,而是把:

  • 主工位
  • 所有关联的替代工位

一起放进候选集合。

然后系统会逐个尝试:

  1. 用该工位重新估算预计时长
  2. 调用 _get_first_available_slot() 找最早可用时间窗
  3. 比较哪个工位能更早做完
  4. 最后把工单排到“最优完成时间”的工位上

这说明替代工位不是前台备注,也不是手工切换列表。

它是排程算法的候选池。

所以你配置了替代工位却没感觉,常见原因并不是字段无效,而是:

  • 替代工位没有 calendar
  • 替代工位反而更慢
  • 替代工位没有空档
  • 替代工位 capacity / efficiency 设置不合理

为什么有时候换到替代工位后时长还会变

因为 Odoo 不是简单把同一工单“搬家”。

源码里如果改用替代工位,会重新计算:

  • 该工位自己的 capacity
  • 该工位自己的 setup / cleanup
  • 该工位自己的 time_efficiency

所以替代工位不是只影响开始时间,也会影响总工时。

这很符合现场:

  • A 工位更快但更忙
  • B 工位空一点,但换线更慢
  • C 工位效率一般,但现在有窗口

Odoo 想解决的是“把工单放到哪台机器上,整体更早完成”,不是只看哪台机器先空出来。


新手最容易误解的三个点

1)capacity 不是每小时产量报表字段

它更接近“单个 cycle 能并行生产多少”。

如果你把它当 KPI 报表口径去填,排程当然会怪。

2)替代工位不是人工调度备注

它会真的被排程逻辑拿来试算,并可能自动成为最终工位。

3)setup / cleanup 不填,排程一定偏乐观

很多团队把固定准备时间省掉,结果系统排出来的计划永远过密。不是算法错,是输入数据天生偏乐观。


实战配置建议

如果你们希望排程更贴近现场,建议这样建模:

对高频产品补产品级 capacity

不要只给工位一个总容量。关键产品应该补 capacity_ids,让 Odoo 知道不同产品在同工位上的节拍差异。

把 setup / cleanup 当真实时间维护

尤其是换模、预热、清洗明显的行业,这两个字段比很多人想象中更重要。

替代工位不要乱挂

只有“工艺上真能替代”的工位才应该挂进 alternative_workcenter_ids。否则系统会认真把不该替代的机器也纳入候选。


排错时该看什么

如果你发现工单排程不合理,建议按这个顺序看:

  1. mrp.workcenter.capacity 是否有产品级覆盖
  2. setup / cleanup 是否维护成了 0
  3. time_efficiency 是否夸张
  4. 替代工位是否没有 calendar 或者时间窗更差
  5. 该工单的 duration_expected 是在主工位还是替代工位条件下算出来的

别只看甘特图结果,要回到 _get_capacity()_get_duration_expected() 的输入参数去看。


最后总结

Odoo 的工位排程逻辑其实很朴素:

  • capacity 决定一批要跑几轮
  • setup / cleanup 决定固定成本
  • efficiency 决定真实速度
  • alternative workcenter 决定有没有更好的落点

所以“工位产能”在 Odoo 里从来不是单字段问题,而是一组会共同影响预计工时与排程结果的参数。

真正重要的不是把某个数字填上去,而是理解:

系统排的是一段可执行的制造时间窗,而不是一条好看的产能档案。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。