先说结论
Odoo 的制造单锁定,不是“界面上多一个小图标”这么简单。
它的真实作用是:把制造单从“还能继续调整执行细节”切到“默认视为已定稿”。尤其在完工后,is_locked 会直接影响你还能不能改 qty_producing、批次、部分组件与成品移动线。
一句话记忆:
state 决定制造单处在生命周期哪一段,lock 决定这一段里你还能动多大。
机制到底在哪里
在 mrp.production 里,is_locked 是显式字段,而且默认值不是固定常量,而是看用户是否属于 mrp.group_unlocked_by_default。这意味着:
- 有些用户新建 MO 默认就是锁着的
- 有些用户默认可编辑
- 同一个系统里,不同角色看到的“默认能不能改”本来就可能不同
更关键的是,完工时 Odoo 会主动把制造单写成:
state = doneis_locked = True
也就是说,完工自动锁定不是偶发现象,而是标准收口动作。
为什么有时 done 了还能改,有时完全改不动
关键在 mrp.production._change_producing() 这一段判断:
draft/cancel直接不走done且is_locked=True时,也直接不让继续改- 只有没被锁死时,系统才会继续根据
qty_producing、lot_producing_ids去重算执行数量
这解释了很多现场疑问:
- 为什么完工后改序列号没反应
- 为什么有人能解锁后补录,有人不行
- 为什么“明明 done 了,但解锁后还能修一点数据”
不是 done 本身绝对禁止,而是 done + locked 才构成真正的硬边界。
Lock 到底保护了什么
别把它只理解成“防误操作”。它保护的其实是三层一致性:
1. 执行数量一致性
qty_producing、qty_produced、工单报工数量、组件消耗数量是联动的。锁定后,系统默认不再继续为这些字段触发后续重算。
2. 追溯一致性
序列号和批次一旦进入成品追溯链,后改会影响:
- move line
- traceability
- 下游收货 / 发货 / 保修 / 维修引用
3. 成本一致性
一旦库存层、估值层、甚至会计凭证已经跟着完工动作走完,继续改制造单并不只是“改个表单”,而是在挑战后续所有依赖数据。
最常见的 4 个误区
误区 1:锁定只是 UI 权限
不是。它参与服务端逻辑判断,不是纯前端按钮状态。
误区 2:done 一定完全不可改
也不对。很多时候是因为还没锁,或者管理员先解锁了。
误区 3:解锁等于可以随便改
解锁只是放开入口,不代表改完一定合理。你仍然可能破坏批次、成本、依赖 move 的一致性。
误区 4:遇到不能编辑先怀疑权限
权限只是原因之一。更常见的是对象已经 done + locked。
正确排错顺序
遇到“为什么这个制造单改不了”,按这个顺序看:
- 先看
state是不是done - 再看
is_locked是否为True - 再看当前用户是否属于默认解锁组
- 再看你改的是
qty_producing、批次、move line 还是普通备注字段 - 最后再判断是否应该解锁,还是应该走补单、返工、拆解或库存调整
什么时候该解锁,什么时候别解
适合解锁:
- 现场刚完工,发现序列号录错
- 执行数量录入偏差,但还没扩散到大量下游单据
- 管理员在受控场景下做纠偏
不适合解锁:
- 成品已经被销售、退货、维修、会计估值广泛引用
- 问题本质不是录错,而是业务上真的需要返工或反向处理
- 团队把“解锁改历史”当成日常流程
一句话记忆法
Odoo 的 lock 不是装饰,它是在告诉系统:这张制造单是否还允许继续参与执行层重算。
DISCUSSION
评论区