package com.engine.attendance.attendanceanalysis.wrapper; import com.engine.attendance.attendanceanalysis.dto.ClockPointDTO; import com.engine.attendance.attendanceanalysis.service.ComprehensiveWorkingHourService; import com.engine.attendance.attendanceanalysis.service.UtilService; import com.engine.attendance.attendanceanalysis.service.impl.ComprehensiveWorkingHourServiceImpl; import com.engine.attendance.attendanceanalysis.service.impl.UtilServiceImpl; import com.engine.attendance.enums.AttendanceItemTypeEnum; import com.engine.attendance.enums.CheckBoxEnum; import com.engine.common.util.CommonUtil; import com.engine.common.util.DateUtil; 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 org.apache.struts.tiles.xmlDefinition.I18nFactorySet; 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 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, List> dataList,List> attendanceItems,List> workHourItems,Map> clockInTimeMap){ log.info("***********analysis userId:{} start***********",userId); log.info("clockInTimeDate : [{}]",dataList); String beforeFourDayDate = DateUtil.getCurrentDateMinusDay(4); String beforeTwoDayDate = DateUtil.getCurrentDateMinusDay(2); String beforeOneDayDate = DateUtil.getCurrentDateMinusDay(1); String nowDate = DateUtil.getCurrentDate(); /** 打卡数据 */ 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",10); 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); //前一天打卡数据 log.info("getClockTimeParam : [{}]",getClockTimeParam); List> beforeOneDayClockInTimeList = utilService.getClockInTime(getClockTimeParam); log.info("beforeOneDayClockInTimeList : [{}]",beforeOneDayClockInTimeList); //分析前一天考勤 Map recordDataTime1 = analysis(userId,beforeOneDayDate,beforeOneDayClockInTimeList,schedulingResultsMap.get(beforeOneDayDate),attendanceItems,workHourItems); clockInTimeMap.put(beforeOneDayDate,recordDataTime1); getClockTimeParam.put("date",beforeTwoDayDate); //前第二天打卡数据 List> beforeTwoDayClockInTimeList = utilService.getClockInTime(getClockTimeParam); log.info("beforeTwoDayClockInTimeList : [{}]",beforeTwoDayClockInTimeList); //分析前第二天考勤 Map recordDataTime2 = analysis(userId,beforeTwoDayDate,beforeTwoDayClockInTimeList,schedulingResultsMap.get(beforeTwoDayDate),attendanceItems,workHourItems); 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){ log.info("***********analysis userId:{},analysisDate:{} start***********",userId,analysisDate); 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 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); //打卡数据 log.info("getClockTimeParam : [{}]",getClockTimeParam); List> clockInTimeList = utilService.getClockInTime(getClockTimeParam); Map recordDataTime = analysis(userId,analysisDate,clockInTimeList,schedulingResultsMap.get(analysisDate),attendanceItems,workHourItems); 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 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"))){ 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 = 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); log.info("recordAbnormalParam clcokInTimeList:{},attendanceItems size :{},scheduleResult :{},analysisDate:[{}],userId:[{}],rqlx:[{}],modeId:[{}]",clcokInTimeData, attendanceItems.size(),scheduleResult,analysisDate,userId,scheduleResult.get(0).get("rqlx")); /** * 计算是否考勤异常,是否有早退、迟到、漏卡的情况 * **/ 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.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); abnormalClockInListByEvction = abnormalClockInListByEvction.stream().filter(e-> (boolean)e.get("record")).collect(Collectors.toList()); 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()); } //休息班次,休息班打卡自动加班不算自动加班,且为正常 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()); } 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