Procházet zdrojové kódy

解决周日报历史数据一天或一周填写多次被多次统计问题

zhangjq před 1 rokem
rodič
revize
ab7597d71e

+ 14 - 0
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/constants/DictConstants.java

@@ -9,4 +9,18 @@ public class DictConstants {
      * 请假类型
      */
     public static final String WF_LEAVE_TYPE = "WF_LEAVE_TYPE";
+
+    /**
+     * 统计日报的部门
+     */
+    public static final String STATISTIC_DAILY_DEPT = "statistic_daily_dept";
+
+
+    /**
+     * 职能部门
+     */
+    public static final String FUNCTIONAL_DEPT = "functional_dept";
+
+
+
 }

+ 53 - 46
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/service/report/ReportServiceImpl.java

@@ -11,6 +11,7 @@ import com.zjugis.framework.common.pojo.CommonResult;
 import com.zjugis.framework.common.pojo.PageResult;
 import com.zjugis.framework.mybatis.core.query.LambdaQueryWrapperX;
 import com.zjugis.framework.security.core.util.SecurityFrameworkUtils;
+import com.zjugis.module.adm.constants.DictConstants;
 import com.zjugis.module.adm.controller.admin.attendance.vo.sheet.AttendanceSheetRelationWorkDay;
 import com.zjugis.module.adm.controller.admin.report.dto.report.ReportListQueryDTO;
 import com.zjugis.module.adm.controller.admin.report.dto.report.ReportPageReqDTO;
@@ -207,7 +208,7 @@ public class ReportServiceImpl implements ReportService {
         if ("daily".equals(reqVO.getReportType())) {
             queryWrapperX.betweenIfPresent(ReportDO::getReportStartDate, DateUtils.getStartDateTime(reqVO.getReportYear(), reqVO.getReportMonth()), DateUtils.getEndDateTime(reqVO.getReportYear(), reqVO.getReportMonth()));
         } else {
-            queryWrapperX.eqIfPresent(ReportDO::getReportYear, reqVO.getReportYear()).eqIfPresent(ReportDO::getReportMonth, reqVO.getReportMonth()).eqIfPresent(ReportDO::getReportWeek,reqVO.getReportWeek());
+            queryWrapperX.eqIfPresent(ReportDO::getReportYear, reqVO.getReportYear()).eqIfPresent(ReportDO::getReportMonth, reqVO.getReportMonth()).eqIfPresent(ReportDO::getReportWeek, reqVO.getReportWeek());
         }
         List<ReportRespVO> reportList = ReportConvert.INSTANCE.convertList(reportMapper.selectList(queryWrapperX));
         if (CollectionUtil.isEmpty(reportList)) {
@@ -349,17 +350,17 @@ public class ReportServiceImpl implements ReportService {
     /**
      * 获取员工工作报告Map(工作日且未请假)
      *
-     * @param reportType      报告类型
-     * @param year            年份
-     * @param month           月份
-     * @param deptId          部门Id
-     * @param userId          用户Id
-     * @param monthWorkDay    工作日
-     * @param allLeaveDayOrWeekMap  每个用户全天请假的日期数量/每个用户全周请假的日期数量
+     * @param reportType           报告类型
+     * @param year                 年份
+     * @param month                月份
+     * @param deptId               部门Id
+     * @param userId               用户Id
+     * @param monthWorkDay         当月工作日
+     * @param allLeaveDayOrWeekMap 每个用户整天请假的天数/整周请假的周数
      * @return
      */
     private Map<String, List<ReportDO>> getReport(String reportType, Short year, Short month, Set<String> deptId, String userId,
-                                                  List<WorkdayDO> monthWorkDay, Map<String,Integer> allLeaveDayOrWeekMap) {
+                                                  List<WorkdayDO> monthWorkDay, Map<String, Integer> allLeaveDayOrWeekMap) {
         LambdaQueryWrapper<ReportDO> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.select(ReportDO::getReportStartDate, ReportDO::getReportYear, ReportDO::getReportMonth, ReportDO::getReportWeek, ReportDO::getDeptId, ReportDO::getUserId, ReportDO::getId);
         queryWrapper.eq(ReportDO::getIsTemp, false);
@@ -378,46 +379,47 @@ public class ReportServiceImpl implements ReportService {
         }
         List<ReportDO> reportList = reportMapper.selectList(queryWrapper);
 
+        //1. 先统一过滤出工作日填写的周日报,并根据每个用户的填写日期/周去重,解决历史数据周日报填写多次被多次统计问题
         List<ReportDO> workDayReportList = new ArrayList<>();
-
-        //1. 先统一过滤出工作日填写的周日报
         if ("daily".equals(reportType)) {
-            Set<LocalDate> workDay = monthWorkDay.stream()
-                    .map(workday -> workday.getDateDay().toLocalDate()).collect(Collectors.toSet());
-            workDayReportList = reportList.stream().filter(report -> workDay.contains(report.getReportStartDate().toLocalDate())).collect(Collectors.toList());
+            Set<LocalDate> workDay = monthWorkDay.stream().map(workday -> workday.getDateDay().toLocalDate()).collect(Collectors.toSet());//工作日的日期集合
+            workDayReportList = reportList.stream().filter(report -> workDay.contains(report.getReportStartDate().toLocalDate()))
+                    .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getUserId() + "-" + c.getReportStartDate()))), ArrayList::new));
         } else {
-            Set<String> workWeek = monthWorkDay.stream().map(workday -> workday.getYear() + "-" + workday.getMonth() + "-" + workday.getWeek()).collect(Collectors.toCollection(HashSet::new));
+            Set<String> workWeek = monthWorkDay.stream().map(workday -> workday.getYear() + "-" + workday.getMonth() + "-" + workday.getWeek()).collect(Collectors.toCollection(HashSet::new));//工作周的周数集合
             workDayReportList = reportList.stream()
                     .filter(report -> {
                         String reportWeek = report.getReportYear() + "-" + report.getReportMonth() + "-" + report.getReportWeek();
                         return workWeek.contains(reportWeek);
-                    }).collect(Collectors.toList());
+                    }).collect(Collectors.collectingAndThen(Collectors.toCollection(
+                            () -> new TreeSet<>(Comparator.comparing(c -> c.getUserId() + "-" + c.getReportYear() + "-" + c.getReportMonth() + "-" + c.getReportWeek()))), ArrayList::new));
+
         }
 
         //获取用户请假数据Map
