From ef3cbc1c6882786e8218b08be3e52ea44587f03b Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期日, 08 十一月 2026 09:45:42 +0800
Subject: [PATCH] feat(hrm): 请假批量导入、加班代申请人、批量排班与节假日区间联动

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceSummaryServiceImpl.java |   46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceSummaryServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceSummaryServiceImpl.java
index 67eb1ef..847ae29 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceSummaryServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceSummaryServiceImpl.java
@@ -1,15 +1,18 @@
 package cn.iocoder.yudao.module.hrm.service.attendance;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceSummaryPageReqVO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceSummaryDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
 import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceRecordMapper;
 import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceSummaryMapper;
 import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceClockTypeEnum;
+import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum;
 import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
@@ -18,9 +21,12 @@
 import org.springframework.validation.annotation.Validated;
 
 import java.math.BigDecimal;
+import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.YearMonth;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 鑰冨嫟缁熻姹囨�� Service 瀹炵幇绫�
@@ -154,12 +160,28 @@
 
     /**
      * 璁$畻搴斿嚭鍕ゅぉ鏁帮紙宸ヤ綔鏃ユ暟閲忥級
+     *
+     * 涓�娆″彇鍑哄尯闂村唴鑺傚亣鏃ラ厤缃紝閬垮厤閫愭棩鏌ヨ銆�
      */
     private int calculateWorkDays(LocalDate startDate, LocalDate endDate) {
+        Map<LocalDate, Integer> holidayTypeMap = attendanceHolidayService
+                .getAttendanceHolidayListByDateRange(startDate, endDate)
+                .stream()
+                .collect(Collectors.toMap(HrmAttendanceHolidayDO::getDate, HrmAttendanceHolidayDO::getType,
+                        (a, b) -> a));
         int workDays = 0;
         LocalDate current = startDate;
         while (!current.isAfter(endDate)) {
-            if (attendanceHolidayService.isWorkDay(current)) {
+            Integer holidayType = holidayTypeMap.get(current);
+            boolean work;
+            if (holidayType != null) {
+                // 鏈夎妭鍋囨棩閰嶇疆鏃舵寜閰嶇疆鍒ゆ柇锛氫紤鎭棩涓嶇畻搴斿嚭鍕わ紝宸ヤ綔鏃ヨ鍏ワ紙鍚皟浼戜笂鐝殑鍛ㄦ湯锛�
+                work = HrmAttendanceHolidayTypeEnum.WORK_DAY.getType().equals(holidayType);
+            } else {
+                DayOfWeek dayOfWeek = current.getDayOfWeek();
+                work = dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
+            }
+            if (work) {
                 workDays++;
             }
             current = current.plusDays(1);
@@ -167,8 +189,28 @@
         return workDays;
     }
 
+    /**
+     * 鑺傚亣鏃ラ厤缃彉鏇村悗锛屽凡鏈夋眹鎬荤殑搴斿嚭鍕ゅぉ鏁颁細涓庢渶鏂伴厤缃笉涓�鑷淬��
+     * 鏌ヨ姹囨�绘椂鎸夋渶鏂拌妭鍋囨棩閲嶇畻涓�娆″苟鍥炲啓锛屼繚璇併�屽簲鍑哄嫟澶╂暟銆嶅缁堝叧鑱旇妭鍋囨棩閰嶇疆銆�
+     */
+    private void refreshWorkDaysOfMonth(String yearMonth) {
+        if (StrUtil.isBlank(yearMonth)) {
+            return;
+        }
+        try {
+            YearMonth ym = YearMonth.parse(yearMonth);
+            attendanceSummaryMapper.updateWorkDaysByYearMonth(yearMonth,
+                    calculateWorkDays(ym.atDay(1), ym.atEndOfMonth()));
+        } catch (Exception ex) {
+            // 鍒锋柊澶辫触涓嶅奖鍝嶆煡璇㈡湰韬紝璁板綍鏃ュ織鍗冲彲
+            log.warn("[refreshWorkDaysOfMonth][yearMonth({}) 鍒锋柊搴斿嚭鍕ゅぉ鏁板け璐", yearMonth, ex);
+        }
+    }
+
     @Override
     public PageResult<HrmAttendanceSummaryDO> getAttendanceSummaryPage(HrmAttendanceSummaryPageReqVO pageReqVO) {
+        // 鏌ヨ鍓嶆寜鏈�鏂拌妭鍋囨棩閲嶇畻璇ユ湀搴斿嚭鍕ゅぉ鏁�
+        refreshWorkDaysOfMonth(pageReqVO.getYearMonth());
         return attendanceSummaryMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<HrmAttendanceSummaryDO>()
                 .eqIfPresent(HrmAttendanceSummaryDO::getUserId, pageReqVO.getUserId())
                 .eqIfPresent(HrmAttendanceSummaryDO::getDeptId, pageReqVO.getDeptId())
@@ -184,6 +226,8 @@
 
     @Override
     public List<HrmAttendanceSummaryDO> getDeptMonthlySummaryList(Long deptId, String yearMonth) {
+        // 鏌ヨ鍓嶆寜鏈�鏂拌妭鍋囨棩閲嶇畻璇ユ湀搴斿嚭鍕ゅぉ鏁�
+        refreshWorkDaysOfMonth(yearMonth);
         return attendanceSummaryMapper.selectListByDeptIdAndYearMonth(deptId, yearMonth);
     }
 

--
Gitblit v1.9.3