tuqin
5 天以前 fa4a310bb94f41bdc7af068bd380fdfeafb881c7
feat(hrm): 薪酬核算新增「岗位工资」「工龄工资」

- 员工信息(hrm_employee)新增 post_salary / seniority_salary,与基本工资同源维护
- 薪酬核算(hrm_salary_calculation)新增同名字段,核算时从员工信息带入
- 应发工资合计与实发工资计算纳入岗位工资、工龄工资
- 修改核算单时对两个新字段做 null 归零,保持与实发工资口径一致
- 薪酬档案(hrm_employee_salary)同步加列,便于后续扩展
- SQL:sql/mysql/hrm_salary_add_post_seniority.sql(幂等)
已添加1个文件
已修改7个文件
137 ■■■■■ 文件已修改
sql/mysql/hrm_salary_add_post_seniority.sql 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/HrmSalaryCalculationRespVO.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/HrmEmployeeSalaryDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/HrmSalaryCalculationDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/hrm_salary_add_post_seniority.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
-- =============================================
-- è–ªé…¬æ ¸ç®—:新增「岗位工资」「工龄工资」
--
-- ä¸šåŠ¡è¯´æ˜Žï¼š
--   1) å²—位工资、工龄工资与「基本工资」同源,在【员工管理】的员工信息中维护
--   2) æ‰§è¡Œè–ªé…¬æ ¸ç®—时带入核算单,并计入应发工资与实发工资
--   3) è–ªé…¬æ¡£æ¡ˆ(hrm_employee_salary)同步加列,便于后续扩展;当前核算以员工信息为准
--
-- è„šæœ¬å¯é‡å¤æ‰§è¡Œï¼ˆå¹‚ç­‰ï¼‰
-- =============================================
SET NAMES utf8mb4;
SET @sch := DATABASE();
-- ---------- 1. å‘˜å·¥ä¿¡æ¯ï¼šå²—位工资 / å·¥é¾„工资 ----------
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_employee' AND COLUMN_NAME = 'post_salary');
SET @sql := IF(@exists = 0,
    'ALTER TABLE `hrm_employee` ADD COLUMN `post_salary` decimal(10,2) DEFAULT ''0.00'' COMMENT ''岗位工资'' AFTER `base_salary`',
    'SELECT ''hrm_employee.post_salary å·²å­˜åœ¨'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_employee' AND COLUMN_NAME = 'seniority_salary');
SET @sql := IF(@exists = 0,
    'ALTER TABLE `hrm_employee` ADD COLUMN `seniority_salary` decimal(10,2) DEFAULT ''0.00'' COMMENT ''工龄工资'' AFTER `post_salary`',
    'SELECT ''hrm_employee.seniority_salary å·²å­˜åœ¨'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ---------- 2. è–ªé…¬æ ¸ç®—单:岗位工资 / å·¥é¾„工资 ----------
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_salary_calculation' AND COLUMN_NAME = 'post_salary');
SET @sql := IF(@exists = 0,
    'ALTER TABLE `hrm_salary_calculation` ADD COLUMN `post_salary` decimal(10,2) DEFAULT ''0.00'' COMMENT ''岗位工资'' AFTER `performance_salary`',
    'SELECT ''hrm_salary_calculation.post_salary å·²å­˜åœ¨'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_salary_calculation' AND COLUMN_NAME = 'seniority_salary');
SET @sql := IF(@exists = 0,
    'ALTER TABLE `hrm_salary_calculation` ADD COLUMN `seniority_salary` decimal(10,2) DEFAULT ''0.00'' COMMENT ''工龄工资'' AFTER `post_salary`',
    'SELECT ''hrm_salary_calculation.seniority_salary å·²å­˜åœ¨'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ---------- 3. è–ªé…¬æ¡£æ¡ˆï¼ˆå¯é€‰ï¼Œå½“前核算不取此表的基本/岗位/工龄工资) ----------
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_employee_salary' AND COLUMN_NAME = 'post_salary');
SET @sql := IF(@exists = 0,
    'ALTER TABLE `hrm_employee_salary` ADD COLUMN `post_salary` decimal(10,2) DEFAULT ''0.00'' COMMENT ''岗位工资'' AFTER `base_salary`',
    'SELECT ''hrm_employee_salary.post_salary å·²å­˜åœ¨'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_employee_salary' AND COLUMN_NAME = 'seniority_salary');
SET @sql := IF(@exists = 0,
    'ALTER TABLE `hrm_employee_salary` ADD COLUMN `seniority_salary` decimal(10,2) DEFAULT ''0.00'' COMMENT ''工龄工资'' AFTER `post_salary`',
    'SELECT ''hrm_employee_salary.seniority_salary å·²å­˜åœ¨'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ---------- 4. æ ¸å¯¹ ----------
SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @sch
  AND TABLE_NAME IN ('hrm_employee', 'hrm_salary_calculation', 'hrm_employee_salary')
  AND COLUMN_NAME IN ('post_salary', 'seniority_salary')
ORDER BY TABLE_NAME, COLUMN_NAME;
SELECT '岗位工资 / å·¥é¾„工资字段初始化完成' AS result;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java
@@ -122,6 +122,16 @@
    @ExcelProperty("基本工资")
    private BigDecimal baseSalary;
    /**
     * å²—位工资
     */
    private BigDecimal postSalary;
    /**
     * å·¥é¾„工资
     */
    private BigDecimal senioritySalary;
    @Schema(description = "角色ID列表")
    private List<Long> roleIds;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java
@@ -93,6 +93,16 @@
    @Schema(description = "基本工资", example = "10000.00")
    private BigDecimal baseSalary;
    /**
     * å²—位工资
     */
    private BigDecimal postSalary;
    /**
     * å·¥é¾„工资
     */
    private BigDecimal senioritySalary;
    @Schema(description = "角色ID列表", example = "[1, 2]")
    private List<Long> roleIds;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/HrmSalaryCalculationRespVO.java
@@ -45,6 +45,14 @@
    @ExcelProperty("基本工资")
    private BigDecimal baseSalary;
    @Schema(description = "岗位工资")
    @ExcelProperty("岗位工资")
    private BigDecimal postSalary;
    @Schema(description = "工龄工资")
    @ExcelProperty("工龄工资")
    private BigDecimal senioritySalary;
    @Schema(description = "绩效工资")
    @ExcelProperty("绩效工资")
    private BigDecimal performanceSalary;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java
@@ -167,6 +167,16 @@
    private BigDecimal baseSalary;
    /**
     * å²—位工资
     */
    private BigDecimal postSalary;
    /**
     * å·¥é¾„工资
     */
    private BigDecimal senioritySalary;
    /**
     * è§’色ID列表
     *
     * ç”¨äºŽåˆ†é…ç³»ç»Ÿç”¨æˆ·è§’色,JSON æ ¼å¼å­˜å‚¨
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/HrmEmployeeSalaryDO.java
@@ -48,6 +48,16 @@
    private BigDecimal baseSalary;
    /**
     * å²—位工资
     */
    private BigDecimal postSalary;
    /**
     * å·¥é¾„工资
     */
    private BigDecimal senioritySalary;
    /**
     * ç»©æ•ˆå·¥èµ„
     */
    private BigDecimal performanceSalary;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/HrmSalaryCalculationDO.java
@@ -58,6 +58,16 @@
    private BigDecimal baseSalary;
    /**
     * å²—位工资
     */
    private BigDecimal postSalary;
    /**
     * å·¥é¾„工资
     */
    private BigDecimal senioritySalary;
    /**
     * ç»©æ•ˆå·¥èµ„
     */
    private BigDecimal performanceSalary;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
@@ -239,6 +239,9 @@
        // é¿å…å‘˜å·¥ä¿¡æ¯ä¸Žè–ªé…¬æ¡£æ¡ˆä¸ä¸€è‡´æ—¶ï¼Œæ ¸ç®—结果与员工档案对不上)
        BigDecimal baseSalary = employee.getBaseSalary() != null ? employee.getBaseSalary() : BigDecimal.ZERO;
        BigDecimal performanceSalary = employeeSalary.getPerformanceSalary() != null ? employeeSalary.getPerformanceSalary() : BigDecimal.ZERO;
        // å²—位工资 / å·¥é¾„工资:与基本工资同源,取员工信息中维护的金额
        BigDecimal postSalary = employee.getPostSalary() != null ? employee.getPostSalary() : BigDecimal.ZERO;
        BigDecimal senioritySalary = employee.getSenioritySalary() != null ? employee.getSenioritySalary() : BigDecimal.ZERO;
        BigDecimal mealAllowance = employeeSalary.getMealAllowance() != null ? employeeSalary.getMealAllowance() : BigDecimal.ZERO;
        BigDecimal transportAllowance = employeeSalary.getTransportAllowance() != null ? employeeSalary.getTransportAllowance() : BigDecimal.ZERO;
        BigDecimal otherAllowance = employeeSalary.getOtherAllowance() != null ? employeeSalary.getOtherAllowance() : BigDecimal.ZERO;
@@ -251,8 +254,8 @@
        BigDecimal totalWorkHours = scheduleStat.totalWorkHours();
        // åº”发工资总额
        BigDecimal totalIncome = baseSalary.add(performanceSalary).add(mealAllowance)
                .add(transportAllowance).add(otherAllowance).add(overtimePay);
        BigDecimal totalIncome = baseSalary.add(performanceSalary).add(postSalary).add(senioritySalary)
                .add(mealAllowance).add(transportAllowance).add(otherAllowance).add(overtimePay);
        // èŽ·å–ç¤¾ä¿åŸºæ•°ï¼šå‘˜å·¥ç¤¾ä¿æ¡£æ¡ˆ > å‘˜å·¥åŸºæœ¬å·¥èµ„
        BigDecimal socialSecurityBase = (socialSecurity != null && socialSecurity.getSocialSecurityBase() != null)
@@ -310,6 +313,8 @@
                .deptId(employee.getDeptId())
                .baseSalary(baseSalary)
                .performanceSalary(performanceSalary)
                .postSalary(postSalary)
                .senioritySalary(senioritySalary)
                .overtimePay(overtimePay)
                .mealAllowance(mealAllowance)
                .transportAllowance(transportAllowance)
@@ -689,6 +694,8 @@
        // å¦åˆ™ä¼šå‡ºçŽ°ã€Œå®žå‘å·¥èµ„æŒ‰ 0 è®¡ç®—、但明细仍保留旧值」的不一致
        calculation.setBaseSalary(nvl(calculation.getBaseSalary()));
        calculation.setPerformanceSalary(nvl(calculation.getPerformanceSalary()));
        calculation.setPostSalary(nvl(calculation.getPostSalary()));
        calculation.setSenioritySalary(nvl(calculation.getSenioritySalary()));
        calculation.setOvertimePay(nvl(calculation.getOvertimePay()));
        calculation.setMealAllowance(nvl(calculation.getMealAllowance()));
        calculation.setTransportAllowance(nvl(calculation.getTransportAllowance()));