docs/sql/hrm_salary_jiuhong_structure.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,82 @@ -- 乿³å工工èµè¡¨ç»ææ©å± -- 1. å工档æ¡è¡¥å ãæ å项ãï¼æ åå·¥èµãå²ä½å·¥èµãå çå·¥èµæ åï¼å /å°æ¶ï¼ãå®å ¨ç¯ä¿å¥æ åãç»©ææ å -- 2. èªé ¬æ ¸ç®ï¼å·¥èµè¡¨ï¼è¡¥å å¾çè¦æ±çå ¨é¨å -- 说æï¼MySQL 8.0 䏿¯æ ADD COLUMN IF NOT EXISTSï¼è¿éç¨åå¨è¿ç¨éåå¤æåæ§è¡ DROP PROCEDURE IF EXISTS add_column_if_missing; DELIMITER $$ CREATE PROCEDURE add_column_if_missing(IN tbl VARCHAR(64), IN col VARCHAR(64), IN ddl TEXT) BEGIN IF (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = tbl AND column_name = col) = 0 THEN SET @sql = ddl; PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st; END IF; END$$ DELIMITER ; -- ---------- å工档æ¡ï¼æ åé¡¹ï¼æ åå¼ç±å工档æ¡ç»´æ¤ï¼ ---------- CALL add_column_if_missing('hrm_employee', 'standard_salary', 'ALTER TABLE hrm_employee ADD COLUMN standard_salary DECIMAL(12,2) NULL COMMENT ''æ åå·¥èµ'' AFTER base_salary'); CALL add_column_if_missing('hrm_employee', 'post_salary', 'ALTER TABLE hrm_employee ADD COLUMN post_salary DECIMAL(12,2) NULL COMMENT ''å²ä½å·¥èµ'' AFTER standard_salary'); CALL add_column_if_missing('hrm_employee', 'overtime_hourly_rate', 'ALTER TABLE hrm_employee ADD COLUMN overtime_hourly_rate DECIMAL(12,2) NULL COMMENT ''å çå·¥èµæ åï¼å /å°æ¶ï¼'' AFTER post_salary'); CALL add_column_if_missing('hrm_employee', 'safety_award_standard', 'ALTER TABLE hrm_employee ADD COLUMN safety_award_standard DECIMAL(12,2) NULL COMMENT ''å®å ¨ç¯ä¿å¥æ å'' AFTER overtime_hourly_rate'); CALL add_column_if_missing('hrm_employee', 'performance_standard', 'ALTER TABLE hrm_employee ADD COLUMN performance_standard DECIMAL(12,2) NULL COMMENT ''ç»©ææ å'' AFTER safety_award_standard'); -- ---------- èªé ¬æ ¸ç®ï¼å·¥èµè¡¨ï¼ ---------- CALL add_column_if_missing('hrm_salary_calculation', 'standard_salary', 'ALTER TABLE hrm_salary_calculation ADD COLUMN standard_salary DECIMAL(12,2) NULL COMMENT ''æ åå·¥èµ'' AFTER dept_id'); CALL add_column_if_missing('hrm_salary_calculation', 'post_salary', 'ALTER TABLE hrm_salary_calculation ADD COLUMN post_salary DECIMAL(12,2) NULL COMMENT ''å²ä½å·¥èµ'' AFTER standard_salary'); CALL add_column_if_missing('hrm_salary_calculation', 'overtime_hourly_rate', 'ALTER TABLE hrm_salary_calculation ADD COLUMN overtime_hourly_rate DECIMAL(12,2) NULL COMMENT ''å çå·¥èµæ åï¼å /å°æ¶ï¼'' AFTER post_salary'); CALL add_column_if_missing('hrm_salary_calculation', 'safety_award_standard', 'ALTER TABLE hrm_salary_calculation ADD COLUMN safety_award_standard DECIMAL(12,2) NULL COMMENT ''å®å ¨ç¯ä¿å¥æ å'' AFTER overtime_hourly_rate'); CALL add_column_if_missing('hrm_salary_calculation', 'performance_standard', 'ALTER TABLE hrm_salary_calculation ADD COLUMN performance_standard DECIMAL(12,2) NULL COMMENT ''ç»©ææ å'' AFTER safety_award_standard'); CALL add_column_if_missing('hrm_salary_calculation', 'paid_attendance_days', 'ALTER TABLE hrm_salary_calculation ADD COLUMN paid_attendance_days DECIMAL(6,2) NULL COMMENT ''计èªåºå¤ï¼å¤©ï¼'' AFTER work_days'); CALL add_column_if_missing('hrm_salary_calculation', 'standard_work_hours', 'ALTER TABLE hrm_salary_calculation ADD COLUMN standard_work_hours DECIMAL(8,2) NULL COMMENT ''æ ååºå¤æ¶é¿ï¼å°æ¶ï¼'' AFTER paid_attendance_days'); CALL add_column_if_missing('hrm_salary_calculation', 'legal_holiday_hours', 'ALTER TABLE hrm_salary_calculation ADD COLUMN legal_holiday_hours DECIMAL(8,2) NULL COMMENT ''æ³å®åæ¥æ¶é¿ï¼å°æ¶ï¼'' AFTER overtime_hours'); CALL add_column_if_missing('hrm_salary_calculation', 'standard_attendance_pay', 'ALTER TABLE hrm_salary_calculation ADD COLUMN standard_attendance_pay DECIMAL(12,2) NULL COMMENT ''æ ååºå¤å·¥èµ'' AFTER legal_holiday_hours'); CALL add_column_if_missing('hrm_salary_calculation', 'legal_holiday_pay', 'ALTER TABLE hrm_salary_calculation ADD COLUMN legal_holiday_pay DECIMAL(12,2) NULL COMMENT ''æ³å®åå·¥èµ'' AFTER overtime_pay'); CALL add_column_if_missing('hrm_salary_calculation', 'safety_award', 'ALTER TABLE hrm_salary_calculation ADD COLUMN safety_award DECIMAL(12,2) NULL COMMENT ''å®å ¨ç¯ä¿å¥'' AFTER legal_holiday_pay'); CALL add_column_if_missing('hrm_salary_calculation', 'floating_performance_pay', 'ALTER TABLE hrm_salary_calculation ADD COLUMN floating_performance_pay DECIMAL(12,2) NULL COMMENT ''æµ®å¨ç»©æå·¥èµ'' AFTER safety_award'); CALL add_column_if_missing('hrm_salary_calculation', 'payable_salary', 'ALTER TABLE hrm_salary_calculation ADD COLUMN payable_salary DECIMAL(12,2) NULL COMMENT ''åºä»å·¥èµ'' AFTER floating_performance_pay'); CALL add_column_if_missing('hrm_salary_calculation', 'seniority_pay', 'ALTER TABLE hrm_salary_calculation ADD COLUMN seniority_pay DECIMAL(12,2) NULL COMMENT ''å·¥é¾å·¥èµ'' AFTER payable_salary'); CALL add_column_if_missing('hrm_salary_calculation', 'night_shift_allowance', 'ALTER TABLE hrm_salary_calculation ADD COLUMN night_shift_allowance DECIMAL(12,2) NULL COMMENT ''å¤çè¡¥å©'' AFTER seniority_pay'); CALL add_column_if_missing('hrm_salary_calculation', 'education_allowance', 'ALTER TABLE hrm_salary_calculation ADD COLUMN education_allowance DECIMAL(12,2) NULL COMMENT ''å¦å补贴'' AFTER night_shift_allowance'); CALL add_column_if_missing('hrm_salary_calculation', 'health_check_allowance', 'ALTER TABLE hrm_salary_calculation ADD COLUMN health_check_allowance DECIMAL(12,2) NULL COMMENT ''使£'' AFTER education_allowance'); CALL add_column_if_missing('hrm_salary_calculation', 'excellent_employee_award', 'ALTER TABLE hrm_salary_calculation ADD COLUMN excellent_employee_award DECIMAL(12,2) NULL COMMENT ''ä¼ç§åå·¥å¥'' AFTER health_check_allowance'); CALL add_column_if_missing('hrm_salary_calculation', 'other_subsidy', 'ALTER TABLE hrm_salary_calculation ADD COLUMN other_subsidy DECIMAL(12,2) NULL COMMENT ''å ¶ä»è¡¥å©'' AFTER excellent_employee_award'); CALL add_column_if_missing('hrm_salary_calculation', 'dept_performance', 'ALTER TABLE hrm_salary_calculation ADD COLUMN dept_performance DECIMAL(12,2) NULL COMMENT ''é¨é¨ç»©æ'' AFTER other_subsidy'); CALL add_column_if_missing('hrm_salary_calculation', 'addition_total', 'ALTER TABLE hrm_salary_calculation ADD COLUMN addition_total DECIMAL(12,2) NULL COMMENT ''å 项å计'' AFTER dept_performance'); CALL add_column_if_missing('hrm_salary_calculation', 'missed_punch_deduction', 'ALTER TABLE hrm_salary_calculation ADD COLUMN missed_punch_deduction DECIMAL(12,2) NULL COMMENT ''æ¼æå¡'' AFTER addition_total'); CALL add_column_if_missing('hrm_salary_calculation', 'late_early_deduction', 'ALTER TABLE hrm_salary_calculation ADD COLUMN late_early_deduction DECIMAL(12,2) NULL COMMENT ''è¿å°æ©é'' AFTER missed_punch_deduction'); CALL add_column_if_missing('hrm_salary_calculation', 'deduction_total', 'ALTER TABLE hrm_salary_calculation ADD COLUMN deduction_total DECIMAL(12,2) NULL COMMENT ''æ£æ¬¾å计'' AFTER other_deduction'); DROP PROCEDURE IF EXISTS add_column_if_missing; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidaySaveReqVO.java
@@ -26,8 +26,8 @@ @NotNull(message = "ç±»åä¸è½ä¸ºç©º") private Integer type; @Schema(description = "æ¯å¦æ³å®è忥ï¼0-å¦ï¼1-æ¯", example = "1") private Integer isLegal; @Schema(description = "æ¯å¦æ³å®è忥ï¼false-å¦ï¼true-æ¯ï¼å ¼å®¹ 0/1 æ°åï¼", example = "true") private Boolean isLegal; @Schema(description = "夿³¨", example = "æ¥èåæ") private String remark; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeRespVO.java
@@ -116,6 +116,26 @@ @ExcelProperty("åºæ¬å·¥èµ") private BigDecimal baseSalary; @Schema(description = "æ åå·¥èµ") @ExcelProperty("æ åå·¥èµ") private BigDecimal standardSalary; @Schema(description = "å²ä½å·¥èµ") @ExcelProperty("å²ä½å·¥èµ") private BigDecimal postSalary; @Schema(description = "å çå·¥èµæ åï¼å /å°æ¶ï¼") @ExcelProperty("å çå·¥èµæ å") private BigDecimal overtimeHourlyRate; @Schema(description = "å®å ¨ç¯ä¿å¥æ å") @ExcelProperty("å®å ¨ç¯ä¿å¥æ å") private BigDecimal safetyAwardStandard; @Schema(description = "ç»©ææ å") @ExcelProperty("ç»©ææ å") private BigDecimal performanceStandard; @Schema(description = "è§è²IDå表") private List<Long> roleIds; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java
@@ -90,6 +90,21 @@ @Schema(description = "åºæ¬å·¥èµ", example = "10000.00") private BigDecimal baseSalary; @Schema(description = "æ åå·¥èµ", example = "8000.00") private BigDecimal standardSalary; @Schema(description = "å²ä½å·¥èµ", example = "2000.00") private BigDecimal postSalary; @Schema(description = "å çå·¥èµæ åï¼å /å°æ¶ï¼", example = "45.98") private BigDecimal overtimeHourlyRate; @Schema(description = "å®å ¨ç¯ä¿å¥æ å", example = "500.00") private BigDecimal safetyAwardStandard; @Schema(description = "ç»©ææ å", example = "1500.00") private BigDecimal performanceStandard; @Schema(description = "è§è²IDå表", example = "[1, 2]") private List<Long> roleIds; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java
@@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.hrm.controller.admin.salary; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; @@ -15,7 +17,9 @@ import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService; import cn.iocoder.yudao.module.hrm.service.salary.HrmSalaryCalculationService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -45,6 +49,8 @@ private HrmEmployeeService employeeService; @Resource private DeptApi deptApi; @Resource private PostApi postApi; @GetMapping("/page") @Operation(summary = "è·å¾èªé ¬æ ¸ç®å页") @@ -84,11 +90,22 @@ .collect(Collectors.toSet()); Map<Long, DeptRespDTO> deptMap = CollUtil.isEmpty(deptIds) ? Collections.emptyMap() : deptApi.getDeptMap(deptIds); // æ¹éè·åå²ä½ä¿¡æ¯ï¼å工表以 JSON æ°ç»å符串ä¿åå²ä½ IDï¼ Set<Long> postIds = new HashSet<>(); for (HrmEmployeeDO employee : employeeMap.values()) { if (StrUtil.isNotBlank(employee.getPostIds())) { postIds.addAll(JSONUtil.toList(employee.getPostIds(), Long.class)); } } Map<Long, PostRespDTO> postMap = CollUtil.isEmpty(postIds) ? Collections.emptyMap() : postApi.getPostMap(postIds); // å¡«å ä¿¡æ¯ for (HrmSalaryCalculationRespVO respVO : respList) { HrmEmployeeDO employee = employeeMap.get(respVO.getUserId()); if (employee != null) { respVO.setUserName(employee.getName()); respVO.setHireDate(employee.getHireDate()); respVO.setPostName(resolvePostName(employee, postMap)); } DeptRespDTO dept = deptMap.get(respVO.getDeptId()); if (dept != null) { @@ -97,6 +114,19 @@ } } /** * è§£æåå·¥å²ä½åç§°ï¼å¤ä¸ªå²ä½ç¨éå·è¿æ¥ï¼ */ private String resolvePostName(HrmEmployeeDO employee, Map<Long, PostRespDTO> postMap) { if (StrUtil.isBlank(employee.getPostIds()) || CollUtil.isEmpty(postMap)) { return null; } return JSONUtil.toList(employee.getPostIds(), Long.class).stream() .filter(postMap::containsKey) .map(id -> postMap.get(id).getName()) .collect(Collectors.joining(",")); } @GetMapping("/get") @Operation(summary = "è·å¾èªé ¬æ ¸ç®") @Parameter(name = "id", description = "æ ¸ç®ID", required = true) yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/HrmSalaryCalculationRespVO.java
@@ -8,6 +8,7 @@ import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; @Schema(description = "管çåå° - èªé ¬æ ¸ç® Response VO") @@ -41,6 +42,126 @@ @ExcelProperty("é¨é¨åç§°") private String deptName; @Schema(description = "å ¥èæ¥æ") @ExcelProperty("å ¥èæ¥æ") private LocalDate hireDate; @Schema(description = "å²ä½åç§°ï¼å¤ä¸ªç¨éå·åéï¼") @ExcelProperty("å²ä½") private String postName; // ========== 乿³å·¥èµè¡¨ï¼æ å项ï¼åèªå工档æ¡ï¼ ========== @Schema(description = "æ åå·¥èµ") @ExcelProperty("æ åå·¥èµ") private BigDecimal standardSalary; @Schema(description = "å²ä½å·¥èµ") @ExcelProperty("å²ä½å·¥èµ") private BigDecimal postSalary; @Schema(description = "å çå·¥èµæ åï¼å /å°æ¶ï¼") @ExcelProperty("å çå·¥èµ(æ å)") private BigDecimal overtimeHourlyRate; @Schema(description = "å®å ¨ç¯ä¿å¥æ å") @ExcelProperty("å®å ¨ç¯ä¿å¥(æ å)") private BigDecimal safetyAwardStandard; @Schema(description = "ç»©ææ å") @ExcelProperty("绩æ(æ å)") private BigDecimal performanceStandard; // ========== 乿³å·¥èµè¡¨ï¼åºå¤ä¸è®¡èª ========== @Schema(description = "æ ååºå¤å¤©æ°") @ExcelProperty("æ ååºå¤å¤©æ°") private Integer workDays; @Schema(description = "计èªåºå¤ï¼å¤©ï¼") @ExcelProperty("计èªåºå¤") private BigDecimal paidAttendanceDays; @Schema(description = "æ ååºå¤æ¶é¿ï¼å°æ¶ï¼") @ExcelProperty("æ ååºå¤æ¶é¿") private BigDecimal standardWorkHours; @Schema(description = "å çæ¶é¿ï¼å°æ¶ï¼") @ExcelProperty("å çæ¶é¿") private BigDecimal overtimeHours; @Schema(description = "æ³å®åæ¥æ¶é¿ï¼å°æ¶ï¼") @ExcelProperty("æ³å®åæ¥æ¶é¿") private BigDecimal legalHolidayHours; @Schema(description = "æ ååºå¤å·¥èµ") @ExcelProperty("æ ååºå¤å·¥èµ") private BigDecimal standardAttendancePay; @Schema(description = "å çå·¥èµ") @ExcelProperty("å çå·¥èµ") private BigDecimal overtimePay; @Schema(description = "æ³å®åå·¥èµ") @ExcelProperty("æ³å®åå·¥èµ") private BigDecimal legalHolidayPay; @Schema(description = "å®å ¨ç¯ä¿å¥") @ExcelProperty("å®å ¨ç¯ä¿å¥") private BigDecimal safetyAward; @Schema(description = "æµ®å¨ç»©æå·¥èµ") @ExcelProperty("æµ®å¨ç»©æå·¥èµ") private BigDecimal floatingPerformancePay; @Schema(description = "åºä»å·¥èµ") @ExcelProperty("åºä»å·¥èµ") private BigDecimal payableSalary; @Schema(description = "å·¥é¾å·¥èµ") @ExcelProperty("å·¥é¾å·¥èµ") private BigDecimal seniorityPay; @Schema(description = "å¤çè¡¥å©") @ExcelProperty("å¤çè¡¥å©") private BigDecimal nightShiftAllowance; @Schema(description = "å¦å补贴") @ExcelProperty("å¦å补贴") private BigDecimal educationAllowance; @Schema(description = "使£") @ExcelProperty("使£") private BigDecimal healthCheckAllowance; @Schema(description = "ä¼ç§åå·¥å¥") @ExcelProperty("ä¼ç§åå·¥å¥") private BigDecimal excellentEmployeeAward; @Schema(description = "å ¶ä»è¡¥å©") @ExcelProperty("å ¶ä»è¡¥å©") private BigDecimal otherSubsidy; @Schema(description = "é¨é¨ç»©æ") @ExcelProperty("é¨é¨ç»©æ") private BigDecimal deptPerformance; @Schema(description = "å 项å计") @ExcelProperty("å 项å计") private BigDecimal additionTotal; @Schema(description = "æ¼æå¡") @ExcelProperty("æ¼æå¡") private BigDecimal missedPunchDeduction; @Schema(description = "è¿å°æ©é") @ExcelProperty("è¿å°æ©é") private BigDecimal lateEarlyDeduction; @Schema(description = "æ£æ¬¾å计") @ExcelProperty("æ£æ¬¾å计") private BigDecimal deductionTotal; @Schema(description = "åºæ¬å·¥èµ") @ExcelProperty("åºæ¬å·¥èµ") private BigDecimal baseSalary; @@ -48,10 +169,6 @@ @Schema(description = "绩æå·¥èµ") @ExcelProperty("绩æå·¥èµ") private BigDecimal performanceSalary; @Schema(description = "å çå·¥èµ") @ExcelProperty("å çå·¥èµ") private BigDecimal overtimePay; @Schema(description = "é¤è¡¥") @ExcelProperty("é¤è¡¥") @@ -88,14 +205,6 @@ @Schema(description = "å®åå·¥èµ") @ExcelProperty("å®åå·¥èµ") private BigDecimal actualSalary; @Schema(description = "åºå¤å¤©æ°") @ExcelProperty("åºå¤å¤©æ°") private Integer workDays; @Schema(description = "å çæ¶é¿") @ExcelProperty("å çæ¶é¿") private BigDecimal overtimeHours; @Schema(description = "æçæ»å·¥æ¶") @ExcelProperty("æçæ»å·¥æ¶") yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/HrmSalaryCalculationSaveReqVO.java
@@ -41,6 +41,78 @@ @NotNull(message = "åºæ¬å·¥èµä¸è½ä¸ºç©º") private BigDecimal baseSalary; @Schema(description = "æ åå·¥èµ") private BigDecimal standardSalary; @Schema(description = "å²ä½å·¥èµ") private BigDecimal postSalary; @Schema(description = "å çå·¥èµæ åï¼å /å°æ¶ï¼") private BigDecimal overtimeHourlyRate; @Schema(description = "å®å ¨ç¯ä¿å¥æ å") private BigDecimal safetyAwardStandard; @Schema(description = "ç»©ææ å") private BigDecimal performanceStandard; @Schema(description = "计èªåºå¤ï¼å¤©ï¼") private BigDecimal paidAttendanceDays; @Schema(description = "æ ååºå¤æ¶é¿ï¼å°æ¶ï¼") private BigDecimal standardWorkHours; @Schema(description = "æ³å®åæ¥æ¶é¿ï¼å°æ¶ï¼") private BigDecimal legalHolidayHours; @Schema(description = "æ ååºå¤å·¥èµ") private BigDecimal standardAttendancePay; @Schema(description = "æ³å®åå·¥èµ") private BigDecimal legalHolidayPay; @Schema(description = "å®å ¨ç¯ä¿å¥") private BigDecimal safetyAward; @Schema(description = "æµ®å¨ç»©æå·¥èµ") private BigDecimal floatingPerformancePay; @Schema(description = "åºä»å·¥èµ") private BigDecimal payableSalary; @Schema(description = "å·¥é¾å·¥èµ") private BigDecimal seniorityPay; @Schema(description = "å¤çè¡¥å©") private BigDecimal nightShiftAllowance; @Schema(description = "å¦å补贴") private BigDecimal educationAllowance; @Schema(description = "使£") private BigDecimal healthCheckAllowance; @Schema(description = "ä¼ç§åå·¥å¥") private BigDecimal excellentEmployeeAward; @Schema(description = "å ¶ä»è¡¥å©") private BigDecimal otherSubsidy; @Schema(description = "é¨é¨ç»©æ") private BigDecimal deptPerformance; @Schema(description = "å 项å计") private BigDecimal additionTotal; @Schema(description = "æ¼æå¡") private BigDecimal missedPunchDeduction; @Schema(description = "è¿å°æ©é") private BigDecimal lateEarlyDeduction; @Schema(description = "æ£æ¬¾å计") private BigDecimal deductionTotal; @Schema(description = "绩æå·¥èµ") private BigDecimal performanceSalary; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/attendance/HrmAttendanceSummaryDO.java
@@ -2,6 +2,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -43,7 +44,10 @@ /** * å¹´æï¼æ ¼å¼ï¼yyyy-MM * * year_month æ¯ MySQL ä¿çåï¼INTERVAL åä½ï¼ï¼ä¸å åå¼å·ä¼æ¥ SQL è¯æ³é误 */ @TableField("`year_month`") private String yearMonth; /** yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/employee/HrmEmployeeDO.java
@@ -160,6 +160,33 @@ private BigDecimal baseSalary; /** * æ åå·¥èµ * * ç¨äºå·¥èµè¡¨ï¼æ ååºå¤å·¥èµ = æ åå·¥èµ Ã· æ ååºå¤å¤©æ° à 计èªåºå¤ */ private BigDecimal standardSalary; /** * å²ä½å·¥èµ */ private BigDecimal postSalary; /** * å çå·¥èµæ åï¼å /å°æ¶ï¼ */ private BigDecimal overtimeHourlyRate; /** * å®å ¨ç¯ä¿å¥æ å */ private BigDecimal safetyAwardStandard; /** * ç»©ææ å */ private BigDecimal performanceStandard; /** * è§è²IDå表 * * ç¨äºåé ç³»ç»ç¨æ·è§è²ï¼JSON æ ¼å¼åå¨ yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/HrmSalaryCalculationDO.java
@@ -53,6 +53,126 @@ private Long deptId; /** * æ åå·¥èµ */ private BigDecimal standardSalary; /** * å²ä½å·¥èµ */ private BigDecimal postSalary; /** * å çå·¥èµæ åï¼å /å°æ¶ï¼ */ private BigDecimal overtimeHourlyRate; /** * å®å ¨ç¯ä¿å¥æ å */ private BigDecimal safetyAwardStandard; /** * ç»©ææ å */ private BigDecimal performanceStandard; /** * 计èªåºå¤ï¼å¤©ï¼ */ private BigDecimal paidAttendanceDays; /** * æ ååºå¤æ¶é¿ï¼å°æ¶ï¼ */ private BigDecimal standardWorkHours; /** * æ³å®åæ¥æ¶é¿ï¼å°æ¶ï¼ */ private BigDecimal legalHolidayHours; /** * æ ååºå¤å·¥èµ */ private BigDecimal standardAttendancePay; /** * æ³å®åå·¥èµ */ private BigDecimal legalHolidayPay; /** * å®å ¨ç¯ä¿å¥ */ private BigDecimal safetyAward; /** * æµ®å¨ç»©æå·¥èµ */ private BigDecimal floatingPerformancePay; /** * åºä»å·¥èµ */ private BigDecimal payableSalary; /** * å·¥é¾å·¥èµ */ private BigDecimal seniorityPay; /** * å¤çè¡¥å© */ private BigDecimal nightShiftAllowance; /** * å¦å补贴 */ private BigDecimal educationAllowance; /** * 使£ */ private BigDecimal healthCheckAllowance; /** * ä¼ç§åå·¥å¥ */ private BigDecimal excellentEmployeeAward; /** * å ¶ä»è¡¥å© */ private BigDecimal otherSubsidy; /** * é¨é¨ç»©æ */ private BigDecimal deptPerformance; /** * å 项å计 */ private BigDecimal additionTotal; /** * æ¼æå¡ */ private BigDecimal missedPunchDeduction; /** * è¿å°æ©é */ private BigDecimal lateEarlyDeduction; /** * æ£æ¬¾å计 */ private BigDecimal deductionTotal; /** * åºæ¬å·¥èµ */ private BigDecimal baseSalary; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java
@@ -35,9 +35,8 @@ // æ ¡éªæ¥ææ¯å¦å·²åå¨é ç½® validateAttendanceHolidayDateExists(createReqVO.getDate()); HrmAttendanceHolidayDO attendanceHoliday = BeanUtils.toBean(createReqVO, HrmAttendanceHolidayDO.class); if (attendanceHoliday.getIsLegal() == null) { attendanceHoliday.setIsLegal(0); } // VO ä¾§ç¨ Boolean å ¼å®¹å端å¾éæ¡ç true/falseï¼è½åºç»ä¸ä¸º 0/1 attendanceHoliday.setIsLegal(Boolean.TRUE.equals(createReqVO.getIsLegal()) ? 1 : 0); attendanceHolidayMapper.insert(attendanceHoliday); return attendanceHoliday.getId(); } @@ -51,6 +50,7 @@ validateAttendanceHolidayDateExists(updateReqVO.getDate()); } HrmAttendanceHolidayDO updateObj = BeanUtils.toBean(updateReqVO, HrmAttendanceHolidayDO.class); updateObj.setIsLegal(Boolean.TRUE.equals(updateReqVO.getIsLegal()) ? 1 : 0); attendanceHolidayMapper.updateById(updateObj); } yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -340,6 +340,14 @@ @Override public List<HrmEmployeeDO> getEmployeeList(Collection<Long> ids) { // ids 为 null æ¶è¡¨ç¤ºæ¥è¯¢å ¨é¨åå·¥ï¼è夿±æ»ãèªé ¬æ ¸ç®çæ¹éåºæ¯ä¾èµæ¤è¯ä¹ï¼ï¼ // æ¾å¼ä¼ å ¥ç©ºéåæ¶è¿å空ï¼é¿å 误æ¥å ¨å if (ids == null) { return employeeMapper.selectList(null); } if (ids.isEmpty()) { return Collections.emptyList(); } return employeeMapper.selectByIds(ids); } yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmSalaryCalculationPageReqVO; import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmLeaveApplicationDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmOvertimeApplicationDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmEmployeeScheduleDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmShiftDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; @@ -21,6 +22,7 @@ import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmEmployeeScheduleMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmShiftMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmOvertimeApplicationMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceRecordMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmEmployeeSalaryMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmEmployeeSocialSecurityMapper; @@ -32,6 +34,7 @@ import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryStructureMapper; import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceClockTypeEnum; import cn.iocoder.yudao.module.hrm.enums.HrmOvertimeTypeEnum; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -110,6 +113,8 @@ private HrmEmployeeScheduleMapper employeeScheduleMapper; @Resource private HrmShiftMapper shiftMapper; @Resource private HrmAttendanceRecordMapper attendanceRecordMapper; @Override public PageResult<HrmSalaryCalculationDO> getSalaryCalculationPage(HrmSalaryCalculationPageReqVO pageReqVO) { @@ -235,17 +240,65 @@ 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; OvertimeSalary overtimeSalary = calculateOvertimeSalary(employee, employeeSalary, period, baseSalary); BigDecimal overtimePay = overtimeSalary.pay(); // ææç累计åºå¤å¤©æ°ä¸æçæ»å·¥æ¶ï¼æ æçæ¶åºå¤å¤©æ°åéé»è®¤ 22ï¼ // ========== 乿³å·¥èµè¡¨ï¼æ å项åèªåå·¥æ¡£æ¡ ========== BigDecimal standardSalary = nvl(employee.getStandardSalary()); BigDecimal postSalary = nvl(employee.getPostSalary()); BigDecimal overtimeHourlyRate = employee.getOvertimeHourlyRate(); BigDecimal safetyAwardStandard = nvl(employee.getSafetyAwardStandard()); BigDecimal performanceStandard = nvl(employee.getPerformanceStandard()); // æ åå·¥èµæªåç¬ç»´æ¤æ¶ï¼æãåºæ¬å·¥èµ + å²ä½å·¥èµãåæ if (standardSalary.signum() == 0 && (baseSalary.signum() > 0 || postSalary.signum() > 0)) { standardSalary = baseSalary.add(postSalary); } // ææç累计åºåºå¤å¤©æ°ä¸æ åå·¥æ¶ï¼æ æçæ¶åé 22 天 à 8 å°æ¶ï¼ ScheduleStat scheduleStat = calculateScheduleStat(employeeId, period); Integer workDays = scheduleStat.scheduledDays() > 0 ? scheduleStat.scheduledDays() : 22; BigDecimal totalWorkHours = scheduleStat.totalWorkHours(); BigDecimal standardWorkHours = scheduleStat.scheduledDays() > 0 ? scheduleStat.totalWorkHours() : BigDecimal.valueOf(workDays).multiply(BigDecimal.valueOf(8)); // åºåå·¥èµæ»é¢ BigDecimal totalIncome = baseSalary.add(performanceSalary).add(mealAllowance) .add(transportAllowance).add(otherAllowance).add(overtimePay); // 计èªåºå¤ = æ ååºå¤å¤©æ° - 缺å¤å¤©æ°ï¼èå¤è®°å½ä¸ç¼ºå¡ç天æ°ï¼æå¤©å»éï¼ int absentDays = countAbsentDays(employeeId, period); BigDecimal paidAttendanceDays = BigDecimal.valueOf(Math.max(workDays - absentDays, 0)); // å çå·¥èµ / æ³å®åå·¥èµï¼å çå·¥èµæ å为空æ¶åéå° åºæ¬å·¥èµ / 21.75 / 8 à åçï¼ OvertimeSalary overtimeSalary = calculateOvertimeSalary(employee, employeeSalary, period, baseSalary, overtimeHourlyRate); BigDecimal overtimeHours = overtimeSalary.hours(); BigDecimal overtimePay = overtimeSalary.pay(); BigDecimal legalHolidayHours = overtimeSalary.legalHolidayHours(); BigDecimal legalHolidayPay = overtimeSalary.legalHolidayPay(); // åºå¤æç®æ¯ä¾ï¼ç¨äºæå®é 计èªåºå¤æç®æ å项 BigDecimal attendanceRatio = workDays > 0 ? paidAttendanceDays.divide(BigDecimal.valueOf(workDays), 6, RoundingMode.HALF_UP) : BigDecimal.ZERO; BigDecimal standardAttendancePay = standardSalary.multiply(attendanceRatio).setScale(2, RoundingMode.HALF_UP); BigDecimal safetyAward = safetyAwardStandard.multiply(attendanceRatio).setScale(2, RoundingMode.HALF_UP); BigDecimal floatingPerformancePay = performanceStandard.multiply(attendanceRatio).setScale(2, RoundingMode.HALF_UP); // åºä»å·¥èµ = æ ååºå¤å·¥èµ + å çå·¥èµ + æ³å®åå·¥èµ + å®å ¨ç¯ä¿å¥ + æµ®å¨ç»©æå·¥èµ BigDecimal payableSalary = standardAttendancePay.add(overtimePay).add(legalHolidayPay) .add(safetyAward).add(floatingPerformancePay); // å 项ï¼å·¥é¾å·¥èµ/å¤çè¡¥å©/å¦å补贴/使£/ä¼ç§åå·¥å¥/å ¶ä»è¡¥å©/é¨é¨ç»©æï¼ä¸æ£é¡¹ // ï¼æ¼æå¡/è¿å°æ©é/å ¶ä»æ£æ¬¾ï¼çææ¶é»è®¤ä¸º 0ï¼æ ¸ç®é¡µå¯æå·¥è°æ´åä¿å BigDecimal seniorityPay = BigDecimal.ZERO; BigDecimal nightShiftAllowance = BigDecimal.ZERO; BigDecimal educationAllowance = BigDecimal.ZERO; BigDecimal healthCheckAllowance = BigDecimal.ZERO; BigDecimal excellentEmployeeAward = BigDecimal.ZERO; BigDecimal otherSubsidy = BigDecimal.ZERO; BigDecimal deptPerformance = BigDecimal.ZERO; BigDecimal additionTotal = BigDecimal.ZERO; BigDecimal missedPunchDeduction = BigDecimal.ZERO; BigDecimal lateEarlyDeduction = BigDecimal.ZERO; BigDecimal deductionTotal = BigDecimal.ZERO; // 计ç¨å£å¾ï¼åºä»å·¥èµ + å 项å计 - æ£æ¬¾å计 BigDecimal totalIncome = payableSalary.add(additionTotal).subtract(deductionTotal); // è·å社ä¿åºæ°ï¼åå·¥ç¤¾ä¿æ¡£æ¡ > æ¹æ¡é»è®¤ç¼´è´¹åºæ° > åå·¥åºæ¬å·¥èµ BigDecimal socialSecurityBase = (socialSecurity != null && socialSecurity.getSocialSecurityBase() != null) @@ -284,8 +337,8 @@ // å ¬ç§¯éæ£é¤ = åºæ° Ã å ¬ç§¯é个人æ¯ä¾ BigDecimal housingFundDeduction = housingFundBase.multiply(housingFundPersonalRatio).setScale(2, RoundingMode.HALF_UP); // 计ç®è¯·åæ£æ¬¾ BigDecimal leaveDeduction = calculateLeaveDeduction(employee, period, baseSalary); // è¯·åæ£æ¬¾ï¼æ°çå·¥èµè¡¨æã计èªåºå¤ãæåæ ååºå¤å·¥èµï¼ä¸ååç¬é夿£ä¸æ¬¡ï¼ä¿çåæ®µå ¼å®¹æ§æ°æ® BigDecimal leaveDeduction = BigDecimal.ZERO; // 计ç®ä¸ªç¨æ£é¤ // åºçº³ç¨æå¾é¢ = åºåå·¥èµ - ç¤¾ä¿æ£é¤ - å ¬ç§¯éæ£é¤ - èµ·å¾ç¹(5000) @@ -301,15 +354,43 @@ BigDecimal otherDeduction = BigDecimal.ZERO; // 计ç®å®åå·¥èµ = åºå - æ£é¤ BigDecimal totalDeduction = socialSecurityDeduction.add(housingFundDeduction) .add(taxDeduction).add(otherDeduction).add(leaveDeduction); BigDecimal actualSalary = totalIncome.subtract(totalDeduction); // ç¨åå·¥èµ = åºä»å·¥èµ + å 项å计 - æ£æ¬¾å计 - ç¤¾ä¿ - å ¬ç§¯é - ä¸ªç¨ BigDecimal actualSalary = payableSalary.add(additionTotal).subtract(deductionTotal) .subtract(socialSecurityDeduction).subtract(housingFundDeduction) .subtract(taxDeduction); return HrmSalaryCalculationDO.builder() .period(period) .userId(employeeId) // 使ç¨åå·¥ID .deptId(employee.getDeptId()) // 乿³å·¥èµè¡¨ï¼æ å项 .standardSalary(standardSalary) .postSalary(postSalary) .overtimeHourlyRate(overtimeHourlyRate) .safetyAwardStandard(safetyAwardStandard) .performanceStandard(performanceStandard) // 乿³å·¥èµè¡¨ï¼åºå¤ä¸è®¡èª .paidAttendanceDays(paidAttendanceDays) .standardWorkHours(standardWorkHours) .legalHolidayHours(legalHolidayHours) .standardAttendancePay(standardAttendancePay) .legalHolidayPay(legalHolidayPay) .safetyAward(safetyAward) .floatingPerformancePay(floatingPerformancePay) .payableSalary(payableSalary) // 乿³å·¥èµè¡¨ï¼å 项 / æ£é¡¹ .seniorityPay(seniorityPay) .nightShiftAllowance(nightShiftAllowance) .educationAllowance(educationAllowance) .healthCheckAllowance(healthCheckAllowance) .excellentEmployeeAward(excellentEmployeeAward) .otherSubsidy(otherSubsidy) .deptPerformance(deptPerformance) .additionTotal(additionTotal) .missedPunchDeduction(missedPunchDeduction) .lateEarlyDeduction(lateEarlyDeduction) .deductionTotal(deductionTotal) // å ¼å®¹æ§å段 .baseSalary(baseSalary) .performanceSalary(performanceSalary) .overtimePay(overtimePay) @@ -323,7 +404,7 @@ .leaveDeduction(leaveDeduction) .actualSalary(actualSalary) .workDays(workDays) // ææç累计åºåºå¤å¤©æ°ï¼æ æçæ¶åé 22 .overtimeHours(overtimeSalary.hours()) .overtimeHours(overtimeHours) .totalWorkHours(totalWorkHours) .status(0) // å¾ ç¡®è®¤ .build(); @@ -406,19 +487,24 @@ } /** * æ±æ»å½æå®¡æ¹éè¿çå çç³è¯·ãå°æ¶å·¥èµæåºæ¬å·¥èµ / 21.75 / 8 计ç®ï¼ * 工使¥é»è®¤ 1.5 åã伿¯æ¥é»è®¤ 2 åãæ³å®è忥é»è®¤ 3 åï¼åå¯ç±èªé ¬ç»æè¦çã * æ±æ»å½æå®¡æ¹éè¿çå çç³è¯·ã * * å工档æ¡ç»´æ¤äºãå çå·¥èµæ åï¼å /å°æ¶ï¼ãæ¶ï¼å çå·¥èµ = å çæ¶é¿ Ã åä»·ï¼ * æ³å®åå·¥èµ = æ³å®åæ¥æ¶é¿ à åä»· à æ³å®è忥åçï¼é»è®¤ 3ï¼ã * æªç»´æ¤åä»·æ¶åéæ§å£å¾ï¼åºæ¬å·¥èµ / 21.75 / 8 à åç±»ååçã * * æ³å®è忥å çåç¬ç»è®¡ï¼ä¸è®¡å ¥ãå çæ¶é¿ãåï¼é¿å ä¸ãæ³å®åå·¥èµãéå¤è®¡èªã */ private OvertimeSalary calculateOvertimeSalary(HrmEmployeeDO employee, HrmEmployeeSalaryDO employeeSalary, String period, BigDecimal baseSalary) { String period, BigDecimal baseSalary, BigDecimal overtimeHourlyRate) { if (employee.getUserId() == null) { return new OvertimeSalary(BigDecimal.ZERO, BigDecimal.ZERO); return OvertimeSalary.EMPTY; } YearMonth month = YearMonth.parse(period); List<HrmOvertimeApplicationDO> applications = overtimeApplicationMapper.selectApprovedByUserAndDateRange( employee.getUserId(), month.atDay(1), month.atEndOfMonth()); if (CollUtil.isEmpty(applications)) { return new OvertimeSalary(BigDecimal.ZERO, BigDecimal.ZERO); return OvertimeSalary.EMPTY; } Long structureId = employeeSalary.getSalaryStructureId() != null ? employeeSalary.getSalaryStructureId() : employee.getSalaryStructureId(); @@ -429,29 +515,62 @@ ? structure.getRestDayOvertimePayRatio() : HrmOvertimeTypeEnum.REST_DAY.getSalaryMultiplier(); BigDecimal legalHolidayMultiplier = structure != null && structure.getLegalHolidayOvertimePayRatio() != null ? structure.getLegalHolidayOvertimePayRatio() : HrmOvertimeTypeEnum.LEGAL_HOLIDAY.getSalaryMultiplier(); BigDecimal hourlySalary = baseSalary.divide(new BigDecimal("21.75"), 8, RoundingMode.HALF_UP) .divide(new BigDecimal("8"), 8, RoundingMode.HALF_UP); BigDecimal hourlySalary = overtimeHourlyRate != null && overtimeHourlyRate.signum() > 0 ? overtimeHourlyRate : baseSalary.divide(new BigDecimal("21.75"), 8, RoundingMode.HALF_UP) .divide(new BigDecimal("8"), 8, RoundingMode.HALF_UP); BigDecimal totalHours = BigDecimal.ZERO; BigDecimal totalPay = BigDecimal.ZERO; BigDecimal legalHolidayHours = BigDecimal.ZERO; BigDecimal legalHolidayPay = BigDecimal.ZERO; for (HrmOvertimeApplicationDO application : applications) { BigDecimal hours = application.getDuration() == null ? BigDecimal.ZERO : application.getDuration(); HrmOvertimeTypeEnum type = HrmOvertimeTypeEnum.valueOfType(application.getOvertimeType()); if (type == null || hours.signum() <= 0) { continue; } BigDecimal multiplier = switch (type) { case WORKDAY -> workdayMultiplier; case REST_DAY -> restDayMultiplier; case LEGAL_HOLIDAY -> legalHolidayMultiplier; }; if (type == HrmOvertimeTypeEnum.LEGAL_HOLIDAY) { legalHolidayHours = legalHolidayHours.add(hours); legalHolidayPay = legalHolidayPay.add(hourlySalary.multiply(hours).multiply(legalHolidayMultiplier)); continue; } BigDecimal multiplier = type == HrmOvertimeTypeEnum.WORKDAY ? workdayMultiplier : restDayMultiplier; totalHours = totalHours.add(hours); totalPay = totalPay.add(hourlySalary.multiply(hours).multiply(multiplier)); } return new OvertimeSalary(totalHours.setScale(1, RoundingMode.HALF_UP), totalPay.setScale(2, RoundingMode.HALF_UP)); totalPay.setScale(2, RoundingMode.HALF_UP), legalHolidayHours.setScale(1, RoundingMode.HALF_UP), legalHolidayPay.setScale(2, RoundingMode.HALF_UP)); } private record OvertimeSalary(BigDecimal hours, BigDecimal pay) {} /** * ç»è®¡å½æèå¤è®°å½ä¸ç¼ºå¡ç天æ°ï¼å䏿¥æå¤æ¬¡ç¼ºå¡åªç®ä¸å¤©ï¼ */ private int countAbsentDays(Long employeeId, String period) { YearMonth month = YearMonth.parse(period); List<HrmAttendanceRecordDO> records = attendanceRecordMapper.selectListByUserIdAndDateBetween( employeeId, month.atDay(1), month.atEndOfMonth()); if (CollUtil.isEmpty(records)) { return 0; } return (int) records.stream() .filter(record -> HrmAttendanceClockTypeEnum.MISSING.getType().equals(record.getClockInType()) || HrmAttendanceClockTypeEnum.MISSING.getType().equals(record.getClockOutType())) .map(HrmAttendanceRecordDO::getDate) .distinct() .count(); } private static BigDecimal nvl(BigDecimal value) { return value == null ? BigDecimal.ZERO : value; } private record OvertimeSalary(BigDecimal hours, BigDecimal pay, BigDecimal legalHolidayHours, BigDecimal legalHolidayPay) { private static final OvertimeSalary EMPTY = new OvertimeSalary( BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); } private record ScheduleStat(int scheduledDays, BigDecimal totalWorkHours) {} @@ -594,6 +713,7 @@ @Transactional(rollbackFor = Exception.class) public void saveSalaryCalculationList(List<HrmSalaryCalculationDO> calculationList) { for (HrmSalaryCalculationDO calculation : calculationList) { normalizeSalaryTotals(calculation); if (calculation.getId() == null) { // æ°å¢è®°å½ï¼çææ ¸ç®åå· String no = noRedisDAO.generateSalaryCalculationNo(); @@ -611,6 +731,50 @@ } /** * ä¿ååæä¹æ³å·¥èµè¡¨å£å¾éç®å计ï¼é¿å å端æ¼ç®ææ§å®¢æ·ç«¯ä¼ å ¥ä¸ä¸è´çå计å¼ã * * å 项å计 = å·¥é¾å·¥èµ + å¤çè¡¥å© + å¦å补贴 + 使£ + ä¼ç§åå·¥å¥ + å ¶ä»è¡¥å© + é¨é¨ç»©æ * æ£æ¬¾å计 = æ¼æå¡ + è¿å°æ©é + å ¶ä»æ£æ¬¾ * ç¨åå·¥èµ = åºä»å·¥èµ + å 项å计 - æ£æ¬¾å计 - ç¤¾ä¿ - å ¬ç§¯é - ä¸ªç¨ * * ä» å½æ¬æ¬¡è®°å½å¸¦æãåºä»å·¥èµãæ¶éç®ï¼åªææ§å段çèæ°æ®ä¿æåæ ·ï¼é¿å ææªç»´æ¤çæ°åæ®µæ¸ æ 0ã */ private void normalizeSalaryTotals(HrmSalaryCalculationDO calculation) { if (calculation.getPayableSalary() == null) { return; } // åºä»å·¥èµ = æ ååºå¤å·¥èµ + å çå·¥èµ + æ³å®åå·¥èµ + å®å ¨ç¯ä¿å¥ + æµ®å¨ç»©æå·¥èµ // ä» å½æ¬æ¬¡è®°å½å¸¦æ°çæ å项æ¶éç®ï¼é¿å æ§æ°æ®ï¼æ è¿äºåï¼è¢«æ¸ é¶ if (calculation.getStandardAttendancePay() != null) { calculation.setPayableSalary(nvl(calculation.getStandardAttendancePay()) .add(nvl(calculation.getOvertimePay())) .add(nvl(calculation.getLegalHolidayPay())) .add(nvl(calculation.getSafetyAward())) .add(nvl(calculation.getFloatingPerformancePay())) .setScale(2, RoundingMode.HALF_UP)); } BigDecimal additionTotal = nvl(calculation.getSeniorityPay()) .add(nvl(calculation.getNightShiftAllowance())) .add(nvl(calculation.getEducationAllowance())) .add(nvl(calculation.getHealthCheckAllowance())) .add(nvl(calculation.getExcellentEmployeeAward())) .add(nvl(calculation.getOtherSubsidy())) .add(nvl(calculation.getDeptPerformance())); BigDecimal deductionTotal = nvl(calculation.getMissedPunchDeduction()) .add(nvl(calculation.getLateEarlyDeduction())) .add(nvl(calculation.getOtherDeduction())); calculation.setAdditionTotal(additionTotal.setScale(2, RoundingMode.HALF_UP)); calculation.setDeductionTotal(deductionTotal.setScale(2, RoundingMode.HALF_UP)); calculation.setActualSalary(calculation.getPayableSalary() .add(calculation.getAdditionTotal()) .subtract(calculation.getDeductionTotal()) .subtract(nvl(calculation.getSocialSecurityDeduction())) .subtract(nvl(calculation.getHousingFundDeduction())) .subtract(nvl(calculation.getTaxDeduction())) .setScale(2, RoundingMode.HALF_UP)); } /** * å é¨çæåæ¾å°è´¦æ¹æ³ï¼ä¾èªå¨çæè°ç¨ï¼ */ private void generatePaymentInternal(String period, List<HrmSalaryCalculationDO> calculationList) {