人力资源

请假批准后,Odoo 为什么要“盖掉”原工时:看懂 Leave 与 Work Entry 的覆盖、冲突与重建

很多用户以为批准请假只是把状态改成已批准。实际上,Odoo 还会重算这一段时间里的 work entries:哪些保留,哪些归档,哪些变成请假工时,取消后又怎样恢复。

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

先说结论

在 Odoo 里,请假批准后发生的事情,绝不只是 hr.leave 状态从申请中变成已批准。

更深的一层是:

系统必须决定,这段时间里员工原本的工作安排要不要被请假覆盖,并且最终在 hr.work.entry 里留下可结算、可校验的结果。

所以 Leave 和 Work Entry 的关系,本质上不是“一个请假单 + 一个标签”,而是时间占用权的重新分配


为什么请假不能只存在于 hr.leave

如果请假只是单独一张单据,而不影响 work entries,会发生什么?

同一天可能同时出现:

  • 正常出勤工时
  • 请假工时
  • 甚至薪资已验证的工时

那系统就没法回答一个很基础的问题:

这个人这一天到底是在上班,还是在请假?

因此 Odoo 在 hr_work_entry_holidays 里专门把请假接进了 work entry 体系。


批准请假时,系统会先创建“请假型 work entry”

源码里的 _cancel_work_entry_conflict() 名字很低调,实际做的事却很关键。

大致流程是:

  1. 找出请假期间与合同重叠的版本
  2. 为这些区间生成对应的 work entry 值
  3. 创建新的请假型 hr.work.entry
  4. 再去对比同期间已存在的其他 work entries

也就是说,批准请假后,系统不是只说“这段时间有假”,而是会真正落一组可参与后续校验和结算的 work entries


为什么有的旧工时会被归档,有的只会失去 leave 关联

源码里的处理非常细:

完全被请假覆盖的旧工时

会被标记为 active = False,也就是归档。

这代表:

  • 这些旧工时已经不再应该参与当前结果
  • 请假把它们完整替代了

与请假有交叉但不完全包含的工时

系统不会粗暴全删,而是把部分冲突对象挑出来处理。

对这些 overlapping entries,源码会把 leave_id 清掉(前提是不是 validated)。

这说明 Odoo 在做的不是“删除一切旧数据”,而是尽可能保留可解释的结构,只把应当让位的部分让位。


为什么 work entry 会进入 conflict

hr.work.entry 本身有独立的校验逻辑。

源码里至少会检查这些异常:

  • 没有 work entry type
  • 同一员工同一天总时长 <= 0 或 > 24 小时
  • 请假类工时完全落在排班之外
  • 已经 validated 的日期又被重新动到

这很能说明问题:

work entry 不是“展示层结果”,而是要被系统当真去校验的业务对象。

所以请假只要碰到:

  • 排班边界
  • 合同边界
  • 已验证工资期间
  • 与旧工时的重叠

就可能触发 conflict,而不是默默通过。


为什么“排班外请假”会报冲突

源码里的 _mark_leaves_outside_schedule() 专门检查:

  • 请假型 work entries 是否落在理论排班之外
  • 如果完全在排班外,就打成 conflict

这背后的业务逻辑很直白:

如果那天本来就不应该上班,你请掉的是谁的班?

当然,现实里有弹性工时、特殊制度,所以源码也对 flexible calendar 做了区别处理。也就是说,Odoo 并不是机械地说“排班外永远不准请”,而是在判断这段请假是否真的占用了应工作时间


请假被拒绝或取消后,为什么还要“重建” work entries

很多系统做到批准就结束了,但 Odoo 更进一步:

  • action_refuse()
  • _move_validate_leave_to_confirm()
  • _action_user_cancel()

这些路径都会调用 _regen_work_entries()

核心逻辑是:

  1. 找到与该请假关联的 work entries
  2. 先归档这些 leave entries
  3. 再按当天版本重新生成正常 attendance work entries

这说明 Odoo 的目标不是简单撤销请假单,而是把那段时间恢复成一个重新自洽的工时世界


这对实施意味着什么

1. 不要把请假理解成纯审批表单

它其实会改写底层工时结果。

2. 不要忽视合同与版本区间

请假能不能正确映射成 work entries,取决于那段时间员工是否有有效合同版本。

3. 工资期已验证后,改请假会更敏感

因为系统会防止你悄悄修改已经进入薪资结算的工时。


最适合记住的一句话

Odoo 里的请假不是“贴在工时上面”的标签,而是会真正占用并重写那段 work entries;批准时覆盖,取消时重建。

DISCUSSION

评论区

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