package com.engine.attendance.attendanceanalysis.wrapper; import com.engine.attendance.attendanceanalysis.service.ForgetClockInService; import com.engine.attendance.attendanceanalysis.service.UtilService; import com.engine.attendance.attendanceanalysis.service.impl.ForgetClockInServiceImpl; import com.engine.attendance.attendanceanalysis.service.impl.UtilServiceImpl; import com.engine.attendance.enums.CheckBoxEnum; import com.engine.attendance.enums.ClassSegmentTypeEnum; import com.engine.common.util.DateUtil; import com.engine.common.util.DbTools; import com.engine.common.util.ServiceUtil; import com.engine.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.HashMap; 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 ForgetClockInService forgetClockInService = ServiceUtil.getService(ForgetClockInServiceImpl.class); private UpdateAttendanceResultWrapper updateAttendanceResultWrapper = ServiceUtil.getService(UpdateAttendanceResultWrapper.class); /** * 考勤分析主逻辑入口 * @param userId 人员id * @param dataList 打卡日期 * @param attendanceItems 考勤项目 */ public void attendanceAnalysis(String userId, List> dataList,List> attendanceItems){ log.info("***********analysis userId:{} start***********",userId); log.info("clockInTimeDate : [{}]",dataList); String beforeThreeDayDate = DateUtil.getCurrentDateMinusDay(3); String beforeTwoDayDate = DateUtil.getCurrentDateMinusDay(2); String beforeOneDayDate = DateUtil.getCurrentDateMinusDay(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",beforeThreeDayDate); classesParamMap.put("endDate",beforeOneDayDate); classesParamMap.put("pblx","0"); classesParamMap.put("pbdx",userId); classesParamMap.put("current","1"); classesParamMap.put("pageSize",10); classesParamMap.put("recurrence",1); classesParamMap.put("attendanceItems",attendanceItems); Map schedulMap = utilService.getSchedulingInFormation(classesParamMap); Map>> schedulingResultsMap = (Map>>)schedulMap.get("schedulingResultsMap"); Map>> schedulingMapBydate = (Map>>)schedulMap.get("schedulingMapBydate"); /**计算获取前一天和第二天打卡数据*/ Map getClockTimeParam = Maps.newHashMap(); getClockTimeParam.put("date",beforeOneDayDate); getClockTimeParam.put("clockInTimeCollect",collect); getClockTimeParam.put("schedulingResultCollect",schedulingResultsMap); //前一天打卡数据 log.info("getClockTimeParam : [{}]",getClockTimeParam); List> beforeOneDayClockInTimeList = utilService.getClockInTime(getClockTimeParam); log.info("beforeOneDayClockInTimeList : [{}]",beforeOneDayClockInTimeList); //分析前一天考勤 analysis(userId,beforeOneDayDate,beforeOneDayClockInTimeList,schedulingResultsMap.get(beforeOneDayDate),attendanceItems,schedulingMapBydate.get(beforeOneDayDate)); getClockTimeParam.put("date",beforeTwoDayDate); //前第二天打卡数据 List> beforeTwoDayClockInTimeList = utilService.getClockInTime(getClockTimeParam); log.info("beforeTwoDayClockInTimeList : [{}]",beforeTwoDayClockInTimeList); //分析前第二天考勤 analysis(userId,beforeTwoDayDate,beforeTwoDayClockInTimeList,schedulingResultsMap.get(beforeTwoDayDate),attendanceItems,schedulingMapBydate.get(beforeTwoDayDate)); } /** * 考勤分析主逻辑入口 * @param userId 人员id * @param analysisDate 分析日期 * @param dataList 需要包含分析日期以及分析日期前后2天的3天打卡数据 * @param attendanceItems 人员考勤项目 */ public void attendanceAnalysisForApi(String userId,String analysisDate, List> dataList,List> attendanceItems,Map schedulMap){ log.info("***********analysis userId:{} start***********",userId); log.info("clockInTimeDate : [{}]",dataList); 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>> schedulingMapBydate = (Map>>)schedulMap.get("schedulingMapBydate"); /**计算获取前一天和第二天打卡数据*/ Map getClockTimeParam = Maps.newHashMap(); getClockTimeParam.put("date",analysisDate); getClockTimeParam.put("clockInTimeCollect",collect); getClockTimeParam.put("schedulingResultCollect",schedulingResultsMap); //前一天打卡数据 log.info("getClockTimeParam : [{}]",getClockTimeParam); List> clockInTimeList = utilService.getClockInTime(getClockTimeParam); analysis(userId,analysisDate,clockInTimeList,schedulingResultsMap.get(analysisDate),attendanceItems,schedulingMapBydate.get(analysisDate)); } /** * 分析数据 * @param userId 分析人员 * @param analysisDate 分析日期 * @param clockInTimeList 打卡数据 * @param scheduleResult 班次 * @param attendanceItems 考勤项目 */ public void analysis(String userId,String analysisDate,List> clockInTimeList,List> scheduleResult,List> attendanceItems,List> scheduleList){ 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")); if (scheduleResult == null || scheduleResult.size() ==0){ //没有排班 Map params = Maps.newHashMap(); params.put("userId",userId); params.put("analysisDate",analysisDate); params.put("modeId",formModeIdMap.get("uf_jcl_kq_cqjg")); params.put("scheduleList",scheduleList); updateAttendanceResultWrapper.recordNoClass(params); return; } recordParam.put("rqlx",scheduleResult.get(0).get("rqlx")); List> needClockInSchedule = scheduleResult.stream().filter(e -> "1".equals(e.get("ksdk")) || "1".equals(e.get("jsdk"))).collect(Collectors.toList()); if(clockInTimeList == null || clockInTimeList.size() == 0){ if (needClockInSchedule.size() > 0){ //全天漏打卡 recordParam.put("cqzt",0); recordParam.put("recordData",forgetClockInService.forgetClockInAllDays()); utilService.recordItem(recordParam); return; } } //请假记录 String sql = "select a.qjry,a.jqlx,a.cxjqj,b.ksrq,b.kssj,b.jsrq,b.jssj,b.qjsc,b.qtj,b.btj from uf_jcl_kq_qjjl a left join uf_jcl_kq_qjjl_dt1 b on a.id = b.mainid where a.qjry=? and b.ksrq=? and (b.cxqj=0 or b.cxqj is null)"; List> askForLeaveList = DbTools.getSqlToList(sql,userId,analysisDate); log.info("askForLeaveList :{}",askForLeaveList); //考勤项目 Map> askForLeaveItems = Maps.newHashMap(); //出差记录 sql = "select b.ccr,a.cclx,a.ccsd,b.ksrq,b.jsrq,b.kssj,b.jssj,b.ccsc,b.qtcc,b.btcc,b.cxcc from uf_jcl_kq_ccjl a left join uf_jcl_kq_ccjl_dt1 b on a.id = b.mainid where b.ccr=? and b.ksrq=? and (b.cxcc=0 or b.cxcc is null)"; List> evectionList = DbTools.getSqlToList(sql,userId,analysisDate); log.info("evectionList :{}",evectionList); //出差项目 Map> evectionItems = Maps.newHashMap(); sql = "select hsl,hsdw,lgsbxydk,tqlghlfzs,fgsbxydk,thfghlfzs,tybcndbjlhbjs,zdycbcndfgzsd,zdycrqqjndxxb,zysd from uf_jcl_kq_kqxm where id=?"; List> askForLeaveAndEvctionSchedule = Lists.newArrayList(); for (Map askForLeaveData : askForLeaveList){ Map askForLeaveItem = DbTools.getSqlToMap(sql,askForLeaveData.get("jqlx")); //全天请假 if (CheckBoxEnum.CHECKED.getKey().equals(askForLeaveData.get("qtj"))){ List> resultList = Lists.newArrayList(); Map resultMap = Maps.newHashMap(); resultMap.put("item",askForLeaveData.get("jqlx")); resultMap.put("itemduration",scheduleResult.get(0).get("edsc")); resultList.add(resultMap); recordParam.put("cqzt",CheckBoxEnum.UNCHECKED.getKey()); recordParam.put("recordData",resultList); utilService.recordItem(recordParam); return; } askForLeaveItems.put(askForLeaveData.get("jqlx").toString(),askForLeaveItem); List> finalScheduleResult = scheduleResult; Map askForLeaveMap = new HashMap(){{ put("bcxx", finalScheduleResult.get(0).get("bcxx")); put("bcsdxx", finalScheduleResult.get(0).get("bcsdxx")); put("edsc", finalScheduleResult.get(0).get("edsc")); put("bdlx", ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey()); put("dtkssj",askForLeaveData.get("kssj")); put("dtjssj",askForLeaveData.get("jssj")); put("ksdk",askForLeaveItem.get("fgsbxydk")); put("jsdk",askForLeaveItem.get("lgsbxydk")); put("tqdkfzs","60"); put("thdkfzs","60"); put("tqlghlfzs",askForLeaveItem.get("tqlghlfzs")); put("thfghlfzs",askForLeaveItem.get("thfghlfzs")); }}; if (!"".equals(Util.null2String(askForLeaveData.get("kssj"))) && !"".equals(Util.null2String(askForLeaveData.get("jssj")))){ //scheduleResult.add(askForLeaveMap); askForLeaveAndEvctionSchedule.add(askForLeaveMap); } } for (Map evectionData :evectionList){ //全天出差 Map evectionItem = DbTools.getSqlToMap(sql,evectionData.get("cclx")); if (CheckBoxEnum.CHECKED.getKey().equals(evectionData.get("qtcc"))) { List> resultList = Lists.newArrayList(); Map resultMap = Maps.newHashMap(); resultMap.put("item", evectionData.get("cclx")); resultMap.put("itemduration", scheduleResult.get(0).get("edsc")); resultList.add(resultMap); recordParam.put("cqzt",CheckBoxEnum.UNCHECKED.getKey()); recordParam.put("recordData",resultList); utilService.recordItem(recordParam); return; } evectionItems.put(evectionData.get("cclx").toString(),evectionItem); List> finalScheduleResult1 = scheduleResult; Map evectionMap = new HashMap(){{ put("bcxx", finalScheduleResult1.get(0).get("bcxx")); put("bcsdxx", finalScheduleResult1.get(0).get("bcsdxx")); put("edsc", finalScheduleResult1.get(0).get("edsc")); put("bdlx", ClassSegmentTypeEnum.EVECTION.getKey()); put("dtkssj",evectionData.get("kssj")); put("dtjssj",evectionData.get("jssj")); put("ksdk",evectionItem.get("fgsbxydk")); put("jsdk",evectionItem.get("lgsbxydk")); put("tqdkfzs","60"); put("thdkfzs","60"); put("tqlghlfzs",evectionItem.get("tqlghlfzs")); put("thfghlfzs",evectionItem.get("thfghlfzs")); }}; if (!"".equals(Util.null2String(evectionData.get("kssj"))) && !"".equals(Util.null2String(evectionData.get("jssj")))){ //scheduleResult.add(evectionMap); askForLeaveAndEvctionSchedule.add(evectionMap); } } scheduleResult = scheduleResult.stream().sorted(Comparator.comparing(e->DateUtil.getTime(analysisDate+" "+e.get("dtkssj")).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); 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 = utilService.getClockInPointCmd(clcokInTimeDataParam); Map recordAbnormalParam = Maps.newHashMap(); recordAbnormalParam.put("clcokInTimeList",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); log.info("recordAbnormalParam clcokInTimeList:{},attendanceItems size :{},scheduleResult :{},analysisDate:[{}],userId:[{}],rqlx:[{}],modeId:[{}]",clcokInTimeData, attendanceItems.size(),scheduleResult,analysisDate,userId,scheduleResult.get(0).get("rqlx")); /** * 正常上下班入结果表 */ // // List> normalList= updateAttendanceResultWrapper.recordNormal(recordAbnormalParam); /** * 计算是否考勤异常,是否有早退、迟到、漏卡的情况 * **/ recordAbnormalParam.put("askForLeaveList",askForLeaveList); recordAbnormalParam.put("askForLeaveItems",askForLeaveItems); recordAbnormalParam.put("evectionList",evectionList); recordAbnormalParam.put("evectionItems",evectionItems); List> abnormalClockInList = updateAttendanceResultWrapper.recordAbnormalClockIn(recordAbnormalParam); /** * 请假 */ recordAbnormalParam.put("abnormalClockInList",abnormalClockInList); Map vactionMap = updateAttendanceResultWrapper.recordAskForLeave(recordAbnormalParam); List> abnormalClockInListByAskForLeave = (List>)vactionMap.get("abnormalClockInList"); List> vactionList = (List>)vactionMap.get("resultList"); recordAbnormalParam.put("offsetAskForLeaveAnomaly",vactionMap.get("offsetAskForLeaveAnomaly")); log.info("请假后消除的异常 : [{}]",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.info("出差外出后消除的异常 : [{}]",recordEvection.get("offsetEvectionAnomaly")); /** * 加班 */ List> recordWorkOverTime= updateAttendanceResultWrapper.recordWorkOverTime(recordAbnormalParam); /** * 计算出勤时长 */ double attendanceDuration = utilService.computeAttendanceDuration(recordAbnormalParam); /** * 入库 */ List> recordData = Lists.newArrayList(); recordData.addAll(vactionList); recordData.addAll(evectionResultList); recordData.addAll(abnormalClockInListByEvction); recordData.addAll(recordWorkOverTime); recordParam.put("recordData",recordData); recordParam.put("recordDataTime",utilService.getNeedRecordClockInTime(clcokInTimeData)); recordParam.put("attendanceDuration",attendanceDuration); log.info("recordParam : {}",recordParam); if (abnormalClockInListByEvction.size()>0){ recordParam.put("cqzt",CheckBoxEnum.CHECKED.getKey()); }else { recordParam.put("cqzt",CheckBoxEnum.UNCHECKED.getKey()); } utilService.recordItem(recordParam); } public List> mergeAskForLeaveAndEvctionSchedule(List> askForLeaveAndEvctionSchedule,String analysisDate){ askForLeaveAndEvctionSchedule = askForLeaveAndEvctionSchedule.stream().sorted(Comparator.comparing(e->DateUtil.getTime(analysisDate+" "+e.get("dtkssj")).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); for (int i=0;i