人力资源

Odoo 薪资为什么不是“工资规则从上到下算一遍”:Structure Type、Rules、Worked Days 与 Inputs 的进数链

很多团队做薪资时,只盯着 salary rule 的公式,仿佛把规则从上到下跑一遍就能得到正确工资。真正更关键的是:Structure Type 决定你在什么制度里算,Worked Days 决定工时口径,Inputs 决定临时变量,Rules 只是最后消费这些输入的计算层。

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

先说结论

Odoo Payroll 最容易被误解成一件事:

  • 先建几条 salary rule
  • 写点 Python 公式
  • 然后工资单从上到下跑完就结束

这只看到了最表面的一层。

真正的计算链更像这样:

  1. Structure Type 决定你在什么工资制度里算
  2. Salary Structure 决定本次工资单挂哪套规则组合
  3. Worked Days 提供工资期里的工时 / 缺勤口径
  4. Inputs 提供补贴、扣款、一次性调整等额外变量
  5. Salary Rules 最后才消费这些输入,产出工资明细

所以 rule 很重要,但 rule 从来不是全部。


为什么 Structure Type 不是“多余的一层”

很多实施第一次做薪资,会觉得 structure type 很像多包了一层壳。

其实它承担的是制度语义:

  • 这类员工按月薪算、周薪算还是小时工算
  • 这类工资单默认需要哪些 worked days 口径
  • 某些规则和输入是否在这一类人群上适用
  • 这一套结构是否对应某地区 / 某法律制度 / 某员工群体

所以它不是纯技术分组,而是工资引擎的制度入口

如果没有这层,后面所有 rule 都会被迫在公式里自己判断:

  • 你是不是小时工
  • 你是不是实习生
  • 你是不是不同国家制度

那规则会很快失控。


Salary Rule 只负责“怎么算”,不负责“数据从哪来”

规则最适合做的是:

  • 取 category / code / amount / quantity / rate
  • 根据 worked days、inputs、contract 或其他上下文算金额
  • 决定某条工资项是否出现

但它并不天然负责:

  • Attendance 和 Time Off 怎么被翻译成 payroll 可用工时
  • 哪些缺勤该进 worked days,哪些只做统计
  • 本月补贴或罚款从哪里注入

所以很多工资单算错,不是 rule 公式有 bug,而是上游输入口径已经错了


Worked Days 是“工资期时间口径”,不是普通出勤报表

Worked Days 之所以重要,是因为它把工资期里的时间结果标准化了。

它通常不是原始考勤流水本身,而是经过 payroll 视角翻译后的工时口径,比如:

  • 正常出勤
  • 带薪假
  • 无薪假
  • 病假
  • 合同外区间
  • 其他需要进入工资单的时间类型

这和前面人力资源文章里讲过的 work entry 心智是连起来的:

  • Attendance 模块不等于 payroll 本身
  • work entry / worked day 才是 payroll 可消费的标准输入

所以工资实施时,第一件事不该问“规则怎么写”,而该先问:

这张工资单里的 Worked Days 到底代表哪套时间翻译结果?


Inputs 是“临时变量入口”,不是规则失败时的补丁

Inputs 常被误用成一个垃圾桶:

  • 规则不好配,就让 HR 手输
  • 数据对不上,就临时补一个 input
  • 什么都可以塞进去

这会把薪资系统越用越脆。

更稳的理解是:

Inputs 适合承载那些:

  • 本期特有
  • 不是固定每月发生
  • 无法从 worked days 或合同主数据稳定推出
  • 但又必须进入工资计算

典型例如:

  • 一次性奖金
  • 临时补贴
  • 手工罚款
  • 某月补发 / 扣回

也就是说,input 是受控的人工入口,不是制度空洞的万能补锅位。


为什么很多规则越写越复杂

因为团队把本该放在前面几层决定的事,全都塞进了 salary rule。

例如他们会在规则里同时判断:

  • 员工属于哪个制度
  • 这个月哪些天该算薪
  • 假勤怎么折算
  • 有没有补贴
  • 哪些国家规则生效

结果就是:

  • rule 读不懂
  • 改一个小政策,十几条公式全得动
  • 调试时看不出错在规则还是错在输入

更好的做法是把职责拆开:

  • structure type 管制度入口
  • worked days 管时间口径
  • inputs 管额外变量
  • rules 只做消费与计算

这样规则才会越来越清晰,而不是越来越像迷宫。


我最建议的排错顺序

工资单结果不对时,我通常按这个顺序看:

1)先看 Structure Type / Structure 是否挂对

如果制度入口就错了,后面所有规则都可能“算得很努力,但方向错了”。

2)再看 Worked Days 是否符合工资期事实

很多金额异常其实是工时口径异常,不是公式异常。

3)再看 Inputs 有没有缺、有没有多、有没有被手工乱输

一次性数据入口最容易被忽视。

4)最后才看 Salary Rule 公式

把公式放在最后看,排错效率通常更高。


这对实施的直接含义

如果你们要做本地化薪资、复杂加班、请假扣薪、补贴和奖金混算,那别把项目设计成“配规则工程”。

更稳的方案应该是:

  • 先定义员工分组和 structure type
  • 再定义 worked days / work entry 翻译口径
  • 再定义哪些数据走 input
  • 最后才设计 rules

这样一来,后续政策变更时你可以改入口层,而不是每次都重写整套公式。


我会怎么跟业务方解释

如果业务方问:

“薪资不就是几条公式吗,为什么还要 structure type、worked days、inputs 这些层?”

我会说:

因为公式只会算,它不会自己决定制度、时间口径和临时变量。Odoo 把这些前置层拆出来,就是为了让工资单不是一堆写满 if/else 的脆弱脚本。


一句话记忆

Odoo Payroll 不是“规则表”,而是“制度入口 + 时间口径 + 临时变量 + 计算规则”组成的多层管线;只盯 salary rule,迟早会把系统配成一团。

DISCUSSION

评论区

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