From 9697bac35fe2c74811afaf66f9cf28b758f3a386 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期五, 28 八月 2026 15:21:22 +0800
Subject: [PATCH] feat(hrm): 新增排班功能,薪酬核算按排班工时
---
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 49 insertions(+), 1 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 8be05ab..6cf8b19 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,8 @@
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.HrmEmployeeScheduleDO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmShiftDO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmEmployeeSalaryDO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmEmployeeSocialSecurityDO;
@@ -16,6 +18,8 @@
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.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.employee.HrmEmployeeMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmEmployeeSalaryMapper;
@@ -39,8 +43,11 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -96,6 +103,10 @@
private HrmSalaryPaymentMapper salaryPaymentMapper;
@Resource
private HrmSalaryPaymentDetailMapper salaryPaymentDetailMapper;
+ @Resource
+ private HrmEmployeeScheduleMapper employeeScheduleMapper;
+ @Resource
+ private HrmShiftMapper shiftMapper;
@Override
public PageResult<HrmSalaryCalculationDO> getSalaryCalculationPage(HrmSalaryCalculationPageReqVO pageReqVO) {
@@ -225,6 +236,11 @@
OvertimeSalary overtimeSalary = calculateOvertimeSalary(employee, employeeSalary, period, baseSalary);
BigDecimal overtimePay = overtimeSalary.pay();
+ // 鎸夋帓鐝疮璁″嚭鍕ゅぉ鏁颁笌鎺掔彮鎬诲伐鏃讹紙鏃犳帓鐝椂鍑哄嫟澶╂暟鍥為��榛樿 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);
@@ -295,8 +311,9 @@
.otherDeduction(otherDeduction)
.leaveDeduction(leaveDeduction)
.actualSalary(actualSalary)
- .workDays(22) // 榛樿宸ヤ綔鏃�
+ .workDays(workDays) // 鎸夋帓鐝疮璁″簲鍑哄嫟澶╂暟锛屾棤鎺掔彮鏃跺洖閫� 22
.overtimeHours(overtimeSalary.hours())
+ .totalWorkHours(totalWorkHours)
.status(0) // 寰呯‘璁�
.build();
}
@@ -401,6 +418,37 @@
private record OvertimeSalary(BigDecimal hours, BigDecimal pay) {}
+ private record ScheduleStat(int scheduledDays, BigDecimal totalWorkHours) {}
+
+ /**
+ * 鎸夋帓鐝〃绱鍛樺伐鐨勫嚭鍕ゅぉ鏁颁笌鎺掔彮鎬诲伐鏃躲��
+ * 浠呯粺璁℃湁鐝鐨勬帓鐝褰曪紝鐝鏍囧噯宸ユ椂涔嬪拰鍗充负鎺掔彮宸ユ椂銆�
+ */
+ private ScheduleStat calculateScheduleStat(Long employeeId, String period) {
+ YearMonth yearMonth = YearMonth.parse(period);
+ List<HrmEmployeeScheduleDO> schedules = employeeScheduleMapper.selectListByEmployeeIdAndPeriod(
+ employeeId, yearMonth.atDay(1), yearMonth.atEndOfMonth());
+ if (CollUtil.isEmpty(schedules)) {
+ return new ScheduleStat(0, BigDecimal.ZERO);
+ }
+ Set<Long> shiftIds = schedules.stream().map(HrmEmployeeScheduleDO::getShiftId)
+ .filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, HrmShiftDO> shiftMap = CollUtil.isEmpty(shiftIds) ? Collections.emptyMap()
+ : shiftMapper.selectBatchIds(shiftIds).stream()
+ .collect(Collectors.toMap(HrmShiftDO::getId, shift -> shift, (a, b) -> a));
+ int scheduledDays = 0;
+ BigDecimal totalWorkHours = BigDecimal.ZERO;
+ for (HrmEmployeeScheduleDO schedule : schedules) {
+ HrmShiftDO shift = schedule.getShiftId() == null ? null : shiftMap.get(schedule.getShiftId());
+ if (shift == null) {
+ continue;
+ }
+ scheduledDays++;
+ totalWorkHours = totalWorkHours.add(shift.getWorkHours() != null ? shift.getWorkHours() : BigDecimal.ZERO);
+ }
+ return new ScheduleStat(scheduledDays, totalWorkHours.setScale(2, RoundingMode.HALF_UP));
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public void confirmSalaryCalculation(List<Long> ids) {
--
Gitblit v1.9.3