sql/mysql/hrm_salary_add_full_attendance_bonus.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,49 @@ -- ============================================= -- èªé ¬æ ¸ç®ï¼æ°å¢ãå ¨å¤å¥ããå®åºå¤©æ°ã -- -- èæ¯ï¼ -- 1) å ¨å¤å¥ï¼ä¸å ¶ä»æ´¥è´´å£å¾ä¸è´ï¼ç±äººå·¥å¨æ ¸ç®åä¸ç»´æ¤ï¼é»è®¤ 0ï¼ï¼è®¡å ¥åºå/å®å -- 2) å®åºå¤©æ°ï¼åèªè夿±æ»è¡¨ hrm_attendance_summary.actual_days -- ãåºåºå¤©æ°ã沿ç¨å work_daysï¼ææç累计çåºåºå¤å¤©æ°ï¼æ æçåé 22ï¼ï¼è¯ä¹ä¸åï¼ä» å端æ¹å -- ãæçå·¥æ¶ãåå total_work_hours ä¿çä½ä¸å使ç¨ï¼å岿°æ®ä¸å é¤ï¼ -- -- èæ¬å¯é夿§è¡ï¼å¹çï¼ -- ============================================= SET NAMES utf8mb4; SET @sch := DATABASE(); -- 1. å ¨å¤å¥ SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_salary_calculation' AND COLUMN_NAME = 'full_attendance_bonus'); SET @sql := IF(@exists = 0, 'ALTER TABLE `hrm_salary_calculation` ADD COLUMN `full_attendance_bonus` decimal(10,2) DEFAULT ''0.00'' COMMENT ''å ¨å¤å¥'' AFTER `other_allowance`', 'SELECT ''full_attendance_bonus å·²åå¨'' 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 = 'actual_days'); SET @sql := IF(@exists = 0, 'ALTER TABLE `hrm_salary_calculation` ADD COLUMN `actual_days` int DEFAULT 0 COMMENT ''å®åºå¤©æ°ï¼åèªè夿±æ»ï¼'' AFTER `work_days`', 'SELECT ''actual_days å·²åå¨'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 3. å岿°æ®åå¡«å®åºå¤©æ°ï¼æååå·¥å卿ä»è夿±æ»å¸¦ä¸æ¬¡ï¼é¿å åå²åå ¨æ¯ 0ï¼ UPDATE `hrm_salary_calculation` c JOIN `hrm_attendance_summary` s ON s.`user_id` = c.`user_id` AND s.`year_month` = c.`period` AND s.`deleted` = b'0' SET c.`actual_days` = s.`actual_days` WHERE c.`deleted` = b'0' AND (c.`actual_days` IS NULL OR c.`actual_days` = 0) AND s.`actual_days` IS NOT NULL; -- 4. æ ¸å¯¹ SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_salary_calculation' AND COLUMN_NAME IN ('work_days','actual_days','full_attendance_bonus','total_work_hours') ORDER BY ORDINAL_POSITION; SELECT COUNT(*) AS æå®åºå¤©æ°çæ ¸ç®åæ° FROM `hrm_salary_calculation` WHERE `deleted` = b'0' AND `actual_days` > 0; SELECT 'èªé ¬æ ¸ç® å ¨å¤å¥/å®åºå¤©æ° åæ®µåå§å宿' AS result; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/HrmSalaryCalculationRespVO.java
@@ -73,6 +73,10 @@ @ExcelProperty("å ¶ä»è¡¥è´´") private BigDecimal otherAllowance; @Schema(description = "å ¨å¤å¥", example = "200.00") @ExcelProperty("å ¨å¤å¥") private BigDecimal fullAttendanceBonus; @Schema(description = "ç¤¾ä¿æ£é¤") @ExcelProperty("ç¤¾ä¿æ£é¤") private BigDecimal socialSecurityDeduction; @@ -97,10 +101,14 @@ @ExcelProperty("å®åå·¥èµ") private BigDecimal actualSalary; @Schema(description = "åºå¤å¤©æ°") @ExcelProperty("åºå¤å¤©æ°") @Schema(description = "åºåºå¤©æ°") @ExcelProperty("åºåºå¤©æ°") private Integer workDays; @Schema(description = "å®åºå¤©æ°ï¼åèªè夿±æ»ï¼", example = "21") @ExcelProperty("å®åºå¤©æ°") private Integer actualDays; @Schema(description = "å çæ¶é¿") @ExcelProperty("å çæ¶é¿") private BigDecimal overtimeHours; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/HrmSalaryCalculationSaveReqVO.java
@@ -41,6 +41,12 @@ @NotNull(message = "åºæ¬å·¥èµä¸è½ä¸ºç©º") private BigDecimal baseSalary; @Schema(description = "å²ä½å·¥èµ") private BigDecimal postSalary; @Schema(description = "å·¥é¾å·¥èµ") private BigDecimal senioritySalary; @Schema(description = "绩æå·¥èµ") private BigDecimal performanceSalary; @@ -55,6 +61,9 @@ @Schema(description = "å ¶ä»è¡¥è´´") private BigDecimal otherAllowance; @Schema(description = "å ¨å¤å¥") private BigDecimal fullAttendanceBonus; @Schema(description = "ç¤¾ä¿æ£é¤") private BigDecimal socialSecurityDeduction; @@ -72,9 +81,12 @@ @NotNull(message = "å®åå·¥èµä¸è½ä¸ºç©º") private BigDecimal actualSalary; @Schema(description = "åºå¤å¤©æ°") @Schema(description = "åºåºå¤©æ°") private Integer workDays; @Schema(description = "å®åºå¤©æ°") private Integer actualDays; @Schema(description = "å çæ¶é¿") private BigDecimal overtimeHours; 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,11 @@ /** * å¹´æï¼æ ¼å¼ï¼yyyy-MM * * 注æï¼year_month æ¯ MySQL çä¿çåï¼YEAR_MONTH 为 interval åä½ï¼ï¼ * å¿ é¡»ç¨åå¼å·å 裹ï¼å¦å MyBatis-Plus æ¼åºç SQL ä¼è¯æ³é误ã */ @TableField("`year_month`") private String yearMonth; /** yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/HrmSalaryCalculationDO.java
@@ -91,6 +91,12 @@ * å ¶ä»è¡¥è´´ */ private BigDecimal otherAllowance; /** * å ¨å¤å¥ * * ä¸å ¶ä»æ´¥è´´ä¸è´ï¼ç±äººå·¥å¨æ ¸ç®åä¸ç»´æ¤ï¼é»è®¤ 0 */ private BigDecimal fullAttendanceBonus; /** * ç¤¾ä¿æ£é¤ @@ -123,11 +129,19 @@ private BigDecimal actualSalary; /** * åºå¤å¤©æ° * åºåºå¤©æ°ï¼ææç累计çåºåºå¤å¤©æ°ï¼æ æçæ¶åé 22ï¼ */ private Integer workDays; /** * å®åºå¤©æ° * * åèªè夿±æ»ï¼hrm_attendance_summary.actual_daysï¼ï¼æ æ±æ»è®°å½æ¶ä¸º 0ã * 说æï¼åãæçæ»å·¥æ¶ãåæ®µä¿çä½ä¸å使ç¨ï¼å岿°æ®ä¸å é¤ï¼ã */ private Integer actualDays; /** * å çæ¶é¿ */ private BigDecimal overtimeHours; 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.HrmAttendanceSummaryDO; 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; @@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSocialSecuritySchemeDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryStructureDO; import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmLeaveApplicationMapper; import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceSummaryMapper; 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; @@ -114,6 +116,8 @@ private HrmEmployeeScheduleMapper employeeScheduleMapper; @Resource private HrmShiftMapper shiftMapper; @Resource private HrmAttendanceSummaryMapper attendanceSummaryMapper; @Override public PageResult<HrmSalaryCalculationDO> getSalaryCalculationPage(HrmSalaryCalculationPageReqVO pageReqVO) { @@ -248,13 +252,25 @@ OvertimeSalary overtimeSalary = calculateOvertimeSalary(employee, employeeSalary, period, baseSalary); BigDecimal overtimePay = overtimeSalary.pay(); // ææç累计åºå¤å¤©æ°ä¸æçæ»å·¥æ¶ï¼æ æçæ¶åºå¤å¤©æ°åéé»è®¤ 22ï¼ // ææç累计åºåºå¤©æ°ä¸æçæ»å·¥æ¶ï¼æ æçæ¶åºåºå¤©æ°åéé»è®¤ 22ï¼ ScheduleStat scheduleStat = calculateScheduleStat(employeeId, period); Integer workDays = scheduleStat.scheduledDays() > 0 ? scheduleStat.scheduledDays() : 22; BigDecimal totalWorkHours = scheduleStat.totalWorkHours(); // åºåå·¥èµæ»é¢ // å®åºå¤©æ°ï¼åèªè夿±æ»ï¼æ æ±æ»è®°å½æ¶æ 0 å¤çï¼ Integer actualDays = 0; HrmAttendanceSummaryDO attendanceSummary = attendanceSummaryMapper.selectByUserIdAndYearMonth(employeeId, period); if (attendanceSummary != null && attendanceSummary.getActualDays() != null) { actualDays = attendanceSummary.getActualDays(); } // å ¨å¤å¥ï¼ä¸å ¶ä»æ´¥è´´ä¸è´ï¼ç±äººå·¥å¨æ ¸ç®åä¸ç»´æ¤ï¼æ°å»ºæ¶é»è®¤ 0 BigDecimal fullAttendanceBonus = BigDecimal.ZERO; // åºåå·¥èµæ»é¢ï¼æ¶å ¥é¡¹å£å¾å¿ é¡»ä¸ calcActualSalary ä¿æä¸è´ï¼ BigDecimal totalIncome = baseSalary.add(performanceSalary).add(postSalary).add(senioritySalary) .add(fullAttendanceBonus) .add(mealAllowance).add(transportAllowance).add(otherAllowance).add(overtimePay); // è·å社ä¿åºæ°ï¼åå·¥ç¤¾ä¿æ¡£æ¡ > åå·¥åºæ¬å·¥èµ @@ -319,15 +335,17 @@ .mealAllowance(mealAllowance) .transportAllowance(transportAllowance) .otherAllowance(otherAllowance) .fullAttendanceBonus(fullAttendanceBonus) .socialSecurityDeduction(socialSecurityDeduction) .housingFundDeduction(housingFundDeduction) .taxDeduction(taxDeduction) .otherDeduction(otherDeduction) .leaveDeduction(leaveDeduction) .actualSalary(actualSalary) .workDays(workDays) // ææç累计åºåºå¤å¤©æ°ï¼æ æçæ¶åé 22 .workDays(workDays) // åºåºå¤©æ°ï¼ææçç´¯è®¡ï¼æ æçæ¶åé 22 .actualDays(actualDays) // å®åºå¤©æ°ï¼åèªè夿±æ» .overtimeHours(overtimeSalary.hours()) .totalWorkHours(totalWorkHours) .totalWorkHours(totalWorkHours) // ä¿çåå²å段ï¼ä¸å¡å·²æ¹ç¨ actualDays .status(0) // å¾ ç¡®è®¤ .build(); } @@ -700,6 +718,7 @@ calculation.setMealAllowance(nvl(calculation.getMealAllowance())); calculation.setTransportAllowance(nvl(calculation.getTransportAllowance())); calculation.setOtherAllowance(nvl(calculation.getOtherAllowance())); calculation.setFullAttendanceBonus(nvl(calculation.getFullAttendanceBonus())); calculation.setSocialSecurityDeduction(nvl(calculation.getSocialSecurityDeduction())); calculation.setHousingFundDeduction(nvl(calculation.getHousingFundDeduction())); calculation.setTaxDeduction(nvl(calculation.getTaxDeduction())); @@ -712,10 +731,16 @@ /** * 计ç®å®åå·¥èµ = æ¶å ¥é¡¹å计 - æ£é¤é¡¹å计ï¼ä¿ç两ä½å°æ° * * æ¶å ¥é¡¹å¿ é¡»ä¸ buildSalaryCalculation ä¸ totalIncome çå£å¾å®å ¨ä¸è´ï¼ * å¦åä¼åºç°ãæ°å»ºæ ¸ç®ç®å¾å¯¹ãä¿®æ¹ä¸æ¬¡æ ¸ç®åå®åå°±åå°ãçä¸ä¸è´ã */ private static BigDecimal calcActualSalary(HrmSalaryCalculationDO c) { BigDecimal income = nvl(c.getBaseSalary()) .add(nvl(c.getPostSalary())) .add(nvl(c.getSenioritySalary())) .add(nvl(c.getPerformanceSalary())) .add(nvl(c.getFullAttendanceBonus())) .add(nvl(c.getOvertimePay())) .add(nvl(c.getMealAllowance())) .add(nvl(c.getTransportAllowance()))