CRM 深度

Odoo CRM 为什么‘标记赢单’不只是把概率改成 100:won stage 选择、date_closed 与 rainbowman 反馈链路讲透

很多人把 Mark Won 理解成一个把 probability 改成 100 的按钮。源码里它还会找最合适的 won stage、处理 date_closed 语义,并在满足条件时生成与 team、来源、国家相关的庆祝反馈。

CRM
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

Odoo CRM 的 Mark Won,不是“把 probability 改成 100”这么简单。

源码真正表达的是三层业务语义:

  1. 这条商机进入哪个 won stage
  2. 它何时算正式 closed
  3. 用户界面要不要给你一个有业务上下文的庆祝反馈

也就是说,赢单在 Odoo 里既是字段变化, 也是一次 漏斗位置确认 + 关闭时间落账 + 正向反馈触发


一、为什么 action_set_won 先找 stage,而不是先改字段

action_set_won() 的核心动作不是直接写:

  • probability = 100

而是先找 适合当前商机的 won stage

源码会把当前 pipeline 里所有 is_won=True 的 stage 拿出来, 再根据当前商机所处 stage 的 sequence 做判断:

  • 优先找 位于当前阶段之后 的第一个 won stage
  • 如果找不到,再回退到 不高于当前阶段 的最后一个 won stage

这解决了一个很现实的问题:

一个 team 里可能不止一个 won stage,而且它们不一定都排在最末尾。

所以 Odoo 不能粗暴地说“赢单就跳到第一个 won stage”。 它要尽量找到和当前进展位置最相称的那个赢单落点。


二、为什么 won 在 Odoo 里是 stage 语义,不只是概率语义

源码注释写得很清楚:

  • won semantic: stage.is_won
  • probability = 100 是 implied

也就是说,在 Odoo 的设计里, 真正定义“赢单”的主语义是 进入 won stage, 100% 概率更像是这个状态的必然后果。

这与 lost 正好形成对照:

  • lost = active=Falseprobability=0
  • won = stage.is_won 且概率被推到 100

所以赢单不是普通标签, 而是一个会影响关闭时间、报表口径和后续交互反馈的业务状态。


三、date_closed 为什么会跟着 stage/probability 联动

write() 里对 stage_idprobabilityactive 有专门联动逻辑。

如果出现这些情况:

  • 概率写到 100
  • 或记录被设为 inactive
  • 或切入 won stage

系统会补 date_closed

但还有一个细节很有意思:

在两个 won stage 之间切换,不应该重写关闭时间

源码会把“本来已经处于 won stage 的记录”单独拿出来处理, 避免只是从 won A 切到 won B 时把 date_closed 重刷一遍。

这说明 Odoo 把 date_closed 理解为:

第一次真正完成赢单/关闭语义的时刻

而不是“任何一次后来改 stage 的时间”。

这对分析成交周期非常重要。 否则你调整 pipeline 结构或补改 stage, 都会把历史 closing date 污染掉。


四、为什么把 stage 本身改成 is_won,也会触发大面积副作用

crm.stage.write() 里还有一段常被忽略的逻辑:

  • 如果一个 stage 被改成 is_won=True
  • 这个 stage 上现有 lead/opportunity 会被统一推到 probability=100
  • 如果又把 is_won 取消,系统会重新计算概率

而且源码的 warning 直接提醒用户:

  • 这会触发大量记录更新
  • 手工概率可能丢失

这说明在 Odoo 里,stage 配置本身就是业务规则,不是纯展示层参数。

你改 stage,是在改漏斗语义,不是在改颜色标签。


五、rainbowman 不是固定彩蛋,它会读业务上下文

action_set_won_rainbowman() 在执行赢单后, 还会尝试生成庆祝反馈。

很多人以为这只是随机一句 “Good job”。 其实 _get_rainbowman_message() 会看不少业务上下文,比如:

  • 当前用户是否存在
  • message 数量是否很多
  • 这是不是这个来源的首单
  • 这是不是这个国家的首单
  • 这次赢单是否几乎一路直达

所以 rainbowman 本质上不是“页面特效”, 而是一种轻量化的销售行为强化反馈

它在告诉你:

  • 这单赢得不容易
  • 或者这单在来源 / 国家维度有纪念意义
  • 或者这条 pipeline 推进得特别漂亮

六、为什么这套设计很像“成交记账”

把上面几段源码连起来,你会发现 Odoo 在赢单时做的不是一件事,而是三件事:

  1. 把商机落到合适的 won stage
  2. 把业务关闭时间钉住
  3. 给销售一个上下文化反馈

这很像会计里的“确认分录时点”。

赢单不是视觉上的“打勾”, 而是系统承认:

  • 这个机会从待推进变成已实现
  • 它该进入哪一种完成态
  • 这次完成值不值得强调

七、实战里最容易误解的 4 件事

1. 以为赢单按钮只改 probability

错。它先决定 won stage,再带出概率和关闭语义。

2. 以为只有一个 won stage 才合理

错。源码本来就支持同一 pipeline 有多个 won stage。

3. 以为在 won stage 间切换会刷新成交日期

源码特意避免这种污染。

4. 以为 rainbowman 只是 UI 特效

不完全。它读取业务上下文,是一种轻量级销售反馈机制。


一句话记忆法

Odoo CRM 的赢单不是“把概率拉满”,而是“落到合适的 won stage、确认 close 时点,再决定要不要给你一个有业务意义的庆祝反馈”。

DISCUSSION

评论区

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