人力资源

Odoo 候选人转投多个岗位为什么不是改一改 job_id:复制申请、初始阶段重算与 talent pool 解绑讲透

很多团队看到“把候选人加到别的岗位”时,第一反应是直接改 job_id。Odoo 的 job_add_applicants 向导并不这么做:它会复制 applicant 数据,为每个目标岗位新建一条申请,按岗位可用阶段重新选最早的非 fold stage,并显式清空 talent pool 关联,避免把人才池语义和真实岗位申请混成一条记录。

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

先说结论

Odoo 里把候选人加到别的岗位,不是把原申请上的 job_id 改一下。

源码真正表达的意思是:

  1. 一个岗位申请就是一条独立 applicant 事实
  2. 新岗位应该重新匹配自己的初始 stage
  3. 人才池语义不能自动继承到正式岗位申请里

所以 job_add_applicants 做的是复制申请并重新路由,而不是修改原申请归属。


为什么不能直接改 job_id

如果只从字段层面看,很多人会觉得:

  • 候选人还是同一个人
  • 只是从岗位 A 转去岗位 B
  • 那直接把 job_id 改成 B 不就好了?

但这会立刻带来几个问题:

  • 原岗位的申请历史被覆盖
  • 原阶段、原评估、原沟通上下文和新岗位混在一起
  • 招聘漏斗统计会失真
  • 同一人多岗位并行申请没法表达

Odoo 选择 copy_data() + create(),本质上是在承认:

候选人是同一个人,不代表申请是同一条业务记录。

这和 CRM 里“同一个联系人可以对应多条商机”是一个思路。


_add_applicants_to_job() 的核心:先复制,再按岗位展开

向导先做:

  • applicant_ids.copy_data()

得到的是申请记录的值快照,而不是直接修改原记录。

然后它对每个 applicant、每个目标 job 组合,生成新的 new_applicants_vals

也就是说,如果:

  • 2 个候选人
  • 3 个目标岗位

结果不是 2 条更新,而是最多 6 条新申请。

这非常关键,因为它说明这不是“批量改字段”,而是一个申请复制工厂

这也正符合招聘业务现实:一个候选人可以同时适合多个岗位,每个岗位都应该有自己独立的推进轨迹。


为什么 stage 要重新算,而且取“最早可用非 fold 阶段”

源码会先按岗位读取招聘阶段:

  • 允许 job_ids 包含该岗位
  • 也允许取全局 stage
  • 再过滤出可用集合
  • 最后按 sequence 取最小值

hr.recruitment.stage 本身还区分:

  • 是否 job specific
  • 是否 fold

这背后的逻辑很成熟:

新申请不应该继承旧申请在别的岗位上的阶段位置。

否则你会出现荒谬情况:

  • 候选人在岗位 A 已经进到面试后期
  • 转投岗位 B 时,系统也把他直接放到后期阶段

这显然不合理。岗位 B 需要自己的招聘语义和起点。所以 Odoo 会为新岗位重新找一个最早的、未折叠阶段,当作重新进入流程的入口。


为什么要清空 talent_pool_ids

新申请 vals 里有一行特别重要:

  • talent_pool_ids: False

这意味着从候选人复制到某个 job 的正式申请时,系统会显式把人才池关联清掉。

这不是遗漏,而是设计立场。

因为人才池是:

  • 可复用的人才身份/储备语义

而岗位申请是:

  • 针对具体 vacancy 的流程语义

如果不清掉,你很容易把“这个人属于人才池”误当成“这条岗位申请也天然属于同一池上下文”。

Odoo 在这里是故意拆边界:

人才池可以是来源或背景,但岗位申请本身必须重新成立。


为什么不是直接复用原申请的阶段和标签

copy_data() 的好处是带来大量已有字段,但 Odoo 仍然会明确覆盖:

  • job_id
  • talent_pool_ids
  • stage_id

这正说明官方知道哪些字段是“可继承的上下文”,哪些是“必须重新定义的岗位语义”。

可继承的通常是:

  • 候选人身份信息
  • 联系方式
  • 其他静态资料

必须重置的则是:

  • 岗位归属
  • 流程阶段
  • 人才池关系

这比“全继承”或者“全清空”都更聪明。


成功后的返回动作,也在强调“新申请是新对象”

action_add_applicants_to_job() 完成后:

  • 如果只生成一条,就直接打开那条新 applicant form
  • 如果生成多条,则给出创建成功通知

这个返回动作很简单,但它传递的产品语言很明确:

系统希望你接下来去看的是新申请对象,不是回到旧申请上继续脑补。

换句话说,复制不是幕后实现细节,而是业务上有意义的新实体创建。


这套设计为什么比“移动候选人”更稳

很多团队内部会说“把这个人转到另一个岗位”。这个说法容易让系统做错。

因为业务上看似是“转”,数据上往往更接近:

  • 保留原申请
  • 为新岗位再建一条申请
  • 两条申请并行存在,后续各走各的评估路径

Odoo 的实现正是站在这个更稳的建模上。

它保护了:

  • 招聘漏斗真实度
  • 岗位阶段独立性
  • 人才池与岗位申请的边界
  • 一个候选人多岗位并行的可能性

一句话记忆

Odoo 候选人转投岗位不是改 job_id,而是复制出新的 applicant,按新岗位重算起始阶段,并把 talent pool 语义和正式申请语义拆开。

DISCUSSION

评论区

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