预约转商机看似只是多建一个 opportunity,实际上还要解决默认上下文注入的白名单边界与 staff user 强制分配问题。
主要参考:
- `enterprise/website_appointment_crm/tests/test_website_appointment_crm.py`
enterprise/website_appointment_crm/models/calendar_event.py-
odoo/addons/appointment_crm/models/calendar_event.py
一、这不是单模块按钮,而是一条跨模块链路
很多人把这个功能理解成某个界面上的一个按钮、一个 smart button,或者一次自动创建。但从源码看,真正重要的是:上游对象先保留业务上下文,中间层做状态/域/权限判断,下游对象再接住这个上下文继续工作。只看最后一个界面动作,很容易把问题看窄。
二、核心跨链路是怎么跑通的
- 预约表单进入后,CRM 只接收预约链路允许带入的默认值,而不是把任意网站 context 原样灌进 lead。
- 第一次预约生成的 lead 会影响下一次预约的 staff user 选择,从而让后续 event 继续挂在同一条机会链路上。
- HTTP tour 测试验证的是“复用上一个 lead + 继续指派同一销售顾问”这件事,而不是只验证 lead 被创建。
这就是为什么我把它归类为“跨模块链路”题:这里至少同时牵涉了业务对象、会计/项目/销售对象,以及状态或权限判断,而不是单个模型内部的小机制。
三、最容易踩错的边界
- 字段白名单的存在,是为了阻断前端上下文把 team/user 任意覆盖掉。
- 未登录访客也能触发预约 lead,但顾问指派仍受 lead 和 appointment type 配置控制。
- calendar event、lead 和 user 三者必须保持一致,否则 CRM 统计会出现一条预约跑进两个销售名下。
这些边界决定了数据是否还能回到正确的模块继续流动。如果边界被自定义绕开,后面最常见的结果就是:报表看起来还能出, drill-down 却已经解释不通。
四、落地时最值得先验的三件事
- 如果业务要求“上次服务谁,下次继续跟进谁”,要先验证 lead 复用策略。
- 自定义预约页面时,不要随便放开 default_* 参数。
- 排查顾问乱跳时,重放 website tour 比手工点点点更可靠。
五、结论
预约进 CRM 不是前端想传什么就传什么,字段白名单和 staff routing 决定了真正落库的上下文。 这也是企业版功能最容易被低估的地方:看上去只是一个入口,实质上是在多个子系统之间持续传递状态、上下文、数据或权限。
DISCUSSION
评论区