From d85ec778237cd9af68c8d6b96895d22e0cf158df Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期一, 02 十一月 2026 14:15:17 +0800
Subject: [PATCH] fix(hrm/system): 修复调岗申请与提交报错、公积金误扣、用户搜索,新增核算批量删除
---
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java | 88 ++++++++++++++++++++++++++++++++++++-------
1 files changed, 73 insertions(+), 15 deletions(-)
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
index 2d8be45..8c61cad 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
+++ b/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) {
@@ -239,38 +243,51 @@
// 閬垮厤鍛樺伐淇℃伅涓庤柂閰。妗堜笉涓�鑷存椂锛屾牳绠楃粨鏋滀笌鍛樺伐妗f瀵逛笉涓婏級
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;
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();
- // 搴斿彂宸ヨ祫鎬婚
- BigDecimal totalIncome = baseSalary.add(performanceSalary).add(mealAllowance)
- .add(transportAllowance).add(otherAllowance).add(overtimePay);
+ // 瀹炲嚭澶╂暟锛氬彇鑷�冨嫟姹囨�伙紙鏃犳眹鎬昏褰曟椂鎸� 0 澶勭悊锛�
+ Integer actualDays = 0;
+ HrmAttendanceSummaryDO attendanceSummary =
+ attendanceSummaryMapper.selectByUserIdAndYearMonth(employeeId, period);
+ if (attendanceSummary != null && attendanceSummary.getActualDays() != null) {
+ actualDays = attendanceSummary.getActualDays();
+ }
+
+ // 鍏ㄥ嫟濂栵細涓庡叾浠栨触璐翠竴鑷达紝鐢变汉宸ュ湪鏍哥畻鍗曚腑缁存姢锛屾柊寤烘椂榛樿 0
+ BigDecimal fullAttendanceBonus = BigDecimal.ZERO;
+
+ // 搴斿彂宸ヨ祫鎬婚锛堟敹鍏ラ」鍙e緞蹇呴』涓� calcActualSalary 淇濇寔涓�鑷达級
+ BigDecimal totalIncome = baseSalary.add(performanceSalary).add(postSalary).add(senioritySalary)
+ .add(fullAttendanceBonus)
+ .add(mealAllowance).add(transportAllowance).add(otherAllowance).add(overtimePay);
// 鑾峰彇绀句繚鍩烘暟锛氬憳宸ョぞ淇濇。妗� > 鍛樺伐鍩烘湰宸ヨ祫
BigDecimal socialSecurityBase = (socialSecurity != null && socialSecurity.getSocialSecurityBase() != null)
? socialSecurity.getSocialSecurityBase() : baseSalary;
- // 鑾峰彇鍏Н閲戝熀鏁帮細鍛樺伐绀句繚妗f > 鍛樺伐鍩烘湰宸ヨ祫
- BigDecimal housingFundBase = (socialSecurity != null && socialSecurity.getHousingFundBase() != null)
- ? socialSecurity.getHousingFundBase() : baseSalary;
-
- // 浠庢柟妗堜腑鑾峰彇缂寸撼姣斾緥锛堜紭鍏堜娇鐢ㄦ柟妗堜腑鐨勬瘮渚嬶紝鍚﹀垯浣跨敤榛樿姣斾緥锛�
+ // 浠庢柟妗堜腑鑾峰彇绀句繚缂寸撼姣斾緥锛堟柟妗堟湭閰嶇疆鏃跺洖閫�榛樿姣斾緥锛�
BigDecimal pensionPersonalRatio = (scheme != null && scheme.getPensionPersonalRatio() != null)
? scheme.getPensionPersonalRatio() : DEFAULT_PENSION_PERSONAL_RATIO;
BigDecimal medicalPersonalRatio = (scheme != null && scheme.getMedicalPersonalRatio() != null)
? scheme.getMedicalPersonalRatio() : DEFAULT_MEDICAL_PERSONAL_RATIO;
BigDecimal unemploymentPersonalRatio = (scheme != null && scheme.getUnemploymentPersonalRatio() != null)
? scheme.getUnemploymentPersonalRatio() : DEFAULT_UNEMPLOYMENT_PERSONAL_RATIO;
- BigDecimal housingFundPersonalRatio = (scheme != null && scheme.getHousingFundPersonalRatio() != null)
- ? scheme.getHousingFundPersonalRatio() : DEFAULT_HOUSING_FUND_PERSONAL_RATIO;
+
+ // 鍏Н閲戜釜浜烘瘮渚嬶細鍙彇鏂规閰嶇疆鍊硷紝涓嶅啀鍥為��榛樿姣斾緥銆�
+ // 鍚﹀垯銆屽叕鍙告病閰嶅叕绉噾鏂规銆嶆椂浼氳鎸夐粯璁� 12% 鎵f锛堣繖灏辨槸瀹㈡埛鍙嶉鐨勯棶棰橈級銆�
+ BigDecimal housingFundPersonalRatio = scheme != null ? scheme.getHousingFundPersonalRatio() : null;
// 绀句繚鎵i櫎 = 鍩烘暟 脳 (鍏昏�佷釜浜烘瘮渚� + 鍖荤枟涓汉姣斾緥 + 澶变笟涓汉姣斾緥)
BigDecimal socialSecurityDeduction = socialSecurityBase
@@ -279,8 +296,15 @@
.add(socialSecurityBase.multiply(unemploymentPersonalRatio))
.setScale(2, RoundingMode.HALF_UP);
- // 鍏Н閲戞墸闄� = 鍩烘暟 脳 鍏Н閲戜釜浜烘瘮渚�
- BigDecimal housingFundDeduction = housingFundBase.multiply(housingFundPersonalRatio).setScale(2, RoundingMode.HALF_UP);
+ // 鍏Н閲戞墸闄わ細蹇呴』鍚屾椂婊¤冻銆屾柟妗堥厤缃簡鍏Н閲戞瘮渚� > 0銆嶄笖銆屽憳宸ユ。妗堥厤缃簡鍏Н閲戝熀鏁� > 0銆嶆墠鎵f锛�
+ // 浠讳竴涓嶆弧瓒抽兘瑙嗕负鍏徃鏈即绾冲叕绉噾锛屾墸娆句负 0銆�
+ BigDecimal housingFundDeduction = BigDecimal.ZERO;
+ BigDecimal housingFundBase = socialSecurity != null ? socialSecurity.getHousingFundBase() : null;
+ if (housingFundPersonalRatio != null && housingFundPersonalRatio.signum() > 0
+ && housingFundBase != null && housingFundBase.signum() > 0) {
+ housingFundDeduction = housingFundBase.multiply(housingFundPersonalRatio)
+ .setScale(2, RoundingMode.HALF_UP);
+ }
// 璁$畻璇峰亣鎵f
BigDecimal leaveDeduction = calculateLeaveDeduction(employee, period, baseSalary);
@@ -310,19 +334,23 @@
.deptId(employee.getDeptId())
.baseSalary(baseSalary)
.performanceSalary(performanceSalary)
+ .postSalary(postSalary)
+ .senioritySalary(senioritySalary)
.overtimePay(overtimePay)
.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();
}
@@ -689,10 +717,13 @@
// 鍚﹀垯浼氬嚭鐜般�屽疄鍙戝伐璧勬寜 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()));
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()));
@@ -705,10 +736,16 @@
/**
* 璁$畻瀹炲彂宸ヨ祫 = 鏀跺叆椤瑰悎璁� - 鎵i櫎椤瑰悎璁★紝淇濈暀涓や綅灏忔暟
+ *
+ * 鏀跺叆椤瑰繀椤讳笌 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()))
@@ -841,4 +878,25 @@
salaryCalculationMapper.deleteById(id);
}
+ /**
+ * 鎵归噺鍒犻櫎鏍哥畻璁板綍锛堝叏閫夊悗涓�閿垹闄わ級
+ *
+ * 璇存槑锛氭寜涓氬姟瑕佹眰锛屾壒閲忓垹闄や笉闄愬埗鐘舵�侊紝鍕鹃�夊嵆鍒犮��
+ * 涓嶅瓨鍦ㄧ殑 ID 鐩存帴璺宠繃锛屼笉鎶ラ敊锛堥伩鍏嶅墠绔嬀閫夊垪琛ㄤ笌搴撲笉涓�鑷存椂鏁翠綋澶辫触锛夈��
+ */
+ @Override
+ public Integer deleteSalaryCalculationList(List<Long> ids) {
+ if (CollUtil.isEmpty(ids)) {
+ return 0;
+ }
+ List<Long> existIds = salaryCalculationMapper.selectBatchIds(ids).stream()
+ .map(HrmSalaryCalculationDO::getId)
+ .collect(Collectors.toList());
+ if (CollUtil.isEmpty(existIds)) {
+ return 0;
+ }
+ salaryCalculationMapper.deleteByIds(existIds);
+ return existIds.size();
+ }
+
}
--
Gitblit v1.9.3