先说结论
Odoo Time Off 类型上的 Ignore Public Holidays,不是一个界面偏好,而是余额语义开关。
/home/ubuntu/odoo-temp/addons/hr_holidays/models/hr_leave_type.py 和 hr_leave.py 说明,这个设置会直接影响:
- 请假时长如何计算
- 公共假期是否从真实请假区间里剔除
- 已有和审批中的假单是否还能安全沿用旧口径
所以它真正表达的是:
公共假期到底算“员工额外请掉的一天”,还是“本来就不用工作的日子”。
第一层:这个开关改变的不是文案,而是 duration 计算路径
hr.leave.type 上的 include_public_holidays_in_duration 会进入 _get_durations() 的计算分支。
当它关闭时,系统会在计算工时/工日时把公共假期当作 leave calendar 的一部分排除出去;当它开启时,又会按另一套口径统计。
这意味着同一个请假区间:
- 在一种设置下可能扣 3 天
- 在另一种设置下可能只扣 2 天
它不是展示差异,而是余额差异。
第二层:为什么源码会专门阻止你在已有重叠假单时切换设置
hr_leave_type.py 里有 _check_overlapping_public_holidays() 约束。
逻辑非常直接:
- 找当前年份的公共假期
- 找该类型下已存在、且时间重叠的请假单
- 如果有,就不允许随便改这个开关
原因很简单:
- 你一改口径
- 历史假单的已扣时长就会变
- 员工余额、审批判断、报表解释都会跟着变
这不是“小改一下配置”,而是重写历史业务含义。
第三层:为什么有些假单会落入“public holiday leaves”特殊分支
hr_leave.py 里 _get_leaves_on_public_holiday() 会挑出 number_of_days 为 0 且带员工的记录。
这说明官方允许一种现实场景:
- 员工提交了覆盖公共假期的请假
- 结果这部分时间按规则不应扣余额
- 于是最终可能形成“有请假记录,但实际扣时长为 0”
这不是脏数据,而是口径明确后的自然结果。
第四层:为什么这个开关会和日历、工作制一起放大差异
请假时长计算本来就要看:
- 员工资源日历
- 按天/半天/小时申请
- 公共假期资源 leaves
- 工作时间列表或工作日数据
所以一旦再叠加 Ignore Public Holidays,差异会被进一步放大:
- 标准工作周和轮班制结果不同
- 小时级请假和按天请假结果不同
- 公司公共假期与员工个人日历交叉时更复杂
这也是为什么它绝不只是一个“勾选习惯”。
第五层:为什么很多团队在上线后才发现自己选错了
因为前期通常只拿一两个简单例子测试:
- 周一到周三请假
- 没有跨节假日
- 也没有小时级申请
这种场景下,两种口径差异不明显。
真正上线后,只要碰到:
- 国定假日夹在请假中间
- 跨年结转
- 不同日历员工混用同一类型
问题就会集中暴露。
第六层:更稳妥的决策原则
我的建议是:
- 先把公司政策说清楚:公共假期是否应消耗假额
- 再用复杂案例回测:跨节日、半天、小时、轮班、多日历
- 确认后尽量不要在生产中途改
- 真要改,也要按年度切换或新建类型迁移,而不是直接覆盖旧类型
这比事后在已有假单上强改开关安全得多。
最容易踩的 4 个坑
1)把这个开关当显示偏好
它影响的是余额解释。
2)生产上线后才开始想口径
到那时已经有历史单据了。
3)只测简单案例
真正复杂的是跨节假日和轮班场景。
4)发现扣数不对就直接切开关
很可能把历史也一起改坏。
排错顺序
- 查 leave type 是否勾选
Ignore Public Holidays - 查该请假区间是否覆盖公司公共假期
- 查员工资源日历与申请单位(天/半天/小时)
- 查该类型是否已有重叠历史单据
- 最后再决定是改配置、改类型,还是新建迁移方案
最后一句话
Odoo 里“忽略公共假期”不是小开关,而是请假余额的解释原则。只要你在已有业务上随便切它,错的就不会只是一张假单,而是整套余额历史。
DISCUSSION
评论区