【薪资】计薪设置、薪资档案
计薪设置与薪资档案模块,由 yudao-module-hrm 后端模块的 salary.config、salary.employeeinfo 包实现,前端实现在 @/views/hrm/salary/config、@/views/hrm/salary/employee-info 目录。
薪资是 HRM 中表最多、链路最长的模块,共 13 张表,按「计薪设置 → 薪资档案 → 月度工资 → 工资条」四段组织。本文解决的是前两段,也就是「按什么规则算、每个人算多少」:
- 计薪设置:计薪周期、计税规则、薪资组、工资项和调薪模板,配置一次后长期沿用。
- 薪资档案与调薪:员工当前薪资 + 定薪调薪记录,支持立即或未来生效。
配置就绪后的月度核算与工资条发放,详见 《【薪资】月度工资、工资条》。
本文涉及表如下图所示:
# 1. 计薪设置
计薪周期,由 HrmSalaryConfigController 提供接口(/hrm/salary/config);计税规则、薪资组、工资项和调薪模板,分别由 HrmSalaryTaxRuleController、HrmSalaryGroupController、HrmSalaryOptionController、HrmSalaryChangeTemplateController 提供接口。
首次初始化计薪周期时,系统会同时创建第一张「未核算」的月度工资表,因此计薪设置是薪资模块的启动开关。
# 1.1 表结构
省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段,下同;需要说明唯一约束时保留
tenant_id,JSON 字段由 TypeHandler 完成对象转换
CREATE TABLE `hrm_salary_config` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`cycle_start_day` int DEFAULT NULL COMMENT '计薪周期开始日',
`cycle_end_day` int DEFAULT NULL COMMENT '计薪周期结束日',
`start_year` int DEFAULT NULL COMMENT '起始年份',
`start_month` int DEFAULT NULL COMMENT '起始月份',
`social_security_month_type` tinyint DEFAULT NULL COMMENT '社保对应月份',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_config_tenant_id` (`tenant_id`)
) ENGINE=InnoDB COMMENT='HRM 薪资配置';
① tenant_id 唯一,因此每个租户只能初始化一套计薪周期。
② cycle_start_day 为 1 时,cycle_end_day 保存为 31;否则结束日为「开始日减 1」,即自然月跨月计薪。初始化后开始日、结束日和起始年月只读,只允许调整社保对应月份。
③ 枚举 social_security_month_type 社保对应月份(HrmSalarySocialSecurityMonthTypeEnum):0 上月、1 当月、2 次月。核算时按该配置读取对应月份的社保记录。
计薪设置还包含以下 5 张配置表:
// TODO @AI:这个每个子表,要拆分独立的小节么?这样貌似更好的截图?理解起来也更舒服?
| 表 | 说明 | 关键约束 |
|---|---|---|
hrm_salary_tax_rule | 计税规则 | 被薪资组引用时不可删除 |
hrm_salary_group | 薪资组 | 员工未命中薪资组时不能参与核算 |
hrm_salary_option_template | 标准工资项目录 | 平台统一维护,code 全局唯一 |
hrm_salary_option | 租户工资项 | tenant_id + code 唯一 |
hrm_salary_change_template | 调薪模板 | 默认模板不可删除 |
hrm_salary_tax_rule 表结构
CREATE TABLE `hrm_salary_tax_rule` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) NOT NULL COMMENT '计税规则名称',
`type` tinyint DEFAULT NULL COMMENT '计税类型',
`tax_enabled` bit DEFAULT NULL COMMENT '是否计税',
`threshold` decimal(12,2) DEFAULT NULL COMMENT '起征阈值',
`decimal_scale` int DEFAULT NULL COMMENT '保留小数位数',
`cycle_type` tinyint DEFAULT NULL COMMENT '计税周期类型',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 计税规则';
① 枚举 type 计税类型(HrmSalaryTaxTypeEnum,字典 hrm_salary_tax_type):1 工资薪金所得税、2 劳务报酬所得税、3 不计税。税率档位由 HrmSalaryTaxRateEnum 内置(工资薪金 7 级、劳务报酬 3 级),不需要在页面维护。
② tax_enabled = 0 时不计算个税;启用后由 threshold 起征阈值、decimal_scale 保留小数位数和 cycle_type 计税周期共同决定计税口径。
③ 枚举 cycle_type 计税周期(HrmSalaryTaxCycleTypeEnum):1 上年 12 月至本年 11 月、2 本年 1 月至 12 月。
④ 薪资组通过 tax_rule_id 选用规则。
hrm_salary_group 表结构
CREATE TABLE `hrm_salary_group` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) NOT NULL COMMENT '薪资组名称',
`salary_standard` decimal(12,2) DEFAULT NULL COMMENT '月计薪标准天数',
`change_rule` varchar(255) DEFAULT NULL COMMENT '转正、调薪月计算规则',
`dept_ids` varchar(20000) DEFAULT NULL COMMENT '适用部门编号 JSON',
`employee_ids` varchar(20000) DEFAULT NULL COMMENT '适用员工编号 JSON',
`tax_rule_id` bigint DEFAULT NULL COMMENT '计税规则编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 薪资组';
① dept_ids 关联 system_dept 表,employee_ids 关联 hrm_employee 表,tax_rule_id 关联 hrm_salary_tax_rule 表。
② 员工先按 employee_ids 精确匹配,再按所在部门及父部门匹配。未命中任何薪资组的员工不能参与月度核算,核算前的准备检查会把这些员工列出来。
③ salary_standard 月计薪标准天数用于按天折算,当前由后端固定写入 21.75;change_rule 同样由后端写入固定说明,不作为用户可配置的分支规则。转正月、调薪月会按周期内每天生效的薪资档案自动混合计算。
hrm_salary_option_template 表结构
CREATE TABLE `hrm_salary_option_template` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`code` int NOT NULL COMMENT '标准工资项编码',
`parent_code` int NOT NULL DEFAULT 0 COMMENT '父工资项编码',
`name` varchar(64) NOT NULL COMMENT '工资项名称',
`type` tinyint NOT NULL DEFAULT 1 COMMENT '工资项类型',
`system_flag` bit NOT NULL DEFAULT 0 COMMENT '是否系统默认项',
`tax_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否计税',
`visible` bit NOT NULL DEFAULT 1 COMMENT '是否显示',
`calculate_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否参与计算',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_option_template_code` (`code`)
) ENGINE=InnoDB COMMENT='HRM 标准工资项目录';
标准目录不带 tenant_id,由平台统一维护。code 全局唯一,parent_code 指向同表 code,用于组织工资项树;标准编码见 HrmSalaryOptionCodeEnum,其中应发工资、应税工资、个人所得税、实发工资和各项累计值属于系统计算项(COMPUTED_CODES),不允许手工填写。
租户通过「同步标准项」把目录复制或补齐到自己的 hrm_salary_option 中。
hrm_salary_option 表结构
CREATE TABLE `hrm_salary_option` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`code` int NOT NULL COMMENT '工资项编码',
`parent_code` int NOT NULL DEFAULT 0 COMMENT '父工资项编码',
`name` varchar(64) NOT NULL COMMENT '工资项名称',
`template_id` bigint DEFAULT NULL COMMENT '标准工资项目录编号',
`type` tinyint NOT NULL DEFAULT 1 COMMENT '工资项类型',
`system_flag` bit NOT NULL DEFAULT 0 COMMENT '是否系统默认项',
`tax_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否计税',
`visible` bit NOT NULL DEFAULT 1 COMMENT '是否显示',
`calculate_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否参与计算',
`enabled` bit NOT NULL DEFAULT 1 COMMENT '是否启用',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_option_tenant_code` (`tenant_id`, `code`)
) ENGINE=InnoDB COMMENT='HRM 租户工资项';
① template_id 关联 hrm_salary_option_template 表的 id 字段;tenant_id + code 唯一,parent_code 指向同租户的父项编码。
② 枚举 type 工资项类型(HrmSalaryOptionTypeEnum,字典 hrm_salary_option_type):0 减项、1 加项、2 计算项。
③ 三个开关的职责不同:enabled 控制企业是否使用该项,visible 控制工资表和工资条是否展示,calculate_enabled 控制是否参与汇总计算。
hrm_salary_change_template 表结构
CREATE TABLE `hrm_salary_change_template` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) NOT NULL COMMENT '调薪模板名称',
`default_status` bit NOT NULL DEFAULT 0 COMMENT '是否默认模板',
`options` varchar(4000) DEFAULT NULL COMMENT '可调整工资项 JSON',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 调薪模板';
options 保存工资项的 code 与名称快照,用于限定定薪、调薪表单可编辑的项目。同一租户只有一条默认模板:默认模板可以修改,也可以把其它模板设为默认,但当前默认模板不能删除。
# 1.2 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 计薪设置] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/config 目录。
# 初始化计薪周期
首次进入 config/index.vue 时填写计薪周期开始日、工资起始年月和社保对应月份。保存后,系统同时创建首张月度工资表。

# 修改计薪周期
初始化后,开始日、结束日和起始年月只读,只允许修改社保对应月份。
# 计税规则
tax-rule/index.vue 展示规则列表及被薪资组使用的数量,新增、修改由 SalaryTaxRuleForm.vue 完成。已被薪资组引用的规则不能删除。

# 薪资组
group/index.vue 展示薪资组列表,新增、修改打开 SalaryGroupForm.vue,配置薪资组名称、计税规则和适用部门 / 员工;表单只读展示固定的 21.75 天 / 月计薪标准,以及转正、调薪生效日前后工资混合计算的说明。保存适用范围时,后端会处理不同薪资组之间重复的部门和员工。

# 工资项
option/index.vue 按「企业工资项」和「系统工资项」两个页签展示工资项树。
- 企业工资项:可【同步标准项】把平台标准目录补齐到本租户,也可通过
SalaryOptionForm.vue新增自定义项。标准项的「删除」等同于停用,只有自定义项才会逻辑删除。 - 系统工资项:只能控制预置项是否展示,不能新增或删除。

# 调薪模板
change-template/index.vue 展示模板列表,新增、修改打开 SalaryChangeTemplateForm.vue 选择可调整工资项。非默认模板才可删除。

# 2. 薪资档案与调薪
员工当前薪资,由 HrmSalaryEmployeeInfoController 提供接口(/hrm/salary/employee-info);定薪、调薪和未来变更记录,由 HrmSalaryChangeRecordController 提供查询、取消和删除接口(/hrm/salary/change-record)。
两张表的 employee_id 都关联 hrm_employee 表,不直接关联后台账号。
# 2.1 主表表结构
CREATE TABLE `hrm_salary_employee_info` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`employee_id` bigint NOT NULL COMMENT '员工编号',
`change_type` tinyint DEFAULT NULL COMMENT '变更类型',
`change_reason` tinyint DEFAULT NULL COMMENT '变更原因',
`effect_time` datetime DEFAULT NULL COMMENT '生效时间',
`regular_salary` decimal(12,2) DEFAULT NULL COMMENT '正式工资',
`probation_salary` decimal(12,2) DEFAULT NULL COMMENT '试用期工资',
`salary_options` varchar(20000) DEFAULT NULL COMMENT '正式工资项快照 JSON',
`probation_salary_options` varchar(20000) DEFAULT NULL COMMENT '试用期工资项快照 JSON',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_employee_info_employee_id` (`employee_id`)
) ENGINE=InnoDB COMMENT='HRM 员工薪资档案';
① employee_id 唯一,每名员工只有一份当前有效薪资档案;历史和未来薪资保存在 hrm_salary_change_record 中。
② 枚举 change_type 变更类型(HrmSalaryEmployeeInfoChangeTypeEnum,字典 hrm_salary_change_type):0 未定薪、1 已定薪、2 已调薪。列表据此把操作按钮显示为【定薪】或【调薪】。
③ 枚举 change_reason 变更原因(HrmSalaryChangeReasonEnum,字典 hrm_salary_change_reason):0 入职定薪、1 入职核定、2 转正、3 晋升、4 调动、5 年中调薪、6 年度调薪、7 特别调薪、8 其他。
④ salary_options、probation_salary_options 是工资项 JSON 快照。后续修改工资项配置不会回写已生效的薪资记录。
该表包含一张记录表:
hrm_salary_change_record(定薪调薪记录):保存每一次定薪、调薪的前后金额与工资项快照,同一员工同时只允许一条待生效记录。
# 2.2 记录表结构
CREATE TABLE `hrm_salary_change_record` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`employee_id` bigint NOT NULL COMMENT '员工编号',
`type` tinyint DEFAULT NULL COMMENT '记录类型',
`reason` tinyint DEFAULT NULL COMMENT '调整原因',
`status` tinyint DEFAULT NULL COMMENT '状态',
`effect_time` datetime DEFAULT NULL COMMENT '生效时间',
`before_total` decimal(12,2) DEFAULT NULL COMMENT '调整前正式薪资',
`after_total` decimal(12,2) DEFAULT NULL COMMENT '调整后正式薪资',
`probation_before_total` decimal(12,2) DEFAULT NULL COMMENT '调整前试用期薪资',
`probation_after_total` decimal(12,2) DEFAULT NULL COMMENT '调整后试用期薪资',
`salary_options` varchar(4000) DEFAULT NULL COMMENT '正式工资项后态快照 JSON',
`probation_salary_options` varchar(4000) DEFAULT NULL COMMENT '试用期工资项后态快照 JSON',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 定薪调薪记录';
① 枚举 type 记录类型(HrmSalaryChangeRecordTypeEnum):1 定薪、2 调薪。
② 枚举 status 记录状态(HrmSalaryChangeRecordStatusEnum,字典 hrm_salary_change_record_status:0 = 待生效,1 = 已生效,2 = 已取消)。详见 §2.3 状态流转。
③ before_total / after_total 便于列表展示变动幅度,两个工资项字段保存变更后的明细。
# 2.3 状态流转
定薪、调薪记录的生命周期由 HrmSalaryEmployeeInfoServiceImpl 与 HrmSalaryChangeRecordServiceImpl 控制。状态枚举 HrmSalaryChangeRecordStatusEnum:
| 状态值 | 枚举 | 说明 | 可执行操作 |
|---|---|---|---|
| 0 | PENDING | 待生效 | 取消、删除 |
| 1 | EFFECTIVE | 已生效 | — |
| 2 | CANCELLED | 已取消 | 删除 |
状态流转说明
立即生效:创建 ──→ 已生效(1)(同步更新 hrm_salary_employee_info)
未来生效:创建 ──→ 待生效(0) ──HrmSalaryChangeJob──→ 已生效(1)
│
└──取消──→ 已取消(2)
- 定薪 / 调薪(
updateSalaryEmployeeInfo):生效时间为今天或过去时,立即更新当前薪资档案;未来日期只创建待生效记录。最早允许的生效日期由后端按当前月度工资表计算。 - 到期生效(HrmSalaryChangeJob):把到期的待生效记录写入
hrm_salary_employee_info,并置为已生效。 - 取消(
cancelSalaryChangeRecord):仅待生效可取消。 - 删除(
deleteSalaryChangeRecord):仅待生效或已取消可删除,已生效记录不可删除,避免破坏调薪历史。
同一员工同时只允许存在一条待生效记录。
# 2.4 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 薪资档案] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/employee-info 目录。
# 列表
支持按姓名、工号、部门、岗位和在职状态筛选,顶部按定薪状态展示页签及数量。未建立档案的员工显示【定薪】,已有档案的员工显示【调薪】。

