人力资源

Odoo 批量分配年假为什么不是给一群员工加同一个数字:allocation mode、小时换天与审批分流讲透

很多团队把批量分配假期额度理解成“选一批人,加 5 天”。Odoo 的 hr.leave.allocation.generate.multi.wizard 源码处理得更细:它先按 employee/company/department/category 四种模式圈定员工,再按各自工时日历把小时制额度折算成天,创建后还会依据 allocation validation type 自动走不同审批分流。

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

先说结论

Odoo 的批量分配假期额度,不是“对一批员工统一加一个数字”。

它真正处理的是三层问题:

  1. 这批额度到底发给谁:员工、公司、部门还是员工标签
  2. 这个数字在不同员工身上怎么落地:尤其是小时制额度如何换算成天数
  3. 生成后谁还需要审批、谁可以直接过:取决于 leave type 的 validation 规则

所以这个向导管理的不是“群发一个余额”,而是批量生成一组仍然符合个体工时和审批边界的 allocation 记录


_get_employee_domain() 说明:批量,不等于无限制

很多人看到“generate multi”就会默认任何负责人都能给任何员工批量发额度。

源码不是这么设计的。

_get_employee_domain() 会先限制:

  • 员工必须在当前 env.companies 范围内
  • 如果当前用户不是 group_hr_holidays_user
  • 还得满足员工是自己负责、或员工用户就是自己

也就是说,Odoo 先把可选人群缩到权限内,再谈批量。

这个顺序很重要。因为假期额度不是一般配置项,它会直接影响员工后续能不能请假、还能请多久。

所以“批量方便”永远排在“权限边界”后面。


四种 allocation_mode,其实是四种圈人逻辑

向导支持:

  • employee
  • company
  • department
  • category

_get_employees_from_allocation_mode() 会据此分别取人。

这背后不是 UI 下拉选项差异,而是四种不同的业务组织方式:

1)By Employee

适合指定名单发放,比如补偿假或定向修正。

2)By Company

适合公司级统一政策,比如新财年全员刷新某类福利额度。

3)By Department

适合部门口径,例如一线轮班团队单独发某类补休额度。

4)By Employee Tag

适合临时或横向人群,比如实习生、项目组、特殊福利组。

也就是说,Odoo 不是在做“批量选择器”,而是在承认 HR 发额度经常不是按一个维度运作。


小时制为什么还要换成 number_of_days

_prepare_allocation_values() 最容易被忽略的一步是:

  • 如果 request_unit != "hour",直接用 duration
  • 如果是小时制,就除以 hours_per_day[employee.id]

hours_per_day 又来自:

  • 员工自己的 resource_calendar_id.hours_per_day
  • 没有再退回公司日历
  • 再没有才退回默认 HOURS_PER_DAY

这说明一个关键事实:

Odoo 在 allocation 模型层,仍然主要把额度存成“天”的统一口径。

所以小时制批量分配时,不能简单把 8 小时当成所有员工都是 1 天。对 6 小时工、4 小时工或者特殊日历员工,这个换算会不一样。

这正是很多自定义最爱偷懒、也最容易埋坑的地方。


为什么标题要按 leave type 和 duration 自动生成

_compute_name()_get_title() 会把 allocation 名称自动做成类似:

  • Time Off Type + 时长 + 单位

这不是小细节。

批量生成之后,一次可能出来几十条、几百条 allocation。如果标题没有把类型和额度说清楚,后面审批列表、审计列表都会很难看。

所以 Odoo 让“批量生成”从一开始就尽量产出可读记录,而不是只追求写库成功。


action_generate_allocations():真正重要的是创建后的审批分流

向导创建 allocation 时会带 context:

  • mail_notify_force_send=False
  • mail_activity_automation_skip=True

这表示官方在批量写入时,明显在控制通知和自动活动的噪音,避免生成几十条记录时立刻把系统炸成消息风暴。

创建之后,真正关键的是两段审批逻辑:

  • no_validation / hr 的 allocation 先 action_approve()
  • 如果当前用户是 HR user,再把 validation_type == 'hr' 的也批准掉

这说明系统不是把所有批量额度一刀切自动通过,而是:

先生成,再根据 leave type 的审批语义做差异化推进。

因此批量分配的“批量”只发生在创建层,不发生在审批规则层。


为什么非 HR 负责人只能用 By Employee

约束 _check_allocation_mode() 规定:

  • 如果不是 HR manager/user
  • allocation_mode 不能用 employee 以外的模式

这其实非常合理。

因为:

  • By Company 是政策级动作
  • By Department 是组织级动作
  • By Tag 往往是横向批量动作

这些都比“给某个具体员工发一笔额度”更接近制度操作。Odoo 把这类批量发放收在 HR 权限内,避免普通负责人误做全局性变更。


这套设计在实施里能避免什么问题

如果你把批量分配做成一个最简单的导入按钮,通常很快会遇到:

  • 跨公司员工被误发额度
  • 小时制员工额度折算不对
  • 部门负责人误给整个公司发额度
  • 审批流被粗暴跳过
  • 一次批量发放制造大量无意义通知

Odoo 这套向导虽然不花哨,但它把这些最容易出事的点都先收住了。


我会怎么给 HR 解释

如果 HR 说:“我不就是给一批人统一发 5 天假吗?”

我会说:

表面上是发 5 天,系统里其实是在按权限圈人、按工时换算、按 leave type 走审批。你看到的是一个数字,Odoo 处理的是一批受规则约束的额度记录。


一句话记忆

Odoo 批量分配假期额度不是群发数字,而是按目标范围取人、按员工工时折算、再按审批规则分流的一次批量建单过程。

DISCUSSION

评论区

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