先说结论
Odoo 没有把“我自己的进度感受”硬塞进团队共享任务阶段里。
从 project.task、project.task.type 和 project.task.stage.personal 看,系统明确拆成两层:
- 共享阶段:团队对任务真实流转的共识
- 个人阶段:某个用户为了管理自己节奏,对同一任务做的私人整理
一句话说:
Odoo 允许同一条任务,同时存在团队阶段和个人阶段,因为协作事实与个人节奏不是一回事。
为什么共享阶段不能承担个人整理职责
共享阶段适合回答的是:
- 任务在团队流程里走到哪一步
- 是否完成、阻塞、验收中
- 这条任务对别人当前意味着什么
但个人工作管理想回答的通常是:
- 我今天想先处理哪件
- 这件事我准备本周推进还是先搁置
- 对我而言它是 inbox 还是 later
Odoo 在 _get_default_personal_stage_create_vals() 里直接给出默认个人阶段:
- Inbox
- Today
- This Week
- This Month
- Later
- Done
- Cancelled
这套词汇明显不是项目流转词汇,而是个人节奏词汇。
为什么 personal stage 是“每用户一套”,不是“每任务一个字段”
project.task.stage.personal 用的是 (user_id, task_id) 这类关系建模。
这很关键。
如果 personal stage 只是任务上的一个普通字段,就只能有一个值,意味着:
- A 觉得这件事今天要做
- B 觉得这件事本月再说
- 两人只能二选一
这显然不符合现实协作。
Odoo 的建模选择告诉我们:
个人阶段不是任务属性,而是“用户与任务之间的私人关系”。
这个判断非常成熟。
为什么系统会自动补个人阶段
_populate_missing_personal_stages() 的逻辑是:
- 找出缺少 personal stage 的记录
- 如果该用户还没有自己的阶段集合,就自动创建一整套默认 personal stage
- 再把任务挂到第一列
这说明 Odoo 不把 personal stage 当高级可选玩具,而是把它当“个人任务视图的基础设施”。
否则用户第一次进入个人任务界面时,就会碰到空结构或状态不完整的问题。
为什么 personal stage 不能挂到项目上
project.task.type 里有显式约束:带 user_id 的 personal stage 不能再关联 project_ids。
也就是说,Odoo 明确禁止:
- 一边说这是个人阶段
- 一边又把它当项目共享阶段复用
这个约束非常有价值,因为它斩断了很多“为了省事把个人列混进项目列”的坏设计。
一旦混起来,后果一般是:
- 团队看板被个人语义污染
- 统计口径变形
- 自动化规则也开始误判
为什么删个人阶段还要先迁移任务
_unlink_if_remaining_personal_stages() 和 _prepare_personal_stages_deletion() 做得很细:
- 如果删完后用户一条 personal stage 都不剩,会直接报错
- 对被删阶段上的任务,会按 sequence 找替代阶段迁移过去
这说明 Odoo 把 personal stage 看成持续性的个人工作容器,而不是一次性标签。
换句话说,删列不是简单删配置,它会影响一个用户对所有任务的私人整理结构。
最容易踩的误区
误区一:把 personal stage 当另一套共享 stage
不是。它的可见性和建模都是按用户隔离的。
误区二:想用 personal stage 直接做项目报表
不合适。项目报表应该主要依据共享阶段和业务字段。
误区三:看到 task 上有 personal_stage_id,就以为所有人看到的是同一个值
其实它是按当前用户上下文计算出来的。
排错顺序
如果用户说“为什么我看不到 personal stage”或“列乱了”,建议查:
- 当前任务是否已经为该用户生成
project.task.stage.personal关系 - 该用户是否已有默认 personal stages
- 是否误删了某些 personal stage,导致迁移到别的列
- 是不是把 personal stage 和项目 stage 概念混着做了自定义
一句话记忆
Odoo 的 personal stage 不是任务的新状态,而是用户给同一条任务套上的私人节奏视图。
DISCUSSION
评论区