先说结论
Odoo 的批量分配假期额度,不是“对一批员工统一加一个数字”。
它真正处理的是三层问题:
- 这批额度到底发给谁:员工、公司、部门还是员工标签
- 这个数字在不同员工身上怎么落地:尤其是小时制额度如何换算成天数
- 生成后谁还需要审批、谁可以直接过:取决于 leave type 的 validation 规则
所以这个向导管理的不是“群发一个余额”,而是批量生成一组仍然符合个体工时和审批边界的 allocation 记录。
_get_employee_domain() 说明:批量,不等于无限制
很多人看到“generate multi”就会默认任何负责人都能给任何员工批量发额度。
源码不是这么设计的。
_get_employee_domain() 会先限制:
- 员工必须在当前
env.companies范围内 - 如果当前用户不是
group_hr_holidays_user - 还得满足员工是自己负责、或员工用户就是自己
也就是说,Odoo 先把可选人群缩到权限内,再谈批量。
这个顺序很重要。因为假期额度不是一般配置项,它会直接影响员工后续能不能请假、还能请多久。
所以“批量方便”永远排在“权限边界”后面。
四种 allocation_mode,其实是四种圈人逻辑
向导支持:
employeecompanydepartmentcategory
而 _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=Falsemail_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
评论区