先说结论
很多人做 HR 系统时,会把员工技能理解成一串当前标签:
- 英语:高级
- Python:中级
- 项目管理:初级
看起来很简单,但 Odoo 的 hr_skills 源码明显不想这么做。
它更接近这个思路:
- 技能是会演化的历史记录
- 认证是带有效期的资格记录
- 修改不应该直接覆盖旧值
- 过期风险还会触发后续提醒
所以员工技能不是“当前画像的一张截图”,而是“能力与资质随时间变化的轨迹”。
为什么源码里一上来就强调“不要直接改旧记录”
hr.individual.skill.mixin 里的注释写得非常直白。
它区分了两类对象:
普通技能
- 同一个技能通常只应有一个当前有效版本
- 不应直接覆盖旧记录
- 更推荐归档旧技能,再创建新技能,保留历史
认证技能
- 同一个技能、同一个等级可以有多条记录
- 前提是有效期不同
- 它们代表的是不同时间段的证书有效性
这意味着 Odoo 从模型层就在反对一种偷懒做法:
员工升级了,就把 skill level 直接改掉。
因为一旦直接改掉,你就失去了“他以前是什么水平、这次变化何时生效”的时间语义。
为什么技能和认证要分开看
源码里 is_certification 是关键开关。
如果它是普通技能,系统更关注“当前有效能力”; 如果它是认证,系统更关注“资格在什么时间段有效”。
这两者听起来很像,实际上业务差别很大:
- 会不会 Python,偏能力
- Odoo 认证顾问证书有效到哪天,偏资格
能力可以逐步成长,资格则往往有明确起止日、续期、失效和到期提醒。
所以 Odoo 没有把它们粗暴混成同一张“技能标签表”。
valid_from / valid_to 为什么是核心,而不是补充字段
在 hr.individual.skill.mixin 里:
valid_fromvalid_to
不是随手加的两个日期,而是整个重叠校验和“当前技能”判断的基础。
比如:
- 普通技能不能和同技能的另一条有效记录重叠
- 认证如果允许编辑有效期,则只禁止“完全相同”的重复项
- 如果
valid_to早于valid_from,直接报错
这说明 Odoo 在建模上已经假设:
技能从来不是纯静态字段,而是时间区间内成立的事实。
为什么普通技能不允许时间重叠
_check_not_overlapping_regular_skill() 里,普通技能的重叠检查很严格。
原因很简单:
如果同一个员工、同一个技能,在同一时期同时有效两条等级不同的记录,比如:
- English: Intermediate
- English: Expert
系统就无法回答“当前到底算哪一级”。
所以普通技能更像一条版本线:
- 旧等级结束
- 新等级开始
它不是多个等级并排成立。
为什么认证可以同技能多条并存
认证的逻辑不一样。
源码允许同一个技能、同一个等级,随着不同 valid_from / valid_to 出现多条记录。
这非常符合证书管理现实:
- 2024 年证书有效到 2025-05-31
- 2025 年新证书又从 2025-06-01 开始
甚至短暂交错、重新发证、补证,都可能需要单独保留历史。
所以 Odoo 不是在问“你会不会”,而是在问:
你在什么时候,持有哪一段有效资格。
“当前技能”是怎么算出来的
hr.employee.skill.get_current_skills_by_employee() 很有代表性。
它会按员工和技能分组,再筛:
valid_to为空,或valid_to >= today
这就是当前有效技能。
但对认证,源码还做了一个很细的处理:
如果当前没有有效认证,它会把 最近过期的那条 拿出来作为结果。
这个细节特别好,因为它体现了产品上的妥协:
- 从资格角度,它已经过期
- 但从管理角度,“最近过期的是哪一张”仍然有参考价值
这比简单显示空白更有用。
为什么系统还会主动创建认证到期提醒
在 hr.employee._add_certification_activity_to_employees() 里,源码会:
- 找出岗位上要求认证的技能
- 找出员工当前拥有的对应认证及
valid_to - 如果缺失,或者三个月内到期
- 给员工、经理或岗位负责人创建活动提醒
这说明 Odoo 不把认证只当作“档案陈列”。
它还把认证接进了日常管理动作:
- 缺证
- 快到期
- 需要上传续证材料
这一下子就从“员工画像功能”变成了“合规运营功能”。
这套设计对 HR 有什么现实意义
1. 能力成长不再覆盖历史
员工从中级成长到高级,系统保留轨迹,而不是只留下最后一个答案。
2. 认证续期更容易做预警
特别适合有执照、合规、审计要求的岗位。
3. 岗位要求和员工现状能做差距分析
如果岗位要求认证,而员工没有或即将过期,系统可以提前催办。
实施时最常见的误解
误解一:技能就是标签
如果只是标签,就不需要有效期和历史,也做不好到期提醒。
误解二:等级变化直接改旧记录最省事
短期省事,长期失去培训、晋升、评估的时间线。
误解三:认证和普通技能是同一种东西
源码已经明确告诉你:它们的重叠规则和当前值逻辑都不一样。
一句话记忆
Odoo 把员工技能做成带时间语义的历史记录,把认证做成带有效期的资格记录;真正重要的不是“现在显示什么等级”,而是“这项能力或资质在什么时候成立”。
DISCUSSION
评论区