人力资源

Odoo 招聘里的技能为什么不是“填个标签就完了”:岗位匹配分、人才池同步与入职后的技能接力

很多团队把招聘技能当成简历备注,但 Odoo 的 hr_recruitment_skills 源码其实把它做成了可匹配、可同步、可继承的能力流水线:岗位要求会算匹配分,候选人与人才池技能会单向同步,最终还能在创建员工时接到员工技能档案。

人力资源
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 27 阅读

先说结论

Odoo 的招聘技能,不是“在候选人上贴几个会 Python、会英语的标签”那么浅。

从源码看,它实际上串起了三层对象:

  1. 岗位技能要求hr.job.skill
  2. 候选人技能记录hr.applicant.skill
  3. 员工技能记录hr.employee.skill

中间还有一个很关键的桥:人才池 applicant

所以它真正实现的是一条能力流水线:

  • 岗位先定义需要什么能力
  • 候选人根据当前技能算匹配度
  • 人才池里技能会被同步维护
  • 候选人转员工时,技能还能直接接到员工档案

这套设计远比“简历标签”成熟得多。


为什么 Odoo 不直接把 applicant skill 做成文本备注

hr_recruitment_skills 给 applicant 增加的不是一个文本字段,而是一整套结构化对象:

  • applicant_skill_ids
  • current_applicant_skill_ids
  • skill_ids
  • matching_skill_ids
  • missing_skill_ids
  • matching_score

这说明产品目标不是“记录看过的技能”,而是:

让候选人的能力可以被比较、计算和延续。

一旦进入结构化模型,系统才有能力做:

  • 当前技能视图
  • 岗位匹配分
  • 缺失技能清单
  • 创建员工时自动继承

如果只是个富文本备注,这些都做不出来。


current_applicant_skill_ids 暗示了什么

这个字段通过 _get_current_skills_by_applicant() 计算得到,说明候选人技能也不是无限平铺的历史碎片。

它在招聘阶段就已经借用了 skills 模块的核心思想:

  • 技能可能有时间语义
  • 当前有效技能和历史技能要分开看

这很重要。

因为招聘不是只关心“这个人曾经会过什么”,而是更关心:

  • 现在匹不匹配岗位
  • 现在缺什么
  • 当前等级是否达到岗位要求

所以current skill 视角在招聘阶段就已经成立了。


匹配分不是“命中几个标签”,而是岗位需求和候选人能力的比例计算

源码里的 _compute_matching_skill_ids() 很值得看。

它不是简单统计“有几个同名技能”,而是:

  1. 读取岗位 job_skill_ids
  2. 取岗位每项技能的 level_progress
  3. 如果岗位要求学历,还把 expected_degree 的分数也算进去
  4. 对候选人的当前技能做比对
  5. 计算 matching_score

这里有两个很像产品经理思维的细节:

1)不是只有技能名,等级进度也参与计算

岗位要求不是“会 Python”这么粗,而是希望达到某个 level progress。

2)候选人超出岗位要求时,也不会无限放大得分

源码里对单项技能得分做了 min(...) 限制,不让某一个超高等级技能把整体匹配度夸张拉满。

这说明 Odoo 想要的是岗位适配度,不是“候选人总能力炫耀值”。


为什么会同时有 matching_skill_idsmissing_skill_ids

这两个字段一起出现,代表系统不是只想说“你有多像”,还想说“你差在哪”。

这对招聘非常实用:

  • 招聘经理可以快速看候选人命中了哪些关键能力
  • 面试官可以围绕缺失技能设计追问
  • 人才池运营可以据此做再培养或转岗推荐

也就是说,源码不是在做一个漂亮的百分比分,而是在做一个可解释的匹配结果


人才池同步为什么是单向的,而且必须单向

测试和源码都说明一件事:

  • 候选人技能新增、修改、删除时,会同步到 linked talent
  • 但反过来,在 talent 上修改,不会反写 applicant

这是一种非常刻意的单向同步设计。

原因很现实:

  • applicant 是具体招聘流程里的主体
  • talent 更像人才池抽象层

如果允许双向无条件同步,就很容易把:

  • 某次面试流程的即时判断
  • 人才池里更泛化的长期画像

混成一锅。

所以 Odoo 选择的方向是:

流程中的 applicant 变动可以刷新 talent,但 talent 上的编辑不强行改写原申请。

这在数据治理上其实很稳。


为什么 create_employee_from_applicant() 里要把技能一起带过去

hr_recruitment_skills 重写了 _get_employee_create_vals(),直接把 applicant 的技能映射成 employee_skill_ids

这件事的意义非常大:

  • 招聘阶段采集的能力,不会在入职时断档
  • 员工技能档案不需要再手工重录一遍
  • 岗位匹配、招聘评价和后续培养可以连起来

也就是说,Odoo 没把“招聘技能”和“员工技能”做成两套断裂世界。

它明确地认为:

候选人被录用后,招聘阶段形成的能力画像应该成为员工主数据的一部分。


这对 appraisal / learning / mobility 有什么后续价值

虽然本文重点在 recruitment,但这条接力链的真正价值在后面才显现:

  • 员工入职后,可以直接接上 hr_skills 的历史与认证管理
  • 岗位要求和员工现状的差距分析更容易做
  • 后续做绩效、培训、内部流动时,招聘阶段的数据不会白费

换句话说,招聘不是 skills 的临时前台,而是skills 生命周期的起点


实施时最容易犯的 4 个错

错一:把 applicant skill 当备注栏

这样你就失去了匹配分、缺口分析和员工继承能力。

错二:只看匹配分,不看缺失技能

百分比只是摘要,真正可执行的是 missing skill 清单。

错三:想做双向同步

talent 与 applicant 的角色不同,强行双向通常会搞乱来源边界。

错四:员工创建后又手工重建技能档案

源码已经给了自动接力点,不需要重复劳动。


我会怎么给业务方解释

如果业务方问:“为什么招聘里要认真维护技能,反正入职后还能再填?”

我会说:

因为 Odoo 把招聘技能当成员工能力主数据的前置采集环节,不是一次性的面试备注。

这句话最能说明它的产品意图。


一句话记忆

Odoo 招聘技能是一条可计算、可同步、可继承的能力流水线:岗位要求算匹配,候选人与人才池同步,录用后无缝接到员工技能。

DISCUSSION

评论区

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