先说结论
Odoo eLearning 真正难运营的,不是“课程能不能报名”,而是:
- 该加进来的人能不能自动成为成员
- 课程一更新,谁应该被提醒回来继续学
- 成员状态能不能随着完成度自然推进
- 认证、完课邮件和激励,能不能在正确时间释放
从 /home/ubuntu/odoo-temp/addons/website_slides/models/slide_channel.py 与 slide_channel_partner.py 看,Odoo 已经把这条链拆得很清楚:
enroll_group_ids负责自动加课slide.channel.partner负责成员生命周期partner_has_new_content负责新内容感知completed_template_id与_send_completed_mail()负责完课释放website_slides_survey再把认证层接到成员关系上
所以一门课的运营主线,不只是“学员有没有进来”,而是:
进来之后,系统能不能不断知道他下一步该干嘛。
第一层:为什么自动加课是课程运营能力,不只是权限便利
slide.channel 上的 enroll_group_ids 很容易被低估。
看起来它只是:
- 这些组的成员自动成为课程成员
但对培训运营来说,它其实是在解决一件很重的事:
课程成员池能不能跟组织结构同步。
比如这些场景:
- 新员工入职后自动加入 onboarding 课程
- 新任销售自动加入产品认证课程
- 某项目组成员自动加入专属培训
如果没有自动加课,培训管理员就只能不停做名单维护:
- 拉人
- 补人
- 查漏
- 处理迟到加入者
而 _add_groups_members() 的存在说明 Odoo 很明确地支持一种思路:
先把课程视为组织角色的默认能力包,而不是一次次手工邀请。
这会直接影响课程覆盖率和运营成本。
第二层:为什么成员关系表一定要有 joined、ongoing、completed 这些状态
slide.channel.partner.member_status 不是简单 enrolled / not enrolled,而是:
invitedjoinedongoingcompleted
这个设计非常关键。
因为课程运营真正关心的不是“进没进课”,而是处在哪个阶段:
invited
人还没真正开始,只能算可触达对象。
joined
已经进来了,但尚未产生学习进展。
ongoing
已经在学习,需要继续牵引。
completed
已经完成,可以触发证书、复训、进阶课推荐。
没有这层状态,你所有运营动作都会变得粗糙:
- 邀请谁
- 提醒谁
- 激励谁
- 谁该收到完课通知
都分不清。
第三层:为什么 completion 必须从真实完成记录回算
_recompute_completion() 会根据 slide.slide.partner 的真实完成记录,重新计算:
completed_slides_countcompletionmember_status
而且还考虑课程内容变化后的回退:
- 以前完成过
- 但课程新增了内容
- 完成度没到 100% 了
- 状态就要从 completed 退回
这件事非常重要。
因为“内容 drip 式释放”或持续上新的课程,最怕的就是系统还把老学员永久当已完成。
一旦课程不断迭代,真正合理的逻辑本来就应该是:
- 内容变了
- 学员当前状态也要重新解释
这正是 Odoo 的做法。
它不是把完课当一次性盖章,而是把完课理解成相对于当前课程内容结构的动态状态。
第四层:为什么新内容提醒不只是发一封邮件那么简单
partner_has_new_content 的计算逻辑很值得看。
它会检查:
- 最近 7 天新发布的内容
- 当前用户对这些内容是否已完成
只有“有新内容且还没学完”时,才会认为这门课对这个人存在新内容提醒价值。
这背后的产品判断很准:
不是所有上新都值得打扰所有人
已经学过的人和未学的人,提醒价值不同。
不是所有提醒都应该无限期有效
最近 7 天这个窗口,说明系统更重视“当前值得回来继续学”的内容。
提醒的前提是还有未完成增量
不是单纯课程有变动就打扰。
这其实就是内容 drip 运营最关键的一点:
提醒应该围绕未完成增量,而不是围绕内容发布动作本身。
第五层:为什么 new content notification 和 completed notification 要分开理解
slide.channel 同时有:
publish_template_id:新内容通知completed_template_id:完课通知
这两个模板看起来都只是邮件模板,但它们代表的是完全不同的运营语义:
新内容通知
是把学员从静止状态拉回 ongoing。
完课通知
是把学员从 ongoing 推进到 completed,并正式收口。
很多课程实施会把这两种邮件混在一起,结果就是:
- 新内容提醒像完课邮件一样隆重
- 完课邮件又像普通上新通知一样没存在感
而 Odoo 把两条模板分开,本质上是在承认课程运营至少有两种完全不同的节奏:
- 召回节奏
- 毕业节奏
这对 drip 内容课程尤其重要。
第六层:为什么 next_slide_id 是 drip 学习体验的关键接口
_compute_next_slide_id() 会找出:
- 已发布
- active
- 非分类节点
- 且当前学员尚未完成
的第一条课件,作为 next_slide_id。
这意味着 Odoo 不只是告诉学员“你还有内容没看”,而是明确告诉他:
- 下一步就看这一个
对 drip learning 来说,这非常关键。
因为内容分批释放时,最容易让学员产生的不是“不想学”,而是“我该从哪继续”。
next_slide_id 就是在把课程结构翻译成单一下一动作。
它看似只是体验优化,实际却非常直接地影响回访与完课率。
第七层:为什么认证释放必须挂在成员关系,而不是只挂问卷分数
虽然认证扩展在 website_slides_survey 里,但它最终仍然会把:
- 认证成功
- 认证人数
- 课程成员是否 certified
落回 slide.channel.partner 这一层。
这和自动加课、新内容提醒、完课通知放在一起看,就会发现 Odoo 的思路非常统一:
- 课程不是一堆内容
- 认证也不是一份孤立问卷
- 真正的运营对象始终是“某个人和某门课之间的关系”
所以 certification release 最合理的节奏,不是“问卷通过立刻万事结束”,而是:
- 先看成员关系是否已进入正确学习阶段
- 再看认证是否完成
- 最后决定是否触发完课闭环和后续动作
这也是为什么课程认证、重修、内容更新这些能力,最终都要回到 membership 这张表上来理解。
实施时最该做的四件事
1. 先定义哪些课程应该跟组织角色自动绑定
别把所有课程都做成手工邀请。
2. 用成员状态而不是总人数做运营看板
真正该关注的是 invited、joined、ongoing、completed 的转化。
3. 上新提醒要围绕未完成增量,不要滥发
否则学员很快就会把课程通知当噪音。
4. 把认证、完课通知和下一课入口放在同一条成员旅程里看
不要把考试、课件、邮件各自当独立系统。
最后一句
Odoo eLearning 最成熟的地方,不是课件上传,也不是报名入口,而是它把自动加课、内容召回、成员进度、完课释放、认证回写都绑在了课程成员关系上。
理解了这一点,你就会发现一门课真正的运营单位不是 slide,也不是 survey,而是:
一个成员此刻在这门课里的位置。
DISCUSSION
评论区