项目深度

Odoo 里程碑为什么不是“打个勾就完了”:进度、逾期与 next milestone 背后的判断逻辑

很多人把项目里程碑理解成列表上的勾选项,但 Odoo 源码里它其实参与项目进度、逾期提醒和 next milestone 判断。本文把背后的逻辑拆开讲。

Odoo 开发 项目
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

很多人看到 Odoo 的 milestone,会把它理解成“项目里的几个检查点”。

但从 project.milestoneproject.project 的源码看,它远不只是一个清单字段。

它至少同时承担三层职责:

  • 任务归档点:任务可以挂到具体 milestone
  • 项目节奏判断点:系统会算哪些 milestone 已达成、哪些逾期
  • 管理视图入口:项目会给出 next_milestone_id、是否逾期、是否可标记完成等信号

一句话说:

Odoo 里程碑不是“给经理看着舒服”的标签,而是项目进度与风险提示的中间层对象。


第一层:milestone 不是任务字段,而是独立模型

Odoo 专门有一个模型:

  • project.milestone

里面有这些关键字段:

  • deadline
  • is_reached
  • reached_date
  • task_ids
  • can_be_marked_as_done
  • is_deadline_exceeded

这说明 milestone 不是从任务里“凑出来”的统计结果,而是一个有自己生命周期的业务对象。

也正因为它是独立对象,任务、项目和销售都能围绕它继续挂语义。


第二层:里程碑完成,不等于“有任务完成”

很多人会误以为:只要 milestone 下面有一张任务 done,这个 milestone 就算完成。

源码不是这么设计的。

_compute_can_be_marked_as_done() 的判断更细:

  • 必须是尚未 reached 的里程碑
  • 必须至少有已关闭任务
  • 且不能还有未关闭任务

也就是说,Odoo 想表达的是:

这个里程碑不是“已经开始有成果”,而是“挂在这个节点下的任务已经收口”。

这和很多团队的真实管理习惯更一致。

因为 milestone 往往不是成果出现的第一刻,而是该阶段可以正式盖章的时刻。


第三层:逾期判断为什么不是看里程碑自己,而是看里程碑 + 任务状态

project.milestone 自己会算 is_deadline_exceeded

  • milestone 尚未 reached
  • 且 deadline 早于今天

这是 milestone 自身层面的“逾期”。

但在 project.project._compute_next_milestone_id() 里,逻辑更进一步。

项目在判断“当前最该关注的 milestone”时,不只是看 deadline,还会看这个 milestone 下面:

  • 是否还有打开中的任务
  • 是否已经有关闭任务

源码里的意思很明确:

场景 A:deadline 已过,但下面根本还没真正开始

这是一种问题。

场景 B:deadline 已过,而且还有打开任务

这更是一种问题。

场景 C:没有打开任务,但已经有关闭任务

这代表它其实已经具备“可标记完成”的条件。

也就是说,项目层在看里程碑时,不是只看时间,还看执行落点。


第四层:next milestone 为什么不是“最早 deadline”那么简单

很多系统会直接取最早未完成里程碑作为 next milestone。

Odoo 源码更谨慎。

_compute_next_milestone_id() 里,它会先把未 reached 的里程碑读出来,再结合任务状态做辅助判断,然后同时生成:

  • next_milestone_id
  • is_milestone_deadline_exceeded
  • can_mark_milestone_as_done

这说明 next milestone 的意义,不只是“下一个日期最近的点”,而是:

当前项目右侧面板最值得提醒管理者的节点。

它既是排序结果,也是风险提示入口。


第五层:项目进度条为什么按 milestone 数量算,而不是按任务工时算

project.project 里,里程碑进度是通过:

  • milestone_count
  • milestone_count_reached
  • milestone_progress

来算的。

而且 milestone_progress = reached / total,本质是节点完成率,不是工时完成率,也不是任务张数完成率。

这说明 Odoo 在 milestone 视角下,更想回答的是:

  • 关键节点推进了多少

而不是:

  • 做了多少零碎任务

所以 milestone 进度天然更适合给客户、管理层和周报场景看。


第六层:为什么 reached_date 是 compute/store,不是普通手填字段

源码里 reached_date 是根据 is_reached 自动算出来的。

这背后的设计很克制:

  • milestone 的事实状态是 is_reached
  • 达成日期是对这个事实的派生记录

也就是说,Odoo 不鼓励“单独改一个达成日期制造完成感”,而是要求先有明确的 reached 语义。

这是很典型的业务系统思路:

先确认状态,再记录状态发生的日期。


新手最容易误解的 4 件事

1. 以为 milestone 就是标签分组

不对。它有独立模型、独立 deadline、独立完成逻辑。

2. 以为有一个任务 done,里程碑就该自动算完成

不对。Odoo 更接近“该节点下任务已经收口”。

3. 以为 next milestone 只是最早 deadline

不对。项目层会结合 milestone 下任务开闭状态一起判断。

4. 以为 milestone progress 是任务进度

不对。它是关键节点进度,不是任务/工时进度。


实战上最该注意什么

1. 不要把 milestone 当任务阶段的别名

阶段解决“任务现在在哪列”,里程碑解决“项目现在推进到哪个关键节点”。两者不是一个维度。

2. 给 milestone 绑定任务时,要控制颗粒度

如果一个 milestone 下挂几十张松散任务,can_be_marked_as_done 的管理意义会变差。

3. 对外汇报时,优先讲 milestone progress,不要只讲任务数量

因为 milestone 更接近业务里程碑,而不是执行碎片。


一句话记忆法

Odoo 里程碑不是“勾一下完成”的清单项,而是“带 deadline、带收口条件、还能驱动项目 next milestone 提示”的项目节点模型。

DISCUSSION

评论区

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