package com.engine.jucailinkq.attendance.attendanceanalysis.cmd.getclockInpoint; import com.engine.jucailinkq.attendance.attendanceanalysis.dto.clockpoint.ClockPointDTO; import com.engine.jucailinkq.attendance.enums.AccountingUnitEnum; import com.engine.jucailinkq.attendance.enums.CheckBoxEnum; import com.engine.jucailinkq.attendance.enums.ClassSegmentTypeEnum; import com.engine.jucailinkq.attendance.enums.ClockPointEnum; import com.engine.common.biz.AbstractCommonCommand; import com.engine.common.entity.BizLogContext; import com.engine.jucailinkq.common.util.DateUtil; import com.engine.jucailinkq.common.util.Utils; import com.engine.core.interceptor.CommandContext; 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 GetClockInPointCmd extends AbstractCommonCommand> { public GetClockInPointCmd(Map params) { this.params = params; } /** * 需要打卡的卡点 */ private List needClockDateList; /** * 分析日期 */ private String analysisDate; @Override public BizLogContext getLogContext() { return null; } @Override public Map execute(CommandContext commandContext) { Map resultMap = Maps.newHashMap(); String analysisDate = Util.null2String(params.get("analysisDate")); this.analysisDate=analysisDate; List> scheduleResult = (List>) params.get("scheduleResult"); List> clockInTimeList = (List>) params.get("clockInTimeList"); List> askForLeaveAndEvctionScheduleList = (List>) params.get("askForLeaveAndEvctionSchedule"); List> needClockInList = scheduleResult.stream().filter(e -> !ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(e.get("bdlx")) && !ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(e.get("bdlx")) && !ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(e.get("bdlx")) ).collect(Collectors.toList()); log.debug("未重新计算卡点时 老的scheduleResult : [{}],askForLeaveAndEvctionScheduleList:[{}]",scheduleResult,askForLeaveAndEvctionScheduleList); //调整加班计时间段的打卡 scheduleResult = adjustWorkOverTimeClock(scheduleResult,analysisDate); //调整请假出差时间段的打卡 askForLeaveAndEvctionScheduleList = adjustAskforSchedule(scheduleResult,analysisDate,askForLeaveAndEvctionScheduleList); log.debug("经过adjustWorkOverTimeClock 加班调整过后的 的scheduleResult: [{}]",scheduleResult); /** * 当请假或外出开始时间和外出时间在上班之外时,不需要打卡 */ //判断是否骑在上班卡或下班卡 boolean ifStartNeedClock=false; String startNeedClockTime = ""; boolean ifEndNeedClock=false; String endNeedClockTime = ""; if (needClockInList.size() > 0 && askForLeaveAndEvctionScheduleList.size() > 0) { String startTime = Utils.getkssjTime(needClockInList.get(0),analysisDate); String endStartTime = Utils.getkssjTime(needClockInList.get(needClockInList.size()-1),analysisDate); String endTime = Utils.getjssjTime(needClockInList.get(needClockInList.size()-1),analysisDate); for (Map askForLeaveAndEvctionSchedule :askForLeaveAndEvctionScheduleList){ String dtkssj = Utils.getkssjTime(askForLeaveAndEvctionSchedule,analysisDate); String dtjssj = Utils.getjssjTime(askForLeaveAndEvctionSchedule,analysisDate); if (DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(startTime))<=0 || DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(endTime)) >= 0){ askForLeaveAndEvctionSchedule.put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(endTime))>=0 || DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(startTime))<=0){ askForLeaveAndEvctionSchedule.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(startTime))<=0 && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(endTime))<0 && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(startTime)) >0){ //骑在开始上班时间 for (Map needClockMap:needClockInList){ String kssj = Utils.getkssjTime(needClockMap,analysisDate); String jssj = Utils.getjssjTime(needClockMap,analysisDate); //中间只要有开始打卡,即上班需要打卡 if (CheckBoxEnum.CHECKED.getKey().equals(needClockMap.get("ksdk")) && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(jssj)) >=0){ ifStartNeedClock=true; startNeedClockTime = dtjssj; } } } if (DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(startTime)) > 0 && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(endTime))>=0 && DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(endTime)) < 0){ //骑在下班时间 for (Map needClockMap:needClockInList){ String kssj = Utils.getkssjTime(needClockMap,analysisDate); //中间只要有结束打卡,即下班需要打卡 if (CheckBoxEnum.CHECKED.getKey().equals(needClockMap.get("jsdk")) && DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(kssj)) <=0){ ifEndNeedClock=true; endNeedClockTime = dtkssj; } } } } } /** * 当请假或外出包含打卡卡点时,判断该卡点是否需要打卡 */ for (Map askForLeaveAndEvctionMap :askForLeaveAndEvctionScheduleList){ String evctiondtkssj = Utils.getkssjTime(askForLeaveAndEvctionMap,analysisDate); String evctionksdk = Util.null2String(askForLeaveAndEvctionMap.get("ksdk")); String evctiondtjssj = Utils.getjssjTime(askForLeaveAndEvctionMap,analysisDate); String evctionjsdk = Util.null2String(askForLeaveAndEvctionMap.get("jsdk")); String zysd = Util.null2String(askForLeaveAndEvctionMap.get("zysd")); List lists = Lists.newArrayList(); for (int i=0;i=0 && !ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(bdlx) && !ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(bdlx) && !ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(bdlx)){ lists.add(dtkssj+"&"+ClockPointEnum.START.getKey()+"&"+Util.null2String(scheduleResult.get(i).get("ksdk"))); } if (DateUtil.getTime(evctiondtkssj).compareTo(DateUtil.getTime(dtjssj)) <= 0 && DateUtil.getTime(evctiondtjssj).compareTo(DateUtil.getTime(dtjssj)) >=0 && !ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(bdlx) && !ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(bdlx) && !ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(bdlx)){ lists.add(dtjssj+"&"+ClockPointEnum.END.getKey()+"&"+Util.null2String(scheduleResult.get(i).get("jsdk"))); } } } //新打卡 List newNeedClockLists = Lists.newArrayList(); //时间-结束卡\开始卡-是否打卡 if (lists.size() == 1){ String str = lists.get(0); if (ClockPointEnum.START.getKey().equals(str.split("&")[1]) && CheckBoxEnum.CHECKED.getKey().equals(evctionjsdk)){ newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0"); }else if (ClockPointEnum.END.getKey().equals(str.split("&")[1]) && CheckBoxEnum.CHECKED.getKey().equals(evctionksdk)){ newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0"); } }else if (lists.size() > 1){ for(int i=0;i 0){ scheduleResult.addAll(askForLeaveAndEvctionScheduleList); scheduleResult = scheduleResult.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); } List needClockDateList = Lists.newArrayList(); for (int i=0;i=0 && DateUtil.getTime(startNeedClockTime).compareTo(DateUtil.getTime(dtjssj)) <0 && !ClassSegmentTypeEnum.EVECTION.getKey().equals(bdlx) && !ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(bdlx)){ String firstKssj = Utils.getkssjTime(scheduleResult.get(0),analysisDate); String kssj = Utils.getkssjTime(scheduleResult.get(i),analysisDate); scheduleResult.get(i).put("ksdk",CheckBoxEnum.CHECKED.getKey()); scheduleResult.get(i).put("tqdkfzs",DateUtil.getBetWeenMinutes(firstKssj,kssj)); needClockDateList.add(0,dtkssj); break; } if (ifEndNeedClock && DateUtil.getTime(endNeedClockTime).compareTo(DateUtil.getTime(dtkssj)) >0 && DateUtil.getTime(endNeedClockTime).compareTo(DateUtil.getTime(dtjssj)) <=0 && !ClassSegmentTypeEnum.EVECTION.getKey().equals(bdlx) && !ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(bdlx)){ String lastjssj = Utils.getjssjTime(scheduleResult.get(scheduleResult.size()-1),analysisDate); String jssj = Utils.getjssjTime(scheduleResult.get(i),analysisDate); scheduleResult.get(i).put("jsdk",CheckBoxEnum.CHECKED.getKey()); scheduleResult.get(i).put("thdkfzs",DateUtil.getBetWeenMinutes(jssj,lastjssj)); needClockDateList.add(dtjssj); break; } } } needClockDateList = needClockDateList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(e).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); this.needClockDateList=needClockDateList; log.debug("经过重新计算卡点时 新的scheduleResult : [{}]",scheduleResult); List clcokInPointList = getClockInPoint(analysisDate, scheduleResult, clockInTimeList,needClockDateList); log.debug("clcokInPointList :[{}]",clcokInPointList); resultMap.put("clcokInPointList", clcokInPointList); resultMap.put("scheduleResult",scheduleResult); resultMap.put("clockInTimeList",clockInTimeList); resultMap.put("needClockDateList",needClockDateList); resultMap.put("askForLeaveAndEvctionScheduleList",askForLeaveAndEvctionScheduleList); return resultMap; } /** * 获取打卡卡点 * * @param analysisDate 分析日期 * @param scheduleResult 需要打卡的班次 * @param clockInTimeList 打卡集合 * @param needClockDateList 需要打卡的时间点 * @return clcokInTimeData 卡点集合 */ public List getClockInPoint(String analysisDate, List> scheduleResult, List> clockInTimeList, List needClockDateList) { /**卡点集合*/ List clcokInTimeData = Lists.newArrayList(); List> restScheduleList = scheduleResult.stream().filter(e -> (ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(e.get("bdlx"))) && CheckBoxEnum.CHECKED.getKey().equals(e.get("dtsfdx"))).collect(Collectors.toList()); for (Map needClockIn : scheduleResult) { /**非请假外出开始打卡逻辑处理*/ if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("ksdk")) && !ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) && !ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx"))) { String dtkssj = Utils.getkssjTime(needClockIn,analysisDate); Map> ksdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtkssj, clockInTimeList); ClockPointEnum timeType = getStartClassTimeType(needClockIn,ksdkNearestClcokInTime,dtkssj,dtkssj); clcokInTimeData.add(ClockPointDTO.builder().classTime(dtkssj).pointType(ClockPointEnum.START).timeType(timeType).record(true).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(ksdkNearestClcokInTime.get(timeType)).build()); } /**非请假外出结束打卡逻辑处理*/ if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("jsdk")) && !ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) && !ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx"))) { String dtjssj = Utils.getjssjTime(needClockIn,analysisDate); Map> jsdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtjssj, clockInTimeList); ClockPointEnum timeType = getEndClassTimeType(needClockIn,jsdkNearestClcokInTime,dtjssj,dtjssj); clcokInTimeData.add(ClockPointDTO.builder().classTime(dtjssj).pointType(ClockPointEnum.END).timeType(timeType).record(true).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(jsdkNearestClcokInTime.get(timeType)).build()); } /** * 请假外出的开始打卡处理 */ if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("ksdk")) && (ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) || ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx")))){ String dtkssj = Utils.getkssjTime(needClockIn,analysisDate); Map> jsdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtkssj, clockInTimeList); ClockPointEnum timeType = getEndClassTimeType(needClockIn,jsdkNearestClcokInTime,dtkssj,dtkssj); clcokInTimeData.add(ClockPointDTO.builder().classTime(dtkssj).pointType(ClockPointEnum.END).record(true).timeType(timeType).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(jsdkNearestClcokInTime.get(timeType)).build()); } /** * 请假外出的结束打卡处理 */ if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("jsdk")) && (ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) || ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx")))){ String dtjssj = Utils.getjssjTime(needClockIn,analysisDate); Map> ksdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtjssj, clockInTimeList); ClockPointEnum timeType = getStartClassTimeType(needClockIn,ksdkNearestClcokInTime,dtjssj,dtjssj); clcokInTimeData.add(ClockPointDTO.builder().classTime(dtjssj).pointType(ClockPointEnum.START).record(true).timeType(timeType).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(ksdkNearestClcokInTime.get(timeType)).build()); } } //根据班次时间排序 clcokInTimeData = clcokInTimeData.stream().sorted(Comparator.comparing(e-> DateUtil.getTime(e.getClassTime()).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); /** * 计算弹性上下班 */ //上下班弹性, flexibleWork(clcokInTimeData,scheduleResult); /** * 计算休息时间段的弹性上下班 */ if (restScheduleList.size() > 0){ flexibleRestClass(restScheduleList,clcokInTimeData,scheduleResult); } /** * 当有2笔需要打卡时,可能会有打卡歧义的情况,歧义情况取2个时间点的中间值,当打卡时间小于中间值归属前一个打卡,大于则相反 */ if (clcokInTimeData.size() > 1) { for (int i = 0; i < clcokInTimeData.size() - 1; i++) { ClockPointDTO beforeClcokDTO = clcokInTimeData.get(i); ClockPointDTO afterClcokInDTO = clcokInTimeData.get(i + 1); Map beforeClcokInTimeMap = beforeClcokDTO.getClockTime(); Map afterClcokInTimeMap = afterClcokInDTO.getClockTime(); //重复 if (beforeClcokInTimeMap != null && beforeClcokInTimeMap == afterClcokInTimeMap) { String beforeTime = beforeClcokDTO.getClassTime(); if (beforeClcokDTO.getElasticTime() != null && !"".equals(beforeClcokDTO.getElasticTime())){ beforeTime = beforeClcokDTO.getElasticTime(); } String afterTime = afterClcokInDTO.getClassTime(); if (afterClcokInDTO.getElasticTime() != null && !"".equals(afterClcokInDTO.getElasticTime())){ afterTime = afterClcokInDTO.getElasticTime(); } long betWeenMinutes = DateUtil.getBetWeenMinutes(beforeTime, afterTime); String middileTime = DateUtil.AfterMinutes(beforeTime, betWeenMinutes / 2); String signdateTime = beforeClcokInTimeMap.get("signdate") + " " + beforeClcokInTimeMap.get("signtime"); ClockPointDTO resetClcokDTO =null; if (DateUtil.getTime(signdateTime).compareTo(DateUtil.getTime(middileTime)) <= 0) { //该打卡归属前一个打卡点,后一个打卡点需要重新设置 resetClcokDTO=afterClcokInDTO; } else if (DateUtil.getTime(signdateTime).compareTo(DateUtil.getTime(middileTime)) > 0) { //该打卡归属后一个打卡点,前一个打卡点需要重新设置 resetClcokDTO=beforeClcokDTO; } //需要重新赋值的打卡时间 String restTime = resetClcokDTO.getClassTime(); if (resetClcokDTO.getElasticTime() != null && !"".equals(resetClcokDTO.getElasticTime())){ restTime = resetClcokDTO.getElasticTime(); } Map> nearestClcokInTime = Utils.getNearestClcokInTimeCmd(restTime, clockInTimeList); //start:开始打卡时间点,end:结束打卡时间点 ClockPointEnum pointType = resetClcokDTO.getPointType(); //empty:漏卡,equal:打卡时间和班次时间相等,before:打卡时间在班次时间之前,after:打卡时间在班次时间之后 ClockPointEnum timeType = resetClcokDTO.getTimeType(); String time = resetClcokDTO.getClassTime(); ClockPointEnum newtimeType = null; if (timeType.equals(ClockPointEnum.BEFORE)){ newtimeType = ClockPointEnum.AFTER; }else if (timeType.equals(ClockPointEnum.AFTER)){ newtimeType = ClockPointEnum.BEFORE; } if (nearestClcokInTime.get(newtimeType) != null){ Map newClockTimeMap = nearestClcokInTime.get(newtimeType); String newClockTime = newClockTimeMap.get("signdate")+ " "+newClockTimeMap.get("signtime"); int index = clcokInTimeData.indexOf(resetClcokDTO); if (newtimeType.equals(ClockPointEnum.BEFORE)){ if (!getBeforeClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,restTime))) <= 0){ newClockTimeMap = null; } if ((index-1) >= 0){ //当重新需要打卡的时间戳与打卡时间之前的打卡集合时,进行比对 ClockPointDTO resetBeforeDTO = clcokInTimeData.get(index-1); Map resetBeforeClcokInTimeMap = resetBeforeDTO.getClockTime(); if (newClockTimeMap == resetBeforeClcokInTimeMap){ newClockTimeMap = null; } } }else if (newtimeType.equals(ClockPointEnum.AFTER)){ if (!getNextClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,restTime))) >= 0){ newClockTimeMap = null; } } if (newClockTimeMap == null){ //当需要调整的卡点为漏卡时将打卡进行退回,若另一个卡点调整后为不漏卡情况,则调整该节点 if (resetClcokDTO == beforeClcokDTO){ resetClcokDTO=afterClcokInDTO; }else if (resetClcokDTO == afterClcokInDTO){ resetClcokDTO=beforeClcokDTO; } if (!resetClcokInTimeData(analysisDate,resetClcokDTO,clockInTimeList,needClockDateList,clcokInTimeData,scheduleResult)){ if (resetClcokDTO == beforeClcokDTO){ resetClcokDTO = afterClcokInDTO; }else if (resetClcokDTO == afterClcokInDTO){ resetClcokDTO = beforeClcokDTO; } if (newClockTimeMap == null){ resetClcokDTO.setTimeType(ClockPointEnum.EMPTY); }else { resetClcokDTO.setTimeType(newtimeType); } resetClcokDTO.setClockTime(newClockTimeMap); } }else { if (newClockTimeMap == null){ resetClcokDTO.setTimeType(ClockPointEnum.EMPTY); }else { resetClcokDTO.setTimeType(newtimeType); } resetClcokDTO.setClockTime(newClockTimeMap); } }else { if (resetClcokDTO == beforeClcokDTO){ resetClcokDTO = afterClcokInDTO; }else if (resetClcokDTO == afterClcokInDTO){ resetClcokDTO = beforeClcokDTO; } if (!resetClcokInTimeData(analysisDate,resetClcokDTO,clockInTimeList,needClockDateList,clcokInTimeData,scheduleResult)){ if (resetClcokDTO == beforeClcokDTO){ resetClcokDTO = afterClcokInDTO; }else if (resetClcokDTO == afterClcokInDTO){ resetClcokDTO = beforeClcokDTO; } resetClcokDTO.setClockTime(null); resetClcokDTO.setTimeType(ClockPointEnum.EMPTY); } } } } } return clcokInTimeData; } public boolean resetClcokInTimeData(String analysisDate,ClockPointDTO resetClcokDTO,List> clockInTimeList, List needClockDateList,List clcokInTimeData,List> scheduleResult){ String restTime = resetClcokDTO.getClassTime(); if (resetClcokDTO.getElasticTime() != null && !"".equals(resetClcokDTO.getElasticTime())){ restTime = resetClcokDTO.getElasticTime(); } Map> nearestClcokInTime = Utils.getNearestClcokInTimeCmd(restTime, clockInTimeList); //start:开始打卡时间点,end:结束打卡时间点 ClockPointEnum pointType = resetClcokDTO.getPointType(); //empty:漏卡,equal:打卡时间和班次时间相等,before:打卡时间在班次时间之前,after:打卡时间在班次时间之后 ClockPointEnum timeType = resetClcokDTO.getTimeType(); String time = resetClcokDTO.getClassTime(); ClockPointEnum newtimeType = null; if (timeType.equals(ClockPointEnum.BEFORE)){ newtimeType = ClockPointEnum.AFTER; }else if (timeType.equals(ClockPointEnum.AFTER)){ newtimeType = ClockPointEnum.BEFORE; } if (nearestClcokInTime.get(newtimeType) != null){ Map newClockTimeMap = nearestClcokInTime.get(newtimeType); String newClockTime = newClockTimeMap.get("signdate")+ " "+newClockTimeMap.get("signtime"); int index = clcokInTimeData.indexOf(resetClcokDTO); if (newtimeType.equals(ClockPointEnum.BEFORE)){ if (pointType.equals(ClockPointEnum.START)){ //开始卡点 Map needClockIn = scheduleResult.stream().filter(e -> { String dtkssj = Utils.getkssjTime(e,analysisDate); if (Utils.ifAskforOrEvctionClassSegment(e.get("bdlx").toString())){ dtkssj = Utils.getjssjTime(e,analysisDate); } if (time.equals(dtkssj)){ return true; }else { return false; } }).collect(Collectors.toList()).get(0); //计算最大提前打卡分钟数 int tqdkfzs = 60; if (Util.null2String(needClockIn.get("tqdkfzs")).equals("") && !"".equals(getBeforeClockTime(needClockDateList,restTime))){ tqdkfzs = DateUtil.getBetWeenMinutes(getBeforeClockTime(needClockDateList,restTime),restTime); }else { tqdkfzs = Util.null2String(needClockIn.get("tqdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("tqdkfzs").toString()); } if (DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(DateUtil.beforeMinutes(restTime, tqdkfzs))) < 0){ newClockTimeMap =null; } } if (!getBeforeClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,restTime))) <= 0){ newClockTimeMap = null; } if ((index-1) >= 0){ //当重新需要打卡的时间戳与打卡时间之前的打卡集合时,进行比对 ClockPointDTO resetBeforeDTO = clcokInTimeData.get(index-1); Map resetBeforeClcokInTimeMap = resetBeforeDTO.getClockTime(); if (newClockTimeMap == resetBeforeClcokInTimeMap){ newClockTimeMap = null; } } }else if (newtimeType.equals(ClockPointEnum.AFTER)){ if (pointType.equals(ClockPointEnum.END)){ //结束卡点 Map needClockIn = scheduleResult.stream().filter(e -> { String dtjssj = Utils.getjssjTime(e,analysisDate); if (Utils.ifAskforOrEvctionClassSegment(e.get("bdlx").toString())){ dtjssj = Utils.getkssjTime(e,analysisDate); } if (time.equals(dtjssj)){ return true; }else { return false; } }).collect(Collectors.toList()).get(0); //计算最大退后打卡分钟数 int thdkfzs = 60; if (Util.null2String(needClockIn.get("thdkfzs")).equals("") && !"".equals(getNextClockTime(needClockDateList,restTime))){ thdkfzs = DateUtil.getBetWeenMinutes(restTime,getNextClockTime(needClockDateList,restTime)); }else { thdkfzs = Util.null2String(needClockIn.get("thdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("thdkfzs").toString()); } if (DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(restTime, thdkfzs))) > 0){ newClockTimeMap = null; } } if (!getNextClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,restTime))) >= 0){ newClockTimeMap = null; } } if (newClockTimeMap != null){ resetClcokDTO.setTimeType(newtimeType); resetClcokDTO.setClockTime(newClockTimeMap); return true; } } return false; } /** * 连续两上上班段(正常工作、班段上加班、加班计划)如果上一个结束与下一个开始都需要打卡,则两个都调整来不需要打卡 * @param scheduleResult * @return */ public List> adjustWorkOverTimeClock(List> scheduleResult,String analysisDate){ List> workscheduleList = scheduleResult.stream().filter(e->!Utils.ifRestClassSegment(e.get("bdlx").toString())).collect(Collectors.toList()); List> restscheduleList = scheduleResult.stream().filter(e->Utils.ifRestClassSegment(e.get("bdlx").toString())).collect(Collectors.toList()); workscheduleList = workscheduleList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); for (int i=0;i scheduleMap = workscheduleList.get(i); if (scheduleMap.get("bdlx").equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())){ String kssj = Utils.getkssjTime(scheduleMap,analysisDate); String jssj = Utils.getjssjTime(scheduleMap,analysisDate); Map beforeScheduleMap = i-1 >=0?workscheduleList.get(i-1):null; Map afterScheduleMap = i+1 <=workscheduleList.size()-1?workscheduleList.get(i+1):null; if (beforeScheduleMap != null && afterScheduleMap != null && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString())){ //加班计划处在工作中间,休息时段加班 String beforejssj = Utils.getjssjTime(beforeScheduleMap,analysisDate); String afterkssj = Utils.getkssjTime(afterScheduleMap,analysisDate); if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0){ beforeScheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); scheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); beforeScheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0){ scheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); afterScheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); } }else { if (beforeScheduleMap != null){ String beforejssj = Utils.getjssjTime(beforeScheduleMap,analysisDate); if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0 && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) && scheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){ scheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); beforeScheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0 && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) && scheduleMap.get("jsdk").equals(CheckBoxEnum.UNCHECKED.getKey()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) && beforeScheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){ scheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0 && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) && scheduleMap.get("jsdk").equals(CheckBoxEnum.UNCHECKED.getKey()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.UNCHECKED.getKey()) && beforeScheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){ int thdkfzs = DateUtil.getBetWeenMinutes(Utils.getjssjTime(beforeScheduleMap,analysisDate),Utils.getjssjTime(scheduleMap,analysisDate))+Integer.valueOf(beforeScheduleMap.get("thdkfzs").toString()); beforeScheduleMap.put("thdkfzs",thdkfzs); } } if (afterScheduleMap != null){ String afterkssj = Utils.getkssjTime(afterScheduleMap,analysisDate); if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0 && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey())){ scheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); afterScheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0 && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.UNCHECKED.getKey()) &&scheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey()) && afterScheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey())){ scheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); } if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0 && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.UNCHECKED.getKey()) &&scheduleMap.get("jsdk").equals(CheckBoxEnum.UNCHECKED.getKey()) && afterScheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey())){ int tqdkfzs = DateUtil.getBetWeenMinutes(Utils.getkssjTime(scheduleMap,analysisDate),Utils.getkssjTime(afterScheduleMap,analysisDate))+Integer.valueOf(afterScheduleMap.get("tqdkfzs").toString()); afterScheduleMap.put("tqdkfzs",tqdkfzs); } } } } } List> newList = Lists.newArrayList(); newList.addAll(workscheduleList); newList.addAll(restscheduleList); newList = newList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); return newList; } /** * 请假出差碰到休息时段时调整打卡 * @param scheduleResult * @param analysisDate * @param askForLeaveAndEvctionScheduleList * @return */ public List> adjustAskforSchedule(List> scheduleResult,String analysisDate,List> askForLeaveAndEvctionScheduleList){ List> restscheduleList = scheduleResult.stream().filter(e->Utils.ifRestClassSegment(e.get("bdlx").toString())).collect(Collectors.toList()); List> newList = Lists.newArrayList(); if (askForLeaveAndEvctionScheduleList.size()>1){ askForLeaveAndEvctionScheduleList = askForLeaveAndEvctionScheduleList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList()); for (int i = 0; i < askForLeaveAndEvctionScheduleList.size() - 1; i++) { String beforeDtkssj = Utils.getkssjTime(askForLeaveAndEvctionScheduleList.get(i),analysisDate); String beforeDtjssj = Utils.getjssjTime(askForLeaveAndEvctionScheduleList.get(i),analysisDate); String afterDtkssj = Utils.getkssjTime(askForLeaveAndEvctionScheduleList.get(i+1),analysisDate); String afterDtjssj= Utils.getkssjTime(askForLeaveAndEvctionScheduleList.get(i+1),analysisDate); List> occupyRestSchedule = restscheduleList.stream().filter(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).compareTo(DateUtil.getTime(beforeDtjssj))<=0 && DateUtil.getTime(Utils.getjssjTime(e,analysisDate)).compareTo(DateUtil.getTime(beforeDtjssj)) >= 0).collect(Collectors.toList()); if (occupyRestSchedule.size() > 0 && DateUtil.getTime(Utils.getjssjTime(occupyRestSchedule.get(0),analysisDate)).compareTo(DateUtil.getTime(afterDtkssj)) >=0){ askForLeaveAndEvctionScheduleList.get(i).put("jsdk",CheckBoxEnum.UNCHECKED.getKey()); askForLeaveAndEvctionScheduleList.get(i+1).put("ksdk",CheckBoxEnum.UNCHECKED.getKey()); } } newList=askForLeaveAndEvctionScheduleList; }else { newList = askForLeaveAndEvctionScheduleList; } return newList; } /** * 早晚上下班弹性 */ public void flexibleWork(List clcokInTimeData,List> scheduleResult){ List> clockInTimeList = (List>) params.get("clockInTimeList"); List> workScheduleList = scheduleResult.stream().filter(e -> ClassSegmentTypeEnum.WORK_TIME.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.EARLY_OVERTIME.getKey().equals(e.get("bdlx"))).collect(Collectors.toList()); if (scheduleResult.size() > 0 && workScheduleList.size()>0) { //请假和外出集合 List> leaveAndEvctionList = scheduleResult.stream().filter(e -> ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.EVECTION.getKey().equals(e.get("bdlx"))).collect(Collectors.toList()); //是否弹性 String sfdx = Util.null2String(workScheduleList.get(0).get("sfdx")); //上班是否需要打卡 String ifToWorkClock = Util.null2String(workScheduleList.get(0).get("ksdk")); //下班是否需要打卡 String ifToCloseClock = Util.null2String(workScheduleList.get(workScheduleList.size()-1).get("jsdk")); //第一条工作时段、早上加班 if (workScheduleList.size() > 0 && CheckBoxEnum.CHECKED.getKey().equals(sfdx)) { //最大弹性分钟 int zddxfz = Integer.valueOf(Util.null2String(workScheduleList.get(0).get("zddxfz"))); //弹性核算 int dxhs = Integer.valueOf(Util.null2String(workScheduleList.get(0).get("dxhs"))); Map ksdkMap = workScheduleList.get(0); //最早上班时间 String kssjStart = Utils.getkssjTime(ksdkMap,analysisDate); Map jsdkMap = workScheduleList.get(workScheduleList.size() - 1); //最晚下班时间 int thdkfzs = Integer.valueOf(Util.null2String(jsdkMap.get("thdkfzs")).equals("")?"60":Util.null2String(jsdkMap.get("thdkfzs"))); String jssjEnd = Utils.getjssjTime(jsdkMap,analysisDate); //弹性上班时间 String flexibleWorkTime = ""; //弹性下班时间 String flexibleOffWorkTime=""; if (leaveAndEvctionList.size() >0){ //第一笔请假、外出时间 Map leaveAndEvctionMap = leaveAndEvctionList.get(0); String leaveAndEvctionkssj = Utils.getkssjTime(leaveAndEvctionMap,analysisDate); //最大开始弹性时间 String minkssjStart = DateUtil.beforeMinutes(kssjStart,zddxfz); String maxkssjStart = DateUtil.AfterMinutes(kssjStart,zddxfz); //请假开始时间在最大开始弹性时间之内 if (DateUtil.getTime(leaveAndEvctionkssj).compareTo(DateUtil.getTime(maxkssjStart))<=0){ //弹性上班卡 flexibleWorkTime = leaveAndEvctionkssj; if (DateUtil.getTime(leaveAndEvctionkssj).compareTo(DateUtil.getTime(minkssjStart)) <0){ flexibleWorkTime=minkssjStart; } //弹性下班时间点 int betweenToWorkTime = DateUtil.getBetWeenMinutes(flexibleWorkTime, kssjStart); //弹性下班时间点 flexibleOffWorkTime = jssjEnd; if (betweenToWorkTime >= 0) { flexibleOffWorkTime = DateUtil.beforeMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime)); } else if (betweenToWorkTime < 0) { flexibleOffWorkTime = DateUtil.AfterMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime)); } } } //弹性上班卡 for (int i = 0; i < clcokInTimeData.size(); i++) { ClockPointDTO clockdto = clcokInTimeData.get(i); //需要计算的班次打卡时间点 String pointTime = clockdto.getClassTime(); //start:开始打卡时间点,end:结束打卡时间点 ClockPointEnum pointType = clockdto.getPointType(); //重新获取最早上班时间 Map> startNearestClcokInTime = Utils.getNearestClcokInTimeCmd(DateUtil.beforeMinutes(clockdto.getClassTime(),zddxfz), clockInTimeList); ClockPointEnum timeType = getStartClassTimeType(ksdkMap,startNearestClcokInTime,kssjStart,DateUtil.beforeMinutes(kssjStart,zddxfz)); clockdto.setTimeType(timeType); clockdto.setClockTime(startNearestClcokInTime.get(timeType)); Map clcokInTime = clockdto.getClockTime(); if (pointTime.equals(kssjStart) && ClockPointEnum.START.equals(pointType) && clcokInTime != null && CheckBoxEnum.CHECKED.getKey().equals(ifToWorkClock)) { //该卡点是弹性开始时间 //弹性上班期间未被请假开始时间占据 if ("".equals(flexibleWorkTime) ){ String signTime = clcokInTime.get("signdate") + " " + clcokInTime.get("signtime"); if (ClockPointEnum.BEFORE.equals(timeType)) { int betWeenTime = DateUtil.getBetWeenMinutes(signTime, kssjStart); if (betWeenTime <= zddxfz) { betWeenTime = Double.valueOf(Utils.getItemdurationDown(dxhs, AccountingUnitEnum.MINUTES.getKey(), betWeenTime, AccountingUnitEnum.MINUTES)).intValue(); flexibleWorkTime = DateUtil.beforeMinutes(kssjStart, betWeenTime); clockdto.setTimeType(ClockPointEnum.EQUAL); } else if (betWeenTime > zddxfz) { flexibleWorkTime = DateUtil.beforeMinutes(kssjStart, zddxfz); } clockdto.setElasticTime(flexibleWorkTime); } else if (ClockPointEnum.AFTER.equals(timeType)) { //迟到 int betWeenTime = DateUtil.getBetWeenMinutes(kssjStart, signTime); if (betWeenTime <= zddxfz) { betWeenTime = Double.valueOf(Utils.getItemduration(dxhs, AccountingUnitEnum.MINUTES.getKey(), betWeenTime, AccountingUnitEnum.MINUTES,Double.valueOf(scheduleResult.get(0).get("edsc").toString()))).intValue(); flexibleWorkTime = DateUtil.AfterMinutes(kssjStart, betWeenTime); clockdto.setTimeType(ClockPointEnum.EQUAL); } else if (betWeenTime > zddxfz) { flexibleWorkTime = DateUtil.AfterMinutes(kssjStart, zddxfz); } clockdto.setElasticTime(flexibleWorkTime); } }else { //弹性上班期间被请假开始时间占据 clockdto.setElasticTime(flexibleWorkTime); } //重新设置打卡时间 int startWorkIndex = needClockDateList.indexOf(kssjStart); needClockDateList.remove(startWorkIndex); needClockDateList.add(startWorkIndex,clockdto.getElasticTime()); } else if (pointTime.equals(jssjEnd) && ClockPointEnum.END.equals(pointType) && CheckBoxEnum.CHECKED.getKey().equals(ifToCloseClock)) { //该卡点是弹性下班点 if ("".equals(flexibleOffWorkTime) && !"".equals(flexibleWorkTime)){ int betweenToWorkTime = DateUtil.getBetWeenMinutes(flexibleWorkTime, kssjStart); //弹性下班时间点 flexibleOffWorkTime = jssjEnd; if (betweenToWorkTime >= 0) { flexibleOffWorkTime = DateUtil.beforeMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime)); } else if (betweenToWorkTime < 0) { flexibleOffWorkTime = DateUtil.AfterMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime)); } } if (!"".equals(flexibleOffWorkTime)){ //重新设置打卡时间 int endWorkIndex = needClockDateList.indexOf(jssjEnd); needClockDateList.remove(endWorkIndex); needClockDateList.add(endWorkIndex,flexibleOffWorkTime); //根据弹性下班时间点重新计算 Map> jsdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(flexibleOffWorkTime, clockInTimeList); ClockPointEnum newtimeType = getEndClassTimeType(jsdkMap,jsdkNearestClcokInTime,flexibleOffWorkTime,flexibleOffWorkTime); clockdto.setClassTime(jssjEnd); clockdto.setPointType(ClockPointEnum.END); clockdto.setTimeType(newtimeType); clockdto.setElasticTime(flexibleOffWorkTime); clockdto.setClockTime(jsdkNearestClcokInTime.get(newtimeType)); } } } } } } /** * 休息时段弹性 */ public void flexibleRestClass(List> restScheduleList,List clcokInTimeData,List> scheduleResult){ String analysisDate = Util.null2String(params.get("analysisDate")); List> clockInTimeList = (List>) params.get("clockInTimeList"); for (Map restSchedule:restScheduleList){ String dtkssj = Utils.getkssjTime(restSchedule,analysisDate); String dtjssj = Utils.getjssjTime(restSchedule,analysisDate); //最大弹性分钟 int dtzddxfz = Integer.valueOf(Util.null2String(restSchedule.get("dtzddxfz"))); //弹性核算 double dtdxhs = Utils.convertDouble(restSchedule.get("dtdxhs")); //下班去休息卡点 ClockPointDTO toRestClockPointDTO = null; //休息完上班卡点,. ClockPointDTO endRestClockPointDTO = null; for (ClockPointDTO clockPointDTO:clcokInTimeData){ if (clockPointDTO.getClassTime().equals(dtkssj) && clockPointDTO.getPointType()==ClockPointEnum.END){ toRestClockPointDTO = clockPointDTO; }else if (clockPointDTO.getClassTime().equals(dtjssj) && clockPointDTO.getPointType()==ClockPointEnum.START){ endRestClockPointDTO = clockPointDTO; } } List> endRestSchedule = scheduleResult.stream().filter(e->dtjssj.equals(Utils.getkssjTime(e,analysisDate))).collect(Collectors.toList()); List> startRestSchedule = scheduleResult.stream().filter(e->dtkssj.equals(Utils.getjssjTime(e,analysisDate))).collect(Collectors.toList()); /** * 当休息时段的开始和结束时间都要打卡时才进行弹性 */ if (toRestClockPointDTO != null && endRestClockPointDTO != null && toRestClockPointDTO.getClockTime() != null){ String toRestClassTime = toRestClockPointDTO.getClassTime(); String endRestClassTime = endRestClockPointDTO.getClassTime(); Map> toRestNearestClcokInTime = Utils.getNearestClcokInTimeCmd(DateUtil.beforeMinutes(dtkssj,dtzddxfz), clockInTimeList); ClockPointEnum timeType = getEndClassTimeType(startRestSchedule.get(0),toRestNearestClcokInTime,dtkssj,DateUtil.AfterMinutes(dtkssj,dtzddxfz)); toRestClockPointDTO.setTimeType(timeType); toRestClockPointDTO.setClockTime(toRestNearestClcokInTime.get(timeType)); Map toRestClockTimeMap = toRestClockPointDTO.getClockTime(); if (toRestClockTimeMap == null || toRestClockTimeMap.size() == 0 || toRestClockPointDTO.getTimeType() == ClockPointEnum.EQUAL || toRestClockPointDTO.getTimeType() == ClockPointEnum.EMPTY){ //不存在打卡时间,打卡时间与班次时间相等,漏卡 continue; } String toRestClockTime = toRestClockTimeMap.get("signdate")+" "+toRestClockTimeMap.get("signtime"); int betweenMinute = 0; //设置下上班的弹性时间 if (toRestClockPointDTO.getTimeType() == ClockPointEnum.BEFORE){ betweenMinute = DateUtil.getBetWeenMinutes(toRestClockTime,toRestClassTime); if (betweenMinute > dtzddxfz){ toRestClockPointDTO.setElasticTime(DateUtil.beforeMinutes(toRestClassTime,dtzddxfz)); toRestClockPointDTO.setTimeType(ClockPointEnum.BEFORE); endRestClockPointDTO.setElasticTime(DateUtil.beforeMinutes(endRestClassTime,dtzddxfz)); }else { betweenMinute = Double.valueOf(Utils.getItemdurationDown(dtdxhs, AccountingUnitEnum.MINUTES.getKey(), betweenMinute, AccountingUnitEnum.MINUTES)).intValue(); endRestClockPointDTO.setElasticTime(DateUtil.beforeMinutes(endRestClassTime,betweenMinute)); } }else if (toRestClockPointDTO.getTimeType() == ClockPointEnum.AFTER){ betweenMinute = DateUtil.getBetWeenMinutes(toRestClassTime,toRestClockTime); betweenMinute = Double.valueOf(Utils.getItemdurationDown(dtdxhs, AccountingUnitEnum.MINUTES.getKey(), betweenMinute, AccountingUnitEnum.MINUTES)).intValue(); endRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(endRestClassTime,betweenMinute)); if (betweenMinute > dtzddxfz){ toRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(toRestClassTime,dtzddxfz)); toRestClockPointDTO.setTimeType(ClockPointEnum.AFTER); endRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(endRestClassTime,dtzddxfz)); }else { betweenMinute = Double.valueOf(Utils.getItemdurationDown(dtdxhs, AccountingUnitEnum.MINUTES.getKey(), betweenMinute, AccountingUnitEnum.MINUTES)).intValue(); endRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(endRestClassTime,betweenMinute)); } } if (betweenMinute <= dtzddxfz){ toRestClockPointDTO.setElasticTime(toRestClockTime); toRestClockPointDTO.setTimeType(ClockPointEnum.EQUAL); } //重新设置打卡时间 int toRestIndex = needClockDateList.indexOf(toRestClockPointDTO.getClassTime()); needClockDateList.remove(toRestIndex); needClockDateList.add(toRestIndex,toRestClockPointDTO.getElasticTime()); int endRestIndex = needClockDateList.indexOf(endRestClockPointDTO.getClassTime()); needClockDateList.remove(endRestIndex); needClockDateList.add(endRestIndex,endRestClockPointDTO.getElasticTime()); //变更休息时间 restSchedule.put("dtkssj",toRestClockPointDTO.getElasticTime().split(" ")[1]); restSchedule.put("dtjssj",endRestClockPointDTO.getElasticTime().split(" ")[1]); //根据弹性上班时间点重新获取打卡时间 Map> ksdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(endRestClockPointDTO.getElasticTime(), clockInTimeList); ClockPointEnum endResttimeType = getStartClassTimeType(endRestSchedule.get(0),ksdkNearestClcokInTime,endRestClockPointDTO.getElasticTime(),endRestClockPointDTO.getElasticTime()); endRestClockPointDTO.setClockTime(ksdkNearestClcokInTime.get(endResttimeType)); endRestClockPointDTO.setTimeType(endResttimeType); if (endRestClockPointDTO.getTimeType() == ClockPointEnum.EMPTY || endRestClockPointDTO.getClockTime() == null){ //当弹性结束未匹配到打卡,弹性失效,进行还原 restSchedule.put("dtkssj",toRestClockPointDTO.getClassTime().split(" ")[1]); restSchedule.put("dtjssj",endRestClockPointDTO.getClassTime().split(" ")[1]); //重新设置打卡时间 toRestIndex = needClockDateList.indexOf(toRestClockPointDTO.getElasticTime()); needClockDateList.remove(toRestIndex); needClockDateList.add(toRestIndex,toRestClockPointDTO.getClassTime()); endRestIndex = needClockDateList.indexOf(endRestClockPointDTO.getElasticTime()); needClockDateList.remove(endRestIndex); needClockDateList.add(endRestIndex,endRestClockPointDTO.getClassTime()); if (toRestClockPointDTO.getClockTime() != null){ String time = toRestClockPointDTO.getClockTime().get("signdate")+" "+toRestClockPointDTO.getClockTime().get("signtime"); if (DateUtil.getTime(time).compareTo(DateUtil.getTime(toRestClockPointDTO.getClassTime())) > 0){ toRestClockPointDTO.setTimeType(ClockPointEnum.AFTER); }else if (DateUtil.getTime(time).compareTo(DateUtil.getTime(toRestClockPointDTO.getClassTime())) ==0){ toRestClockPointDTO.setTimeType(ClockPointEnum.EQUAL); }else { toRestClockPointDTO.setTimeType(ClockPointEnum.BEFORE); } } toRestClockPointDTO.setElasticTime(null); endRestClockPointDTO.setElasticTime(null); } } } } /** * 获取开始打卡的打卡数据在卡点的位置 * @param needClockIn * @param ksdkNearestClcokInTime * @return */ public ClockPointEnum getStartClassTimeType(Map needClockIn,Map> ksdkNearestClcokInTime,String dtkssj,String minelasticTime){ int tqdkfzs = 60; if (Util.null2String(needClockIn.get("tqdkfzs")).equals("") && !"".equals(getBeforeClockTime(needClockDateList,dtkssj))){ tqdkfzs = DateUtil.getBetWeenMinutes(getBeforeClockTime(needClockDateList,dtkssj),dtkssj); }else { tqdkfzs = Util.null2String(needClockIn.get("tqdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("tqdkfzs").toString()); } ClockPointEnum timeType = ClockPointEnum.EMPTY; if (ksdkNearestClcokInTime.get(ClockPointEnum.EQUAL) != null) { timeType = ClockPointEnum.EQUAL; } if (ClockPointEnum.EMPTY.equals(timeType) && ksdkNearestClcokInTime.get(ClockPointEnum.BEFORE) != null) { String clockInTime = ksdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signdate") + " " + ksdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signtime"); if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.beforeMinutes(minelasticTime, tqdkfzs))) >= 0 && (getBeforeClockTime(needClockDateList,dtkssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,dtkssj))) > 0)) { //打卡时间大于等于最早打卡时间 timeType = ClockPointEnum.BEFORE; } } if (ClockPointEnum.EMPTY.equals(timeType) && ksdkNearestClcokInTime.get(ClockPointEnum.AFTER) != null) { String clockInTime = ksdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signdate") + " " + ksdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signtime"); if (getNextClockTime(needClockDateList,dtkssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtkssj))) < 0) { //打卡时间小于结束时间 timeType = ClockPointEnum.AFTER; } } return timeType; } /** * 获取结束打卡的打卡数据在卡点的位置 * @param needClockIn * @param jsdkNearestClcokInTime * @return */ public ClockPointEnum getEndClassTimeType(Map needClockIn,Map> jsdkNearestClcokInTime,String dtjssj,String maxelasticTime){ int thdkfzs = 60; if (Util.null2String(needClockIn.get("thdkfzs")).equals("") && !"".equals(getNextClockTime(needClockDateList,dtjssj))){ thdkfzs = DateUtil.getBetWeenMinutes(dtjssj,getNextClockTime(needClockDateList,dtjssj)); }else { thdkfzs = Util.null2String(needClockIn.get("thdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("thdkfzs").toString()); } ClockPointEnum timeType = ClockPointEnum.EMPTY; if (jsdkNearestClcokInTime.get(ClockPointEnum.EQUAL) != null) { timeType = ClockPointEnum.EQUAL; } if (ClockPointEnum.EMPTY.equals(timeType) && jsdkNearestClcokInTime.get(ClockPointEnum.AFTER) != null) { String clockInTime = jsdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signdate") + " " + jsdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signtime"); if (dtjssj.equals(maxelasticTime)){ if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(maxelasticTime, thdkfzs))) <= 0 && (getNextClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtjssj))) < 0)) { timeType = ClockPointEnum.AFTER; } }else { //弹性逻辑 if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(maxelasticTime, thdkfzs))) <= 0 && (getNextClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtjssj))) < 0 || DateUtil.getTime(maxelasticTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtjssj))) >= 0)) { timeType = ClockPointEnum.AFTER; } } if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(maxelasticTime, thdkfzs))) <= 0) { timeType = ClockPointEnum.AFTER; } } if (ClockPointEnum.EMPTY.equals(timeType) && jsdkNearestClcokInTime.get(ClockPointEnum.BEFORE) != null) { String clockInTime = jsdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signdate") + " " + jsdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signtime"); if (dtjssj.equals(maxelasticTime)){ if (getBeforeClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,dtjssj))) > 0) { timeType = ClockPointEnum.BEFORE; } }else { int betweenTime = DateUtil.getBetWeenMinutes(dtjssj,maxelasticTime); if (getBeforeClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,dtjssj))) > 0 || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.beforeMinutes(dtjssj,betweenTime))) >=0) { timeType = ClockPointEnum.BEFORE; } } } return timeType; } public String getNextClockTime(List needClockDateList,String time){ int index = 0; for (int i=0;i needClockDateList,String time){ int index = 0; for (int i=0;i= 0){ return needClockDateList.get(index); }else { return ""; } } /** * 判断是否是工作(包含加班)类型时段 * @param classSegmentType * @return */ public boolean ifWorkClassSegment(String classSegmentType){ if (classSegmentType.equals(ClassSegmentTypeEnum.WORK_TIME.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.EXTENDED_OVERTIME.getKey()) ||classSegmentType.equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.EARLY_OVERTIME.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.OVERTIME_IN_CLASS.getKey())){ return true; }else { return false; } } public ClockPointEnum getTimeType(ClockPointDTO clockPointDTO,Map clockInMap){ if (clockInMap == null){ return ClockPointEnum.EMPTY; } String clockInTime = clockInMap.get("signdate")+ " "+clockInMap.get("signtime"); int compare = DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(clockPointDTO.getClassTime())); if (compare == 0){ return ClockPointEnum.EQUAL; }else if (compare > 0){ return ClockPointEnum.AFTER; }else { return ClockPointEnum.BEFORE; } } }