Activity 接力

Odoo 计划活动为什么不会无限接龙:mail.activity.type 的 suggest / trigger 与完成后续接链路讲透

很多人以为 Odoo Activity 的“下一步”只是界面上的推荐按钮。实际上,mail.activity.type 里 suggest 和 trigger 是两套完全不同的机制:一套负责给人选项,一套负责在完成时自动长出下一条。看懂这条链,才能把提醒真正配置成流程。

Odoo 开发 协同办公
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 10 阅读

先说结论

Odoo 里的 Activity “下一步”并不是一个单一功能,而是两套机制:

  • suggest:完成当前活动后,系统给你推荐下一步类型,是否创建由人决定
  • trigger:完成当前活动后,系统直接自动创建下一条活动

这两个机制都挂在 mail.activity.type 上,但它们在源码里被明确设计成互斥

所以如果你把它们理解成“一个是推荐列表,一个是推荐列表里的默认值”,就会把系统看浅。

官方真正表达的是:

Odoo 可以把 activity 配成“人为接力”,也可以配成“自动接力”,但不能同时把同一个类型两种逻辑都开满。

第一层:为什么 activity type 才是流程规则,而不是 activity 本身

很多人盯着 mail.activity 看,觉得 activity 才是核心。

但如果顺着源码看,你会发现真正决定流程感的,是 mail.activity.type

这个模型上最关键的几个字段是:

  • chaining_type
  • triggered_next_type_id
  • suggested_next_type_ids
  • delay_count
  • delay_unit
  • delay_from

它们共同回答的是:

  1. 完成后有没有下一步
  2. 下一步是系统自动建,还是让用户手选
  3. 下一步的截止日期从哪一天开始算

也就是说,mail.activity 更像一次具体执行,mail.activity.type 才像流程模板。

第二层:为什么 suggest 和 trigger 被设计成互斥

mail_activity_type.py 里有两个成对的计算/逆向方法:

  • _compute_suggested_next_type_ids() / _inverse_suggested_next_type_ids()
  • _compute_triggered_next_type_id() / _inverse_triggered_next_type_id()

官方逻辑很直接:

  • 如果 chaining_type == 'trigger',就把 suggested_next_type_ids 清空
  • 如果 chaining_type == 'suggest',就把 triggered_next_type_id 清空

这说明系统并不希望一个 activity type 既“自动长下一条”,又“让人挑多个推荐”。

原因很现实。

如果两套都开:

  • 用户会看到推荐项
  • 系统又自动建一条
  • 最终流程会出现重复接力、责任混乱、截止日冲突

所以 Odoo 在模型层先把规则收紧了。

这是一种很典型的产品设计思路:

与其允许你配出歧义流程,不如直接限制成两种清晰模式。

第三层:完成 activity 时,系统到底在哪一步决定“下一条怎么来”

关键在 mail.activity 的完成链路。

很多人只看到界面上的 Mark Done,但源码里真正重要的是:

  • action_feedback()
  • action_feedback_schedule_next()
  • _action_done()

其中 _action_done() 最值得看。

它在遍历活动时,会先检查:

  • 当前 activity 的 chaining_type 是不是 trigger

如果是,系统会:

  1. 带上 activity_previous_deadline=activity.date_deadline 上下文
  2. _prepare_next_activity_values()
  3. 把结果收集进 next_activities_values
  4. 最后统一 create() 出新的 mail.activity

也就是说,自动接力不是界面层行为,而是完成动作里的业务逻辑

这点非常关键,因为它解释了两个现象:

  • 哪怕不是从某个特定前端按钮完成,只要走到这条完成链,trigger 仍然会生效
  • 下一条 activity 的创建时机,和“当前活动被标记完成”是同一个事务语义里的事情

第四层:suggest 模式到底在做什么

如果是 suggest,系统不会在 _action_done() 里直接长下一条。

它做的是另一件事:把“前一条活动类型”传给后续界面逻辑。

