From 578f84ece732a710278e7914396e127d8a27ed8a Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期日, 08 十一月 2026 10:05:18 +0800
Subject: [PATCH] feat(hrm): 排班管理联动已审批请假

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmEmployeeScheduleServiceImpl.java |   87 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 86 insertions(+), 1 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmEmployeeScheduleServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmEmployeeScheduleServiceImpl.java
index 2c597c6..15f64c2 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmEmployeeScheduleServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmEmployeeScheduleServiceImpl.java
@@ -6,14 +6,19 @@
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveRespVO;
+import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleLeaveRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleListReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleSaveReqVO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmLeaveApplicationDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO;
 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.mysql.approval.HrmLeaveApplicationMapper;
 import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum;
+import cn.iocoder.yudao.module.hrm.enums.HrmLeaveTypeEnum;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 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.employee.HrmEmployeeMapper;
@@ -26,6 +31,7 @@
 
 import java.time.DayOfWeek;
 import java.time.LocalDate;
+import java.time.LocalTime;
 import java.time.YearMonth;
 import java.util.*;
 import java.util.function.Function;
@@ -53,6 +59,8 @@
     private DeptApi deptApi;
     @Resource
     private HrmAttendanceHolidayService attendanceHolidayService;
+    @Resource
+    private HrmLeaveApplicationMapper leaveApplicationMapper;
 
     @Override
     public List<HrmEmployeeScheduleRespVO> getScheduleList(HrmEmployeeScheduleListReqVO reqVO) {
@@ -191,12 +199,20 @@
                 .collect(Collectors.toMap(HrmAttendanceHolidayDO::getDate, HrmAttendanceHolidayDO::getType,
                         (a, b) -> a));
 
-        // 5. 鎸夋棩鏈熼�愬ぉ鐢熸垚鎺掔彮锛氫紤鎭棩鍒犻櫎鍘熺彮娆★紝宸ヤ綔鏃� upsert
+        // 5. 棰勫姞杞界洰鏍囧憳宸ョ殑宸插鎵硅鍋囷細璇峰亣褰撳ぉ璺宠繃锛屼笉鎺掔彮涔熶笉娓呴櫎宸叉湁鎺掔彮
+        Map<Long, Set<LocalDate>> leaveDateMap = buildLeaveDateMap(employees,
+                reqVO.getStartDate(), reqVO.getEndDate());
+
+        // 6. 鎸夋棩鏈熼�愬ぉ鐢熸垚鎺掔彮锛氫紤鎭棩鍒犻櫎鍘熺彮娆★紝宸ヤ綔鏃� upsert
         int itemCount = 0;
         for (LocalDate date = reqVO.getStartDate(); !date.isAfter(reqVO.getEndDate()); date = date.plusDays(1)) {
             boolean rest = isRestDay(date, reqVO.getRestMode(), holidayTypeMap.get(date))
                     || reqVO.getShiftId() == null;
             for (HrmEmployeeDO employee : employees) {
+                // 鍛樺伐褰撳ぉ鍦ㄨ鍋囨湡鍐咃紝淇濇寔鍘熸帓鐝笉鍔�
+                if (leaveDateMap.getOrDefault(employee.getId(), Collections.emptySet()).contains(date)) {
+                    continue;
+                }
                 HrmEmployeeScheduleDO existing = existingMap.get(scheduleKey(employee.getId(), date));
                 if (rest) {
                     if (existing != null) {
@@ -226,6 +242,75 @@
         return respVO;
     }
 
+    @Override
+    public List<HrmEmployeeScheduleLeaveRespVO> getApprovedLeaveList(LocalDate startDate, LocalDate endDate) {
+        if (startDate == null || endDate == null || endDate.isBefore(startDate)) {
+            return Collections.emptyList();
+        }
+        List<HrmLeaveApplicationDO> leaves = leaveApplicationMapper.selectApprovedListByTimeRange(
+                startDate.atStartOfDay(), endDate.atTime(LocalTime.MAX), null);
+        if (CollUtil.isEmpty(leaves)) {
+            return Collections.emptyList();
+        }
+        Set<Long> userIds = leaves.stream().map(HrmLeaveApplicationDO::getUserId)
+                .filter(Objects::nonNull).collect(Collectors.toSet());
+        Map<Long, HrmEmployeeDO> userEmployeeMap = CollUtil.isEmpty(userIds) ? Collections.emptyMap()
+                : employeeMapper.selectList(new LambdaQueryWrapperX<HrmEmployeeDO>()
+                        .in(HrmEmployeeDO::getUserId, userIds)).stream()
+                .filter(employee -> employee.getUserId() != null)
+                .collect(Collectors.toMap(HrmEmployeeDO::getUserId, Function.identity(), (a, b) -> a));
+        return leaves.stream().map(leave -> {
+            HrmEmployeeDO employee = userEmployeeMap.get(leave.getUserId());
+            if (employee == null) {
+                return null;
+            }
+            HrmEmployeeScheduleLeaveRespVO respVO = new HrmEmployeeScheduleLeaveRespVO();
+            respVO.setId(leave.getId());
+            respVO.setEmployeeId(employee.getId());
+            respVO.setEmployeeName(employee.getName());
+            respVO.setLeaveType(leave.getLeaveType());
+            respVO.setLeaveTypeName(HrmLeaveTypeEnum.getNameByStatus(leave.getLeaveType()));
+            respVO.setStartTime(leave.getStartTime());
+            respVO.setEndTime(leave.getEndTime());
+            respVO.setDuration(leave.getDuration());
+            return respVO;
+        }).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
+    /**
+     * 鏋勫缓銆屽憳宸D -> 璇峰亣鏃ラ泦鍚堛�嶆槧灏勶紙鍙彇瀹℃壒閫氳繃鐨勮鍋囷紝涓旇鍓埌鎺掔彮鏃ユ湡鑼冨洿鍐咃級
+     */
+    private Map<Long, Set<LocalDate>> buildLeaveDateMap(List<HrmEmployeeDO> employees,
+                                                        LocalDate startDate, LocalDate endDate) {
+        Map<Long, HrmEmployeeDO> userEmployeeMap = employees.stream()
+                .filter(employee -> employee.getUserId() != null)
+                .collect(Collectors.toMap(HrmEmployeeDO::getUserId, Function.identity(), (a, b) -> a));
+        if (userEmployeeMap.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        List<HrmLeaveApplicationDO> leaves = leaveApplicationMapper.selectApprovedListByTimeRange(
+                startDate.atStartOfDay(), endDate.atTime(LocalTime.MAX), userEmployeeMap.keySet());
+        if (CollUtil.isEmpty(leaves)) {
+            return Collections.emptyMap();
+        }
+        Map<Long, Set<LocalDate>> result = new HashMap<>();
+        for (HrmLeaveApplicationDO leave : leaves) {
+            HrmEmployeeDO employee = userEmployeeMap.get(leave.getUserId());
+            if (employee == null || leave.getStartTime() == null || leave.getEndTime() == null) {
+                continue;
+            }
+            LocalDate from = leave.getStartTime().toLocalDate().isBefore(startDate)
+                    ? startDate : leave.getStartTime().toLocalDate();
+            LocalDate to = leave.getEndTime().toLocalDate().isAfter(endDate)
+                    ? endDate : leave.getEndTime().toLocalDate();
+            Set<LocalDate> dates = result.computeIfAbsent(employee.getId(), key -> new HashSet<>());
+            for (LocalDate date = from; !date.isAfter(to); date = date.plusDays(1)) {
+                dates.add(date);
+            }
+        }
+        return result;
+    }
+
     private Set<Long> getSelfAndChildDeptIds(Long deptId) {
         Set<Long> deptIds = new LinkedHashSet<>();
         deptIds.add(deptId);

--
Gitblit v1.9.3