其他深度

Odoo 在线课程为什么不只是“学员看完视频”:邀请入课、完成率、下一课与 Karma 激励引擎讲透

很多人把 Odoo eLearning 当成内容展示页,但源码里的 slide.channel 与 slide.channel.partner 把入课、可见性、下一课推荐、结课邮件和 Karma 激励全绑在一起。看懂这套成员引擎,课程运营才不会停留在“发链接看课”。

其他
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

Odoo eLearning 的课程页看起来像内容站,但底层并不是“文章列表 + 视频列表”这么简单。

/home/ubuntu/odoo-temp/addons/website_slides/models/slide_channel.pyaddons/website_slides/models/slide_channel_partner.py 来看,真正支撑课程运营的是两层对象:

  • slide.channel:课程本身,负责可见性、入课策略、内容统计和规则
  • slide.channel.partner:课程成员关系,负责邀请、完成率、成员状态和下一课

再加上 Karma 字段、完成邮件和 prerequisite 逻辑,Odoo 实际上做的是一套轻量的学习增长引擎。

所以它真正解决的问题不是“用户能不能打开课程页”,而是:

一个人如何被邀请进课程、如何逐步推进、何时算完成,以及完成后系统如何继续激励他。


第一层:为什么课程不是内容容器,而是规则容器

slide.channel 上有很多人第一次不会在意,但其实很关键的字段:

  • visibility
  • enroll
  • enroll_group_ids
  • partner_ids
  • completed
  • completion
  • prerequisite_channel_ids
  • karma_gen_channel_finish
  • completed_template_id

如果它只是一个内容容器,这么多“成员和规则”字段本来没必要放在课程对象上。

这说明 Odoo 的产品判断很明确:

课程不只是内容集合,而是一个有准入机制、有推进逻辑、有激励结果的学习空间。

这和很多“把知识库页包装成课程页”的做法差别很大。

在 Odoo 里,你不仅要管:

  • 课里放了什么内容

还要管:

  • 谁能看
  • 谁算成员
  • 谁是被邀请未加入
  • 谁已经进行中
  • 谁已经完成
  • 完成后系统要不要给奖励或发邮件

第二层:为什么课程成员必须有独立模型

slide.channel.partner 是这套设计的核心之一。

它不是一张普通中间表,而是一张带业务状态的成员关系表。

上面直接挂着:

  • member_status
  • invited
  • joined
  • ongoing
  • completed
  • completion
  • completed_slides_count
  • last_invitation_date
  • invitation_link
  • next_slide_id

并且有唯一约束:

  • 同一个 channel_id + partner_id 只能有一条成员关系

这套设计说明官方不是把“是否在课里”看成一个布尔值,而是看成一条持续演化的成员生命周期。

这很重要,因为课程运营最怕的就是以下状态全挤在一起:

  • 被邀请但还没进来的人
  • 进来了但没开始的人
  • 开始了但没学完的人
  • 学完了的人

如果没有独立成员模型,你只能用一堆临时字段拼凑,最后连转化漏斗都看不清。


第三层:邀请链接为什么要按人和课程算哈希

_compute_invitation_link() 会基于:

  • partner_id
  • channel_id

生成邀请链接,并用 _get_invitation_hash() 做 HMAC。

这意味着 Odoo 的邀请不是泛用分享链接,而是面向具体成员的入课凭证

它带来的好处很现实:

1. 邀请可以追踪到人

谁被邀请、谁还没进来,不会因为一个公共链接被无限转发而失真。

2. 课程可做 invitation-only 模式

visibility = membersenroll = invite 时,课程可以真正变成“仅成员可见”。

3. 后续状态变迁有基础

只有先有成员记录,系统才能知道这个人是 invited、joined 还是 ongoing。

这就是为什么课程邀请在 Odoo 里不只是“发一封邮件”,而是成员关系建模的一部分。


第四层:完成率为什么不只是前端进度条

_recompute_completion() 是最值得研究的方法之一。

它会基于 slide.slide.partner 的完成记录,去统计当前成员在本课程下:

  • 已完成内容数
  • completion 百分比
  • 是否达到 total_slides
  • 对应应该落在哪个 member_status

状态切换逻辑也很清晰:

  • 0%:joined
  • 0~100%:ongoing
  • 100%:completed

而且一旦从未完成变成完成,会触发:

  • _post_completion_update_hook(completed=True)
  • _send_completed_mail()

如果后续因内容变化或回退导致不再完成,还能反向撤销完成态与相关 Karma。

这说明 Odoo 的“完成率”不是 UI 装饰,而是驱动成员生命周期和激励逻辑的核心指标。


第五层:为什么“下一课”推荐要在 SQL 层精确计算

_compute_next_slide_id() 用了一段非常直接的 SQL:

  • 只看当前课程已发布、激活、非分类的 slide
  • 排除当前成员已经完成的内容
  • 按 sequence、id 取第一条未完成内容

这段逻辑看上去简单,但很有产品味道。

它表达的是:

课程推进不应该让学员自己在内容堆里找方向,系统应该永远知道他下一步最合理的内容是什么。

很多在线学习产品表面上有“继续学习”按钮,底层却只是在前端缓存最近打开项。 Odoo 这里则是用成员完成记录严格算出“下一课”。

这就让课程具备了真正的引导性,而不只是内容目录。


第六层:Karma 机制为什么对学习产品很重要

slide.channelslide.channel.partner 里有两类 Karma 字段:

互动门槛

  • karma_review
  • karma_slide_comment
  • karma_slide_vote

完成奖励

  • karma_gen_channel_rank
  • karma_gen_channel_finish

这说明 Odoo 想要的不是被动看课,而是社区式学习参与

尤其 _post_completion_update_hook() 会在成员完成课程时给对应用户加 Karma,若完成状态被撤销则反向扣回。

这套机制很值钱,因为它把学习行为和社区声誉打通了:

  • 学完课程的人更有资格评论、投票、参与互动
  • 高价值用户不是靠人工授予,而是靠行为累计

对于企业培训、伙伴学院、客户教育平台来说,这比单纯统计观看次数要有运营价值得多。


第七层:课程可见性和入课策略为什么要配合看

visibilityenroll 是最容易被误配的一组字段。

源码里甚至有约束:

  • visibility = members 时,enroll 必须是 invite

这条规则的意思很明确:

如果你把课程设置成“只有成员可见”,那入课方式就不能还是完全开放。

这类约束看似严格,实际上是在帮你防止配置自相矛盾。

因为学习业务里最常见的翻车场景就是:

  • 想做内训课程,却留着公开入课
  • 想做合作伙伴认证,却让任何登录用户都能直接加入
  • 想靠邀请管理学习路径,却没有成员准入边界

Odoo 在模型层提前把这些矛盾压住了。


和“会员学习进度”那篇最不一样的地方

如果说之前那篇更偏“成员与 next slide 的主链”,这次更值得看的,是课程为什么会长成一套状态机 + 激励器

重点不只是“你学到哪里了”,而是:

  • 你怎么被纳入课程
  • 课程是否允许你看
  • 你现在是哪种成员状态
  • 系统接下来要推你去哪一课
  • 你完成后是否会收到邮件、获得 Karma、解锁更多互动权限

这才是 Odoo eLearning 和普通内容站之间真正的鸿沟。


最后一句话

Odoo 在线课程最容易被低估的地方,不是视频播放,不是文章管理,而是它把成员关系、学习推进和社区激励做成了同一套引擎。

所以理解 website_slides 最好的方式不是“课件系统”,而是:

它是一套以课程成员为中心的学习运营系统。

DISCUSSION

评论区

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