-        Map<String, List<AttendanceSheetRelationWorkDay>> userStatisticAttendanceData = attendanceSheetService.statisticAttendanceData(deptId, userId, year, month);
+        Map<String, List<AttendanceSheetRelationWorkDay>> userLeaveAttendanceDataMap = attendanceSheetService.statisticAttendanceData(deptId, userId, year, month);
 
 
-        //2. 针对每个用户,排除掉每个用户请假日/周填写的周日报
+        //2. 针对每个用户,排除掉每个用户请假日/周填写的周日报(防止有人请假填写的周日报计入统计中)
         Map<String, List<ReportDO>> reportMap = workDayReportList.stream().collect(Collectors.groupingBy(ReportDO::getUserId));
         for (String reportUserId : reportMap.keySet()) {
             List<ReportDO> userReportList = reportMap.get(reportUserId);
 
             //用户请假数据
-            List<AttendanceSheetRelationWorkDay> attendanceSheetDOS = userStatisticAttendanceData.get(reportUserId);
-
-            if (CollectionUtil.isEmpty(attendanceSheetDOS)) {
+            List<AttendanceSheetRelationWorkDay> userLeaveAttendanceDataList = userLeaveAttendanceDataMap.get(reportUserId);
+            if (CollectionUtil.isEmpty(userLeaveAttendanceDataList)) {
                 continue;
             }
 
-            int allLeaveDayOrWeekCount  = 0;
+            int allLeaveDayOrWeekCount = 0;//整周/整天请假的次数
             //判断整天请假/整周请假,并过滤
             if ("daily".equals(reportType)) {
                 Set<LocalDate> allLeaveDaySet = new HashSet<>();
-                Map<LocalDateTime, List<AttendanceSheetRelationWorkDay>> dayLeaveMap = attendanceSheetDOS.stream().collect(Collectors.groupingBy(AttendanceSheetRelationWorkDay::getAttendanceDate));
+                Map<LocalDateTime, List<AttendanceSheetRelationWorkDay>> dayLeaveMap = userLeaveAttendanceDataList.stream().collect(Collectors.groupingBy(AttendanceSheetRelationWorkDay::getAttendanceDate));
                 for (LocalDateTime date : dayLeaveMap.keySet()) {
+                    //对考勤类型去重,确保每半天最多只统计一次请假
                     Long leaveCount = dayLeaveMap.get(date).stream().filter(distinctByKey(c -> c.getAttendanceType())).collect(Collectors.counting());
-                    //次数大于等于2,说明上下午都请假,算整天请假
+                    //当天请假次数大于等于2,说明上下午都请假,算整天请假
                     if (leaveCount >= 2) {
                         allLeaveDaySet.add(date.toLocalDate());
                     }
@@ -429,15 +431,15 @@ public class ReportServiceImpl implements ReportService {
                 }
             } else {
                 Set<String> allLeaveWeekSet = new HashSet<>();
-                //每周的工作日数量
+                //每周的工作日列表Map
                 Map<String, List<WorkdayDO>> workDayCount = monthWorkDay.stream().collect(Collectors.groupingBy(c -> c.getYear() + "-" + c.getMonth() + "-" + c.getWeek()));
-                //每周的请假次数
-                Map<String, List<AttendanceSheetRelationWorkDay>> weekLeaveMap = attendanceSheetDOS.stream().collect(Collectors.groupingBy(c -> c.getYear() + "-" + c.getMonth() + "-" + c.getWeek()));
+                //每周的请假列表Map
+                Map<String, List<AttendanceSheetRelationWorkDay>> weekLeaveMap = userLeaveAttendanceDataList.stream().collect(Collectors.groupingBy(c -> c.getYear() + "-" + c.getMonth() + "-" + c.getWeek()));
                 for (String date : weekLeaveMap.keySet()) {
-                    List<WorkdayDO> workdayDOS = workDayCount.get(date);
                     Long leaveCount = weekLeaveMap.get(date).stream().collect(Collectors.counting());
+                    List<WorkdayDO> workdayList = workDayCount.get(date) == null ? new ArrayList<>() : workDayCount.get(date);
                     //如果该周请假的次数 >= 该周工作日 * 2 (上下午),则说明该周都请假
-                    if (leaveCount >= (workdayDOS == null ? 0 : workdayDOS.size() * 2)) {
+                    if (leaveCount >= workdayList.size() * 2) {
                         allLeaveWeekSet.add(date);
                     }
                 }
@@ -446,9 +448,7 @@ public class ReportServiceImpl implements ReportService {
                 if (CollectionUtil.isNotEmpty(allLeaveWeekSet)) {
                     userReportList = userReportList.stream().filter(c -> !allLeaveWeekSet.contains(c.getReportYear() + "-" + c.getReportMonth() + "-" + c.getReportWeek())).collect(Collectors.toList());
                 }
-
             }
-
             allLeaveDayOrWeekMap.put(reportUserId, allLeaveDayOrWeekCount);
 
             reportMap.put(reportUserId, userReportList);
@@ -457,6 +457,13 @@ public class ReportServiceImpl implements ReportService {
         return reportMap;
     }
 
+    /**
+     * 去重
+     *
+     * @param keyExtractor
+     * @param <T>
+     * @return
+     */
     private <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
         Set<Object> seen = ConcurrentHashMap.newKeySet();
         return t -> seen.add(keyExtractor.apply(t));
@@ -477,10 +484,10 @@ public class ReportServiceImpl implements ReportService {
     }
 
     /**
-     * 工作报告统计列表
+     * 用户工作报告统计列表
      *
      * @param reportStatisticReqDTO
-     * @return
+     * @return 每个用户统计结果
      */
     public List<ReportStatisticRespVO> getReportStatisticsList(ReportStatisticReqDTO reportStatisticReqDTO) {
         Short year = reportStatisticReqDTO.getYear();
@@ -518,22 +525,21 @@ public class ReportServiceImpl implements ReportService {
             userList = userList.stream().filter(user -> userId.equals(user.getId())).collect(Collectors.toList());
         }
 
-        //当月工作日
+        //获取当月工作日列表及工作日/周数量
         List<WorkdayDO> monthWorkDay = new ArrayList<>();
-        //计算应填数量 = 工作日或工作周数量
-        Integer shouldFillCount = 0;
+        Integer workDayOrWeekCount = 0;
         if ("daily".equals(reportType)) {
             monthWorkDay = workdayService.getMonthWorkDayNum(year, month);
-            shouldFillCount = monthWorkDay.size();
+            workDayOrWeekCount = monthWorkDay.size();
         } else {
             monthWorkDay = workdayService.getMonthWorkWeekNum(year, month);
-            shouldFillCount = (int) monthWorkDay.stream().map(WorkdayDO::getWeek).distinct().count();
+            workDayOrWeekCount = (int) monthWorkDay.stream().map(WorkdayDO::getWeek).distinct().count();
         }
 
-        //获取人员工作报告Map(工作日/周且未整天/整周请假)
-        Map<String,Integer> allLeaveDayOrWeekMap  = new HashMap<>();
 
-        Map<String,List<ReportDO>> staffReportMap = this.getReport(reportType, year, month, deptIds, userId, monthWorkDay,allLeaveDayOrWeekMap);
+        Map<String, Integer> allLeaveDayOrWeekMap = new HashMap<>(); //存放整天请假的天数/整周请假的周数
+        //获取人员工作报告Map(在工作日/周 且 未整天/整周请假 填写的周日报)
+        Map<String, List<ReportDO>> staffReportMap = this.getReport(reportType, year, month, deptIds, userId, monthWorkDay, allLeaveDayOrWeekMap);
 
         List<ReportStatisticRespVO> respList = new ArrayList<>();
         for (AdminUserRespDTO staff : userList) {
@@ -548,12 +554,13 @@ public class ReportServiceImpl implements ReportService {
             statisticRespVO.setDeptId(staff.getDeptId());
             statisticRespVO.setDeptName(staff.getDeptName());
 
+            //应填数量 = 工作日/周数量 - 请假天数/周数
             Integer leaveDays = allLeaveDayOrWeekMap.get(staff.getId()) == null ? 0 : allLeaveDayOrWeekMap.get(staff.getId());
-            statisticRespVO.setShouldFilledCount(shouldFillCount - leaveDays);
+            statisticRespVO.setShouldFilledCount(workDayOrWeekCount - leaveDays);
             List<ReportDO> staffReportList = staffReportMap.get(staff.getId());
             statisticRespVO.setFilledCount(staffReportList == null ? 0 : staffReportList.size());
             statisticRespVO.setNotFilledCount(statisticRespVO.getShouldFilledCount() - statisticRespVO.getFilledCount() < 0 ? 0 : statisticRespVO.getShouldFilledCount() - statisticRespVO.getFilledCount());
-            statisticRespVO.setFillRate(statisticRespVO.getFilledCount() * 1.0 / shouldFillCount > 1 ? 1 : statisticRespVO.getFilledCount() * 1.0 / statisticRespVO.getShouldFilledCount());
+            statisticRespVO.setFillRate(statisticRespVO.getFilledCount() * 1.0 / statisticRespVO.getShouldFilledCount() > 1 ? 1 : statisticRespVO.getFilledCount() * 1.0 / statisticRespVO.getShouldFilledCount());
 
             respList.add(statisticRespVO);
         }
@@ -609,8 +616,8 @@ public class ReportServiceImpl implements ReportService {
         functionalDept.setName("职能部门");
         deptList.add(functionalDept);
 
-        //获取职能部门下属部门,并将职能部门下属部门parentId设置为父部门为001
-        List<DictDataRespDTO> functionalDeptList = dictApi.getDictDataList("functional_dept").getData();
+        //获取职能部门下属部门,并将职能部门下属部门parentId设置为职能部门001
+        List<DictDataRespDTO> functionalDeptList = dictApi.getDictDataList(DictConstants.FUNCTIONAL_DEPT).getData();
         List<String> functionalDeptIdList = functionalDeptList.stream().map(DictDataRespDTO::getValue).collect(Collectors.toList());
         for (DeptRespDTO dept : deptList) {
             if (functionalDeptIdList.contains(dept.getId())) {
@@ -619,7 +626,7 @@ public class ReportServiceImpl implements ReportService {
         }
 
         //获取统计日报的部门(市场部门)
-        List<DictDataRespDTO> dailyReportDeptList = dictApi.getDictDataList("statistic_daily_dept").getData();
+        List<DictDataRespDTO> dailyReportDeptList = dictApi.getDictDataList(DictConstants.STATISTIC_DAILY_DEPT).getData();
         List<String> dailyReportDeptIdList = dailyReportDeptList.stream().map(DictDataRespDTO::getValue).collect(Collectors.toList());
 
         //获取每个用户周报统计结果