diff --git a/src/com/engine/attendance/attendanceanalysis/service/ShiftService.java b/src/com/engine/attendance/attendanceanalysis/service/ShiftService.java new file mode 100644 index 0000000..76d39fb --- /dev/null +++ b/src/com/engine/attendance/attendanceanalysis/service/ShiftService.java @@ -0,0 +1,9 @@ +package com.engine.attendance.attendanceanalysis.service; + +import java.util.List; +import java.util.Map; + +public interface ShiftService { + + Map punchMatchShift(String empId, String schedulingResultId, List> clockInData); +} diff --git a/src/com/engine/attendance/attendanceanalysis/service/impl/ShiftServiceImpl.java b/src/com/engine/attendance/attendanceanalysis/service/impl/ShiftServiceImpl.java new file mode 100644 index 0000000..ab661f6 --- /dev/null +++ b/src/com/engine/attendance/attendanceanalysis/service/impl/ShiftServiceImpl.java @@ -0,0 +1,494 @@ +package com.engine.attendance.attendanceanalysis.service.impl; + +import com.engine.attendance.attendanceanalysis.dto.ClockPointDTO; +import com.engine.attendance.attendanceanalysis.service.ShiftService; +import com.engine.attendance.attendanceanalysis.service.UtilService; +import com.engine.attendance.attendanceanalysis.wrapper.UpdateAttendanceResultWrapper; +import com.engine.attendance.attendanceplan.service.AttendancePlanService; +import com.engine.attendance.attendanceplan.service.impl.AttendancePlanServiceImpl; +import com.engine.attendance.enums.CheckBoxEnum; +import com.engine.attendance.enums.ClassBelongToEnum; +import com.engine.attendance.enums.ClassSegmentTypeEnum; +import com.engine.attendance.enums.ClockPointEnum; +import com.engine.common.cmd.GetDateCmd; +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.*; +import java.util.stream.Collectors; + +/** + * @Author: sy + * @Description: 班次相关功能实现类 + * @Date: 2024/5/11 + **/ +@Slf4j +public class ShiftServiceImpl extends Service implements ShiftService { + private AttendancePlanService basicsetService = ServiceUtil.getService(AttendancePlanServiceImpl.class); + private UtilService utilService = ServiceUtil.getService(UtilServiceImpl.class); + private UpdateAttendanceResultWrapper updateAttendanceResultWrapper = ServiceUtil.getService(UpdateAttendanceResultWrapper.class); + /** + * 打卡匹配班次,返回班次id + * @param empId 打卡人员id + * @param schedulingResultId 排班结果主表数据id + * @param clockInData 需要包含分析日期以及分析日期前后2天的3天原始打卡数据 + * @return + */ + @Override + public Map punchMatchShift(String empId, String schedulingResultId, List> clockInData) { + //查询排班结果 + String pbSql = "select * from uf_pbjg where id = " + schedulingResultId; + Map pbData = DbTools.getSqlToMap(pbSql); + String shiftTeamId = Util.null2String(pbData.get("hxbz")); + String punchDate = Util.null2String(pbData.get("bcrq")); + + Map result = null; + Map maxPriorityResult = null; + if (!shiftTeamId.equals("")) { + //候选班次 + String bcSql = "select * from uf_jcl_kq_hxbz_dt1 where mainid = " + shiftTeamId; + List> bcData = DbTools.getSqlToList(bcSql); + if (bcData.size() > 0) { + List> waitCompareResultList = new ArrayList<>(); + //循环匹配,输出匹配结果 + for (Map bcMap : bcData) { + //获取班次要求打卡数据和请假、出差、加班数据处理后的卡点数据 + Map waitCompareMap = dealClockInData(empId, pbData, clockInData, bcMap.get("bcxx").toString()); + waitCompareMap.put("priorityValue", Util.null2String(bcMap.get("yxj"))); + waitCompareResultList.add(waitCompareMap); + } + //比较匹配结果 + for (Map compareMap : waitCompareResultList) { + //分析每组数据,生成对应的ABCDE + compareMap = countMatchItem(compareMap); + String compareB = Util.null2String(compareMap.get("judgePartB")); + if (compareB.equals("")) { + continue; + } + if (result == null) { + result = compareMap; + continue; + } + //1-比较各候选班次实际打卡正常的时间点个数B + String resultB = Util.null2String(result.get("judgePartB")); + if (resultB.compareTo(compareB) != 0) { + result = resultB.compareTo(compareB) < 0 ? compareMap : result; + continue; + } + //2-B相同时,比较B/A最大。各候选班次(结合了请假、出差、加班等)需要打卡的时间点个数A + String resultA = Util.null2String(result.get("judgePartA")); + String compareA = Util.null2String(compareMap.get("judgePartA")); + double resultBDividedA = (resultA.equals("") || resultA.equals("0")) ? 999 : Double.parseDouble(resultB) / Double.parseDouble(resultA); + double compareBDividedA = (compareA.equals("") || compareA.equals("0")) ? 999 : Double.parseDouble(compareB) / Double.parseDouble(compareA); + if (resultBDividedA != compareBDividedA) { + result = resultBDividedA < compareBDividedA ? compareMap : result; + continue; + } + //3-B/A相同时C最小。异常总分钟数C + String resultC = Util.null2String(result.get("judgePartC")); + String compareC = Util.null2String(compareMap.get("judgePartC")); + if (resultC.compareTo(compareC) != 0) { + result = resultC.compareTo(compareC) > 0 ? compareMap : result; + continue; + } + //4-C相同时D最小,冗余总分钟数D + String resultD = Util.null2String(result.get("judgePartD")); + String compareD = Util.null2String(compareMap.get("judgePartD")); + if (resultD.compareTo(compareD) != 0) { + result = resultD.compareTo(compareD) > 0 ? compareMap : result; + continue; + } + //5-D相同时E最小,班次优先级E(候选班组上有各班次的优先级设置) + String resultE = Util.null2String(result.get("judgePartE")); + String compareE = Util.null2String(compareMap.get("judgePartE")); + if (resultE.compareTo(compareE) != 0) { + result = resultE.compareTo(compareE) > 0 ? compareMap : result; + } + } + //全天没有打卡时,看上一个工作日的班次为优先,如果前一个工作日也没有班次,按优先级 + if (result == null) { + //获取上一个工作日的班次 + String lastWorkDayInfoSql = "select * from uf_jcl_kq_cqjg where rqlx = 0 and ygid = " + empId + " and rq < '" + punchDate + "' order by rq desc limit 1;"; + Map lastWorkDayInfo = DbTools.getSqlToMap(lastWorkDayInfoSql); + String bcId = Util.null2String(lastWorkDayInfo.get("bc")); + List> bcInfo = waitCompareResultList.stream().filter(f ->f.get("bcId").toString().equals(bcId)).collect(Collectors.toList()); + if (!bcId.equals("") && bcInfo.size() > 0) { + result = bcInfo.get(0); + } else { + //上一个工作日没有班次时 + maxPriorityResult = waitCompareResultList.stream().min(Comparator.comparing(e ->new Integer(String.valueOf(e.get("judgePartE"))))).get(); + result = maxPriorityResult; + } + } + } + + } + + return result; + } + + /** + * 计算卡点数据的匹配条件元素的具体数值 + * 考量元素有: + * 各候选班次(结合了请假、出差、加班等)需要打卡的时间点个数A; + * 各候选班次实际打卡正常的时间点个数B; + * 异常总分钟数C; + * 冗余总分钟数D; + * 班次优先级E(候选班组上有各班次的优先级设置) + * @param compareMap 班次匹配卡点数据 + * @return + */ + private Map countMatchItem(Map compareMap) { + List clockInTimeData = (List) compareMap.get("clockInTimeData"); + int requireClockInNum = clockInTimeData == null ? 0 : clockInTimeData.size(); + int rightClockInNum = 0; + int abnormalMinutes = 0; + int redundantMinutes = 0; + if (clockInTimeData == null || clockInTimeData.size() == 0) { + compareMap.put("judgePartA", String.valueOf(requireClockInNum)); + compareMap.put("judgePartB", String.valueOf(rightClockInNum)); + compareMap.put("judgePartC", String.valueOf(abnormalMinutes)); + compareMap.put("judgePartD", String.valueOf(redundantMinutes)); + compareMap.put("judgePartE", compareMap.get("priorityValue")); + return compareMap; + } + //班次要求打卡时间,时间格式2023-11-12 09:15 + String classTime = ""; + //弹性要求打卡时间,时间格式2023-11-12 09:15 + String elasticTime = ""; + String compareTime = ""; + //实际打卡数据。格式为 + // {2023-11-12 09:00|0|3|2023-11-12 09:15 ={signtime=09:11:00, id=48, userid=53, signdate=2023-11-12}} + // 班次时间|打卡类型(上班卡或下班卡)|打卡时间处所在位置timeType|弹性时间 = 打卡时间map集合 + Map clockTimeMap = new HashMap<>(); + //实际打卡时间 + String clockTime = ""; + ClockPointEnum pointType; + ClockPointEnum timeType; + for (ClockPointDTO dto : clockInTimeData) { + pointType = dto.getPointType(); + timeType = dto.getTimeType(); + clockTimeMap = dto.getClockTime(); + clockTime = (clockTimeMap != null ? Util.null2String(clockTimeMap.get("signtime")) : "") + + " " + + (clockTimeMap != null ? Util.null2String(clockTimeMap.get("signtime")) : ""); + classTime = dto.getClassTime(); + elasticTime = dto.getElasticTime(); + compareTime = Util.null2String(elasticTime).equals("") ? classTime : elasticTime; + //判断这个需要打卡的时间点,有没有正常打卡 + if (ClockPointEnum.EMPTY.equals(timeType) || clockTimeMap == null || clockTime.length() < 16) { + continue; + } else if (ClockPointEnum.START.equals(pointType) && ClockPointEnum.AFTER.equals(timeType)) { + //迟到,异常打卡-记录异常分钟数 + int betweenTime = DateUtil.getBetWeenMinutes(compareTime,clockTime.substring(0, 16)); + abnormalMinutes = abnormalMinutes + betweenTime; + } else if (ClockPointEnum.START.equals(pointType) && ClockPointEnum.BEFORE.equals(timeType)) { + //早到,正常打卡-记录冗余分钟数、打卡正常的时间点个数 + rightClockInNum++; + int betweenTime = DateUtil.getBetWeenMinutes(clockTime.substring(0, 16),compareTime); + redundantMinutes = redundantMinutes + betweenTime; + } else if (ClockPointEnum.END.equals(pointType) && ClockPointEnum.BEFORE.equals(timeType)) { + //早退,异常打卡-记录异常分钟数 + int betweenTime = DateUtil.getBetWeenMinutes(clockTime.substring(0, 16),compareTime); + abnormalMinutes = abnormalMinutes + betweenTime; + } else if (ClockPointEnum.END.equals(pointType) && ClockPointEnum.AFTER.equals(timeType)) { + //晚退,正常打卡-记录冗余分钟数、打卡正常的时间点个数 + rightClockInNum++; + int betweenTime = DateUtil.getBetWeenMinutes(compareTime,clockTime.substring(0, 16)); + redundantMinutes = redundantMinutes + betweenTime; + } else if (ClockPointEnum.EQUAL.equals(timeType)) { + //准点打卡,正常打卡-记录打卡正常的时间点个数 + rightClockInNum++; + } + + } + compareMap.put("judgePartA", String.valueOf(requireClockInNum)); + compareMap.put("judgePartB", String.valueOf(rightClockInNum)); + compareMap.put("judgePartC", String.valueOf(abnormalMinutes)); + compareMap.put("judgePartD", String.valueOf(redundantMinutes)); + compareMap.put("judgePartE", compareMap.get("priorityValue")); + + return compareMap; + } + + /** + * 获取班次要求打卡数据和请假、出差、加班数据处理后的卡点数据 + * @param empId + * @param clockInData 需要包含分析日期以及分析日期前后2天的3天打卡数据 + * @return + */ + private Map dealClockInData(String empId, Map pbData, List> clockInData, String shiftId) { + Map clockInDataMatchInfo = new HashMap<>(); + String punchDate = Util.null2String(pbData.get("bcrq")); + String startBeforeDate = DateUtil.beforeDay(punchDate,2); + String endAfterDate = DateUtil.AfterDay(punchDate,2); + //获取考勤项目 + Map param = Maps.newHashMap(); + param.put("startDate",startBeforeDate); + param.put("endDate",endAfterDate); + param.put("resourceId",empId); + Map dataMap = basicsetService.getAttendanceItemsByPerson(param); + List> attendanceItems = (List>)dataMap.get("data"); + //1-组装班次数据 + Map>> schedulingResultsMap = getShiftData(empId, pbData, shiftId); + List> shiftData = schedulingResultsMap.get(punchDate); + //2-拿到当天打卡数据 + Map>> collect = Maps.newHashMap(); + if (clockInData != null && clockInData.size() >0){ + collect = clockInData.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("signdate")))); + } +// Map> clockInTimeMap = Maps.newHashMap(); // + + Map getClockTimeParam = Maps.newHashMap(); + getClockTimeParam.put("date",punchDate); + getClockTimeParam.put("clockInTimeList",clockInData); + getClockTimeParam.put("schedulingResultCollect",schedulingResultsMap); +// getClockTimeParam.put("clockInTimeMap",clockInTimeMap); + getClockTimeParam.put("clockInTimeCollect",collect); + getClockTimeParam.put("userId",empId); + //打卡数据 + log.info("getClockTimeParam : [{}]",getClockTimeParam); + List> clockInTimeList = utilService.getClockInTime(getClockTimeParam); + //3-组装出差和请假的数据 + Map workingHourparam = Maps.newHashMap(); + workingHourparam.put("clockInTimeCollect",clockInTimeList); + workingHourparam.put("analysisDate",punchDate); + workingHourparam.put("userId",empId); + workingHourparam.put("attendanceItems",attendanceItems); + workingHourparam.put("scheduleResult",shiftData); + Map evectionDataMap = updateAttendanceResultWrapper.getEvection(workingHourparam); + Map askForLeaveDataMap = updateAttendanceResultWrapper.getAskForLeave(workingHourparam); + //4-调用考勤分析中的卡点数据处理方法 + List> askForLeaveAndEvctionSchedule = Lists.newArrayList(); + askForLeaveAndEvctionSchedule.addAll((List>)askForLeaveDataMap.get("askForLeaveSchedule")); + askForLeaveAndEvctionSchedule.addAll((List>)evectionDataMap.get("evectionSchedule")); + if (askForLeaveAndEvctionSchedule.size() > 0){ + askForLeaveAndEvctionSchedule = mergeAskForLeaveAndEvctionSchedule(askForLeaveAndEvctionSchedule,punchDate); + } + Map clockInTimeDataParam = Maps.newHashMap(); + clockInTimeDataParam.put("analysisDate",punchDate); + clockInTimeDataParam.put("scheduleResult",shiftData); + clockInTimeDataParam.put("clockInTimeList",clockInTimeList); + clockInTimeDataParam.put("askForLeaveAndEvctionSchedule",askForLeaveAndEvctionSchedule); + List clockInTimeData = utilService.getClockInPointCmd(clockInTimeDataParam); + + if(clockInTimeData != null && clockInTimeData.size() > 0) { + clockInTimeData = clockInTimeData.stream().filter(ClockPointDTO::isRecord).collect(Collectors.toList()); + } + clockInDataMatchInfo.put("bcId", shiftId); + clockInDataMatchInfo.put("clockInTimeData", clockInTimeData); + return clockInDataMatchInfo; + } + + /** + * 获取班次数据 + * @param empId + * @return + */ + private Map>> getShiftData(String empId, Map pbData, String shiftId) { + + String punchDate = Util.null2String(pbData.get("bcrq")); + String schedulingRule = Util.null2String(pbData.get("pbgl")); + String dateType = Util.null2String(pbData.get("rqlx")); + String restSign = Util.null2String(pbData.get("sfxx")); + + String startBeforeDate = DateUtil.beforeDay(punchDate,2); + String endAfterDate = DateUtil.AfterDay(punchDate,2); + + /** 获取人员班次*/ + Map classesParamMap = Maps.newHashMap(); + classesParamMap.put("tableName","uf_pbjg"); + classesParamMap.put("startDate",startBeforeDate); + classesParamMap.put("endDate",endAfterDate); + classesParamMap.put("pblx","0"); + classesParamMap.put("pbdx",empId); + classesParamMap.put("current","1"); + classesParamMap.put("pageSize",10); + classesParamMap.put("recurrence",1); + + classesParamMap.put("punchDate",punchDate); + classesParamMap.put("schedulingRule",schedulingRule); + classesParamMap.put("dateType",dateType); + classesParamMap.put("restSign",restSign); + classesParamMap.put("shiftId",shiftId); + Map>> schedulMap = getSchedulingInFormation(classesParamMap); + + return schedulMap; + } + + private Map>> getSchedulingInFormation(Map params) { + + String punchDate = Util.null2String(params.get("punchDate")); + String schedulingRule = Util.null2String(params.get("schedulingRule")); + String dateType = Util.null2String(params.get("dateType")); + String restSign = Util.null2String(params.get("restSign")); + String shiftId = Util.null2String(params.get("shiftId")); + + String bcSql = "select * from uf_jcl_kq_bcxx where id = " + shiftId; + Map bcData = DbTools.getSqlToMap(bcSql); + String bcsdxx = Util.null2String(bcData.get("bcsdxx")); + + String sql = "select a.id bcxx,a.edsc,a.zgzsc,a.bcsdxx,a.sfdx,a.sfkt,b.bdlx,a.btgz,a.fgsjd,a.zddxfz,a.dxhs,b.kssj dtkssj,b.jssj dtjssj,b.ksdk,b.jsdk,b.tqdkfzs,b.thdkfzs,b.edxss,b.sfdx dtsfdx,b.zddxfz dtzddxfz,b.dxhs dtdxhs,b.gsrq from uf_jcl_kq_bcxx a left join uf_jcl_kq_bcxx_dt1 b on a.id=b.mainid where a.id =" + shiftId; + List> dataList = DbTools.getSqlToList(sql); + Map>> resultMap = Maps.newHashMap(); + List> classs = Lists.newArrayList(); + for (Map map:dataList){ + Map newMap = Maps.newHashMap(); + newMap.putAll(map); + newMap.put("rqlx",dateType); + newMap.put("sfxx",restSign); + classs.add(newMap); + } + resultMap.put(punchDate,classs); + + /** 加班计划*/ + sql = "select b.jbry,b.ksrq,b.kssj,a.jblx,b.jsrq,b.jssj,b.jbsc from uf_jcl_kq_jbjh a left join uf_jcl_kq_jbjh_dt1 b on a.id=b.mainid where b.jbry =? and b.ksrq>=? and b.ksrq<=? and (b.jbcx=0 or b.jbcx is null)"; + Map>> overtimePlanMap = DbTools.getSqlToList(sql,params.get("pbdx"),params.get("startDate"),params.get("endDate")).stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("ksrq")))); + + //考勤项目 + List> attendanceItems = new ArrayList<>(); + //日期集合 + Map dateParam = Maps.newHashMap(); + dateParam.put("nd",Util.null2String(params.get("startDate")).split("-")[0]); + dateParam.put("glpb",schedulingRule); + Map result = commandExecutor.execute(new GetDateCmd(dateParam)); + List> list = (List>)result.get("data"); + Map dateMap = list.stream().collect(Collectors.toMap(e->Util.null2String(e.get("rq")),e->Util.null2String(e.get("rqlx")))); + + + for (Map.Entry>> e: overtimePlanMap.entrySet()){ + if (resultMap.get(e.getKey()) == null){ + resultMap.put(e.getKey(),Lists.newArrayList()); + } + List> resultList = resultMap.get(e.getKey()); +// List> schedulingdateMap = schedulingMapBydate.get(e.getKey()); + Map overtimePlan = e.getValue().get(0); + + + Map map = Maps.newHashMap(); + if (!overtimePlan.get("ksrq").equals(overtimePlan.get("jsrq"))){ + map.put("sfkt","1"); + }else { + map.put("sfkt","0"); + } + //查找对应的考勤项目 + String querySql = "select id keyid,ksjbbxydk,jsjbbxydk,tqdkyxfzs,thdkyxfzs,jbwdhlfzs,jbzzhlfzs,tqdkjrjb,thdkjrjb,jbscbdccsqsc,zdkcjcxxsc,ccclfs,rzdjbxss,yzdjbxss,zzdjbxss,jbzdzjqye,jbqsfzs,ccqszhdhsfzs,hsl,hsdw from uf_jcl_kq_kqxm where id=?"; + attendanceItems = DbTools.getSqlToList(querySql,overtimePlan.get("jblx")); + + + map.put("bcxx", punchDate.compareTo(e.getKey()) != 0 ? "0" : shiftId); + map.put("bcsdxx", punchDate.compareTo(e.getKey()) != 0 ? "": bcsdxx); + if (resultList.size()>0){ + map.put("edsc",Util.null2String(resultList.get(0).get("edsc"))); + map.put("sfdx",Util.null2String(resultList.get(0).get("sfdx"))); + map.put("zddxfz",Util.null2String(resultList.get(0).get("zddxfz"))); + map.put("dxhs",Util.null2String(resultList.get(0).get("dxhs"))); + }else { + map.put("edsc","0"); + } + map.put("bdlx", ClassSegmentTypeEnum.OVERTIME_PLAN.getKey()); + map.put("dtkssj",overtimePlan.get("kssj")); + map.put("dtjssj",overtimePlan.get("jssj")); + map.put("ksdk","0"); + map.put("jsdk","0"); + if (punchDate.compareTo(e.getKey()) == 0){ + map.put("sfxx", restSign); + } + map.put("tqdkfzs","60"); + map.put("thdkfzs","60"); + map.put("rqlx",dateMap.get(e.getKey())); + map.put("edxss",overtimePlan.get("jbsc")); + map.put("jblx",attendanceItems); + map.put("gsrq", ClassBelongToEnum.NOWDAY.getKey()); + if (attendanceItems.size() >0){ + map.put("ksdk",attendanceItems.get(0).get("ksjbbxydk")); + map.put("jsdk",attendanceItems.get(0).get("jsjbbxydk")); + map.put("tqdkfzs",attendanceItems.get(0).get("tqdkyxfzs")); + map.put("thdkfzs",attendanceItems.get(0).get("thdkyxfzs")); + map.put("jbwdhlfzs",attendanceItems.get(0).get("jbwdhlfzs")); + map.put("jbzzhlfzs",attendanceItems.get(0).get("jbzzhlfzs")); + } + if (resultList.size() > 1){ + String kssjbegin = Utils.getkssjTime(resultList.get(0),e.getKey()); + String kssjend = Utils.getkssjTime(resultList.get(resultList.size()-1),e.getKey()); + String kssj = overtimePlan.get("ksrq")+" "+overtimePlan.get("kssj"); + if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(kssjbegin)) <0){ + //加班计划在开头 + if (resultList.get(0).get("dtkssj").equals(overtimePlan.get("jssj")) && + resultList.get(0).get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) && + map.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) && + map.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){ + //当加班结束时间和早上打卡时间重合时 + + } + resultList.add(0,map); + }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(kssjend)) >0){ + //加班计划在末尾 + if (resultList.get(0).get("dtjssj").equals(overtimePlan.get("kssj")) && + resultList.get(0).get("jsdk").equals(CheckBoxEnum.CHECKED.getKey()) && + map.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) && + map.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){ + //当加班结束时间和晚上下班时间重合时1 + + } + resultList.add(map); + }else { + //加班计划在中间 + for (int j=1;j=0 && DateUtil.getTime(kssj3).compareTo(DateUtil.getTime(kssj2)) <=0){ + resultList.add(j,map); + break; + } + } + } + }else { + resultList.add(map); + } + + } + log.info("SchedulingResults : [{}]",resultMap); + return resultMap; + } + + /** + * 合并请假或出差 + * @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