CRM × 网站

Odoo CRM 为什么有些在线聊天会露出客户商机、有些却完全没有:session store、lead 读权限与 opportunity_ids 暴露边界讲透

很多人以为 Odoo 在线聊天侧边栏里看到的客户商机是前端自己查出来的,但 crm_livechat 真正做的是更保守的 session store 下发:只有当前用户具备 crm.lead 读取权时,livechat session 才会附带 customer partner 的 opportunity_ids;否则这块数据会被整块裁掉。

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

先说结论

Odoo 在线聊天里看到“这个访客关联了哪些商机”,并不是前端自己拿 partner 再临时查一遍 CRM。

真正的机制是:

  • livechat session 会通过 store 向前端下发一组可显示字段;
  • crm_livechat 只在当前用户有 crm.lead 读取权限时,才把 livechat_customer_partner_ids.opportunity_ids 这一层加进去;
  • 如果没有权限,这块结构根本不会发给前端。

所以这里的关键不是“前端显示了什么”,而是:

后端先决定什么数据有资格进入聊天会话快照。


一、为什么这件事发生在 session store,而不是聊天窗口自己再发请求

_get_livechat_session_fields_to_store() 的意义,在于它定义了“当前 livechat 会话允许带给前端的数据轮廓”。

这和常见的“前端打开侧栏后再单独请求一份 CRM 数据”很不一样。

Odoo 选 store 模式有几个明显好处:

  1. 会话初始化时一次性带齐必要数据
  2. 实时 UI 不用再自己拼权限逻辑
  3. 聊天前端只消费已授权的数据,不再重复发散查询

换句话说,商机可见性在这里不是一个“展示层功能”,而是会话快照的一部分。


二、为什么没有 crm.lead 读取权时,不是“显示空列表”,而是整个字段都不发

源码里最关键的一行其实是:

  • 先拿父类的 fields_to_store
  • 如果 self.env["crm.lead"].has_access("read") 不成立,直接 return。

这意味着 Odoo 的选择不是:

  • opportunity_ids 作为空数组下发;
  • 再让前端自己理解“你没权限,所以是空的”。

而是更彻底地:

  • 你没有权限,就别收到这块字段定义。

这两者差别很大。

前者只是把结果清空,后者则是在协议层就声明“这段数据结构不属于你”。

这是一种更干净的安全模型,因为它避免了前端去推断:

  • 到底是真的没有商机;
  • 还是有商机但你没权限;
  • 还是接口坏了。

Odoo 这里选的是最保守、也最清楚的一条线。


三、为什么要通过 Store.Many 暴露到 livechat_customer_partner_ids.opportunity_ids

Store.Many 暴露的是一个嵌套关系:

  • 先是当前 livechat 里的客户 partner;
  • 再是这个 partner 对应的 opportunity_ids
  • only_data=True,只下发纯数据。

这说明 Odoo 要给坐席的不是一大坨 CRM 详情,而是一个足够轻、足够快、足够可行动的关联视图

它想解决的问题是:

  • 这个来访者是不是已经在 pipeline 里;
  • 坐席要不要按已有商机语境接话;
  • 有没有必要把人再重复建成新线索。

也就是说,这里暴露商机不是为了“在聊天里浏览 CRM”,而是为了让客服/销售在会话当下做更准确的判断。


四、为什么这套机制能减少前台越权和误导

如果没有这层 store 裁剪,常见的坏味道会很多:

  • 前端知道 partner id,就想自己再调 CRM 接口;
  • 不同聊天角色拿到的数据结构不一致,却没有统一权限出口;
  • UI 上看起来像是“没有商机”,其实只是因为权限被拦在另一个接口。

现在因为机会信息是否存在,是由 store 构建阶段统一决定:

  • 权限判断只在服务端做一次;
  • 前端要么拿到这块数据,要么根本没有这块字段;
  • 聊天窗口显示语义更稳定。

这其实是把“安全”和“可维护性”一次性都解决了。


五、为什么这不等于“有权限的人就能看到所有 CRM 内容”

这里也要注意一个常见误解。

_get_livechat_session_fields_to_store() 暴露的是:

  • customer partner 下的 opportunity_ids
  • 并不是把完整 lead / opportunity 表单字段通通搬进聊天窗口。

这意味着 Odoo 在做的是最小必要暴露

  • 先告诉你“有无商机、哪些商机”;
  • 而不是直接把 CRM 全量详情塞进会话。

这套收口很合理,因为在线聊天场景要求的是快速判断,不是完整审阅后台记录。


六、实施里最容易误判的几个点

1. 以为机会列表是前端自己算出来的

不对,它是后端 session store 明确下发的。

2. 以为没看到商机就说明客户没有历史机会

不一定,也可能是当前用户没有 crm.lead 读取权。

3. 以为权限不足时会收到空数组

不是,很多时候是整块字段结构根本不会出现。

4. 以为聊天窗口会暴露完整 CRM 详情

不会,Odoo 只下发最小必要的关系数据。


七、排错顺序建议

在线聊天里看不到客户商机时,我建议按这个顺序查:

  1. 当前坐席是否具备 crm.lead 读取权限;
  2. 当前 livechat session 是否绑定到了 customer partner;
  3. store 快照里是否存在 livechat_customer_partner_ids.opportunity_ids
  4. partner 本身是否真的有关联商机;
  5. 前端是否把“字段不存在”和“字段为空”误当成同一回事。

一句话记忆

Odoo 在线聊天里的商机可见性,不是前端想看什么就查什么,而是后端 session store 先按 CRM 权限把会话数据裁好再发。

DISCUSSION

评论区

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