项目深度

Odoo 私有任务和子任务为什么不是“随便挂父子关系”:private task、display_in_project 与跨项目联动的真实边界

很多人以为子任务只是层级关系,但 Odoo 其实同时在维护项目继承、显示位置和公司一致性。理解 private task、parent_id 与 display_in_project 的规则,才能知道哪些子任务会跟着父任务走,哪些会被单独展示。

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

先说结论

Odoo 的子任务,不只是 parent_id 指向一下父任务那么简单。

/home/ubuntu/odoo-temp/addons/project/models/project_task.pyaddons/project/tests/test_multicompany.py 里,官方实际上维护了三层东西:

  • 父子层级关系
  • 项目归属继承
  • 在项目中是否单独显示(display_in_project

再加上 private task 约束和公司一致性,你会发现:

  • 子任务默认会继承父任务项目
  • 同项目子任务通常不单独占据项目主列表
  • 子任务也可以脱离父项目、单独显示
  • private task 不能再挂父任务
  • 父任务换项目时,子任务可能被一起带走

所以理解子任务的关键不是“树结构”,而是:Odoo 在同时管理层级、展示和归属。


第一层:为什么 private task 不能再往下挂父任务

源码里有一个很直接的约束:

  • private task 不能有 parent

也就是:

  • project_id IS NULL
  • parent_id IS NOT NULL

这种情况会被禁止。

原因并不复杂。

private task 的语义是:

  • 它不属于某个项目
  • 更像个人或独立待办

而父子任务在项目模块中的主要价值,是把复杂工作拆进项目执行结构里。

如果允许 private task 任意挂在项目任务下面,就会出现语义混乱:

  • 上层是项目工作
  • 下层却是脱离项目的私人记录
  • 统计和展示很难定义

所以 Odoo 干脆直接不让这种混搭成立。


第二层:子任务为什么默认继承父任务项目

_compute_project_id 和相关测试都说明了一件事:

  • 当子任务不应该单独在项目里展示时
  • 如果它有父任务
  • 并且父任务有项目

那么它会继承父任务的项目。

这其实非常符合业务直觉。

因为大多数子任务,本来就是父任务的拆解步骤:

  • 需求评审
  • 开发
  • 自测
  • 客户确认

它们不是新的项目归属,只是同一项目下更细的执行颗粒。

所以继承项目,是默认策略。


第三层:display_in_project 才是“它算不算项目主任务”的关键

很多人会忽略 display_in_project,但这个字段非常重要。

它的作用不是控制归属,而是控制展示层级

从源码逻辑可以读出:

  • 如果子任务和父任务在同一个项目里
  • 且它只是父任务的内部拆分
  • 那么通常 display_in_project = False

这意味着它不一定作为项目主列表中的独立任务突出展示。

但如果:

  • 子任务被改到另一个项目
  • 或者它需要在当前项目中单独显露

display_in_project 可以变成 True。

这就是为什么一些团队会困惑:

  • 我明明创建了子任务
  • 为什么项目主面板看着不像多了一条主任务

因为 Odoo 认为它更像父任务内部结构,而不是项目一级卡片。


第四层:跨项目子任务不是禁用,而是有边界

很多系统干脆不允许跨项目父子关系,Odoo 不是完全不允许,而是把边界做得很明确。

测试中可以看到:

  • 子任务可以因为项目变动而重新计算展示和公司
  • 改变父任务或子任务的项目时,系统会同步处理 company 与 display_in_project

换句话说,Odoo 允许你表达复杂结构,但要求你接受它的后果:

  • 归属会变
  • 公司会变
  • 展示方式会变

所以跨项目子任务不是“点一下关系就行”,而是一次归属重算。


第五层:为什么父任务一换项目,子任务会被一起牵动

测试中很关键的一点是:

  • 父任务换项目
  • 子任务如果仍然属于这个父层级链路
  • 它的项目、显示方式、公司都可能跟着变

这背后的原则非常稳定:

父子关系不是纯文本引用,而是结构性归属关系。

既然是结构归属,父项迁移,子项当然不能假装没看见。

这也是很多实施项目里会踩坑的地方:

  • 先随手建一堆子任务
  • 后来想把父任务挪到另一个项目
  • 结果一串数据都跟着变了

这不是副作用,而是模型本来就这么设计的。


第六层:排错时最常见的四个问题

问题一:子任务不见了

先看是不是:

  • display_in_project = False
  • 它被折叠在父任务下面,而不是消失

问题二:子任务怎么突然成 private task

通常不是“自己掉了”,而是:

  • 公司或项目归属冲突
  • 系统为了保证一致性,把它从项目里摘出来

问题三:为什么不能给 private task 指定 parent

因为 private task 本来就不属于项目执行树,这不是 UI 限制,是模型约束。

问题四:父任务换项目后,为什么子任务也被带走

因为父子结构在 Odoo 里带有归属含义,不是单纯参考关系。


实战建议:什么时候应该用子任务,什么时候该用独立任务

更适合子任务的场景

  • 明显属于同一交付件的拆解
  • 希望保留父项总览和子项执行细节
  • 不需要在项目主列表里全部平铺出来

更适合独立任务的场景

  • 任务可能会跨项目迁移
  • 负责人、优先级、节奏都独立
  • 需要单独做看板管理与统计
  • 将来很可能脱离父项单独存在

也就是说,子任务适合“内部分解”,独立任务适合“独立经营”。


最后一句

Odoo 子任务难理解,不是因为字段复杂,而是因为它同时在回答三个问题:

  • 这是谁的子项?
  • 它属于哪个项目?
  • 它该不该在项目主视图中独立显示?

把这三层分开看,private task、父子关系和跨项目行为就都顺了。

DISCUSSION

评论区

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