package com.engine.jucailinkq.attendance.attendanceanalysis.wrapper; import com.engine.jucailinkq.attendance.attendanceanalysis.dto.clockpoint.ClockPointDTO; import com.engine.jucailinkq.attendance.attendanceanalysis.service.ComprehensiveWorkingHourService; import com.engine.jucailinkq.attendance.attendanceanalysis.service.UtilService; import com.engine.jucailinkq.attendance.attendanceanalysis.service.impl.ComprehensiveWorkingHourServiceImpl; import com.engine.jucailinkq.attendance.attendanceanalysis.service.impl.UtilServiceImpl; import com.engine.jucailinkq.attendance.enums.CheckBoxEnum; import com.engine.jucailinkq.attendance.enums.ClassSegmentTypeEnum; import com.engine.jucailinkq.common.util.CommonUtil; import com.engine.jucailinkq.common.util.DateUtil; import com.engine.common.util.ServiceUtil; import com.engine.jucailinkq.common.util.Utils; import com.engine.core.impl.Service; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import weaver.general.Util; import java.time.ZoneOffset; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 考勤分析主题逻辑 */ @Slf4j public class AttendanceAnalysisWrapper extends Service { private UtilService utilService = ServiceUtil.getService(UtilServiceImpl.class); private UpdateAttendanceResultWrapper updateAttendanceResultWrapper = ServiceUtil.getService(UpdateAttendanceResultWrapper.class); private ComprehensiveWorkingHourService comprehensiveWorkingHourService = ServiceUtil.getService(ComprehensiveWorkingHourServiceImpl.class); /** * 考勤分析主逻辑入口 * * @param userId 人员id * @param dataList 打卡数据 * @param attendanceItems 考勤项目 */ public void attendanceAnalysis(String userId, String nowDate, List> dataList, List> attendanceItems, List> workHourItems, Map> clockInTimeMap, List> attendaceResult) { log.info("***********analysis userId:{} start***********", userId); log.info("clockInTimeDate : [{}]", dataList); String beforeFourDayDate = DateUtil.beforeDay(nowDate, 4); String beforeTwoDayDate = DateUtil.beforeDay(nowDate, 2); String beforeOneDayDate = DateUtil.beforeDay(nowDate, 1); /** 打卡数据 */ Map>> collect = Maps.newHashMap(); if (dataList != null && dataList.size() > 0) { collect = dataList.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("signdate")))); } /** 获取人员班次*/ Map classesParamMap = Maps.newHashMap(); classesParamMap.put("tableName", "uf_pbjg"); classesParamMap.put("startDate", beforeFourDayDate); classesParamMap.put("endDate", nowDate); classesParamMap.put("pblx", "0"); classesParamMap.put("pbdx", userId); classesParamMap.put("current", "1"); classesParamMap.put("pageSize", 9999); classesParamMap.put("recurrence", 1); classesParamMap.put("clockInTimeMap", clockInTimeMap); classesParamMap.put("attendanceItems", attendanceItems); classesParamMap.put("clockInData", dataList); Map schedulMap = utilService.getSchedulingInFormation(classesParamMap); Map>> schedulingResultsMap = (Map>>) schedulMap.get("schedulingResultsMap"); /**计算获取前一天和第二天打卡数据*/ Map getClockTimeParam = Maps.newHashMap(); getClockTimeParam.put("date", beforeOneDayDate); getClockTimeParam.put("clockInTimeList", dataList); getClockTimeParam.put("clockInTimeCollect", collect); getClockTimeParam.put("schedulingResultCollect", schedulingResultsMap); getClockTimeParam.put("clockInTimeMap", clockInTimeMap); getClockTimeParam.put("userId", userId); Map>> attendaceResultMap = Maps.newHashMap(); if (attendaceResult != null && attendaceResult.size() > 0) { attendaceResultMap = attendaceResult.stream().collect(Collectors.groupingBy(e -> e.get("rq").toString())); } List> beforeOneDayDateattendaceResult = attendaceResultMap.get(beforeOneDayDate); if (beforeOneDayDateattendaceResult == null || beforeOneDayDateattendaceResult.size() == 0 || (!CheckBoxEnum.CHECKED.getKey().equals(beforeOneDayDateattendaceResult.get(0).get("sgsj")) && !"3".equals(beforeOneDayDateattendaceResult.get(0).get("sjzt")))) { //前一天打卡数据 List> beforeOneDayClockInTimeList = utilService.getClockInTime(getClockTimeParam); //分析前一天考勤 Map recordDataTime1 = analysis(userId, beforeOneDayDate, beforeOneDayClockInTimeList, schedulingResultsMap.get(beforeOneDayDate), attendanceItems, workHourItems,(Map)schedulMap.get("clockInTimeDataMap")); clockInTimeMap.put(beforeOneDayDate, recordDataTime1); } getClockTimeParam.put("date", beforeTwoDayDate); List> beforeTwoDayDateattendaceResult = attendaceResultMap.get(beforeTwoDayDate); if (beforeTwoDayDateattendaceResult == null || beforeTwoDayDateattendaceResult.size() == 0 || (!CheckBoxEnum.CHECKED.getKey().equals(beforeTwoDayDateattendaceResult.get(0).get("sgsj")) && !"3".equals(beforeTwoDayDateattendaceResult.get(0).get("sjzt")))) { //前第二天打卡数据 List> beforeTwoDayClockInTimeList = utilService.getClockInTime(getClockTimeParam); log.debug("beforeTwoDayClockInTimeList : [{}]", beforeTwoDayClockInTimeList); //分析前第二天考勤 Map recordDataTime2 = analysis(userId, beforeTwoDayDate, beforeTwoDayClockInTimeList, schedulingResultsMap.get(beforeTwoDayDate), attendanceItems, workHourItems,(Map)schedulMap.get("clockInTimeDataMap")); clockInTimeMap.put(beforeTwoDayDate, recordDataTime2); } } /** * 考勤分析主逻辑入口 * * @param userId 人员id * @param analysisDate 分析日期 * @param dataList 需要包含分析日期以及分析日期前后2天的3天打卡数据 * @param attendanceItems 人员考勤项目 */ public void attendanceAnalysisForApi(String userId, String analysisDate, List> dataList, List> attendanceItems, Map schedulMap, List> workHourItems, Map> clockInTimeMap,List> attendaceResult) { log.info("***********analysis userId:{},analysisDate:{} start***********", userId, analysisDate); log.info("clockInTimeDate : [{}]", dataList); log.info("attendaceResult : [{}]",attendaceResult); if (attendaceResult!=null && attendaceResult.size()>0 && (CheckBoxEnum.CHECKED.getKey().equals(attendaceResult.get(0).get("sgsj")) || "3".equals(attendaceResult.get(0).get("sjzt")))) { return; } Map>> collect = Maps.newHashMap(); if (dataList != null && dataList.size() > 0) { collect = dataList.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("signdate")))); } Map>> schedulingResultsMap = (Map>>) schedulMap.get("schedulingResultsMap"); Map getClockTimeParam = Maps.newHashMap(); getClockTimeParam.put("date", analysisDate); getClockTimeParam.put("clockInTimeList", dataList); getClockTimeParam.put("schedulingResultCollect", schedulingResultsMap); getClockTimeParam.put("clockInTimeMap", clockInTimeMap); getClockTimeParam.put("clockInTimeCollect", collect); getClockTimeParam.put("userId", userId); //打卡数据 List> clockInTimeList = utilService.getClockInTime(getClockTimeParam); Map recordDataTime = analysis(userId, analysisDate, clockInTimeList, schedulingResultsMap.get(analysisDate), attendanceItems, workHourItems,(Map)schedulMap.get("clockInTimeDataMap")); clockInTimeMap.put(analysisDate, recordDataTime); } /** * 分析数据 * * @param userId 分析人员 * @param analysisDate 分析日期 * @param clockInTimeList 打卡数据 * @param scheduleResult 班次 * @param attendanceItems 考勤项目 */ public Map analysis(String userId, String analysisDate, List> clockInTimeList, List> scheduleResult, List> attendanceItems, List> workHourItems ,Map clockInTimeDataMap) { Map recordParam = Maps.newHashMap(); Map formModeIdMap = Utils.getFormmodeIdMap(); recordParam.put("userId", userId); recordParam.put("analysisDate", analysisDate); recordParam.put("classInfo", scheduleResult); recordParam.put("formmodeIdMap", formModeIdMap); recordParam.put("attendanceDuration", 0); recordParam.put("modeId", formModeIdMap.get("uf_jcl_kq_cqjg")); Map workingHourparam = Maps.newHashMap(); workingHourparam.put("clockInTimeCollect", clockInTimeList); workingHourparam.put("analysisDate", analysisDate); workingHourparam.put("userId", userId); workingHourparam.put("attendanceItems", attendanceItems); workingHourparam.put("scheduleResult", scheduleResult); /** * 津贴 */ Map allowanceMap = updateAttendanceResultWrapper.allowanceHandle(recordParam); if (workHourItems != null && workHourItems.size() > 0) { workingHourparam.put("workHourItem", workHourItems.get(0)); String ifPriority = Util.null2String(workHourItems.get(0).get("hlpbyxsyzhgs")); //核算工时的日期类型 String hsgsdrqlx = Util.null2String(workHourItems.get(0).get("hsgsdrqlx")); String rqlx = Utils.getDateType(analysisDate, Util.null2String(workHourItems.get(0).get("qyrl"))); if (CheckBoxEnum.CHECKED.getKey().equals(ifPriority) && CommonUtil.ifContainStr(hsgsdrqlx, rqlx, ",")) { comprehensiveWorkingHourService.excuteByWorkHour(workingHourparam); return null; } } if (scheduleResult == null || scheduleResult.size() == 0) { //没有排班 Map params = Maps.newHashMap(); params.put("userId", userId); params.put("analysisDate", analysisDate); params.put("clockInTimeCollect", clockInTimeList); params.put("modeId", formModeIdMap.get("uf_jcl_kq_cqjg")); params.put("workHourItems", workHourItems); params.put("attendanceItems", attendanceItems); params.put("allowanceMap", allowanceMap); updateAttendanceResultWrapper.recordNoClass(params); return null; } recordParam.put("rqlx", scheduleResult.get(0).get("rqlx")); //休息班次,休息班打卡自动加班不算自动加班,扣除原有的工作时段 if (scheduleResult.get(0).get("sfxx") != null && CheckBoxEnum.CHECKED.getKey().equals(scheduleResult.get(0).get("sfxx")) && scheduleResult.get(0).get("xxbdkzdjb") != null && CheckBoxEnum.UNCHECKED.getKey().equals(scheduleResult.get(0).get("xxbdkzdjb"))) { List> overTimePlanList = scheduleResult.stream().filter(e->e.get("bdlx").equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())).collect(Collectors.toList()); if (overTimePlanList.size() >0){ scheduleResult = scheduleResult.stream().filter(e->ClassSegmentTypeEnum.OVERTIME_PLAN.getKey().equals(e.get("bdlx")) || Utils.ifRestClassSegment(e.get("bdlx").toString()) || Utils.ifAskforOrEvctionClassSegment(e.get("bdlx").toString())).collect(Collectors.toList()); }else { //没有加班计划,直接记为休息 updateAttendanceResultWrapper.recordRest(recordParam); return null; } } List> askForLeaveAndEvctionSchedule = Lists.newArrayList(); //请假记录 Map askForLeaveDataMap = updateAttendanceResultWrapper.getAskForLeave(workingHourparam); if (askForLeaveDataMap.get("alldayVaction") != null) { //全天请假 recordParam.put("cqzt", CheckBoxEnum.UNCHECKED.getKey()); recordParam.put("recordData", askForLeaveDataMap.get("alldayVaction")); utilService.recordItem(recordParam); return null; } askForLeaveAndEvctionSchedule.addAll((List>) askForLeaveDataMap.get("askForLeaveSchedule")); //出差记录 Map evectionDataMap = updateAttendanceResultWrapper.getEvection(workingHourparam); if (evectionDataMap.get("alldayEvection") != null) { //全天出差 recordParam.put("cqzt", CheckBoxEnum.UNCHECKED.getKey()); recordParam.put("recordData", evectionDataMap.get("alldayEvection")); utilService.recordItem(recordParam); return null; } askForLeaveAndEvctionSchedule.addAll((List>) evectionDataMap.get("evectionSchedule")); if (askForLeaveAndEvctionSchedule.size() > 0) { askForLeaveAndEvctionSchedule = mergeAskForLeaveAndEvctionSchedule(askForLeaveAndEvctionSchedule, analysisDate); } Map clcokInTimeDataParam = Maps.newHashMap(); clcokInTimeDataParam.put("analysisDate", analysisDate); clcokInTimeDataParam.put("scheduleResult", scheduleResult); clcokInTimeDataParam.put("clockInTimeList", clockInTimeList); clcokInTimeDataParam.put("askForLeaveAndEvctionSchedule", askForLeaveAndEvctionSchedule); //打卡卡点以及匹配的打卡时间 List clcokInTimeData = null; if (clockInTimeDataMap.get(analysisDate) != null){ clcokInTimeData = (List)clockInTimeDataMap.get(analysisDate); }else { clcokInTimeData = utilService.getClockInPointCmd(clcokInTimeDataParam); } Map recordAbnormalParam = Maps.newHashMap(); recordAbnormalParam.put("clcokInTimeData", clcokInTimeData); recordAbnormalParam.put("attendanceItems", attendanceItems); recordAbnormalParam.put("scheduleResult", scheduleResult); recordAbnormalParam.put("analysisDate", analysisDate); recordAbnormalParam.put("userId", userId); recordAbnormalParam.put("rqlx", scheduleResult.get(0).get("rqlx")); recordAbnormalParam.put("formmodeIdMap", formModeIdMap); /** * 计算是否考勤异常,是否有早退、迟到、漏卡的情况 * **/ recordAbnormalParam.put("askForLeaveList", askForLeaveDataMap.get("askForLeaveList")); recordAbnormalParam.put("askForLeaveItems", askForLeaveDataMap.get("askForLeaveItems")); recordAbnormalParam.put("evectionList", evectionDataMap.get("evectionList")); recordAbnormalParam.put("evectionItems", evectionDataMap.get("evectionItems")); List> abnormalClockInList = updateAttendanceResultWrapper.recordAbnormalClockIn(recordAbnormalParam); //需要记录的异常卡点 List> needRecordAbnormalClockInList = abnormalClockInList.stream().filter(e -> (boolean) e.get("record")).collect(Collectors.toList()); //不需要记录的异常卡点 List> notRecordAbnormalClockInList = abnormalClockInList.stream().filter(e -> !(boolean) e.get("record")).collect(Collectors.toList()); /** * 出勤津贴 */ recordAbnormalParam.put("abnormalClockInList", needRecordAbnormalClockInList); recordAbnormalParam.put("notRecordAbnormalClockInList", notRecordAbnormalClockInList); String ifnotWork = Util.null2String(allowanceMap.get("ifnotWork")); if (!"".equals(ifnotWork)) { //次日免班 recordParam.put("recordData", Lists.newArrayList()); recordParam.put("recordDataTime", Maps.newHashMap()); recordParam.put("attendanceDuration", scheduleResult.get(0).get("edsc").toString()); recordParam.put("cqzt", CheckBoxEnum.UNCHECKED.getKey()); utilService.recordItem(recordParam); return null; } if (!"".equals(Util.null2String(allowanceMap.get("delayMinute")))) { recordAbnormalParam.put("delayMinute", allowanceMap.get("delayMinute")); updateAttendanceResultWrapper.removeAbnormal(recordAbnormalParam); } /** * 请假 */ Map vactionMap = updateAttendanceResultWrapper.recordAskForLeave(recordAbnormalParam); List> abnormalClockInListByAskForLeave = (List>) vactionMap.get("abnormalClockInList"); List> vactionList = (List>) vactionMap.get("resultList"); recordAbnormalParam.put("offsetAskForLeaveAnomaly", vactionMap.get("offsetAskForLeaveAnomaly")); log.debug("请假后消除的异常 : [{}]", vactionMap.get("offsetAskForLeaveAnomaly")); /** * 出差、外出 */ recordAbnormalParam.put("abnormalClockInList", abnormalClockInListByAskForLeave); Map recordEvection = updateAttendanceResultWrapper.recordEvection(recordAbnormalParam); List> abnormalClockInListByEvction = (List>) recordEvection.get("abnormalClockInList"); List> evectionResultList = (List>) recordEvection.get("resultList"); recordAbnormalParam.put("abnormalClockInList", abnormalClockInListByEvction); recordAbnormalParam.put("offsetEvectionAnomaly", recordEvection.get("offsetEvectionAnomaly")); log.debug("出差外出后消除的异常 : [{}]", recordEvection.get("offsetEvectionAnomaly")); /** * 加班 * workOverTimeItemList:加班项目集合 * overTimeHolidayList:假期余额集合 * overTimeResultList:加班结果余额 */ Map recordWorkOverTime = updateAttendanceResultWrapper.recordWorkOverTime(recordAbnormalParam); /** * 计算出勤时长 */ double attendanceDuration = utilService.computeAttendanceDuration(recordAbnormalParam); /** * 入库 */ List> recordData = Lists.newArrayList(); recordData.addAll(vactionList); recordData.addAll(evectionResultList); abnormalClockInListByEvction = abnormalClockInListByEvction.stream().filter(e -> (boolean) e.get("record")).collect(Collectors.toList()); recordData.addAll(abnormalClockInListByEvction); List> workOverTimeItemList = (List>)recordWorkOverTime.get("workOverTimeItemList"); if (workOverTimeItemList.size() > 0){ recordData.addAll(workOverTimeItemList); } recordParam.put("recordData", recordData); recordParam.put("recordDataTime", utilService.getNeedRecordClockInTime(clcokInTimeData)); recordParam.put("attendanceDuration", attendanceDuration); recordParam.put("overTimeHolidayList",recordWorkOverTime.get("overTimeHolidayList") == null?Lists.newArrayList():recordWorkOverTime.get("overTimeHolidayList")); recordParam.put("overTimeResultList",recordWorkOverTime.get("overTimeResultList") == null?Lists.newArrayList():recordWorkOverTime.get("overTimeResultList")); log.info("recordParam : {}", recordParam); if (abnormalClockInListByEvction.size() > 0) { recordParam.put("cqzt", CheckBoxEnum.CHECKED.getKey()); } else { recordParam.put("cqzt", CheckBoxEnum.UNCHECKED.getKey()); } //休息班次,休息班打卡自动加班不算自动加班,且为正常 if (scheduleResult.get(0).get("sfxx") != null && CheckBoxEnum.CHECKED.getKey().equals(scheduleResult.get(0).get("sfxx"))) { recordParam.put("sfxx", CheckBoxEnum.CHECKED.getKey()); recordParam.put("cqzt", CheckBoxEnum.UNCHECKED.getKey()); recordParam.put("attendanceDuration", 0); } utilService.recordItem(recordParam); return (Map) recordParam.get("recordDataTime"); } /** * 合并请假或出差 * * @param askForLeaveAndEvctionSchedule * @param analysisDate * @return */ public List> mergeAskForLeaveAndEvctionSchedule(List> askForLeaveAndEvctionSchedule, String analysisDate) { askForLeaveAndEvctionSchedule = askForLeaveAndEvctionSchedule.stream().sorted(Comparator.comparing(e -> DateUtil.getTime(Utils.getkssjTime(e, analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); for (int i = 0; i < askForLeaveAndEvctionSchedule.size() - 1; i++) { String beforeDtkssj = askForLeaveAndEvctionSchedule.get(i).get("dtkssj").toString(); String beforeDtjssj = askForLeaveAndEvctionSchedule.get(i).get("dtjssj").toString(); for (int j = i + 1; j < askForLeaveAndEvctionSchedule.size(); j++) { String dtkssj = askForLeaveAndEvctionSchedule.get(j).get("dtkssj").toString(); String dtjssj = askForLeaveAndEvctionSchedule.get(j).get("dtjssj").toString(); if (beforeDtjssj.equals(dtkssj)) { askForLeaveAndEvctionSchedule.get(i).put("dtjssj", dtjssj); askForLeaveAndEvctionSchedule.get(i).put("jsdk", askForLeaveAndEvctionSchedule.get(j).get("jsdk")); askForLeaveAndEvctionSchedule.get(i).put("thfghlfzs", askForLeaveAndEvctionSchedule.get(j).get("thfghlfzs")); askForLeaveAndEvctionSchedule.remove(askForLeaveAndEvctionSchedule.get(j)); j--; i--; } } } return askForLeaveAndEvctionSchedule; } }