mail.activity 上:

  • previous_activity_type_id 记录前一步是什么
  • has_recommended_activities 会根据前一步的 suggested_next_type_ids 算出来
  • _onchange_previous_activity_type_id() 会在有 trigger 时自动切默认类型
  • _onchange_recommended_activity_type_id() 则允许用户点选推荐项后切换 activity_type_id

换句话说:

  • trigger 是系统替你生成下一步
  • suggest 是系统替你缩小选择范围

它不是“没做事”,而是在把经验路径提前塞给用户。

这很适合 CRM、项目跟进、审批回访这类流程:

  • 你不想完全自动化
  • 但你又不想让执行人每次都从全部活动类型里盲选

第五层:为什么截止日期不是简单“今天加几天”

mail.activity.type._get_date_deadline() 还藏着一个容易被低估的点:

  • delay_from == 'current_date':从当前日期往后推
  • delay_from == 'previous_activity' 且上下文有 activity_previous_deadline:从上一条活动截止日期往后推

这两种算法,决定的是流程节奏的参考基准。

区别非常大。

如果按 current_date

  • 你今天才补做完上一条
  • 下一条从今天重新起算
  • 整条流程会整体向后漂移

如果按 previous_activity

  • 下一条仍然按原计划节奏推
  • 你晚做上一条,并不会自动把整个流程拖长

这就是为什么有些 activity 流程更像“建议跟进”,有些更像“固定节奏的 SLA”。

第六层:为什么删除 activity type 时,Odoo 还要把旧活动改成 Todo

mail.activity.type.unlink() 里有一段很有意思的处理:

  • 如果删除某个 activity type,系统会先把现存活动改挂到 mail.mail_activity_data_todo
  • 然后再删类型本身

这说明官方很在意历史活动不能因为配置变化而失去语义落点

同样地,一些核心类型还不允许删,比如 To-Do、Call、Meeting 这些基础类型。

这背后表达的思想很清楚:

Activity type 不是随手写的标签,它是流程配置的一部分,删改要非常保守。

实战里怎么用 suggest,怎么用 trigger

更适合 suggest 的场景

  • 销售跟进:打完电话后,可能发报价,也可能约会议
  • 项目协作:处理完某一步后,下一个动作要由负责人判断
  • 审批追踪:系统给出推荐,但不替你决定

更适合 trigger 的场景

  • 合同到期前固定提醒
  • 某个文件上传后必须补一个复核动作
  • 某项交付完成后一定要长出回访或质检动作

一句话:

  • 存在业务分歧时,用 suggest
  • 下一步几乎确定时,用 trigger

最容易踩的 4 个坑

1)以为 suggest 会自动建下一条

不会。

它主要是推荐,不是自动执行。

2)以为 trigger 只是前端默认值

不是。

trigger 是完成动作里的真实业务逻辑,走 _action_done() 时会创建新的 activity。

3)没搞懂 delay_from

如果你的流程节奏总是“越跟越晚”,先看是不是把本来该按 previous_activity 的规则配成了 current_date

4)把 activity type 当成无关紧要的字典

不是。

它是流程编排器。删、改、归档,都会影响现有流程和用户体验。

排查“为什么没自动长下一条”的顺序

推荐按这个顺序看:

  1. 当前 activity type 的 chaining_type 是不是 trigger
  2. triggered_next_type_id 是否真的配置了
  3. 完成动作是否走了 action_feedback() / _action_done() 主链
  4. 新 activity 的 deadline 计算是否受 delay_from 影响
  5. 有没有把“推荐”误当成“自动生成”

这样排查,通常比盯着界面按钮更快。

最后一句

Odoo Activity 真正有价值的地方,不是“能记待办”,而是它允许你把待办配置成人工判断型接力自动衔接型接力

所以你要理解的不是“下一步按钮在哪里”,而是:

当前这个 activity type,到底是在给人建议,还是在替流程自动接棒。

一旦把 suggest 和 trigger 分清,很多 activity 配置会立刻清爽很多。

DISCUSSION

评论区

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