# 定薪与调薪
通过弹窗 SalaryEmployeeInfoForm.vue 完成。表单按调薪模板限定可填写的工资项,分别维护正式、试用期工资项,并填写生效时间、原因和备注。

# 批量调薪
选择多名员工后打开 SalaryEmployeeInfoBatchForm.vue,统一设置调薪项、调整方式(按比例 / 按金额,HrmSalaryBatchAdjustTypeEnum)、生效时间和原因。批量处理中,立即生效的记录同步更新当前档案,未来记录保持待生效,接口返回每名员工的成功或失败原因。

# Excel 导入
SalaryEmployeeInfoImportForm.vue 支持「固定工资导入」和「调薪导入」两种模板,上传后展示成功数和逐行失败原因。导入时会排除系统计算类的父级工资项目录(EMPLOYEE_INFO_IMPORT_EXCLUDED_PARENT_CODES)。

# 薪资详情与变更记录
点击员工姓名进入 employee-info/detail/index.vue。SalaryEmployeeInfoDetails.vue 展示当前正式、试用期工资和工资项;SalaryChangeRecordList.vue 展示全部定薪、调薪记录,并提供取消、删除操作。

# 3. 与其它模块的衔接
- 员工:定薪、调薪都以
hrm_employee.id为业务关联,员工入职后即可定薪,不要求绑定后台账号。 - 月度工资:核算时读取计薪周期内生效的薪资档案,因此调薪的生效日期决定了它从哪个月开始计入工资,详见 《【薪资】月度工资、工资条》。