先说结论
很多人第一次看到 Odoo 项目里的客户评分,会以为它只是:
- 任务完成后
- 自动发一封满意度调查邮件
但从 /home/ubuntu/odoo-temp/addons/project/models/project_task_type.py 和 project_task.py 来看,它真正的设计不是“任务发邮件”,而是:
- 阶段是否开启评分
- 评分在什么时候发送
- 评分模板是否可用
- 系统消息类型是否显隐
- 周期性催评由谁统一调度
也就是说,Odoo 把“客户评分”建模成了 阶段级规则,而不是任务上的临时动作。
评分邮件只是结果,真正的控制中心在 task stage。
第一层:评分能力不是挂在任务上,而是挂在阶段上
project.task.type 里有一组很关键的字段:
rating_activerating_statusrating_status_periodrating_template_idrating_request_deadline
这套字段说明了一个核心事实:
Odoo 不是问“这张任务要不要发评分”,而是在问“进入这个阶段的任务,应该按什么规则发评分”。
这和很多人的直觉不一样。
因为直觉上你会把评分理解成任务动作;但 Odoo 更像是在做流程建模:
- 某个阶段代表“适合收集反馈”
- 所有进入这个阶段的任务,遵守相同规则
这比手工在每张任务上打勾稳得多,也更适合规模化交付团队。
第二层:为什么官方把评分开关和模板开关绑在一起
project.task.type.write() 里有一段很有代表性的逻辑。
当 rating_active 被打开或关闭时,Odoo 不只是改一个布尔值,而是连带处理:
project.mt_project_task_rating的 hidden/defaultproject.mt_task_rating的 hiddenproject.rating_project_request_email_template的 active
这说明官方对评分功能的理解是:
- 它不只是一个字段
- 它还牵涉到消息追踪入口
- 还牵涉到默认评分邮件模板是否应该处于启用状态
换句话说,评分被视为一整套“流程能力包”。
这也是为什么你不能把它当“随手发一封满意度邮件”来看。
第三层:评分触发不是只有一种,阶段支持不同发送节奏
rating_status 和 rating_status_period 很关键。
从字段帮助和计算逻辑可看出,阶段评分至少支持这样的语义:
- 一次性触发
- 周期性触发
而 _compute_rating_request_deadline() 会根据周期生成下一个发送截止时间:
- daily → 1 天
- weekly → 7 天
- bimonthly → 15 天
- monthly → 30 天
- quarterly → 90 天
- yearly → 365 天
这意味着 Odoo 的目标不是“任务完结发一次问卷”,而是:
只要任务仍处在某个需要持续跟踪满意度的阶段,就可以按节奏重复发送评分请求。
这特别适合长期服务型项目,比如:
- 运维支持
- 持续顾问服务
- 多轮交付阶段
第四层:定期催评不是每张任务自己跑,而是阶段级调度统一扫
project.task.type._send_rating_all() 很能说明官方设计。
它会:
- 查出所有
rating_active=True、rating_status='periodic'且rating_request_deadline到期的阶段 - 对这些阶段下的项目任务统一调用
stage.project_ids.task_ids._send_task_rating_mail() - 然后把阶段自己的下一次 deadline 重算
这里非常值得注意的一点是:
- 扫描单位是 stage,不是 task
这说明 Odoo 把“到点了该催评分”理解成一种流程规则巡检,而不是每条任务各自持有一个 cron。
这样设计有两个好处:
1. 调度模型更简单
不用给每张任务都维护单独的定时状态。
2. 规则更统一
一个阶段代表一套服务承诺;所有处于这个阶段的任务按同一规则被处理。
第五层:真正发评分时,Odoo 还会检查对象是否适合发送
在 project_task.py 里,任务发评分请求时并不是无脑发。
从 _send_task_rating_mail() 附近逻辑看,它会关注:
- 阶段上是否有
rating_template_id - 是否能得到 partner
- partner 不能等于当前内部用户
- 模板发送时还会考虑语言
- 模板不会对
is_template任务乱发
这背后体现的是一个很现实的边界:
评分对象必须是“真实外部协作对象”,而不是系统里的任意关联联系人。
否则你就会得到很多荒谬情况:
- 给内部员工发客户满意度邮件
- 给模板任务发评分
- 语言错乱
- 没客户却强行发空邮件
官方显然在尽量避免这些事故。
第六层:为什么这套设计比“任务完成发问卷”更成熟
如果只做“done 就发问卷”,你会很快遇到这些问题:
- 某些项目阶段并不代表真正完成
- 有些项目要持续收集反馈,不是只收一次
- 不同阶段的邮件口径可能不同
- 某些阶段要禁用评分
而 Odoo 用阶段建模后,这些问题就自然有了解法:
- 用阶段表达业务语义
- 用模板表达沟通口径
- 用状态和周期表达触发时机
这也是 ERP 产品常见的建模思路:
不是围着按钮设计,而是围着流程节点设计。
新手最容易误解的 4 件事
1. 以为评分就是任务上的一个邮件按钮
不对。评分核心逻辑在 project.task.type。
2. 以为每个任务自己记住下次什么时候催评
不对。定期巡检的主入口是阶段级 _send_rating_all()。
3. 以为开启评分只影响发不发邮件
不对。它还会影响消息子类型和模板启停。
4. 以为任何 partner 都能收到评分请求
不对。任务发送时还会检查 partner、模板、语言以及模板任务等边界。
实战上最该注意什么
1. 如果你要自定义评分时机,先想清楚是“任务规则”还是“阶段规则”
很多需求更适合扩展阶段,而不是往任务里硬塞字段。
2. 不要只改前端勾选项
评分相关的消息类型、模板激活状态也可能要一起校准。
3. 周期性催评场景,要特别注意不要重复轰炸客户
虽然官方支持 periodic,但业务上仍要控制阶段语义和周期长度。
一句话记忆法
Odoo 项目评分不是“任务发问卷”,而是“阶段定义规则、调度按阶段巡检、任务在合适对象上执行发送”的一整套自动化机制。
DISCUSSION
评论区