先说结论
很多团队把制造单上的 Deadline 只当看板上的提醒日期。
但在 Odoo 源码里,date_deadline 远不只是 UI 标记。
它同时承担三层语义:
- 这张 MO 最晚应在何时完成
- 相关 stock move 应该按什么时间节奏被拉动
- 系统何时要把这张单标成 delayed
所以 Deadline 不是一个孤零零的字段,而是一条会向下传导、向外联动的时间约束。
一句话记住:
Odoo 的 Deadline 不是“提醒你一下”,而是在给制造链和库存链同时施加时间压力。
默认日期为什么会优先围绕 deadline 展开
在 mrp.production.py 里,_get_default_date_start() 和 _get_default_date_finished() 都先看 context 里有没有 default_date_deadline。
如果有:
date_finished默认就是这个 deadlinedate_start会默认回推一小时
这个细节很能说明问题。
Odoo 的初始思维不是“先有生产开始时间,再顺便算个 deadline”,而是:
如果上游已经告诉我最晚完成时间,那制造起止时间应该围着它来搭。
这就是典型的交付驱动型制造时间建模。
date_deadline 为什么来自 finished moves
字段定义上,date_deadline 是 compute 字段;在 _compute_date_deadline() 里,Odoo 会取:
move_finished_ids上存在的 deadline- 选其中最早的一个作为 MO 的
date_deadline
这说明制造单的 deadline,并不是只靠 MO 自己关起门来定义,而是和成品去向链路连着。
从业务上理解也合理:
- 制造为什么要赶这个时间
- 往往不是因为车间自己想赶
- 而是因为成品的后续 move、交付承诺、需求链已经给了时间压力
所以 MO deadline 更像是从需求端反推到制造端的最晚完成点。
改 date_start 时,为什么原料 move 的日期和 deadline 也会一起改
在 write() 里,如果生产单的 date_start 被修改,Odoo 会把 move_raw_ids 写成:
date = production.date_startdate_deadline = production.date_start
这一步特别值得注意。
它意味着:
原料 move 的时间压力,默认是围绕开工时点组织的。
很符合现场逻辑:
- 原料不是在完工时才需要
- 而是在开工时就该准备好
所以你把 MO 开工日往前拉,系统也会把原料 move 的时间要求一起往前拉。
改 date_finished 时,为什么 finished move 也要跟着改
同一个 write() 逻辑里,如果改了 date_finished,系统会把 move_finished_ids.date 跟着更新。
这表示成品 move 的时间语义是围绕“预计或实际完工时间”来走的。
也就是说,Odoo 在内部已经把:
- 原料 move 时间
- 成品 move 时间
- MO 起止时间
拆成不同口径去维护,而不是全部塞成一个统一时间戳。
is_delayed 到底是怎么判的
很多用户以为 delayed 只要看“今天过没过 deadline”。
源码不是这么简单。
在 _compute_is_delayed() 里,Odoo 会要求:
- 生产单状态在
confirmed、progress、to_close - 并且
date_deadline存在 - 且满足以下之一:
date_deadline < nowdate_deadline < date_finished
这说明 delayed 有两种含义:
一种是“已经拖到现在还没做完”
即 deadline 早于当前时间。
另一种是“按排定完工时间看,已经注定晚交”
即 deadline 已经早于 date_finished。
第二种特别关键,因为它说明 Odoo 不只是做事后报警,还会做计划层面的提前预警。
合并制造单时,deadline 为什么还会往来源 move 传播
在合并生产单的链路里,源码会把:
- 新生产单 raw moves 的
move_orig_ids - 写上
date_deadline = production.date_start
这句很有意思。
它说明 Odoo 不希望合并动作把原先上游需求链的时间约束丢掉。
也就是说,即使几张单合成一张,系统仍然尝试把新的开工要求继续传回来源 move。
从业务视角看,就是:
- 单据形态可以变
- 时间承诺不能凭空消失
新手最容易误解的点
1)Deadline 不是单纯备注字段
它会参与默认时间、move 时间和 delayed 状态的计算。
2)MO deadline 不一定是手工拍脑袋填的
它很多时候来自 finished move / 下游需求链。
3)delayed 不只是“已经超时”
如果计划完工时间已经晚于 deadline,系统也会认为有延误风险。
4)改 MO 日期可能同时改动库存链时间语义
尤其是 date_start 对 raw moves、date_finished 对 finished moves 的影响,很容易被忽略。
实施和开发注意点
一,不要把 deadline 培训成“看板备注”
如果用户只把它当提醒,他们会看不懂为什么改 MO 时间会影响原料或成品 move 的日期。
二,二开改时间时要想清楚影响面
如果你只改了 MO 上的一个日期字段,却没有意识到:
- raw move 会跟着变
- finished move 会跟着变
- delayed 状态会重算
后续就容易出现计划报表、看板状态和库存日期互相打架。
三,排错时建议顺序
- 先看
date_deadline来源是不是来自 finished moves - 再看
date_start/date_finished最近有没有被改写 - 检查 raw / finished move 日期有没有同步变化
- 最后再看
is_delayed是因为当前已超期,还是因为计划完工时间已晚于 deadline
最后总结
Odoo 把制造 Deadline 设计成了一条真正参与运算的时间约束,而不是看板装饰。
它会:
- 影响默认起止时间
- 从 finished moves 反推到 MO
- 再把开工/完工时间压回 raw / finished moves
- 最后用于 delayed 风险判断
一句话记住:
在 Odoo 里,Deadline 不是显示给人看的日期,而是驱动制造与库存时间链的一根主线。
DISCUSSION
评论区