先说结论
Odoo 的人才池不是“给 applicant 打一个 pool 标签”。
/home/ubuntu/odoo-temp/addons/hr_recruitment/models/hr_talent_pool.py 和 hr_applicant.py 一起看,会发现官方真正设计的是:
- 某申请可以直接属于一个或多个 talent pool
- 该申请会把自己设为
pool_applicant_id - 其他申请即使没有手工进池,只要邮箱、电话、LinkedIn 与池中申请对上,也会被识别为和人才池有关
所以人才池管理的不是“这条记录被分到哪个组”,而是:
这个候选人在不同申请记录之间,身份是否还能被追成同一个人。
第一层:talent_pool_ids 是显式归属,pool_applicant_id 是主锚点
Applicant 创建或写入时,如果已经有 talent_pool_ids 但没有 pool_applicant_id,源码会把自己设成自己的锚点。
这一步很重要,因为官方不是想让每一条申请都独立贴标签,而是想先定义:
- 哪一条申请是“进入人才池的主记录”
- 其他申请如何沿着这个主记录被识别
所以 pool_applicant 更像身份锚点,不只是普通外键。
第二层:为什么关联条件不是 applicant id,而是邮箱、电话、LinkedIn
_compute_talent_pool_count() 和相关逻辑明确会使用:
email_normalizedpartner_phone_sanitizedlinkedin_profile
这说明 Odoo 很清楚招聘场景里的现实:
- 同一个人可能给不同岗位投多次
- 也可能隔很久重新申请
- 甚至可能尚未统一到同一个 partner
如果只按 applicant 记录 id 看,系统根本认不出“这还是同一个候选人”。
第三层:为什么要把“直接进池”和“间接关联进池”分开算
源码明显区分了:
- 直接 linked:自己有
talent_pool_ids或pool_applicant_id - 间接 linked:自己没进池,但 identity 特征和池中人重合
这两类对象都和人才池有关,但语义不同:
- 直接 linked:HR 明确判定应纳入长期关注
- 间接 linked:系统提示“这个人其实已经在你的长期视野里了”
这能显著减少招聘团队重复运营同一候选人的概率。
第四层:为什么源码要做 normalized email 和 sanitized phone
因为招聘数据天然很脏:
- 邮箱有大小写、空格、格式差异
- 电话有国家码、空格、分隔符差异
- LinkedIn 也可能带不同 URL 形式
如果不先做标准化,人才池就会变成“同一个人看起来像三个人”。
这说明官方把人才池当作 候选人身份连续性系统,而不是营销标签页。
第五层:为什么人才池统计要做 count,而不是只给一个布尔值
talent_pool_count 不是简单 yes/no,而是“关联到几个池”。
这有实际意义:
- 一个候选人可能同时适合多个岗位方向
- 也可能被多个招聘团队长期关注
- count 高并不一定说明他更好,但说明复用关系更强
这对后续人才复用、岗位推荐、内部协作都比单纯的 in/out 更有价值。
第六层:人才池最常见的误区是把它做成“废弃候选人仓库”
如果你只是把未录用者都拖进 pool,却不维护 identity 关联、标签与后续触达,人才池很快会失效。
Odoo 的源码方向其实更像:
- 把有潜力的人持续挂在长期网络里
- 当他们再次出现时,系统能认出来
- 然后提醒招聘团队:这不是一条全新的陌生线索
这才叫人才池。
最容易踩的 4 个坑
1)把 talent pool 当静态标签
它更像身份网络。
2)只看 applicant id,不做 identity 标准化
同一人会被拆散。
3)忽略间接关联申请
你会重复运营同一候选人。
4)把人才池当“未录用垃圾箱”
这样它不会产生长期价值。
排错顺序
- 看 applicant 是否有
talent_pool_ids - 看是否自动生成了
pool_applicant_id - 查
email_normalized、partner_phone_sanitized、linkedin_profile - 查相关申请是否已在池中
- 再判断为什么某条申请显示有 pool count 或没有被识别出来
最后一句话
Odoo 人才池的重点不是“把申请分组”,而是“让候选人身份在多次申请之间不断线”。只把它当标签功能,你就会浪费它最有价值的部分。
DISCUSSION
评论区