先说结论
Odoo 的 website.visitor 并不是“没有 partner 就什么都做不了”。
在 website_crm 里,消息入口前会走一层补救逻辑:
- 先看 visitor 是否已有关联 lead;
- 按 lead 的置信度排序;
- 如果这些 lead 还没 partner,尝试从主 lead 补建 partner;
- 最后把消息编辑器上下文指向最可信的那条 CRM 记录。
所以 visitor 到 CRM 消息的链路,并不完全依赖你事先把客户主数据建好。
一、为什么 visitor 需要“先选主 lead”
一个 visitor 可能对应多条 lead。
这时最大问题不是“能不能发消息”,而是:
消息应该挂到哪条记录上,才最像真实商业对象?
源码用的是 lead_ids._sort_by_confidence_level(reverse=True)。
排序依据包括:
- 不是 lost 的优先;
- opportunity 比 lead 更可信;
- 阶段越靠后越可信;
- 概率越高越可信;
- 更新、更高 id 的记录更靠前。
这本质上是在做“主叙事选择”。
二、为什么没有 partner 也不立刻失败
_check_for_message_composer() 里,如果 visitor 有 lead,但还没有 partner,系统不会马上退出。
它会:
- 取排序后的主 lead;
- 看这些 lead 有没有已挂 partner;
- 如果都没有,就对主 lead 调
_handle_partner_assignment(create_missing=True); - 尝试把 partner 补出来,再把 visitor 也挂上这个 partner。
这说明 Odoo 不想因为主数据尚未完全成形,就把前台和销售沟通硬生生切断。
三、消息上下文为什么要绑定到 lead,而不是只绑 partner
_prepare_message_composer_context() 返回的是:
default_model = 'crm.lead'default_res_id = 最可信 leaddefault_partner_ids = partner.ids
也就是说,消息不是只对着联系人发,而是对着具体销售机会发。
这样做的好处很明显:
- chatter 历史会留在正确的 CRM 记录上;
- 销售能看到消息和商机状态放在一起;
- 后续跟进不需要在联系人和商机之间来回跳。
四、这套逻辑解决了什么业务尴尬
它主要解决三类尴尬场景:
- 访客已经表现出兴趣,但还没形成干净 partner;
- 重复 lead 并存,不知道该以哪条为主;
- 销售想回消息,但系统不该把上下文挂错对象。
Odoo 的策略不是“条件不完美就阻止沟通”,而是尽量选出最可信记录,让沟通先发生。
五、最容易误会的地方
1. 以为 visitor 发消息一定依赖已有 partner
不一定,源码会尝试补建。
2. 以为排序只看最近创建的 lead
不是,它综合看类型、阶段、概率、活跃状态。
3. 以为消息只属于联系人,不属于商机
在这里,消息上下文明确优先落在 crm.lead。
六、排错顺序
visitor 不能进入消息编辑器时,先查:
- 是否存在
lead_ids; - lead 里是否已有 partner;
_handle_partner_assignment是否能正常补建;- 排序后的主 lead 是否就是你预期那条。
一句话记忆
Odoo Website Visitor 的消息入口,不是“先有完美主数据再沟通”,而是先挑最可信 lead,必要时补建 partner,再把消息挂回正确 CRM 上下文。
DISCUSSION
评论区