diff --git a/.gitignore b/.gitignore index f21a676..7311d6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /weaver-develop.iml /out/ -.idea/ +/.idea/ HELP.md target/ diff --git a/.idea/artifacts/weaver_develop_jar.xml b/.idea/artifacts/weaver_develop_jar.xml index 6258dfe..2aff103 100644 --- a/.idea/artifacts/weaver_develop_jar.xml +++ b/.idea/artifacts/weaver_develop_jar.xml @@ -1,6 +1,6 @@ - $PROJECT_DIR$/out/artifacts/weaver_develop_jar + $PROJECT_DIR$/../../../../weaver/ecology/WEB-INF/lib diff --git a/src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java b/src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java new file mode 100644 index 0000000..7400c8c --- /dev/null +++ b/src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java @@ -0,0 +1,2904 @@ +package com.engine.kq.biz; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.entity.KQOvertimeRulesDetailEntity; +import com.engine.kq.entity.TimeScopeEntity; +import com.engine.kq.entity.WorkTimeEntity; +import com.engine.kq.jucailin.util.KQDateUtil; +import com.engine.kq.log.KQLog; +import com.engine.kq.timer.KQOvertimeCardBean; +import com.engine.kq.util.KQDurationCalculatorUtil; +import com.engine.kq.wfset.bean.OvertimeBalanceTimeBean; +import com.engine.kq.wfset.bean.SplitBean; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.sql.Timestamp; +import org.apache.commons.collections4.CollectionUtils; +import weaver.common.DateUtil; +import weaver.conn.RecordSet; +import weaver.general.Util; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +/** + * 根据加班规则计算加班和调休数据 + * 主要是针对 流程+打卡 打卡 这几种方式 + */ +public class KQOverTimeRuleCalBiz { + private KQLog kqLog = new KQLog(); + + /** + * 生成加班数据 + * @param resourceid + * @param fromDate + * @param toDate + * @param eventtype + */ + public void buildOvertime(String resourceid, String fromDate, String toDate, String eventtype){ + + try{ + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + Map changeTypeMap = Maps.newHashMap(); + Map overRulesDetailMap = Maps.newHashMap(); + Map> restTimeMap = Maps.newHashMap(); + Map computingModeMap = Maps.newHashMap(); + //先获取一些前提数据,加班規則和假期規則 + getOverTimeDataMap(resourceid, fromDate, toDate, dateFormatter,changeTypeMap,overRulesDetailMap,restTimeMap,computingModeMap); + Map eventLogMap = Maps.newHashMap(); + eventLogMap.put("fromDate", fromDate); + eventLogMap.put("toDate", toDate); + eventLogMap.put("eventtype", eventtype); + KQOvertimeLogBiz kqEventLogBiz = new KQOvertimeLogBiz(); + String logKey = "|key|"+resourceid+"_"+fromDate+"_"+toDate; + String main_uuid = kqEventLogBiz.logEvent(resourceid,eventLogMap,"buildOvertime|生成加班调休"+logKey); + + LocalDate localFromDate = LocalDate.parse(fromDate); + LocalDate localToDate = LocalDate.parse(toDate); + LocalDate preFromDate = localFromDate.minusDays(1); + LocalDate nextToDate = localToDate.plusDays(1); + //之前是考虑外部考勤数据导入跨天打卡,判断归属的问题,向前算一天,现在不管了,都是默认只处理当天的 + if(eventtype.indexOf("#flow,") > -1 || eventtype.indexOf("punchcard") > -1 || true){ + //如果是正常走的加班流程,就是流程开始日期和结束日期,只有补卡,打卡,同步的时候才需要处理一下前一天和后一天的数据 + preFromDate = localFromDate; + nextToDate = localToDate; + } + long betweenDays = nextToDate.toEpochDay() - preFromDate.toEpochDay(); + for (int i = 0; i <= betweenDays; i++) { + LocalDate curLocalDate = preFromDate.plusDays(i); + String splitDate = curLocalDate.format(dateFormatter); + String key = resourceid + "_" + splitDate; + Map overtimeLogMap = Maps.newLinkedHashMap(); + Map eventMap = Maps.newLinkedHashMap(); + //加班日志记录类 + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTimeEntity = kqWorkTime.getWorkTime(resourceid, splitDate); + Map workTimeEntityLogMap = Maps.newHashMap(); + workTimeEntityLogMap.put("resourceid", resourceid); + workTimeEntityLogMap.put("splitDate", splitDate); + workTimeEntityLogMap.put("workTimeEntity", workTimeEntity); + String uuid = kqEventLogBiz.logDetailWorkTimeEntity(resourceid,workTimeEntityLogMap,main_uuid,"doComputingMode|加班打卡|key|"+key); + + try{ + Map lsCheckInfoMaps = Maps.newLinkedHashMap(); + //获取加班打卡数据 + getOverTimeCardDataMap(resourceid, splitDate, splitDate, dateFormatter,kqTimesArrayComInfo,overRulesDetailMap,changeTypeMap,lsCheckInfoMaps,eventMap); + + Iterator> iterator = lsCheckInfoMaps.entrySet().iterator(); + while (iterator.hasNext()) { + Entry next = iterator.next(); + String mapKey = next.getKey(); + KQOvertimeCardBean kqOvertimeCardBean = next.getValue(); + String[] mapKeys = mapKey.split("_"); + if (mapKeys.length != 2) { + continue; + } + String realSplitDate = mapKeys[1]; + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + int computingMode = Util.getIntValue(""+computingModeMap.get(changeType_key),-1); + + boolean isOk = true; +//把原来下面一个方法里的内容要抽出来,是因为存在如下的问题,如果我是跨天打卡,次日3点,加班归属点设置的是次日2点,2-3这部分的是属于第二天的,需要判断下第二天的加班方式是不是doComputingMode2,如果不是就需要去走对应的doComputingMode方法 + if(2 == computingMode){ + isOk = doComputingMode2WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(3 == computingMode){ + isOk = doComputingMode3WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(4 == computingMode){ + isOk = doComputingMode4WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + } + if(!isOk){ + continue; + } + } + }catch (Exception e){ + kqLog.info("加班生成数据报错:KQOverTimeRuleCalBiz:"); + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + }finally { + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode|对应的加班数据|key|"+key); + } + + } + fromDate=preFromDate.format(dateFormatter); + updateTiaoXiu(resourceid, fromDate, toDate); + }catch (Exception e){ + kqLog.info("加班生成数据报错:KQOverTimeRuleCalBiz:"); + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + } + } + + + /** + * 更新调休 + * @param resourceid + * @param fromDate + * @param toDate + */ + public void updateTiaoXiu(String resourceid, String fromDate, String toDate){ + Timestamp updateDate = KQDateUtil.getUpdateTimeStamp(); + //假期类型的缓存类 + KQLeaveRulesComInfo rulesComInfo = new KQLeaveRulesComInfo(); + //[调休]的假期类型的ID + String leaveRulesId = ""; + //找到[调休]的假期类型ID + rulesComInfo.setTofirstRow(); + while (rulesComInfo.next()) { + if (KQLeaveRulesBiz.isTiaoXiu(rulesComInfo.getId())) { + if("1".equals(rulesComInfo.getIsEnable())){ + leaveRulesId = rulesComInfo.getId(); + break; + } + } + } + if("".equals(leaveRulesId) || null == leaveRulesId){ + return; + } + RecordSet recordSet = new RecordSet(); + String sql = " select * from kq_balanceOfLeave " + + " where (isDelete is null or isDelete<>1) and resourceId=" + resourceid + + " and leaveRulesId=" + leaveRulesId + + " and effectiveDate>='" + fromDate + "' and effectiveDate<='" +toDate+"'"+ + " order by belongYear asc,effectiveDate asc,id asc "; + recordSet.executeQuery(sql); + String all_tiaoxiuids = ""; + BigDecimal duration = new BigDecimal("0"); + while (recordSet.next()) { + //额外 + BigDecimal extraAmount = new BigDecimal(Util.null2s(recordSet.getString("extraAmount"), "0")); + //加班生成调休 + BigDecimal tiaoxiuAmount = new BigDecimal(Util.null2s(recordSet.getString("tiaoxiuamount"), "0")); + //已休 + BigDecimal usedAmount = new BigDecimal(Util.null2s(recordSet.getString("usedAmount"), "0")); + + if (extraAmount.add(tiaoxiuAmount).subtract(usedAmount).doubleValue() >= 0) { + continue; + } + String id = recordSet.getString("id"); + if(id.length() > 0 && Util.getIntValue(id) > 0){ + all_tiaoxiuids += ","+id; + duration =duration.add(extraAmount).add(tiaoxiuAmount).subtract(usedAmount); + } + } + duration = duration.abs(); + List updateList = new ArrayList(); + sql = " select * from kq_balanceOfLeave " + + " where (isDelete is null or isDelete<>1) and resourceId=" + resourceid + + " and leaveRulesId=" + leaveRulesId + + " and effectiveDate>='" + fromDate + "'"+ + " order by belongYear asc,effectiveDate asc,id asc "; + recordSet.executeQuery(sql); + int total = recordSet.getCounts(); + int index = 0; + while (recordSet.next()) { + index++; + String id = recordSet.getString("id"); + //额外 + BigDecimal extraAmount = new BigDecimal(Util.null2s(recordSet.getString("extraAmount"), "0")); + //加班生成调休 + BigDecimal tiaoxiuAmount = new BigDecimal(Util.null2s(recordSet.getString("tiaoxiuamount"), "0")); + //已休 + BigDecimal usedAmount = new BigDecimal(Util.null2s(recordSet.getString("usedAmount"), "0")); + + if (extraAmount.add(tiaoxiuAmount).subtract(usedAmount).doubleValue() <= 0) { + continue; + } + BigDecimal temp = extraAmount.add(tiaoxiuAmount).subtract(usedAmount).subtract(duration); + /*该假期剩余假期余额不足以扣减,记录错误日志,退出方法*/ + if (index == total && temp.doubleValue() < 0) { + kqLog.info("该人员的该假期所有的剩余假期余额都不足以扣减。" + + "resourceId=" + resourceid + ",date=" + fromDate + ",ruleId=" + leaveRulesId + ",duration=" + duration + ",extraAmount=" + extraAmount.doubleValue() + ",usedAmount=" + usedAmount.doubleValue()); + String newUsedAmount = usedAmount.add(duration).setScale(5, RoundingMode.HALF_UP).toPlainString(); + String updateSql = "update kq_balanceOfLeave set usedAmount=" + (newUsedAmount) + ", update_time=? where id=" + id; + updateList.add(updateSql); + break; + } + if (temp.doubleValue() >= 0) { + String newUsedAmount = usedAmount.add(duration).setScale(5, RoundingMode.HALF_UP).toPlainString(); + String updateSql = "update kq_balanceOfLeave set usedAmount=" + (newUsedAmount) + ", update_time=? where id=" + id; + updateList.add(updateSql); + break; + } else { + duration = duration.add(usedAmount).subtract(extraAmount).subtract(tiaoxiuAmount); + String newUsedAmount = extraAmount.add(tiaoxiuAmount).setScale(5, RoundingMode.HALF_UP).toPlainString(); + String updateSql = "update kq_balanceOfLeave set usedAmount=" + (newUsedAmount) + ", update_time=? where id=" + id; + updateList.add(updateSql); + continue; + } + } + if(all_tiaoxiuids.length() > 0) { + all_tiaoxiuids = all_tiaoxiuids.substring(1); + updateList.add("update kq_balanceOfLeave set isDelete=1, update_time=? where id in (" +all_tiaoxiuids+")"); + } + kqLog.info("updateList:"+updateList); + /*SQL操作批处理*/ + for (int i = 0; i < updateList.size(); i++) { + boolean flag = recordSet.executeUpdate(updateList.get(i),updateDate); + if (!flag) { + kqLog.info("刷新加班流程数据失败:数据库更新失败" ); + return; + } + } + + } + + /** + * 需审批,以打卡为准,取流程和打卡的交集 + */ + private void doComputingMode4(String resourceid, String splitDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap, + Map> restTimeMap, Map computingModeMap, + KQTimesArrayComInfo kqTimesArrayComInfo, String main_uuid, + Map lsCheckInfoMaps) throws Exception{ + String key = resourceid+"_"+splitDate; + //加班日志记录类 + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTimeEntity = kqWorkTime.getWorkTime(resourceid, splitDate); + Map workTimeEntityLogMap = Maps.newHashMap(); + workTimeEntityLogMap.put("resourceid", resourceid); + workTimeEntityLogMap.put("splitDate", splitDate); + workTimeEntityLogMap.put("workTimeEntity", workTimeEntity); + KQOvertimeLogBiz kqEventLogBiz = new KQOvertimeLogBiz(); + String uuid = kqEventLogBiz.logDetailWorkTimeEntity(resourceid,workTimeEntityLogMap,main_uuid,"doComputingMode4|加班计算,需审批,以打卡为准,取流程和打卡的交集|key|"+key); + Map overtimeLogMap = Maps.newLinkedHashMap(); + + Map eventMap = Maps.newLinkedHashMap(); + + Iterator> iterator = lsCheckInfoMaps.entrySet().iterator(); + while (iterator.hasNext()) { + Entry next = iterator.next(); + String mapKey = next.getKey(); + KQOvertimeCardBean kqOvertimeCardBean = next.getValue(); + String[] mapKeys = mapKey.split("_"); + if (mapKeys.length != 2) { + continue; + } + String realSplitDate = mapKeys[1]; + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + int computingMode = Util.getIntValue(""+computingModeMap.get(changeType_key),-1); + + boolean isOk = true; +//把原来下面一个方法里的内容要抽出来,是因为存在如下的问题,如果我是跨天打卡,次日3点,加班归属点设置的是次日2点,2-3这部分的是属于第二天的,需要判断下第二天的加班方式是不是doComputingMode2,如果不是就需要去走对应的doComputingMode方法 + if(2 == computingMode){ + isOk = doComputingMode2WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(3 == computingMode){ + isOk = doComputingMode3WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(4 == computingMode){ + isOk = doComputingMode4WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + } + if(!isOk){ + continue; + } + } + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode4|对应的加班流程数据|key|"+key); + + } + + /** + * 把获取打卡数据后处理的部分拆出来 + */ + private boolean doComputingMode4WithCard(KQOvertimeCardBean kqOvertimeCardBean, String mapKey, String resourceid, Map changeTypeMap, DateTimeFormatter dateFormatter, Map overtimeLogMap, + String splitDate, Map overRulesDetailMap, Map eventMap, KQTimesArrayComInfo kqTimesArrayComInfo, Map> restTimeMap, KQOvertimeLogBiz kqEventLogBiz, String uuid, + String realSplitDate) throws Exception{ + + Map> splitBeanMaps = Maps.newHashMap(); + //获取加班流程数据 + getOverTimeFlowData(resourceid,realSplitDate,realSplitDate,splitBeanMaps,dateFormatter); + + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + LocalDate localbelongDate = LocalDate.parse(realSplitDate); + LocalDate preLocalDate = localbelongDate.minusDays(1); + String preSplitDate = preLocalDate.format(dateFormatter); + String preChange_key = preSplitDate+"_"+resourceid; + int preChangeType = Util.getIntValue(""+changeTypeMap.get(preChange_key),-1); + String preChangeType_key = preSplitDate+"_"+preChangeType; + LocalDate nextLocalDate = localbelongDate.plusDays(1); + String nextSplitDate = nextLocalDate.format(dateFormatter); + String nextChange_key = nextSplitDate+"_"+resourceid; + int nextChangeType = Util.getIntValue(""+changeTypeMap.get(nextChange_key),-1); + String nextChangeType_key = nextSplitDate+"_"+nextChangeType; + + String changetypeName = 1==changeType ? "节假日" : (2 == changeType ? "工作日" : (3 == changeType ? "休息日" : "异常")); + String changetypeLogInfo = change_key+"|changeType|"+changeType+"|"+changetypeName; + logOvertimeMap(overtimeLogMap, changetypeLogInfo, mapKey+"|"+"加班日期属性|changetypeLogInfo"); + + clearOvertimeTX(resourceid, realSplitDate,overtimeLogMap,splitDate); + logOvertimeMap(overtimeLogMap, kqOvertimeCardBean, mapKey+"|"+"打卡和上下班数据|KQOvertimeCardBean"); + + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + if(kqOvertimeRulesDetailEntity == null){ + String overRuleInfo = "changeType_key:"+changeType_key+":kqOvertimeRulesDetailEntity:"+kqOvertimeRulesDetailEntity; + logOvertimeMap(overtimeLogMap, overRuleInfo, mapKey+"|"+"加班规则为null|kqOvertimeRulesDetailEntity"); + return false; + } + int overtimeEnable = kqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + String overtimeEnableInfo = "overtimeEnable:"+overtimeEnable; + logOvertimeMap(overtimeLogMap, overtimeEnableInfo, mapKey+"|"+"未开启加班规则|overtimeEnable"); + return false; + } + + if(kqOvertimeCardBean != null){ + + int[] initArrays = kqTimesArrayComInfo.getInitArr(); + List> hasOverTime4SignList = Lists.newArrayList(); + getHasOverTimeData(resourceid,realSplitDate,hasOverTime4SignList); + Map signinoffMap = buildOvertimeCard(kqOvertimeCardBean, resourceid, realSplitDate, kqTimesArrayComInfo, restTimeMap, changeType_key,initArrays,hasOverTime4SignList, + overRulesDetailMap,true,overtimeLogMap, preChangeType_key,nextChangeType_key); + logOvertimeMap(overtimeLogMap, signinoffMap, mapKey+"|"+"获取上下班打卡数据|signinoffMap"); + + String signinTime = Util.null2String(signinoffMap.get("signinTime")); + String signoutTime = Util.null2String(signinoffMap.get("signoutTime")); + String signinDate = Util.null2String(signinoffMap.get("signinDate")); + String signoutDate = Util.null2String(signinoffMap.get("signoutDate")); + int signinTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signinTime); + int signoutTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signoutTime); + + if(signinTimeIndex < signoutTimeIndex){ + //先覆盖打卡 打卡区间都是1 + int over_count = kqTimesArrayComInfo.getCnt(initArrays, signinTimeIndex, signoutTimeIndex, 1); + String overCountLogInfo = "signinTimeIndex:"+signinTimeIndex+":signoutTimeIndex:"+signoutTimeIndex+":over_count:"+over_count; + logOvertimeMap(overtimeLogMap, overCountLogInfo, mapKey+"|"+"打卡区间,得到打卡时长|over_count"); + if(over_count > 0){ + int restTimeType = 1; + String kqOvertimeRulesDetailEntityLogInfo = kqOvertimeRulesDetailEntity==null ? "" :JSON.toJSONString(kqOvertimeRulesDetailEntity); + logOvertimeMap(overtimeLogMap, kqOvertimeRulesDetailEntityLogInfo, mapKey+"|具体这个人这一天对应的加班规则|KQOvertimeRulesDetailEntity"); + int minimumLen = -1; + if(kqOvertimeRulesDetailEntity != null){ + minimumLen = kqOvertimeRulesDetailEntity.getMinimumLen(); + if(over_count < minimumLen){ + String minInfo = "over_count:"+over_count+":minimumLen:"+minimumLen; + logOvertimeMap(overtimeLogMap, minInfo, mapKey+"|打卡时长小于最小加班时长|over_count splitBeans = splitBeanMaps.get(mapKey); + String flowinfo = ""; + if(splitBeans != null && !splitBeans.isEmpty()){ + flowinfo = JSON.toJSONString(splitBeans, SerializerFeature.DisableCheckSpecialChar,SerializerFeature.DisableCircularReferenceDetect); + } + eventMap.put(mapKey+"|"+"加班流程数据|flowinfo", flowinfo); + + if(splitBeans == null || splitBeans.isEmpty()){ + return false; + } + + for (int m = 0; m < splitBeans.size(); m++) { + SplitBean splitBean = splitBeans.get(m); + String dataid = splitBean.getDataId(); + String detailid = splitBean.getDetailId(); + String flow_fromdate = splitBean.getFromDate(); + String flow_fromtime = splitBean.getFromTime(); + String flow_todate = splitBean.getToDate(); + String flow_totime = splitBean.getToTime(); + String fromdatedb = splitBean.getFromdatedb(); + String fromtimedb = splitBean.getFromtimedb(); + String todatedb = splitBean.getTodatedb(); + String totimedb = splitBean.getTotimedb(); + String requestid = splitBean.getRequestId(); + double d_mins = splitBean.getD_Mins(); + if(d_mins <= 0){ + continue; + } + String flow_key = mapKey+"|"+"flow_fromdate|"+flow_fromdate+"|flow_todate|"+flow_todate + +"|flow_fromtime|"+flow_fromtime+"|flow_totime|"+flow_totime; + //如果打卡数据有了,再拿流程数据去覆盖,得到有效的打卡区间,这个区间肯定已经是去除了上下班时间和休息时间还有重复打卡的部分 + List cross_time_list = Lists.newArrayList(); +// cross_time_list里存的是排除了工作时间的打卡段,找到1表示找到打卡开始的点了,找到-2表示找到打卡结束的点了 + get_cross_time_list(cross_time_list,initArrays,signinTimeIndex,signoutTimeIndex,1,-2); + logOvertimeMap(overtimeLogMap, cross_time_list, flow_key+"|cross_time_list"); + int[] initArrays_flow = Arrays.copyOfRange(initArrays,0,initArrays.length); + if(flow_fromdate.compareTo(realSplitDate) > 0){ + flow_fromtime = kqTimesArrayComInfo.turn24to48Time(flow_fromtime); + } + if(flow_todate.compareTo(realSplitDate) > 0){ + flow_totime = kqTimesArrayComInfo.turn24to48Time(flow_totime); + } + int flow_fromIndex = kqTimesArrayComInfo.getArrayindexByTimes(flow_fromtime); + int flow_toIndex = kqTimesArrayComInfo.getArrayindexByTimes(flow_totime); + //在已经打卡的区间1上覆盖2,那么在有效打卡范围内是2的就是交集的部分 + Arrays.fill(initArrays_flow, flow_fromIndex, flow_toIndex,2); + + int across_mins = 0; + for(int i = 0 ; i < cross_time_list.size() ;) { + int cross_fromtime_index = cross_time_list.get(i); + int cross_totime_index = cross_time_list.get(i + 1); + //前面打卡区间段已经都被流程给覆盖了,所以取获取打卡区间段内有多少流程的标识2,就是交叉部分了 + int flow_count = kqTimesArrayComInfo.getCnt(initArrays_flow, cross_fromtime_index, cross_totime_index, 2); + logOvertimeMap(overtimeLogMap, flow_count, flow_key+"|取打卡和流程相交的时长|flow_count"); + + if(flow_count > 0){ + List flow_cross_time_list = Lists.newArrayList(); + // 找到2表示找到流程开始的点了,找到1表示找到流程结束的点了 + get_cross_time_list(flow_cross_time_list,initArrays_flow,cross_fromtime_index,cross_totime_index,2,1); + + logOvertimeMap(overtimeLogMap, flow_cross_time_list, flow_key+"|取打卡和流程相交的区间|flow_cross_time_list"); + for(int j = 0 ; j < flow_cross_time_list.size() ;){ + int flow_cross_fromtime_index = flow_cross_time_list.get(j); + int flow_cross_totime_index = flow_cross_time_list.get(j+1); + + int mins = flow_cross_totime_index-flow_cross_fromtime_index; + if(mins <= 0){ + String crossInfo = "flow_cross_fromtime_index:"+flow_cross_fromtime_index+":flow_cross_totime_index:"+flow_cross_totime_index+":mins:"+mins; + logOvertimeMap(overtimeLogMap, crossInfo, flow_key+"|打卡时长小于最小加班时长|crossInfo"); + continue; + } + across_mins += mins; + + String flow_cross_key = "加班计算区间|"+kqTimesArrayComInfo.getTimesByArrayindex(flow_cross_fromtime_index)+"-"+kqTimesArrayComInfo.getTimesByArrayindex(flow_cross_totime_index); + logOvertimeMap(overtimeLogMap, mins, flow_cross_key+"|原始加班区间生成的加班时长|mins"); + + j =j + 2; + } }else{ + + } + i = i +2; + } + + if(kqOvertimeRulesDetailEntity != null){ + //我这个方法是针对每次生成的加班数据做排除休息时长的处理 + restTimeType = kqOvertimeRulesDetailEntity.getRestTimeType(); + if(restTimeType == 2){ + across_mins = new KQOverTimeFlowBiz().handle_restlength(across_mins,restTimeMap,changeType_key); + } + } + int card_mins = over_count; + double double_mins = getD_MinsByUnit((1.0*across_mins)); + across_mins = (int)double_mins; + if(across_mins <= 0){ + logOvertimeMap(overtimeLogMap, across_mins, flow_key+"|经过单位换算之后时长为0|across_mins"); + continue; + } + if(across_mins < minimumLen){ + String minInfo = "across_mins:"+across_mins+":minimumLen:"+minimumLen; + logOvertimeMap(overtimeLogMap, minInfo, flow_key+"|打卡时长小于最小加班时长|over_count otherParam = Maps.newHashMap(); + otherParam.put("overtime_type", overtime_type); + otherParam.put("changeType", String.valueOf(changeType)); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + if(2 == paidLeaveEnableType){ + logOvertimeMap(overtimeLogMap, overtime_type, flow_key+"|关联调休与否来自于流程选择,加班类型下拉框值|overtime_type"); + } + + int paidLeaveEnable = getPaidLeaveEnable(kqOvertimeRulesDetailEntity, overtime_type); + + otherParam.put("overtimeLogMap", overtimeLogMap); + logOvertimeMap(overtimeLogMap, across_mins, flow_key+"|最终生成的加班分钟数|overtime_mins"); + tiaoxiuId = KQBalanceOfLeaveBiz.addExtraAmountByDis5(resourceid,realSplitDate,across_mins+"","0",workingHours,requestid,"1",realSplitDate,otherParam); + if(Util.getIntValue(tiaoxiuId) > 0){ + kqLog.info("doComputingMode4 生成调休成功,调休id:"+tiaoxiuId+":resourceid:"+resourceid+":realSplitDate:"+realSplitDate); + }else{ + kqLog.info("doComputingMode4 生成调休失败,调休id:"+tiaoxiuId+":resourceid:"+resourceid+":realSplitDate:"+realSplitDate); + } + logOvertimeMap(overtimeLogMap, tiaoxiuId, flow_key+"|最终生成的调休id|tiaoxiuId"); + + String flow_overtime_sql = "insert into kq_flow_overtime (requestid,resourceid,fromdate,fromtime,todate,totime,duration_min,expiringdate,belongdate," + + "workMins,durationrule,changetype,paidLeaveEnable,computingMode,tiaoxiuId,uuid,fromdatedb,fromtimedb,todatedb,totimedb,flow_mins,card_mins,ori_belongdate,flow_dataid,create_time,update_time,creator)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + if (rs.getDBType().equals("postgresql")) { + flow_overtime_sql = "insert into kq_flow_overtime (requestid,resourceid,fromdate,fromtime,todate,totime,duration_min,expiringdate,belongdate," + + "workMins,durationrule,changetype,paidLeaveEnable,computingMode,tiaoxiuId,uuid,fromdatedb,fromtimedb,todatedb,totimedb,flow_mins,card_mins,ori_belongdate,flow_dataid,create_time,update_time,creator)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?::timestamp,?::timestamp,?) "; + } + signinTime = kqTimesArrayComInfo.turn48to24Time(signinTime); + signoutTime = kqTimesArrayComInfo.turn48to24Time(signoutTime); + if(signinTime.length() == 5){ + signinTime = signinTime+":00"; + } + if(signoutTime.length() == 5){ + signoutTime = signoutTime+":00"; + } + Long cur = System.currentTimeMillis(); + Timestamp date = new Timestamp(cur); + boolean isUp = rs.executeUpdate(flow_overtime_sql, requestid,resourceid,signinDate,signinTime,signoutDate,signoutTime,across_mins,"",realSplitDate, + "",unit,changeType,paidLeaveEnable,computingMode,tiaoxiuId,overtime_uuid,fromdatedb,fromtimedb,todatedb,totimedb,d_mins,card_mins,splitDate,flow_dataid,date,date,Util.getIntValue(resourceid)); + + String overtimeid = get_overtime_uuid(overtime_uuid); + kqEventLogBiz.updateOvertimeId(uuid, overtimeid); + } + }else{ + //有打卡没有流程 + logOvertimeMap(overtimeLogMap, mapKey, mapKey+"|"+"加班流程为空"); + } + }else{ + logOvertimeMap(overtimeLogMap, overCountLogInfo, mapKey+"|"+"打卡数据时长为0"); + } + }else{ + String overCountLogInfo = "signinTimeIndex:"+signinTimeIndex+":signoutTimeIndex:"+signoutTimeIndex; + logOvertimeMap(overtimeLogMap, overCountLogInfo, mapKey+"|"+"打卡数据异常"); + } + }else{ + logOvertimeMap(overtimeLogMap, "打卡数据KQOvertimeCardBean为null", mapKey+"|"+"打卡和上下班数据|KQOvertimeCardBean"); + } + return true; + } + + /** + * 得到有效的打卡区间,这个区间肯定已经是去除了上下班时间和休息时间还有重复打卡的部分 + * @param cross_time_list + * @param initArrays + * @param fromIndex + * @param toIndex + * @param cross_from_index + * @param cross_to_index + */ + public void get_cross_time_list(List cross_time_list, int[] initArrays, + int fromIndex, int toIndex,int cross_from_index,int cross_to_index) { + for(int i = fromIndex ; i < toIndex+1 ; i++){ + if(cross_time_list.isEmpty()){ + if(initArrays[i] == cross_from_index){ + cross_time_list.add(i); + } + }else{ + if(cross_time_list.size() % 2 != 0){ + if(initArrays[i] == cross_to_index){ + cross_time_list.add(i); + } + }else{ + if(initArrays[i] == cross_from_index){ + cross_time_list.add(i); + } + } + } + } + if(cross_time_list.size() % 2 != 0){ + cross_time_list.add(toIndex); + } + } + + /** + * 处理加班方式是 无需审批,根据打卡时间计算加班时长 + */ + private void doComputingMode3(String resourceid, String splitDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap, + Map> restTimeMap, Map computingModeMap, + KQTimesArrayComInfo kqTimesArrayComInfo, String main_uuid, + Map lsCheckInfoMaps) throws Exception{ + String key = resourceid+"_"+splitDate; + //加班日志记录类 + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTimeEntity = kqWorkTime.getWorkTime(resourceid, splitDate); + Map workTimeEntityLogMap = Maps.newHashMap(); + workTimeEntityLogMap.put("resourceid", resourceid); + workTimeEntityLogMap.put("splitDate", splitDate); + workTimeEntityLogMap.put("workTimeEntity", workTimeEntity); + KQOvertimeLogBiz kqEventLogBiz = new KQOvertimeLogBiz(); + String uuid = kqEventLogBiz.logDetailWorkTimeEntity(resourceid,workTimeEntityLogMap,main_uuid,"doComputingMode3|加班计算,无需审批,根据打卡时间计算加班时长|key|"+key); + Map overtimeLogMap = Maps.newLinkedHashMap(); + + Map eventMap = Maps.newHashMap(); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode3|对应的打卡数据|key|"+key); + + Iterator> iterator = lsCheckInfoMaps.entrySet().iterator(); + while (iterator.hasNext()) { + Entry next = iterator.next(); + String mapKey = next.getKey(); + KQOvertimeCardBean kqOvertimeCardBean = next.getValue(); + String[] mapKeys = mapKey.split("_"); + if (mapKeys.length != 2) { + continue; + } + String realSplitDate = mapKeys[1]; + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + int computingMode = Util.getIntValue(""+computingModeMap.get(changeType_key),-1); + + boolean isOk = true; +//把原来下面一个方法里的内容要抽出来,是因为存在如下的问题,如果我是跨天打卡,次日3点,加班归属点设置的是次日2点,2-3这部分的是属于第二天的,需要判断下第二天的加班方式是不是doComputingMode2,如果不是就需要去走对应的doComputingMode方法 + if(2 == computingMode){ + isOk = doComputingMode2WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(3 == computingMode){ + isOk = doComputingMode3WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(4 == computingMode){ + isOk = doComputingMode4WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + } + if(!isOk){ + continue; + } + } + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode3|对应的加班流程数据|key|"+key); + + + } + + /** + * 把获取打卡数据后处理的部分拆出来 + */ + private boolean doComputingMode3WithCard(KQOvertimeCardBean kqOvertimeCardBean, String mapKey, String resourceid, Map changeTypeMap, DateTimeFormatter dateFormatter, Map overtimeLogMap, + String splitDate, Map overRulesDetailMap, Map eventMap, KQTimesArrayComInfo kqTimesArrayComInfo, Map> restTimeMap, KQOvertimeLogBiz kqEventLogBiz, String uuid, + String realSplitDate) throws Exception{ + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + LocalDate localbelongDate = LocalDate.parse(realSplitDate); + LocalDate preLocalDate = localbelongDate.minusDays(1); + String preSplitDate = preLocalDate.format(dateFormatter); + String preChange_key = preSplitDate+"_"+resourceid; + int preChangeType = Util.getIntValue(""+changeTypeMap.get(preChange_key),-1); + String preChangeType_key = preSplitDate+"_"+preChangeType; + LocalDate nextLocalDate = localbelongDate.plusDays(1); + String nextSplitDate = nextLocalDate.format(dateFormatter); + String nextChange_key = nextSplitDate+"_"+resourceid; + int nextChangeType = Util.getIntValue(""+changeTypeMap.get(nextChange_key),-1); + String nextChangeType_key = nextSplitDate+"_"+nextChangeType; + + String changetypeName = 1==changeType ? "节假日" : (2 == changeType ? "工作日" : (3 == changeType ? "休息日" : "异常")); + String changetypeLogInfo = change_key+"|changeType|"+changeType+"|"+changetypeName; + logOvertimeMap(overtimeLogMap, changetypeLogInfo, "加班日期属性|changetypeLogInfo"); + + clearOvertimeTX(resourceid, realSplitDate,overtimeLogMap, splitDate); + + logOvertimeMap(overtimeLogMap, kqOvertimeCardBean, "打卡和上下班数据|KQOvertimeCardBean"); + + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + if(kqOvertimeRulesDetailEntity == null){ + String overRuleInfo = "changeType_key:"+changeType_key+":kqOvertimeRulesDetailEntity:"+kqOvertimeRulesDetailEntity; + logOvertimeMap(overtimeLogMap, overRuleInfo, mapKey+"|"+"加班规则为null|kqOvertimeRulesDetailEntity"); + return false; + } + int overtimeEnable = kqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + String overtimeEnableInfo = "overtimeEnable:"+overtimeEnable; + logOvertimeMap(overtimeLogMap, overtimeEnableInfo, mapKey+"|"+"未开启加班规则|overtimeEnable"); + return false; + } + if(kqOvertimeCardBean != null){ + + int[] initArrays = kqTimesArrayComInfo.getInitArr(); + Map signinoffMap = buildOvertimeCard(kqOvertimeCardBean, resourceid, realSplitDate, kqTimesArrayComInfo, restTimeMap, changeType_key,initArrays,Lists.newArrayList(),overRulesDetailMap, + true, overtimeLogMap, preChangeType_key,nextChangeType_key); + logOvertimeMap(overtimeLogMap, signinoffMap, "获取上下班打卡数据|signinoffMap"); + + String signinTime = Util.null2String(signinoffMap.get("signinTime")); + String signoutTime = Util.null2String(signinoffMap.get("signoutTime")); + String signinDate = Util.null2String(signinoffMap.get("signinDate")); + String signoutDate = Util.null2String(signinoffMap.get("signoutDate")); + int signinTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signinTime); + int signoutTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signoutTime); + String flow_cross_key = mapKey+"|"+"加班计算区间|"+signinTime+"-"+signoutTime; + + if(signinTimeIndex < signoutTimeIndex){ + int over_count = kqTimesArrayComInfo.getCnt(initArrays, signinTimeIndex, signoutTimeIndex, 1); + String countLogInfo = "signinTimeIndex:"+signinTimeIndex+":signoutTimeIndex:"+signoutTimeIndex+":over_count:"+over_count; + logOvertimeMap(overtimeLogMap, countLogInfo, mapKey+"|"+"打卡区间,得到打卡时长|over_count"); + if(over_count > 0){ + //表示加班打卡是存在的 + int restTimeType = 1; + if(kqOvertimeRulesDetailEntity != null){ + int minimumLen = kqOvertimeRulesDetailEntity.getMinimumLen(); + if(over_count < minimumLen){ + return false; + } + logOvertimeMap(overtimeLogMap, JSON.toJSONString(kqOvertimeRulesDetailEntity), mapKey+"|"+"加班规则|KQOvertimeRulesDetailEntity"); + //我这个方法是针对每次生成的加班数据做排除休息时长的处理 + restTimeType = kqOvertimeRulesDetailEntity.getRestTimeType(); + if(restTimeType == 2){ + over_count = new KQOverTimeFlowBiz().handle_restlength(over_count,restTimeMap,changeType_key); + } + } + if(over_count <= 0){ + logOvertimeMap(overtimeLogMap, "没有打卡数据", mapKey+"|"+"打卡时长|over_count"); + return false; + } + logOvertimeMap(overtimeLogMap, over_count, mapKey+"|"+"经历过休息时间之后的加班时长|over_rest_count"); + + int mins = over_count; + double double_mins = getD_MinsByUnit((1.0*mins)); + mins = (int)double_mins; + + RecordSet rs = new RecordSet(); + String overtime_uuid = UUID.randomUUID().toString(); + String tiaoxiuId = ""; + String workingHours = ""; + int computingMode = 3; + + Map otherParam = Maps.newHashMap(); + otherParam.put("changeType", String.valueOf(changeType)); + int unit = KQOvertimeRulesBiz.getMinimumUnit(); + + int paidLeaveEnable = kqOvertimeRulesDetailEntity.getPaidLeaveEnable(); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + + logOvertimeMap(overtimeLogMap, mins, flow_cross_key+"|最终生成的加班分钟数|overtime_mins"); + tiaoxiuId = KQBalanceOfLeaveBiz.addExtraAmountByDis5(resourceid,realSplitDate,mins+"","0",workingHours,"","",realSplitDate,otherParam); + if(Util.getIntValue(tiaoxiuId) > 0){ + kqLog.info("doComputingMode3 生成调休成功,调休id:"+tiaoxiuId+":resourceid:"+resourceid+":realSplitDate:"+realSplitDate); + }else{ + kqLog.info("doComputingMode3 生成调休失败,调休id:"+tiaoxiuId+":resourceid:"+resourceid+":realSplitDate:"+realSplitDate); + } + Long cur = System.currentTimeMillis(); + Timestamp date = new Timestamp(cur); + + String flow_overtime_sql = "insert into kq_flow_overtime (requestid,resourceid,fromdate,fromtime,todate,totime,duration_min,expiringdate,belongdate," + + "workMins,durationrule,changetype,paidLeaveEnable,computingMode,tiaoxiuId,uuid,fromdatedb,fromtimedb,todatedb,totimedb,flow_mins,ori_belongdate,create_time,update_time,creator)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + if (rs.getDBType().equals("postgresql")) { + flow_overtime_sql = "insert into kq_flow_overtime (requestid,resourceid,fromdate,fromtime,todate,totime,duration_min,expiringdate,belongdate," + + "workMins,durationrule,changetype,paidLeaveEnable,computingMode,tiaoxiuId,uuid,fromdatedb,fromtimedb,todatedb,totimedb,flow_mins,ori_belongdate,create_time,update_time,creator)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?::timestamp,?::timestamp,?) "; + } + signinTime = kqTimesArrayComInfo.turn48to24Time(signinTime); + signoutTime = kqTimesArrayComInfo.turn48to24Time(signoutTime); + boolean isUp = rs.executeUpdate(flow_overtime_sql, "",resourceid,signinDate,signinTime,signoutDate,signoutTime,mins,"",realSplitDate, + "",unit,changeType,paidLeaveEnable,computingMode,tiaoxiuId,overtime_uuid,"","","","",0,splitDate,date,date,Util.getIntValue(resourceid)); + + String overtimeid = get_overtime_uuid(overtime_uuid); + kqEventLogBiz.updateOvertimeId(uuid, overtimeid); + } + }else{ + logOvertimeMap(overtimeLogMap, "打卡区间不正确|"+flow_cross_key, mapKey+"|"+"打卡区间,得到打卡时长|over_count"); + } + }else{ + logOvertimeMap(overtimeLogMap, "打卡数据KQOvertimeCardBean为null", mapKey+"|"+"打卡和上下班数据|KQOvertimeCardBean"); + } + return true; + } + + /** + * 获取生成的加班id + * @param overtime_uuid + * @return + */ + public String get_overtime_uuid(String overtime_uuid) { + RecordSet rs = new RecordSet(); + String sql = "select * from kq_flow_overtime where uuid='"+overtime_uuid+"' "; + rs.executeQuery(sql); + if(rs.next()){ + return rs.getString("id"); + } + return ""; + } + + /** + * 按加班的时间段设置转调休时长 + * @param kqOvertimeRulesDetailEntity + * @return + */ + public List get_timepointList(KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity) { + List timepointList = Lists.newArrayList(); + KQOvertimeRulesBiz kqOvertimeRulesBiz = new KQOvertimeRulesBiz(); + int ruleDetailid = kqOvertimeRulesDetailEntity.getId(); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + if(1 == paidLeaveEnableType){ + int paidLeaveEnableDefaultType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableDefaultType(); + + if(paidLeaveEnableDefaultType == 3){ + Map> balanceTimethDetailMap = kqOvertimeRulesBiz.getBalanceTimeDetailMap(ruleDetailid); + if(balanceTimethDetailMap != null && !balanceTimethDetailMap.isEmpty()){ + timepointList = balanceTimethDetailMap.get("timepointList"); + } + } + }else if(2 == paidLeaveEnableType){ + int paidLeaveEnableFlowType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableFlowType(); + + if(paidLeaveEnableFlowType == 3){ + Map> balanceTimethDetailMap = kqOvertimeRulesBiz.getBalanceTimeDetailMap(ruleDetailid); + if(balanceTimethDetailMap != null && !balanceTimethDetailMap.isEmpty()){ + timepointList = balanceTimethDetailMap.get("timepointList"); + } + } + } + return timepointList; + } + + /** + * 加班补偿规则里,按照加班时段补偿方式需要获取每一个时间区间内的加班时长 + * @param timepointList + * @param overtimeBalanceTimeBeans + * @param kqTimesArrayComInfo + * @param initArrays + * @param toTime_index + * @param fromTime_index + * @param arrayIndexValue + */ + public void get_overtimeBalanceTimeBeans(List timepointList, + List overtimeBalanceTimeBeans, + KQTimesArrayComInfo kqTimesArrayComInfo, int[] initArrays, + int toTime_index,int fromTime_index,int arrayIndexValue) { + //如果 [按加班的时间段设置转调休时长] 是这种方式,还需要根据时间点来判断时间区间内的加班时长,艹 + for(int k = 0 ; k < timepointList.size() ; k++){ + OvertimeBalanceTimeBean overtimeBalanceTimeBean = new OvertimeBalanceTimeBean(); + String start_pointtime = timepointList.get(k); + int start_pointtime_index = kqTimesArrayComInfo.getArrayindexByTimes(start_pointtime); + if(k == 0){ + if(start_pointtime_index > fromTime_index){ + int timepoint_curMins = kqTimesArrayComInfo.getCnt(initArrays, fromTime_index,start_pointtime_index,arrayIndexValue); + OvertimeBalanceTimeBean ori_overtimeBalanceTimeBean = new OvertimeBalanceTimeBean(); + ori_overtimeBalanceTimeBean.setTimepoint(kqTimesArrayComInfo.getTimesByArrayindex(start_pointtime_index)); + ori_overtimeBalanceTimeBean.setTimepoint_start(kqTimesArrayComInfo.getTimesByArrayindex(fromTime_index)); + ori_overtimeBalanceTimeBean.setTimepoint_end(kqTimesArrayComInfo.getTimesByArrayindex(start_pointtime_index)); + ori_overtimeBalanceTimeBean.setTimepoint_mins(timepoint_curMins); + ori_overtimeBalanceTimeBean.setNeedTX(false); + overtimeBalanceTimeBeans.add(ori_overtimeBalanceTimeBean); + } + } + if(start_pointtime_index > toTime_index){ + continue; + } + overtimeBalanceTimeBean.setList_index(k); + int start_index = -1; + int end_index = -1; + if(k == timepointList.size()-1){ + start_index = start_pointtime_index; + end_index = toTime_index; + }else{ + if(k+1 < timepointList.size()){ + String end_pointtime = timepointList.get(k+1); + start_index = start_pointtime_index; + end_index = kqTimesArrayComInfo.getArrayindexByTimes(end_pointtime); + } + } + if(start_index < end_index){ + int timepoint_curMins = kqTimesArrayComInfo.getCnt(initArrays, start_index,end_index,arrayIndexValue); + overtimeBalanceTimeBean.setTimepoint(kqTimesArrayComInfo.getTimesByArrayindex(start_index)); + overtimeBalanceTimeBean.setTimepoint_start(kqTimesArrayComInfo.getTimesByArrayindex(start_index)); + overtimeBalanceTimeBean.setTimepoint_end(kqTimesArrayComInfo.getTimesByArrayindex(end_index)); + overtimeBalanceTimeBean.setTimepoint_mins(timepoint_curMins); + overtimeBalanceTimeBean.setNeedTX(true); + overtimeBalanceTimeBeans.add(overtimeBalanceTimeBean); + } + } + } + + /** + * 处理加班方式是 需审批,以打卡为准,但是不能超过审批时长的加班时长 + */ + private void doComputingMode2(String resourceid, String splitDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap, + Map> restTimeMap, Map computingModeMap, + KQTimesArrayComInfo kqTimesArrayComInfo, String main_uuid, + Map lsCheckInfoMaps) throws Exception{ + String key = resourceid+"_"+splitDate; + //加班日志记录类 + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTimeEntity = kqWorkTime.getWorkTime(resourceid, splitDate); + Map workTimeEntityLogMap = Maps.newHashMap(); + workTimeEntityLogMap.put("resourceid", resourceid); + workTimeEntityLogMap.put("splitDate", splitDate); + workTimeEntityLogMap.put("workTimeEntity", workTimeEntity); + KQOvertimeLogBiz kqEventLogBiz = new KQOvertimeLogBiz(); + String uuid = kqEventLogBiz.logDetailWorkTimeEntity(resourceid,workTimeEntityLogMap,main_uuid,"doComputingMode2|加班计算,需审批,以打卡为准,但是不能超过审批时长的加班时长|key|"+key); + Map overtimeLogMap = Maps.newLinkedHashMap(); + + Map eventMap = Maps.newHashMap(); + + Iterator> iterator = lsCheckInfoMaps.entrySet().iterator(); + while (iterator.hasNext()){ + Entry next = iterator.next(); + String mapKey = next.getKey(); + KQOvertimeCardBean kqOvertimeCardBean = next.getValue(); + String[] mapKeys = mapKey.split("_"); + if(mapKeys.length != 2){ + continue; + } + String realSplitDate = mapKeys[1]; + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + int computingMode = Util.getIntValue(""+computingModeMap.get(changeType_key),-1); + + boolean isOk = true; +//把原来下面一个方法里的内容要抽出来,是因为存在如下的问题,如果我是跨天打卡,次日3点,加班归属点设置的是次日2点,2-3这部分的是属于第二天的,需要判断下第二天的加班方式是不是doComputingMode2,如果不是就需要去走对应的doComputingMode方法 + if(2 == computingMode){ + isOk = doComputingMode2WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(3 == computingMode){ + isOk = doComputingMode3WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + }else if(4 == computingMode){ + isOk = doComputingMode4WithCard(kqOvertimeCardBean,mapKey,resourceid,changeTypeMap, + dateFormatter,overtimeLogMap,splitDate,overRulesDetailMap,eventMap,kqTimesArrayComInfo, + restTimeMap,kqEventLogBiz,uuid,realSplitDate); + } + if(!isOk){ + continue; + } + } + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode2|对应的加班流程数据|key|"+key); + + } + + /** + * 把获取打卡数据后处理的部分拆出来 + */ + public boolean doComputingMode2WithCard(KQOvertimeCardBean kqOvertimeCardBean, String mapKey, + String resourceid, Map changeTypeMap, DateTimeFormatter dateFormatter, + Map overtimeLogMap, String splitDate, + Map overRulesDetailMap, + Map eventMap, KQTimesArrayComInfo kqTimesArrayComInfo, + Map> restTimeMap, KQOvertimeLogBiz kqEventLogBiz, String uuid, + String realSplitDate) throws Exception{ + String change_key = realSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = realSplitDate+"_"+changeType; + + Map> splitBeanMaps = Maps.newHashMap(); + //获取加班流程数据 + getOverTimeFlowData(resourceid,realSplitDate,realSplitDate,splitBeanMaps,dateFormatter); + LocalDate localbelongDate = LocalDate.parse(realSplitDate); + LocalDate preLocalDate = localbelongDate.minusDays(1); + String preSplitDate = preLocalDate.format(dateFormatter); + String preChange_key = preSplitDate+"_"+resourceid; + int preChangeType = Util.getIntValue(""+changeTypeMap.get(preChange_key),-1); + String preChangeType_key = preSplitDate+"_"+preChangeType; + LocalDate nextLocalDate = localbelongDate.plusDays(1); + String nextSplitDate = nextLocalDate.format(dateFormatter); + String nextChange_key = nextSplitDate+"_"+resourceid; + int nextChangeType = Util.getIntValue(""+changeTypeMap.get(nextChange_key),-1); + String nextChangeType_key = nextSplitDate+"_"+nextChangeType; + + String changetypeName = 1==changeType ? "节假日" : (2 == changeType ? "工作日" : (3 == changeType ? "休息日" : "异常")); + String changetypeLogInfo = change_key+"|changeType|"+changeType+"|"+changetypeName; + logOvertimeMap(overtimeLogMap, changetypeLogInfo, mapKey+"|"+"加班日期属性|changetypeLogInfo"); + + clearOvertimeTX(resourceid, realSplitDate,overtimeLogMap, splitDate); + logOvertimeMap(overtimeLogMap, kqOvertimeCardBean, mapKey+"|"+"打卡和上下班数据|KQOvertimeCardBean"); + + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + if(kqOvertimeRulesDetailEntity == null){ + String overRuleInfo = "changeType_key:"+changeType_key+":kqOvertimeRulesDetailEntity:"+kqOvertimeRulesDetailEntity; + logOvertimeMap(overtimeLogMap, overRuleInfo, mapKey+"|"+"加班规则为null|kqOvertimeRulesDetailEntity"); + return false; + } + int overtimeEnable = kqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + String overtimeEnableInfo = "overtimeEnable:"+overtimeEnable; + logOvertimeMap(overtimeLogMap, overtimeEnableInfo, mapKey+"|"+"未开启加班规则|overtimeEnable"); + return false; + } + + if(kqOvertimeCardBean != null){ + if(splitBeanMaps.containsKey(mapKey)) { + List splitBeans = splitBeanMaps.get(mapKey); + String flowinfo = ""; + if(splitBeans != null && !splitBeans.isEmpty()){ + flowinfo = JSON.toJSONString(splitBeans, SerializerFeature.DisableCheckSpecialChar,SerializerFeature.DisableCircularReferenceDetect); + }else{ + logOvertimeMap(overtimeLogMap, "打卡数据KQOvertimeCardBean为null", mapKey+"|"+"打卡和上下班数据|KQOvertimeCardBean"); + return false; + } + eventMap.put(mapKey+"|"+"加班流程数据|flowinfo", flowinfo); + for (int m = 0; m < splitBeans.size(); m++) { + int[] initArrays_flow = kqTimesArrayComInfo.getInitArr(); + SplitBean splitBean = splitBeans.get(m); + String dataid = splitBean.getDataId(); + String detailid = splitBean.getDetailId(); + String flow_fromdate = splitBean.getFromDate(); + String flow_fromtime = splitBean.getFromTime(); + String flow_todate = splitBean.getToDate(); + String flow_totime = splitBean.getToTime(); + String fromdatedb = splitBean.getFromdatedb(); + String fromtimedb = splitBean.getFromtimedb(); + String todatedb = splitBean.getTodatedb(); + String totimedb = splitBean.getTotimedb(); + String requestid = splitBean.getRequestId(); + double d_mins = splitBean.getD_Mins(); + if(d_mins <= 0){ + continue; + } + String flow_key = mapKey+"|"+"dataid|"+dataid+"|"+"detailid|"+detailid+"|"+"requestid|"+requestid+"|flow_fromdate|"+flow_fromdate + +"|flow_fromtime|"+flow_fromtime+"|flow_todate|"+flow_todate+"|flow_totime|"+flow_totime; + int flow_count = (int) d_mins; + String flowLogInfo = "flow_fromdate:"+flow_fromdate+":flow_fromtime:"+flow_fromtime + +":flow_todate:"+flow_todate+":flow_totime:"+flow_totime+":requestid:"+requestid + +":d_mins:"+d_mins; + logOvertimeMap(overtimeLogMap, flowLogInfo, flow_key+"|加班流程信息|flowLogInfo"); + + List> hasOverTimeList = Lists.newArrayList(); + getHasOverTimeData(resourceid,realSplitDate,hasOverTimeList); + logOvertimeMap(overtimeLogMap, hasOverTimeList, flow_key+"|是否已经生成过加班,返回已经生成过加班的区间|hasOverTimeList"); + + if(flow_fromdate.compareTo(realSplitDate) > 0){ + flow_fromtime = kqTimesArrayComInfo.turn24to48Time(flow_fromtime); + } + if(flow_todate.compareTo(realSplitDate) > 0){ + flow_totime = kqTimesArrayComInfo.turn24to48Time(flow_totime); + } + int flow_fromIndex = kqTimesArrayComInfo.getArrayindexByTimes(flow_fromtime); + int flow_toIndex = kqTimesArrayComInfo.getArrayindexByTimes(flow_totime); + Arrays.fill(initArrays_flow, flow_fromIndex, flow_toIndex,1); + int all_has_duration_min = 0; + //因为存在下班后的打卡和上班前的打卡。这两块的打卡需要合在一起来和合在一起的流程比较时长 + Map hasCardMap = Maps.newHashMap(); + if(hasOverTimeList != null && !hasOverTimeList.isEmpty()){ + for(int p = 0 ; p < hasOverTimeList.size(); p++){ + Map hasOverTimeMap = hasOverTimeList.get(p); + String duration_min = Util.null2String(hasOverTimeMap.get("duration_min")); + String flow_dataid = Util.null2String(hasOverTimeMap.get("flow_dataid")); + String ori_belongdate = Util.null2String(hasOverTimeMap.get("ori_belongdate")); + String has_requestid = Util.null2String(hasOverTimeMap.get("requestid")); + + String card_fromdate = Util.null2String(hasOverTimeMap.get("fromdate_flow")); + String card_fromtime = Util.null2String(hasOverTimeMap.get("fromtime_flow")); + String card_todate = Util.null2String(hasOverTimeMap.get("todate_flow")); + String card_totime = Util.null2String(hasOverTimeMap.get("totime_flow")); + String card_key = card_fromdate+"_"+card_fromtime+"_"+card_todate+"_"+card_totime; + + int int_duration_min = Util.getIntValue(duration_min,0); + String has_key = has_requestid; + String cur_key = requestid; + if(flow_dataid.length() > 0){ + has_key += "_"+dataid+"_"+detailid; + cur_key += "_"+flow_dataid; + } + //为什么要加这个判断呢,因为有可能我请假3小时,打卡1小时,然后这个时候生成1小时加班,然后我后面又补卡了2小时,这时候,加班流程虽然已经 +// 生成过加班,但是其实只用了1小时,还需要拿这个加班流程来,减去已经用的1小时,d_mins就是这个加班流程实际可用的加班流程时长 + if(has_key.equalsIgnoreCase(cur_key)){ + if(int_duration_min > 0){ + d_mins = d_mins-(int_duration_min*1.0); + } + } + all_has_duration_min += int_duration_min; + if(hasCardMap.containsKey(card_key)){ + int tmp_int_duration_min = Util.getIntValue(hasCardMap.get(card_key)); + hasCardMap.put(card_key, ""+(int_duration_min+tmp_int_duration_min)); + }else{ + hasCardMap.put(card_key, int_duration_min+""); + } + } + } + if(d_mins > 0){ + + int[] initArrays = kqTimesArrayComInfo.getInitArr(); + Map signinoffMap = buildOvertimeCard(kqOvertimeCardBean, resourceid, realSplitDate, kqTimesArrayComInfo, restTimeMap, changeType_key,initArrays,hasOverTimeList, + overRulesDetailMap, false, overtimeLogMap,preChangeType_key,nextChangeType_key); + + String signinTime = Util.null2String(signinoffMap.get("signinTime")); + String signoutTime = Util.null2String(signinoffMap.get("signoutTime")); + String signinDate = Util.null2String(signinoffMap.get("signinDate")); + String signoutDate = Util.null2String(signinoffMap.get("signoutDate")); + int signinTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signinTime); + int signoutTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signoutTime); + + if(signinTimeIndex < signoutTimeIndex){ + String nowCardKey = signinDate+"_"+kqTimesArrayComInfo.turn48to24Time(signinTime) + +"_"+signoutDate+"_"+kqTimesArrayComInfo.turn48to24Time(signoutTime); + int over_count = kqTimesArrayComInfo.getCnt(initArrays, signinTimeIndex, signoutTimeIndex, 1); + int card_mins = over_count; + logOvertimeMap(overtimeLogMap, over_count, flow_key+"|加班打卡生成的时长|over_count"); + if(over_count > 0){ + //表示加班打卡是存在的 + String flow_cross_key = flow_key+"|加班计算区间|"+signinTime+"-"+signoutTime; + + int restTimeType = 1; + if(kqOvertimeRulesDetailEntity != null){ + int minimumLen = kqOvertimeRulesDetailEntity.getMinimumLen(); + if(card_mins < minimumLen){ + continue; + } + logOvertimeMap(overtimeLogMap, JSON.toJSONString(kqOvertimeRulesDetailEntity), flow_key+"|加班规则|KQOvertimeRulesDetailEntity"); + //我这个方法是针对每次生成的加班数据做排除休息时长的处理 打卡数据也要去掉休息时长 + restTimeType = kqOvertimeRulesDetailEntity.getRestTimeType(); + if(restTimeType == 2){ + over_count = new KQOverTimeFlowBiz().handle_restlength(over_count,restTimeMap,changeType_key); + } + } + if(all_has_duration_min > 0){ + for(Entry me : hasCardMap.entrySet()){ + String cardKey = me.getKey(); + String cardValue = me.getValue(); + if(cardKey.equalsIgnoreCase(nowCardKey)){ + }else{ + all_has_duration_min = all_has_duration_min - Util.getIntValue(cardValue); + } + } + over_count = over_count-all_has_duration_min; + } + if(over_count <= 0){ + continue; + } + int mins = over_count < d_mins ? over_count : (int)d_mins; + double double_mins = getD_MinsByUnit((1.0*mins)); + mins = (int)double_mins; + + RecordSet rs = new RecordSet(); + String overtime_uuid = UUID.randomUUID().toString(); + String flow_dataid = dataid+"_"+detailid; + String tiaoxiuId = ""; + int computingMode = 2; + + int unit = KQOvertimeRulesBiz.getMinimumUnit(); + String workingHours = ""; + String overtime_type = splitBean.getOvertime_type(); + Map otherParam = Maps.newHashMap(); + otherParam.put("overtime_type", overtime_type); + otherParam.put("changeType", String.valueOf(changeType)); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + if(2 == paidLeaveEnableType){ + logOvertimeMap(overtimeLogMap, overtime_type, flow_cross_key+"|关联调休与否来自于流程选择,加班类型下拉框值|overtime_type"); + } + + int paidLeaveEnable = getPaidLeaveEnable(kqOvertimeRulesDetailEntity, overtime_type); + + logOvertimeMap(overtimeLogMap, mins, flow_cross_key+"|最终生成的加班时长|mins"); + otherParam.put("overtimeLogMap", overtimeLogMap); + + tiaoxiuId = KQBalanceOfLeaveBiz.addExtraAmountByDis5(resourceid,realSplitDate,mins+"","0",workingHours,requestid,"1",flow_fromdate,otherParam); + if(Util.getIntValue(tiaoxiuId) > 0){ + kqLog.info("doComputingMode2 生成调休成功,调休id:"+tiaoxiuId+":resourceid:"+resourceid+":realSplitDate:"+realSplitDate+":requestid:"+requestid); + }else{ + kqLog.info("doComputingMode2 生成调休失败,调休id:"+tiaoxiuId+":resourceid:"+resourceid+":realSplitDate:"+realSplitDate+":requestid:"+requestid); + } + logOvertimeMap(overtimeLogMap, tiaoxiuId, flow_cross_key+"|最终生成的调休id|tiaoxiuId"); + + Long cur = System.currentTimeMillis(); + Timestamp date = new Timestamp(cur); + String flow_overtime_sql = "insert into kq_flow_overtime (requestid,resourceid,fromdate,fromtime,todate,totime,duration_min,expiringdate,belongdate," + + "workMins,durationrule,changetype,paidLeaveEnable,computingMode,tiaoxiuId,uuid,fromdatedb,fromtimedb,todatedb,totimedb,flow_mins,card_mins,ori_belongdate,flow_dataid,create_time,update_time,creator)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + if (rs.getDBType().equals("postgresql")) { + flow_overtime_sql = "insert into kq_flow_overtime (requestid,resourceid,fromdate,fromtime,todate,totime,duration_min,expiringdate,belongdate," + + "workMins,durationrule,changetype,paidLeaveEnable,computingMode,tiaoxiuId,uuid,fromdatedb,fromtimedb,todatedb,totimedb,flow_mins,card_mins,ori_belongdate,flow_dataid,create_time,update_time,creator)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?::timestamp,?::timestamp,?) "; + } + signinTime = kqTimesArrayComInfo.turn48to24Time(signinTime); + signoutTime = kqTimesArrayComInfo.turn48to24Time(signoutTime); + if(fromtimedb.length() == 5){ + fromtimedb = fromtimedb+":00"; + } + if(totimedb.length() == 5){ + totimedb = totimedb+":00"; + } + boolean isUp = rs.executeUpdate(flow_overtime_sql, requestid,resourceid,fromdatedb,fromtimedb,todatedb,totimedb,mins,"",realSplitDate, + "",unit,changeType,paidLeaveEnable,computingMode,tiaoxiuId,overtime_uuid,signinDate,signinTime,signoutDate,signoutTime,flow_count,card_mins,splitDate,flow_dataid,date,date,Util.getIntValue(resourceid)); + String overtimeid = get_overtime_uuid(overtime_uuid); + kqEventLogBiz.updateOvertimeId(uuid, overtimeid); + } + } + }else{ + logOvertimeMap(overtimeLogMap, "流程时长d_mins为0,不生成加班", flow_key+"|加班流程信息|flowLogInfo"); + } + } + } + + }else{ + logOvertimeMap(overtimeLogMap, "打卡数据KQOvertimeCardBean为null", "打卡和上下班数据|KQOvertimeCardBean"); + } + return true; + } + + /** + * 打卡的时长计算,流程+打卡 和纯打卡的可以拿来共用 + * needHasOverTime 是否需要按照打卡区间排除重复打卡的数据,第二种流程和打卡比较时长的不需要这个方式 + */ + public Map buildOvertimeCard(KQOvertimeCardBean kqOvertimeCardBean, + String resourceid, String splitDate, KQTimesArrayComInfo kqTimesArrayComInfo, + Map> restTimeMap, String changeType_key, int[] initArrays, + List> hasOverTimeList, + Map overRulesDetailMap, boolean needHasOverTime, + Map overtimeLogMap, String preChangeType_key, String nextChangeType_key) throws Exception{ + Map signinoffMap = Maps.newHashMap(); + + String signinDate = kqOvertimeCardBean.getSigninDate(); + String signinTime = kqOvertimeCardBean.getSigninTime(); + String signoutDate = kqOvertimeCardBean.getSignoutDate(); + String signoutTime = kqOvertimeCardBean.getSignoutTime(); + + if(hasOverTimeList.isEmpty()){ + getHasOverTimeData(resourceid,splitDate,hasOverTimeList); + } + + if(signinDate.compareTo(splitDate) > 0){ + signinTime = kqTimesArrayComInfo.turn24to48Time(signinTime); + if(signinTime.length() > 0){ + signinTime = signinTime+ ":00"; + } + } + if(signoutDate.compareTo(splitDate) > 0){ + signoutTime = kqTimesArrayComInfo.turn24to48Time(signoutTime); + if(signoutTime.length() > 0){ + signoutTime = signoutTime+ ":00"; + } + } + if(signinTime.length() == 0 || signoutTime.length() == 0){ + return signinoffMap; + } + + int signinTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signinTime); + int signoutTimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(signoutTime); + + signinoffMap.put("signinTime", signinTime); + signinoffMap.put("signoutTime", signoutTime); + signinoffMap.put("signinDate", signinDate); + signinoffMap.put("signoutDate", signoutDate); + //先把打卡数据都列出来 置位1 + if(signinTimeIndex < signoutTimeIndex){ + Arrays.fill(initArrays, signinTimeIndex, signoutTimeIndex,1); + } + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + if(restTimeMap.containsKey(preChangeType_key)){ + //昨日的排除休息时间跨天的情况 + List restTimeList = restTimeMap.get(preChangeType_key); + if(CollectionUtils.isNotEmpty(restTimeList)){ + for(int k =0 ; k < restTimeList.size() ; k++) { + String[] restTimes = restTimeList.get(k); + if (restTimes.length == 2) { + int restStart = kqTimesArrayComInfo.getArrayindexByTimes(restTimes[0]); + int restEnd = kqTimesArrayComInfo.getArrayindexByTimes(restTimes[1]); + restStart = restStart-1440; + restEnd = restEnd-1440; + if(restEnd > 0){ + //休息时段跨天了 + if(restStart > 0){ + Arrays.fill(initArrays, restStart, restEnd, 1); + }else { + Arrays.fill(initArrays, 0, restEnd, 1); + } + } + } + } + } + + } + if(restTimeMap.containsKey(changeType_key)){ + List restTimeList = restTimeMap.get(changeType_key); + logOvertimeMap(overtimeLogMap, restTimeList, "非工作时间设置的排除休息时间区间|restTimeList"); + //再把休息时间填充上去 + if(!restTimeList.isEmpty()){ + int restTimeType = 1; + if(kqOvertimeRulesDetailEntity != null){ + restTimeType = kqOvertimeRulesDetailEntity.getRestTimeType(); + } + if(restTimeType == 1){ + for(int j =0 ; j < restTimeList.size() ; j++){ + String[] restTimes = restTimeList.get(j); + if(restTimes.length == 2){ + int restStart = kqTimesArrayComInfo.getArrayindexByTimes(restTimes[0]); + int restEnd = kqTimesArrayComInfo.getArrayindexByTimes(restTimes[1]); + if(restEnd == 1439){ + //针对跨天的休息时段单独处理排除掉23:59-00:00的时间 + restEnd = 1440; + } + if(restStart < restEnd){ + Arrays.fill(initArrays, restStart, restEnd, -2); + } + } + } + } + } + } +// handleType 是否是处理昨日的,今日的还是明日的,0是处理今日的,1是处理明日的上下班时间和休息时间都要+1440,2是处理昨日的,需要减去1440 + int handleType = 2; + KQOvertimeRulesDetailEntity preKqOvertimeRulesDetailEntity = overRulesDetailMap.get(preChangeType_key); + clearWorkAndRestTime(resourceid,DateUtil.addDate(splitDate, -1),handleType,kqTimesArrayComInfo,overtimeLogMap,preKqOvertimeRulesDetailEntity,initArrays,signinTimeIndex); + handleType = 0; + clearWorkAndRestTime(resourceid,splitDate,handleType,kqTimesArrayComInfo,overtimeLogMap,kqOvertimeRulesDetailEntity,initArrays,signinTimeIndex); + handleType = 1; + KQOvertimeRulesDetailEntity nextKqOvertimeRulesDetailEntity = overRulesDetailMap.get(nextChangeType_key); + clearWorkAndRestTime(resourceid,DateUtil.addDate(splitDate, 1),handleType, kqTimesArrayComInfo, + overtimeLogMap, nextKqOvertimeRulesDetailEntity, initArrays, signinTimeIndex); + + if(!hasOverTimeList.isEmpty() && needHasOverTime){ + if(hasOverTimeList != null && !hasOverTimeList.isEmpty()){ + for(int p = 0 ; p < hasOverTimeList.size(); p++){ + Map hasOverTimeMap = hasOverTimeList.get(p); + String duration_min = Util.null2String(hasOverTimeMap.get("duration_min")); + String fromdate = Util.null2String(hasOverTimeMap.get("fromdate")); + String fromtime = Util.null2String(hasOverTimeMap.get("fromtime")); + String todate = Util.null2String(hasOverTimeMap.get("todate")); + String totime = Util.null2String(hasOverTimeMap.get("totime")); + if(fromdate.compareTo(splitDate) > 0){ + fromtime = kqTimesArrayComInfo.turn24to48Time(fromtime); + } + if(todate.compareTo(splitDate) > 0){ + totime = kqTimesArrayComInfo.turn24to48Time(totime); + } + int begintimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(fromtime); + int endtimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(totime); + if(begintimeIndex < endtimeIndex){ + Arrays.fill(initArrays, begintimeIndex, endtimeIndex, -2); + } + } + } + } + return signinoffMap; + } + + /** + * 把指定的打卡区间内的上下班时间和休息时间去除 + * @param resourceid + * @param splitDate + * @param handleType 是否是处理昨日的,今日的还是明日的,0是处理今日的,1是处理明日的上下班时间和休息时间都要+1440,2是处理昨日的 + * @param kqTimesArrayComInfo + * @param overtimeLogMap + * @param kqOvertimeRulesDetailEntity + * @param initArrays + * @param signinTimeIndex + */ + public void clearWorkAndRestTime(String resourceid, String splitDate, int handleType, + KQTimesArrayComInfo kqTimesArrayComInfo, + Map overtimeLogMap, + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity, int[] initArrays, + int signinTimeIndex) { + + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTime = kqWorkTime.getWorkTime(resourceid, splitDate); + if (workTime == null || (workTime != null && (workTime.getWorkMins() == 0 || workTime.getNonWorkShift() == 1))) { + }else{ + if (workTime.getKQType().equals("3")) {//自由工时 + //目前自由工时不加班 + } else { + boolean oneSign = false; + List lsSignTime = new ArrayList<>(); + List lsWorkTime = new ArrayList<>(); + List lsRestTime = new ArrayList<>(); + if (workTime != null) { + lsSignTime = workTime.getSignTime();//允许打卡时间 + lsWorkTime = workTime.getWorkTime();//工作时间 + lsRestTime = workTime.getRestTime();//休息时段时间 + oneSign = lsWorkTime!=null&&lsWorkTime.size()==1; + + if(lsWorkTime != null && !lsWorkTime.isEmpty()){ + + for (int i = 0; lsWorkTime != null && i < lsWorkTime.size(); i++) { + TimeScopeEntity workTimeScope = lsWorkTime.get(i); + if(oneSign){ + boolean is_flow_humanized = KQSettingsBiz.is_flow_humanized(); + if(is_flow_humanized){ + String workBeginTime = Util.null2String(workTimeScope.getBeginTime()); + int workBeginIdx = kqTimesArrayComInfo.getArrayindexByTimes(workBeginTime); + String workEndTime = Util.null2String(workTimeScope.getEndTime()); + int workEndIdx = kqTimesArrayComInfo.getArrayindexByTimes(workEndTime); + + Map shifRuleMap = Maps.newHashMap(); + //个性化设置只支持一天一次上下班 + ShiftInfoBean shiftInfoBean = new ShiftInfoBean(); + shiftInfoBean.setSplitDate(splitDate); + shiftInfoBean.setShiftRuleMap(workTime.getShiftRuleInfo()); + shiftInfoBean.setSignTime(lsSignTime); + shiftInfoBean.setWorkTime(lsWorkTime); + List logList = Lists.newArrayList(); + KQShiftRuleInfoBiz.getShiftRuleInfo(shiftInfoBean, resourceid, shifRuleMap,logList); + if(!shifRuleMap.isEmpty()){ + if(shifRuleMap.containsKey("shift_beginworktime")){ + String shift_beginworktime = Util.null2String(shifRuleMap.get("shift_beginworktime")); + if(shift_beginworktime.length() > 0){ + workBeginTime = Util.null2String(shift_beginworktime); + workBeginIdx = kqTimesArrayComInfo.getArrayindexByTimes(workBeginTime); + workTimeScope.setBeginTime(workBeginTime); + workTimeScope.setBeginTimeAcross(workBeginIdx>=1440?true:false); + } + } + if(shifRuleMap.containsKey("shift_endworktime")){ + String shift_endworktime = Util.null2String(shifRuleMap.get("shift_endworktime")); + if(shift_endworktime.length() > 0){ + workEndTime = Util.null2String(shift_endworktime); + workEndIdx = kqTimesArrayComInfo.getArrayindexByTimes(workEndTime); + workTimeScope.setEndTime(workEndTime); + workTimeScope.setEndTimeAcross(workEndIdx>=1440?true:false); + } + } + } + } + } + } + + //目前只处理上班前和下班后的加班数据,上班中间的数据不处理,所以从第一次上班时间到最后下班时间都是无效的加班打卡 + TimeScopeEntity first_TimeScopeEntity = lsWorkTime.get(0); + TimeScopeEntity last_TimeScopeEntity = lsWorkTime.get(lsWorkTime.size()-1); + + String begintime = first_TimeScopeEntity.getBeginTime(); + String endtime = last_TimeScopeEntity.getEndTime(); + int begintimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(begintime); + int endtimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(endtime); + if(1 == handleType){ + begintimeIndex = begintimeIndex + 1440; + endtimeIndex = endtimeIndex + 1440; + if(begintimeIndex >= initArrays.length){ + begintimeIndex = initArrays.length-1; + } + if(endtimeIndex >= initArrays.length){ + endtimeIndex = initArrays.length-1; + } + } + if(2 == handleType){ + begintimeIndex = begintimeIndex - 1440; + endtimeIndex = endtimeIndex - 1440; + } + String workTimeLogInfo = "begintime:"+begintime+":endtime:"+endtime+":handleType:"+handleType; + logOvertimeMap(overtimeLogMap, workTimeLogInfo, "工作日的上下班时间|workTimeLogInfo"); + if(begintimeIndex >= 0 && endtimeIndex >= 0 && begintimeIndex < endtimeIndex){ + Arrays.fill(initArrays, begintimeIndex, endtimeIndex, -2); + } + if(0 == handleType){ + if(kqOvertimeRulesDetailEntity != null){ + int startTime = kqOvertimeRulesDetailEntity.getStartTime(); + if(startTime > -1){ + int after_endtimeIndex = endtimeIndex + startTime; + if(after_endtimeIndex > 0 && after_endtimeIndex > endtimeIndex){ + if(endtimeIndex < 0){ + endtimeIndex = 0; + } + Arrays.fill(initArrays, endtimeIndex, after_endtimeIndex, -2); + } + } + int has_cut_point = kqOvertimeRulesDetailEntity.getHas_cut_point(); + if(has_cut_point == 1){ + int before_startTime = kqOvertimeRulesDetailEntity.getBefore_startTime(); + if(before_startTime > -1 && begintimeIndex > 0){ + int before_begintimeIndex = begintimeIndex - before_startTime; + if(before_begintimeIndex < 0){ + before_begintimeIndex = 0; + } + if(before_begintimeIndex > signinTimeIndex){ + Arrays.fill(initArrays, signinTimeIndex, before_begintimeIndex, -2); + } + } + } + } + } + if(2 == handleType){ + if(kqOvertimeRulesDetailEntity != null){ + int startTime = kqOvertimeRulesDetailEntity.getStartTime(); + if(startTime > -1){ + int after_endtimeIndex = endtimeIndex + startTime; + if(after_endtimeIndex > 0 && after_endtimeIndex > endtimeIndex){ + if(endtimeIndex < 0){ + endtimeIndex = 0; + } + Arrays.fill(initArrays, endtimeIndex, after_endtimeIndex, -2); + } + } + int has_cut_point = kqOvertimeRulesDetailEntity.getHas_cut_point(); + if(has_cut_point == 1){ + int before_startTime = kqOvertimeRulesDetailEntity.getBefore_startTime(); + if(before_startTime > -1){ + int before_begintimeIndex = begintimeIndex - before_startTime; + if(before_begintimeIndex < 0){ + before_begintimeIndex = 0; + } + if(before_begintimeIndex > signinTimeIndex){ + Arrays.fill(initArrays, signinTimeIndex, before_begintimeIndex, -2); + } + } + } + } + } + } + if(lsRestTime != null && !lsRestTime.isEmpty()){ + String restTimeLogInfo = JSON.toJSONString(lsRestTime); + logOvertimeMap(overtimeLogMap, restTimeLogInfo, "工作日的休息时间|restTimeLogInfo"); + for(int p = 0 ; p < lsRestTime.size(); p++){ + TimeScopeEntity rest_TimeScopeEntity = lsRestTime.get(p); + String begintime = rest_TimeScopeEntity.getBeginTime(); + String endtime = rest_TimeScopeEntity.getEndTime(); + int begintimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(begintime); + int endtimeIndex = kqTimesArrayComInfo.getArrayindexByTimes(endtime); + if(1 == handleType){ + begintimeIndex = begintimeIndex + 1440; + endtimeIndex = endtimeIndex + 1440; + if(begintimeIndex >= initArrays.length){ + begintimeIndex = initArrays.length-1; + } + if(endtimeIndex >= initArrays.length){ + endtimeIndex = initArrays.length-1; + } + } + if(2 == handleType){ + begintimeIndex = begintimeIndex - 1440; + if(begintimeIndex < 0){ + begintimeIndex = 0; + } + endtimeIndex = endtimeIndex - 1440; + if(endtimeIndex < 0){ + endtimeIndex = 0; + } + } + if(begintimeIndex >= 0 && endtimeIndex >= 0 && begintimeIndex < endtimeIndex){ + Arrays.fill(initArrays, begintimeIndex, endtimeIndex, -2); + } + } + } + + } + } + } + } + + /** + * 根据打卡数据和加班归属 拆分出来需要计算加班的区段 + * @param resourceid + * @param fromDate + * @param toDate + * @param dateFormatter + * @param kqTimesArrayComInfo + * @param overRulesDetailMap + * @param changeTypeMap + * @param lsCheckInfoMaps + * @param eventMap + */ + public void getOverTimeCardDataMap(String resourceid, String fromDate, String toDate, + DateTimeFormatter dateFormatter, + KQTimesArrayComInfo kqTimesArrayComInfo, + Map overRulesDetailMap, + Map changeTypeMap, Map lsCheckInfoMaps, + Map eventMap) throws Exception{ + + KQOverTimeFlowBiz kqOverTimeFlowBiz = new KQOverTimeFlowBiz(); + + List lsCheckInfos = Lists.newArrayList(); + Map result = getSignData(resourceid, fromDate, dateFormatter,eventMap,lsCheckInfos,changeTypeMap,overRulesDetailMap); + + //获取一下当天的上班时间 + String firstworkDate = Util.null2String(result.get("firstworkDate")); + String firstworkTime = Util.null2String(result.get("firstworkTime")); + int pre_has_cut_point = Util.getIntValue(Util.null2String(result.get("pre_has_cut_point"))); + String pre_cut_point = Util.null2String(result.get("pre_cut_point")); + int has_cut_point = Util.getIntValue(Util.null2String(result.get("has_cut_point"))); + String cut_point = Util.null2String(result.get("cut_point")); + int before_startTime = Util.getIntValue(Util.null2String(result.get("before_startTime"))); + int preChangeType = Util.getIntValue(Util.null2String(result.get("preChangeType"))); + int changeType = Util.getIntValue(Util.null2String(result.get("changeType"))); + + LocalDate localbelongDate = LocalDate.parse(fromDate); + String splitDate = localbelongDate.format(dateFormatter); + LocalDate preLocalDate = localbelongDate.minusDays(1); + String preSplitDate = preLocalDate.format(dateFormatter); + String nextSplitDate = localbelongDate.plusDays(1).format(dateFormatter); + + String preKey = resourceid+"_"+preSplitDate; + String key = resourceid+"_"+splitDate; + String nextkey = resourceid+"_"+nextSplitDate; + + eventMap.put("lsCheckInfos", lsCheckInfos); + if(!lsCheckInfos.isEmpty()){ + Map signMap = (Map) lsCheckInfos.get(0); + String signindate = ""; + String signintime = ""; + String signoutdate = ""; + String signouttime = ""; + + if(signMap != null && !signMap.isEmpty()){ + signindate = Util.null2String(signMap.get("signindate")); + signintime = Util.null2String(signMap.get("signintime")); + signoutdate = Util.null2String(signMap.get("signoutdate")); + signouttime = Util.null2String(signMap.get("signouttime")); + if(lsCheckInfos.size() > 1){ + Map lastSignMap = (Map) lsCheckInfos.get(lsCheckInfos.size()-1); + signoutdate = Util.null2String(lastSignMap.get("signoutdate")); + signouttime = Util.null2String(lastSignMap.get("signouttime")); + } + } + KQOvertimeCardBean kqOvertimeBean = new KQOvertimeCardBean(); + kqOvertimeBean.setSigninDate(signindate); + kqOvertimeBean.setSigninTime(signintime); + kqOvertimeBean.setSignoutDate(signoutdate); + kqOvertimeBean.setSignoutTime(signouttime); + kqOvertimeBean.setBelongDate(splitDate); + eventMap.put("pre_has_cut_point", pre_has_cut_point); + eventMap.put("has_cut_point", has_cut_point); + if(pre_has_cut_point == 0){ + //未设置打卡归属 + if(preChangeType == 2){ + eventMap.put("preChangeType", preChangeType); + //如果前一天是工作日 + String pre_overtime_cut_point = ""; + ShiftInfoBean pre_shiftInfoBean = KQDurationCalculatorUtil + .getWorkTime(resourceid, preSplitDate, false); + if(pre_shiftInfoBean != null){ + boolean isfree = pre_shiftInfoBean.isIsfree(); + eventMap.put("isfree", isfree); + if(!isfree){ + List workLongTimeIndex = pre_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + SplitBean splitBean = new SplitBean(); + splitBean.setResourceId(resourceid); + kqOverTimeFlowBiz.get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,pre_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + pre_overtime_cut_point = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + }else{ + //自由班制直接给0点 + pre_overtime_cut_point = "00:00"; + } + eventMap.put("pre_overtime_cut_point", pre_overtime_cut_point); + if(pre_overtime_cut_point.length() >= 0){ + rePutCheckInfoMap(lsCheckInfoMaps, kqOvertimeBean, preKey, key, pre_overtime_cut_point, splitDate,eventMap,has_cut_point,result,nextkey); + } + }else{ + String errorMsg = "前一天是工作日但是前一天的ShiftInfoBean班次获取不到信息"; + eventMap.put("errorMsg", errorMsg); + } + }else { + eventMap.put("changeType", changeType); + if(changeType == 2){ + eventMap.put("firstworkTime", firstworkTime); + result.put("cut_point", cut_point); + if(has_cut_point == 1 && before_startTime > 0){ + firstworkTime = kqTimesArrayComInfo.getTimesByArrayindex(kqTimesArrayComInfo.getArrayindexByTimes(firstworkTime)-before_startTime); + } + //如果前一天是非工作日,今天是工作日的话 + rePutCheckInfoMap(lsCheckInfoMaps, kqOvertimeBean, preKey, key, firstworkTime, splitDate, + eventMap, has_cut_point,result,nextkey); + }else{ + //如果前一天是非工作日,今天是非工作日的话,那就是打卡获取的是啥就是啥 + lsCheckInfoMaps.put(key, kqOvertimeBean); + } + } + }else{ + String pre_splittime = ""; + List pre_lsCheckInfos = Lists.newArrayList(); + getSignData(resourceid, preSplitDate, dateFormatter, eventMap, pre_lsCheckInfos, changeTypeMap, overRulesDetailMap); + if(!pre_lsCheckInfos.isEmpty()){ + Map preSignMap = (Map) pre_lsCheckInfos.get(0); + String pre_signindate = ""; + String pre_signintime = ""; + String pre_signoutdate = ""; + String pre_signouttime = ""; + if(preSignMap != null && !preSignMap.isEmpty()){ + pre_signindate = Util.null2String(preSignMap.get("signindate")); + pre_signintime = Util.null2String(preSignMap.get("signintime")); + pre_signoutdate = Util.null2String(preSignMap.get("signoutdate")); + pre_signouttime = Util.null2String(preSignMap.get("signouttime")); + if(pre_signindate.length() > 0 && pre_signintime.length() > 0){ + pre_splittime = pre_signindate+" "+pre_signintime; + }else if(pre_signoutdate.length() > 0 && pre_signouttime.length() > 0){ + pre_splittime = pre_signoutdate+" "+pre_signouttime; + } + } + } + eventMap.put("pre_cut_point", pre_cut_point); + //设置了打卡归属 那么一天的打卡就可能被前一天给拆成两部分和后一天的打卡归属给拆分成两部分 + rePutCheckInfoCutPointMap(lsCheckInfoMaps, kqOvertimeBean, preKey, key, pre_cut_point, splitDate, + eventMap,cut_point,nextSplitDate,nextkey,has_cut_point,pre_splittime,result); + } + } + eventMap.put("lsCheckInfos_after", lsCheckInfoMaps); + } + + /** + * 获取打卡数据 + * @param resourceid + * @param belongDate + * @param dateFormatter + * @param eventMap + * @param lsCheckInfos + * @param changeTypeMap + * @param overRulesDetailMap + */ + public Map getSignData(String resourceid, String belongDate, + DateTimeFormatter dateFormatter, Map eventMap, + List lsCheckInfos, Map changeTypeMap, + Map overRulesDetailMap) throws Exception{ + Map result = Maps.newHashMap(); + String firstworkDate = ""; + String firstworkTime = ""; + + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + LocalDate localbelongDate = LocalDate.parse(belongDate); + String splitDate = localbelongDate.format(dateFormatter); + LocalDate preLocalDate = localbelongDate.minusDays(1); + String preSplitDate = preLocalDate.format(dateFormatter); + String nextSplitDate = localbelongDate.plusDays(1).format(dateFormatter); + + String change_key = splitDate+"_"+resourceid; + String preChange_key = preSplitDate+"_"+resourceid; + String nextChange_key = nextSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + int preChangeType = Util.getIntValue(""+changeTypeMap.get(preChange_key),-1); + int nextChangeType = Util.getIntValue(""+changeTypeMap.get(nextChange_key),-1); + String changeType_key = splitDate+"_"+changeType; + String preChangeType_key = preSplitDate+"_"+preChangeType; + + KQOvertimeRulesDetailEntity curKqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + KQOvertimeRulesDetailEntity preKqOvertimeRulesDetailEntity = overRulesDetailMap.get(preChangeType_key); + + int pre_has_cut_point = 0; + String pre_cut_point = ""; + if(preKqOvertimeRulesDetailEntity != null){ + pre_has_cut_point = preKqOvertimeRulesDetailEntity.getHas_cut_point(); + pre_cut_point = preKqOvertimeRulesDetailEntity.getCut_point(); + } + int has_cut_point = 0; + String cut_point = ""; + int before_startTime = -1; + if(curKqOvertimeRulesDetailEntity != null){ + has_cut_point = curKqOvertimeRulesDetailEntity.getHas_cut_point(); + cut_point = curKqOvertimeRulesDetailEntity.getCut_point(); + before_startTime =curKqOvertimeRulesDetailEntity.getBefore_startTime(); + } + + result.put("pre_has_cut_point", ""+pre_has_cut_point); + result.put("pre_cut_point", pre_cut_point); + result.put("has_cut_point", ""+has_cut_point); + result.put("cut_point", cut_point); + result.put("before_startTime", ""+before_startTime); + result.put("preChangeType", ""+preChangeType); + result.put("changeType", ""+changeType); + + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTime = kqWorkTime.getWorkTime(resourceid, splitDate); + + LocalDate pre_curLocalDate = localbelongDate.minusDays(1); + String preDate = pre_curLocalDate.format(dateFormatter); + LocalDate next_curLocalDate = localbelongDate.plusDays(1); + String nextDate = next_curLocalDate.format(dateFormatter); + boolean isNonWork = false; + if (workTime == null || (workTime.getWorkMins() == 0 && workTime.getNonWorkShift() != 1)) { + isNonWork = true; + } + + if (isNonWork) { + Map signMap = getRestSignInfo(resourceid,splitDate,preDate,nextDate,curKqOvertimeRulesDetailEntity,eventMap,preKqOvertimeRulesDetailEntity); + if(signMap != null && !signMap.isEmpty()){ + lsCheckInfos.add(signMap); + } + }else{ + if (workTime.getKQType().equals("3")) {//自由工时 + //目前自由工时不加班 + } else { + boolean oneSign = false; + List lsSignTime = new ArrayList<>(); + List lsWorkTime = new ArrayList<>(); + List lsRestTime = new ArrayList<>(); + oneSign = lsWorkTime!=null&&lsWorkTime.size()==1; + boolean need_middle_time = false; + + if (workTime != null) { + if(workTime.getNonWorkShift() == 1){ + //非工作日班次 计算逻辑 + lsSignTime = workTime.getSignTime();//允许打卡时间 + TimeScopeEntity signTimeScopeStart = lsSignTime.get(0); + TimeScopeEntity signTimeScopeEnd = lsSignTime.get(lsSignTime.size()-1); + TimeScopeEntity signTimeScope = new TimeScopeEntity(); + signTimeScope.setBeginTime(signTimeScopeStart.getBeginTime()); + signTimeScope.setBeginTimeAcross(signTimeScopeStart.getBeginTimeAcross()); + signTimeScope.setEndTime(signTimeScopeEnd.getEndTime()); + signTimeScope.setEndTimeAcross(signTimeScopeEnd.getEndTimeAcross()); + + int i = 0; + result.put("lsWorkTime_size", "1"); + Map signMap = getSignInfo(resourceid,signTimeScope,null,splitDate,preDate,nextDate,kqTimesArrayComInfo,eventMap,i,result); + if(signMap != null && !signMap.isEmpty()){ + //目前一天多次打卡的话,只获取第一次和最后一次打卡 + lsCheckInfos.add(signMap); + } + }else{ + lsSignTime = workTime.getSignTime();//允许打卡时间 + lsWorkTime = workTime.getWorkTime();//工作时间 + result.put("lsWorkTime_size", ""+lsWorkTime.size()); + lsRestTime = workTime.getRestTime();//休息时段时间 + oneSign = lsWorkTime!=null&&lsWorkTime.size()==1; + if(lsWorkTime != null){ + TimeScopeEntity timeScopeEntity0 = lsWorkTime.get(0); + TimeScopeEntity timeScopeEntity1 = lsWorkTime.get(lsWorkTime.size()-1); + String beginTime = timeScopeEntity0.getBeginTime(); + String endTime = timeScopeEntity1.getEndTime(); + boolean endTimeAcross = timeScopeEntity1.getEndTimeAcross(); + result.put("beginTime", beginTime); + result.put("endTime", endTime); + result.put("endTimeAcross", endTimeAcross?"1":"0"); + } + for (int i = 0; lsWorkTime != null && i < lsWorkTime.size(); i++) { + TimeScopeEntity signTimeScope = lsSignTime.get(i); + TimeScopeEntity workTimeScope = lsWorkTime.get(i); + if(i == 0){ + firstworkDate = splitDate; + firstworkTime = workTimeScope.getBeginTime(); + } + if(!oneSign){ + if(!need_middle_time){ + //多次打卡的时候,中间打卡不算加班 + if(i != 0 && i != lsWorkTime.size()-1){ + continue; + } + } + }else { + boolean is_flow_humanized = KQSettingsBiz.is_flow_humanized(); + if(is_flow_humanized){ + String workBeginTime = Util.null2String(workTimeScope.getBeginTime()); + String ori_workBeginTime = workBeginTime; + int workBeginIdx = kqTimesArrayComInfo.getArrayindexByTimes(workBeginTime); + boolean workBenginTimeAcross = workTimeScope.getBeginTimeAcross(); + String workEndTime = Util.null2String(workTimeScope.getEndTime()); + String ori_workEndTime = workEndTime; + int workEndIdx = kqTimesArrayComInfo.getArrayindexByTimes(workEndTime); + boolean workEndTimeAcross = workTimeScope.getEndTimeAcross(); + + Map shifRuleMap = Maps.newHashMap(); + //个性化设置只支持一天一次上下班 + ShiftInfoBean shiftInfoBean = new ShiftInfoBean(); + shiftInfoBean.setSplitDate(splitDate); + shiftInfoBean.setShiftRuleMap(workTime.getShiftRuleInfo()); + shiftInfoBean.setSignTime(lsSignTime); + shiftInfoBean.setWorkTime(lsWorkTime); + List logList = Lists.newArrayList(); + KQShiftRuleInfoBiz.getShiftRuleInfo(shiftInfoBean, resourceid, shifRuleMap,logList); + if(!shifRuleMap.isEmpty()){ + if(shifRuleMap.containsKey("shift_beginworktime")){ + String shift_beginworktime = Util.null2String(shifRuleMap.get("shift_beginworktime")); + if(shift_beginworktime.length() > 0){ + workBeginTime = Util.null2String(shift_beginworktime); + workBeginIdx = kqTimesArrayComInfo.getArrayindexByTimes(workBeginTime); + workTimeScope.setBeginTime(workBeginTime); + workTimeScope.setBeginTimeAcross(workBeginIdx>=1440?true:false); + if(i == 0){ + firstworkDate = workBeginIdx>=1440 ? nextDate : splitDate; + firstworkTime = workBeginTime; + } + } + } + if(shifRuleMap.containsKey("shift_endworktime")){ + String shift_endworktime = Util.null2String(shifRuleMap.get("shift_endworktime")); + if(shift_endworktime.length() > 0){ + workEndTime = Util.null2String(shift_endworktime); + workEndIdx = kqTimesArrayComInfo.getArrayindexByTimes(workEndTime); + workTimeScope.setEndTime(workEndTime); + workTimeScope.setEndTimeAcross(workEndIdx>=1440?true:false); + } + } + } + } + } + Map signMap = getSignInfo(resourceid,signTimeScope,workTimeScope,splitDate,preDate,nextDate,kqTimesArrayComInfo,eventMap,i,result); + if(signMap != null && !signMap.isEmpty()){ + //目前一天多次打卡的话,只获取第一次和最后一次打卡 + lsCheckInfos.add(signMap); + } + } + } + } + } + } + + if(firstworkDate.length() > 0 && firstworkTime.length() > 0){ + result.put("firstworkDate", firstworkDate); + result.put("firstworkTime", firstworkTime); + } + return result; + } + + public void rePutCheckInfoCutPointMap(Map lsCheckInfoMaps, + KQOvertimeCardBean kqOvertimeBean, String preKey, String key, String pre_cut_point, + String splitDate, Map eventMap, String cut_point, String nextDate, + String nextkey, int has_cut_point, String pre_splitdatetime, Map result) { + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + String preDate = DateUtil.addDate(splitDate, -1); + + String pre_cut_points = pre_cut_point+":00"; + String pre_date_cut_point = splitDate+" "+pre_cut_points; + + String cut_points = cut_point+":00"; + String cur_date_cut_point = nextDate+" "+cut_points; + + String signindate = kqOvertimeBean.getSigninDate(); + String signoutdate = kqOvertimeBean.getSignoutDate(); + String signintime = kqOvertimeBean.getSigninTime(); + String signouttime = kqOvertimeBean.getSignoutTime(); + String signindatetime = kqOvertimeBean.getSigninDate()+" "+kqOvertimeBean.getSigninTime(); + String signoutdatetime = ""; + if(kqOvertimeBean.getSignoutDate().length() > 0 && kqOvertimeBean.getSignoutTime().length() > 0){ + //如果是休息日的话,可能存在没有上班时间的情况 + signoutdatetime = kqOvertimeBean.getSignoutDate()+" "+kqOvertimeBean.getSignoutTime(); + } + String pre_splittime_date = ""; + String pre_splittime_time = ""; + if(pre_splitdatetime.length() > 0){ + String[] pre_splittimes = pre_splitdatetime.split(" "); + if(pre_splittimes.length == 2){ + pre_splittime_date = pre_splittimes[0]; + pre_splittime_time = pre_splittimes[1]; + } + } + + String timeInfo = "date_cut_point:"+pre_date_cut_point+":signoutdatetime:"+signoutdatetime+":signindatetime:"+signindatetime; + String timeCompare1 = "date_cut_point.compareTo(signoutdatetime):"+pre_date_cut_point.compareTo(signoutdatetime); + String timeCompare2 = "date_cut_point.compareTo(signindatetime):"+pre_date_cut_point.compareTo(signindatetime); + eventMap.put("timeInfo", timeInfo); + eventMap.put("timeCompare1", timeCompare1); + eventMap.put("timeCompare2", timeCompare2); + if(pre_date_cut_point.compareTo(signindatetime) > 0){ + //如果归属大于签到时间,小于签退时间,表示归属之前是属于前一天的,归属之后的是属于今天的 + //开启了归属之后,归属点之前的打卡就属于前一天的签退卡了,相当于是从前一天的下班时间到这个卡都算是前一天的加班卡,和不开归属的时候不一样 + KQOvertimeCardBean preKqOvertimeBean = new KQOvertimeCardBean(); + if(pre_splittime_date.length() > 0 && pre_splittime_time.length() > 0){ + preKqOvertimeBean.setSigninDate(pre_splittime_date); + preKqOvertimeBean.setSigninTime(pre_splittime_time); + preKqOvertimeBean.setSignoutDate(signindate); + preKqOvertimeBean.setSignoutTime(signintime); + preKqOvertimeBean.setBelongDate(preDate); + lsCheckInfoMaps.put(preKey, preKqOvertimeBean); + } + if(signoutdatetime.length() > 0 && signoutdatetime.compareTo(pre_date_cut_point) > 0){ + KQOvertimeCardBean curOvertimeBean = new KQOvertimeCardBean(); + curOvertimeBean.setSigninDate(splitDate); + curOvertimeBean.setSigninTime(pre_cut_points); + curOvertimeBean.setSignoutDate(signoutdate); + curOvertimeBean.setSignoutTime(signouttime); + curOvertimeBean.setBelongDate(splitDate); + lsCheckInfoMaps.put(key, curOvertimeBean); + } + + }else if(signoutdatetime.length() > 0 && pre_date_cut_point.compareTo(signoutdatetime) > 0){ + //如果归属大于签退时间 表示这个时间都是属于前一天的 + lsCheckInfoMaps.put(preKey, kqOvertimeBean); + }else { + lsCheckInfoMaps.put(key, kqOvertimeBean); + } + if(signoutdate.length() > 0){ + if(signoutdate.compareTo(splitDate) > 0){ + if(1 == has_cut_point){ + KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo(); + String overtimePoint = Util.null2String(kqSettingsComInfo.getMain_val("overtime_point"),"0"); + boolean needPointCut = false; + if("1".equals(overtimePoint)){ + needPointCut = true; + } + //如果签退大于签到 表示打卡跨天 + if(cur_date_cut_point.compareTo(signoutdatetime) < 0){ + String hasSigninDate = signindate; + String hasSigninTime = signintime; + if(lsCheckInfoMaps.containsKey(key)){ + KQOvertimeCardBean hasOvertimeBean = lsCheckInfoMaps.get(key); + hasSigninDate = hasOvertimeBean.getSigninDate(); + hasSigninTime = hasOvertimeBean.getSigninTime(); + } + KQOvertimeCardBean curOvertimeBean = new KQOvertimeCardBean(); + curOvertimeBean.setSigninDate(hasSigninDate); + curOvertimeBean.setSigninTime(hasSigninTime); + curOvertimeBean.setSignoutDate(nextDate); + curOvertimeBean.setSignoutTime(cut_points); + if(needPointCut){ + //这个是新加的开关,为了保证历史数据,只能这样加了 + if(result.containsKey("beginTime")){ + //上班前打卡和班次开始时间作为第一段加班区间 + curOvertimeBean.setSignoutDate(splitDate); + curOvertimeBean.setSignoutTime(result.get("beginTime")+":00"); + } + } + curOvertimeBean.setBelongDate(splitDate); + lsCheckInfoMaps.put(key, curOvertimeBean); + + KQOvertimeCardBean nextOvertimeBean = new KQOvertimeCardBean(); + nextOvertimeBean.setSigninDate(nextDate); + nextOvertimeBean.setSigninTime(cut_points); + if(needPointCut){ + //这个是新加的开关,为了保证历史数据,只能这样加了 + if(result.containsKey("endTime") && result.containsKey("endTimeAcross")){ + if(result.get("endTimeAcross").equals("1")){ + String endTime = kqTimesArrayComInfo.turn48to24Time(result.get("endTime"))+":00"; + if(cut_points.compareTo(endTime) > 0){ + //如果下班时间跨天了,但是下班时间早于临界点 + //下班时间和开启的加班归属点作为第二段加班区间 + KQOvertimeCardBean curNextOvertimeBean = new KQOvertimeCardBean(); + curNextOvertimeBean.setSigninDate(nextDate); + curNextOvertimeBean.setSigninTime(endTime); + curNextOvertimeBean.setSignoutDate(nextDate); + curNextOvertimeBean.setSignoutTime(cut_points); + curNextOvertimeBean.setBelongDate(splitDate); + if(lsCheckInfoMaps.containsKey(key)){ + KQOvertimeCardBean kqOvertimeCardBean = lsCheckInfoMaps.get(key); + curNextOvertimeBean.setSigninDate(kqOvertimeCardBean.getSigninDate()); + curNextOvertimeBean.setSigninTime(kqOvertimeCardBean.getSigninTime()); + } + lsCheckInfoMaps.put(key, curNextOvertimeBean); + }else{ + nextOvertimeBean.setSigninDate(nextDate); + nextOvertimeBean.setSigninTime(endTime); + } + }else{ + //下班时间和开启的加班归属点作为第二段加班区间 + String endTime = result.get("endTime")+":00"; + KQOvertimeCardBean curNextOvertimeBean = new KQOvertimeCardBean(); + curNextOvertimeBean.setSigninDate(splitDate); + curNextOvertimeBean.setSigninTime(endTime); + curNextOvertimeBean.setSignoutDate(nextDate); + curNextOvertimeBean.setSignoutTime(cut_points); + curNextOvertimeBean.setBelongDate(splitDate); + if(lsCheckInfoMaps.containsKey(key)){ + KQOvertimeCardBean kqOvertimeCardBean = lsCheckInfoMaps.get(key); + curNextOvertimeBean.setSigninDate(kqOvertimeCardBean.getSigninDate()); + curNextOvertimeBean.setSigninTime(kqOvertimeCardBean.getSigninTime()); + } + lsCheckInfoMaps.put(key, curNextOvertimeBean); + } + } + } + nextOvertimeBean.setSignoutDate(signoutdate); + nextOvertimeBean.setSignoutTime(signouttime); + nextOvertimeBean.setBelongDate(nextDate); + //加班归属点和跨天的下班签退卡作为第三段加班区间 + lsCheckInfoMaps.put(nextkey, nextOvertimeBean); + } + } + } + } + } + + + /** + * 重新把打卡数据按照归属来赋值 + */ + public void rePutCheckInfoMap(Map lsCheckInfoMaps, + KQOvertimeCardBean kqOvertimeBean, + String preKey, String key, String overtime_cut_point, String splitDate, + Map eventMap, int has_cut_point, Map result, String nextkey){ + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + + String nextDate = DateUtil.addDate(splitDate, 1); + String cut_point = Util.null2String(result.get("cut_point")); + String next_overtime_cut_points = cut_point+":00"; + String next_date_cut_point = nextDate+" "+next_overtime_cut_points; + + String preDate = DateUtil.addDate(splitDate, -1); + String overtime_cut_points = overtime_cut_point+":00"; + String date_cut_point = splitDate+" "+overtime_cut_points; + String signindate = kqOvertimeBean.getSigninDate(); + String signoutdate = kqOvertimeBean.getSignoutDate(); + String signintime = kqOvertimeBean.getSigninTime(); + String signouttime = kqOvertimeBean.getSignoutTime(); + String signindatetime = kqOvertimeBean.getSigninDate()+" "+kqOvertimeBean.getSigninTime(); + String signoutdatetime = ""; + if(kqOvertimeBean.getSignoutDate().length() > 0 && kqOvertimeBean.getSignoutTime().length() > 0){ + //如果是休息日的话,可能存在没有上班时间的情况 + signoutdatetime = kqOvertimeBean.getSignoutDate()+" "+kqOvertimeBean.getSignoutTime(); + } + + String timeInfo = "date_cut_point:"+date_cut_point+":signoutdatetime:"+signoutdatetime+":signindatetime:"+signindatetime; + String timeCompare1 = "date_cut_point.compareTo(signoutdatetime):"+date_cut_point.compareTo(signoutdatetime); + String timeCompare2 = "date_cut_point.compareTo(signindatetime):"+date_cut_point.compareTo(signindatetime); + eventMap.put("timeInfo", timeInfo); + eventMap.put("timeCompare1", timeCompare1); + eventMap.put("timeCompare2", timeCompare2); + if(date_cut_point.compareTo(signindatetime) > 0){ + //如果归属大于签到时间,小于签退时间,表示归属之前是属于前一天的,归属之后的是属于今天的 + //不开启了归属的时候,根据打卡的性质来判断,如果是签到卡,那么签到时间到前一天上班时间,这段区间内算是前一天的加班卡,和开启了归属不一样 + KQOvertimeCardBean preKqOvertimeBean = new KQOvertimeCardBean(); + preKqOvertimeBean.setSigninDate(signindate); + preKqOvertimeBean.setSigninTime(signintime); + preKqOvertimeBean.setSignoutDate(splitDate); + preKqOvertimeBean.setSignoutTime(overtime_cut_points); + preKqOvertimeBean.setBelongDate(preDate); + preKqOvertimeBean.setHas_cut_point("0"); + lsCheckInfoMaps.put(preKey, preKqOvertimeBean); + + if(signoutdatetime.length() > 0 && signoutdatetime.compareTo(date_cut_point) > 0){ + + KQOvertimeCardBean curOvertimeBean = new KQOvertimeCardBean(); + curOvertimeBean.setSigninDate(splitDate); + curOvertimeBean.setSigninTime(overtime_cut_points); + curOvertimeBean.setSignoutDate(signoutdate); + curOvertimeBean.setSignoutTime(signouttime); + curOvertimeBean.setBelongDate(splitDate); + curOvertimeBean.setHas_cut_point("0"); + lsCheckInfoMaps.put(key, curOvertimeBean); + } + }else if(signoutdatetime.length() > 0 && date_cut_point.compareTo(signoutdatetime) > 0){ + //如果归属大于签退时间 表示这个时间都是属于前一天的 + lsCheckInfoMaps.put(preKey, kqOvertimeBean); + }else{ + //如果归属 小于签到时间,则都属于今天 + lsCheckInfoMaps.put(key, kqOvertimeBean); + } + + if(signoutdate.length() > 0){ + if(signoutdate.compareTo(splitDate) > 0){ + if(1 == has_cut_point){ + KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo(); + String overtimePoint = Util.null2String(kqSettingsComInfo.getMain_val("overtime_point"),"0"); + boolean needPointCut = false; + if("1".equals(overtimePoint)){ + needPointCut = true; + } + //没这个开关的话不会有下面的逻辑 + if(needPointCut){ + //如果签退大于签到 表示打卡跨天 + if(next_date_cut_point.compareTo(signoutdatetime) < 0){ + String hasSigninDate = signindate; + String hasSigninTime = signintime; + if(lsCheckInfoMaps.containsKey(key)){ + KQOvertimeCardBean hasOvertimeBean = lsCheckInfoMaps.get(key); + hasSigninDate = hasOvertimeBean.getSigninDate(); + hasSigninTime = hasOvertimeBean.getSigninTime(); + } + KQOvertimeCardBean curOvertimeBean = new KQOvertimeCardBean(); + curOvertimeBean.setSigninDate(hasSigninDate); + curOvertimeBean.setSigninTime(hasSigninTime); + curOvertimeBean.setSignoutDate(nextDate); + curOvertimeBean.setSignoutTime(next_overtime_cut_points); + //这个是新加的开关,为了保证历史数据,只能这样加了 + if(result.containsKey("beginTime")){ + //上班前打卡和班次开始时间作为第一段加班区间 + curOvertimeBean.setSignoutDate(splitDate); + curOvertimeBean.setSignoutTime(result.get("beginTime")+":00"); + } + curOvertimeBean.setBelongDate(splitDate); + lsCheckInfoMaps.put(key, curOvertimeBean); + + KQOvertimeCardBean nextOvertimeBean = new KQOvertimeCardBean(); + nextOvertimeBean.setSigninDate(nextDate); + nextOvertimeBean.setSigninTime(next_overtime_cut_points); + //这个是新加的开关,为了保证历史数据,只能这样加了 + if(result.containsKey("endTime") && result.containsKey("endTimeAcross")){ + if(result.get("endTimeAcross").equals("1")){ + String tmp1 = nextDate+" "+kqTimesArrayComInfo.turn48to24Time(result.get("endTime"))+":00"; + if(next_date_cut_point.compareTo(tmp1) > 0){ + //如果跨天归属点大于下班时间,需要再根据归属点分割下 + KQOvertimeCardBean curNextOvertimeBean = new KQOvertimeCardBean(); + curNextOvertimeBean.setSigninDate(nextDate); + curNextOvertimeBean.setSigninTime(kqTimesArrayComInfo.turn48to24Time(result.get("endTime"))+":00"); + curNextOvertimeBean.setSignoutDate(nextDate); + curNextOvertimeBean.setSignoutTime(next_overtime_cut_points); + curNextOvertimeBean.setBelongDate(splitDate); + if(lsCheckInfoMaps.containsKey(key)){ + KQOvertimeCardBean kqOvertimeCardBean = lsCheckInfoMaps.get(key); + curNextOvertimeBean.setSigninDate(kqOvertimeCardBean.getSigninDate()); + curNextOvertimeBean.setSigninTime(kqOvertimeCardBean.getSigninTime()); + } + lsCheckInfoMaps.put(key, curNextOvertimeBean); + }else{ + nextOvertimeBean.setSigninDate(nextDate); + nextOvertimeBean.setSigninTime(kqTimesArrayComInfo.turn48to24Time(result.get("endTime"))+":00"); + } + }else{ + //下班时间和开启的加班归属点作为第二段加班区间 + KQOvertimeCardBean curNextOvertimeBean = new KQOvertimeCardBean(); + curNextOvertimeBean.setSigninDate(splitDate); + curNextOvertimeBean.setSigninTime(result.get("endTime")+":00"); + curNextOvertimeBean.setSignoutDate(nextDate); + curNextOvertimeBean.setSignoutTime(next_overtime_cut_points); + curNextOvertimeBean.setBelongDate(splitDate); + if(lsCheckInfoMaps.containsKey(key)){ + KQOvertimeCardBean kqOvertimeCardBean = lsCheckInfoMaps.get(key); + curNextOvertimeBean.setSigninDate(kqOvertimeCardBean.getSigninDate()); + curNextOvertimeBean.setSigninTime(kqOvertimeCardBean.getSigninTime()); + } + lsCheckInfoMaps.put(key, curNextOvertimeBean); + } + } + nextOvertimeBean.setSignoutDate(signoutdate); + nextOvertimeBean.setSignoutTime(signouttime); + nextOvertimeBean.setBelongDate(nextDate); + //加班归属点和跨天的下班签退卡作为第三段加班区间 + lsCheckInfoMaps.put(nextkey, nextOvertimeBean); + } + } + } + } + } + } + + + /** + * 获取加班流程数据 + * @param resourceid + * @param fromDate + * @param toDate + * @param splitBeanMaps + * @param dateFormatter + */ + private void getOverTimeFlowData(String resourceid, String fromDate, String toDate, + Map> splitBeanMaps, + DateTimeFormatter dateFormatter) { + LocalDate localFromDate = LocalDate.parse(fromDate); + LocalDate preFromDate = localFromDate.minusDays(1); + LocalDate localToDate = LocalDate.parse(toDate); + long betweenDays = localToDate.toEpochDay() - preFromDate.toEpochDay(); + for (int k = 0; k <= betweenDays; k++) { + LocalDate curLocalDate = preFromDate.plusDays(k); + String splitDate = curLocalDate.format(dateFormatter); + String key = resourceid+"_"+splitDate; + String order_sql = " order by belongdate,fromtime "; + KQFlowDataBiz kqFlowDataBiz = new KQFlowDataBiz.FlowDataParamBuilder().belongDateParam(splitDate).resourceidParam(resourceid).orderby_sqlParam(order_sql).build(); + Map flowMaps = Maps.newHashMap(); + List splitBeans = kqFlowDataBiz.getOverTimeData(flowMaps); + if(!splitBeans.isEmpty()){ + splitBeanMaps.put(key, splitBeans); + } + } + } + + /** + * 获取非工作日的打卡数据 + * @param resourceid + * @param splitDate + * @param preDate + * @param nextDate + * @param curKqOvertimeRulesDetailEntity + * @param eventMap + * @param preKqOvertimeRulesDetailEntity + * @return + */ + private Map getRestSignInfo(String resourceid, String splitDate, String preDate, + String nextDate, + KQOvertimeRulesDetailEntity curKqOvertimeRulesDetailEntity, + Map eventMap, + KQOvertimeRulesDetailEntity preKqOvertimeRulesDetailEntity) { + Map signMap = Maps.newHashMap(); + WorkTimeEntity pre_workTime = new KQWorkTime().getWorkTime(resourceid, preDate); + List pre_lsSignTime = new ArrayList<>(); + + if (pre_workTime != null) { + pre_lsSignTime = pre_workTime.getSignTime();//允许打卡时间 + pre_lsSignTime = pre_lsSignTime != null ? pre_lsSignTime : new ArrayList<>(); + } + WorkTimeEntity next_workTime = new KQWorkTime().getWorkTime(resourceid, nextDate); + List next_lsSignTime = new ArrayList<>(); + + if (next_workTime != null) { + next_lsSignTime = next_workTime.getSignTime();//允许打卡时间 + next_lsSignTime = next_lsSignTime != null ? next_lsSignTime : new ArrayList<>(); + } + + signMap = getNonWorkSignInfo(resourceid,nextDate,splitDate,pre_lsSignTime,next_lsSignTime,curKqOvertimeRulesDetailEntity,eventMap,preKqOvertimeRulesDetailEntity); + + return signMap; + } + + + /** + * 获取非工作日的打卡数据 封装处理下 + * @param resourceid + * @param nextDate + * @param kqDate + * @param pre_lsSignTime + * @param next_lsSignTime + * @param curKqOvertimeRulesDetailEntity + * @param eventMap + * @param preKqOvertimeRulesDetailEntity + * @return + */ + public Map getNonWorkSignInfo(String resourceid, String nextDate, String kqDate, + List pre_lsSignTime, + List next_lsSignTime, + KQOvertimeRulesDetailEntity curKqOvertimeRulesDetailEntity, + Map eventMap, + KQOvertimeRulesDetailEntity preKqOvertimeRulesDetailEntity) { + Map signMap = Maps.newHashMap(); + KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo(); + String overtimePoint = Util.null2String(kqSettingsComInfo.getMain_val("overtime_point"),"0"); + boolean needPointCut = false; + if("1".equals(overtimePoint)){ + needPointCut = true; + } + KQFormatSignData kqFormatSignData = new KQFormatSignData(); + List lsCheckInfo = new ArrayList<>(); + Map checkInfo = null; + RecordSet rs = new RecordSet(); + String pre_Worktime4Today = ""; + if(!pre_lsSignTime.isEmpty()){ + TimeScopeEntity pre_signTimeScope = pre_lsSignTime.get(pre_lsSignTime.size()-1); + if(pre_signTimeScope.getEndTimeAcross()){ + pre_Worktime4Today = pre_signTimeScope.getEndTime(); + } + } + String next_Worktime4Today = ""; + if(!next_lsSignTime.isEmpty()){ + TimeScopeEntity next_signTimeScope = next_lsSignTime.get(next_lsSignTime.size()-1); + if(next_signTimeScope.isBeginTimePreAcross()){ + next_Worktime4Today = next_signTimeScope.getBeginTime(); + } + } + String signBeginDateTime = kqDate+" 00:00:00"; + String signEndDateTime = kqDate+" 23:59:59"; + //有这么一种情况,比如前一天是工作日,最晚签退是2点,然后工作日的归属是设置的5点,那么如果4点打一个卡的话,其实是需要生成加班的,因为4带你这个卡是昨日的签退 + String ore_signBeginDateTime = signBeginDateTime; + String base_sql = kqFormatSignData.signSignSql(rs); + + int pre_has_cut_point = preKqOvertimeRulesDetailEntity != null ? preKqOvertimeRulesDetailEntity.getHas_cut_point() : 0; + + if(pre_Worktime4Today.length() > 0){ + if(!needPointCut && pre_has_cut_point == 1){ + String cut_point = Util.null2String(preKqOvertimeRulesDetailEntity.getCut_point()); + if(cut_point.length() > 0){ + if(cut_point.compareTo(pre_Worktime4Today) > 0){ + pre_Worktime4Today = cut_point; + }else{ + if(pre_Worktime4Today.length() == 5){ + pre_Worktime4Today += ":00"; + } + ore_signBeginDateTime = kqDate+" "+pre_Worktime4Today; + } + /** + 打卡数据:2022/04/29 09:00:00----2022/04/29 23:59:59---2022/04/30 00:00:00----2022/04/30 02:00:00 + 加班流程:2022-04-29 20:00---2022-04-30 03:00 + 加班规则:2022-04-29周五工作日自定义跨天归属设置为00:00,取交集,然后30号的00:00-02:00两个小时加班无法生成 + 问题原因:当29的下班卡结束打卡时间在自定义跨天00:00之后,那么读卡范围是:29号结束打卡时间(pre_Worktime4Today)开始的 + */ + pre_Worktime4Today = cut_point+":01"; + } + } + if(pre_Worktime4Today.length() == 5){ + pre_Worktime4Today += ":00"; + } + signBeginDateTime = kqDate+" "+pre_Worktime4Today; + }else{ + if(!needPointCut && pre_has_cut_point == 1){ + String cut_point = Util.null2String(preKqOvertimeRulesDetailEntity.getCut_point()); + if(cut_point.length() > 0){ + String cut_point_time = kqDate+" "+cut_point+":00"; + signBeginDateTime = cut_point_time; + } + } + } + if(next_Worktime4Today.length() > 0){ + if(next_Worktime4Today.length() == 5){ + next_Worktime4Today += ":00"; + } + signEndDateTime = kqDate+" "+next_Worktime4Today; + }else{ + if(curKqOvertimeRulesDetailEntity != null){ + int cur_has_cut_point = curKqOvertimeRulesDetailEntity.getHas_cut_point(); + if(!needPointCut && cur_has_cut_point == 1){ + String cut_point = Util.null2String(curKqOvertimeRulesDetailEntity.getCut_point()); + if(cut_point.length() > 0){ + String cut_point_time = nextDate+" "+cut_point+":00"; + signEndDateTime = cut_point_time; + } + } + } + } + String sql = "select * from ("+base_sql+") a "+" order by signdate asc,signtime asc "; + rs.executeQuery(sql,resourceid,signBeginDateTime,signEndDateTime); + String nonwork_card_sql = "sql:"+sql+"|resourceid|"+resourceid+"|signBeginDateTime|"+signBeginDateTime+"|signEndDateTime|"+signEndDateTime; + eventMap.put("非工作日打卡sql|nonwork_card_sql", nonwork_card_sql); + eventMap.put("非工作日打卡sql结果|nonwork_card_sql_getCounts", rs.getCounts()); + int idx = 0; + while (rs.next()){ + String signId = Util.null2String(rs.getString("id")); + String signdate = Util.null2String(rs.getString("signdate")); + String signtime = Util.null2String(rs.getString("signtime")); + + checkInfo = new HashMap<>(); + checkInfo.put("signId", signId);//签到签退标识 + checkInfo.put("signDate", signdate);//签到签退日期 + checkInfo.put("signTime", signtime);//签到签退时间 + idx++; + if(idx==1){//第一条算签到 + checkInfo.put("signType", "1"); + lsCheckInfo.add(checkInfo); + }else if(idx==rs.getCounts()){//最后一条算签退 + checkInfo.put("signType", "2"); + lsCheckInfo.add(checkInfo); + } + } + if(lsCheckInfo != null && !lsCheckInfo.isEmpty()){ + if(lsCheckInfo.size() == 2){ + Map begin_signMap = (Map) lsCheckInfo.get(0); + Map end_signMap = (Map) lsCheckInfo.get(lsCheckInfo.size()-1); + signMap.put("signindate", begin_signMap.get("signDate")); + signMap.put("signintime", begin_signMap.get("signTime")); + signMap.put("signoutdate", end_signMap.get("signDate")); + signMap.put("signouttime", end_signMap.get("signTime")); + }else if(lsCheckInfo.size() == 1){ + Map begin_signMap = (Map) lsCheckInfo.get(0); + signMap.put("signindate", begin_signMap.get("signDate")); + signMap.put("signintime", begin_signMap.get("signTime")); + } + }else{ + if(pre_has_cut_point == 1){ + sql = "select * from ("+base_sql+") a "+" order by signdate asc,signtime asc "; + rs.executeQuery(sql,resourceid,ore_signBeginDateTime,signEndDateTime); + nonwork_card_sql = "sql:"+sql+"|resourceid|"+resourceid+"|ore_signBeginDateTime|"+ore_signBeginDateTime+"|signEndDateTime|"+signEndDateTime; + eventMap.put("昨日开启了打卡归属,非工作日打卡sql|nonwork_card_sql", nonwork_card_sql); + eventMap.put("昨日开启了打卡归属,非工作日打卡sql结果|nonwork_card_sql_getCounts", rs.getCounts()); + idx = 0; + while (rs.next()){ + String signId = Util.null2String(rs.getString("id")); + String signdate = Util.null2String(rs.getString("signdate")); + String signtime = Util.null2String(rs.getString("signtime")); + + checkInfo = new HashMap<>(); + checkInfo.put("signId", signId);//签到签退标识 + checkInfo.put("signDate", signdate);//签到签退日期 + checkInfo.put("signTime", signtime);//签到签退时间 + idx++; + if(idx==1){//第一条算签到 + checkInfo.put("signType", "1"); + lsCheckInfo.add(checkInfo); + }else if(idx==rs.getCounts()){//最后一条算签退 + checkInfo.put("signType", "2"); + lsCheckInfo.add(checkInfo); + } + } + if(lsCheckInfo != null && !lsCheckInfo.isEmpty()){ + //这种情况下,就只是把签到卡传回去作为前一天的签退了 + Map begin_signMap = (Map) lsCheckInfo.get(0); + signMap.put("signindate", begin_signMap.get("signDate")); + signMap.put("signintime", begin_signMap.get("signTime")); + } + } + } + return signMap; + } + /** + * 获取工作日的打卡数据 + * @param userId + * @param signTimeScope + * @param workTimeScope + * @param kqDate + * @param preDate + * @param nextDate + * @param kqTimesArrayComInfo + * @param eventMap + * @param index + * @param result + * @return + */ + public Map getSignInfo(String userId, TimeScopeEntity signTimeScope, + TimeScopeEntity workTimeScope, String kqDate, String preDate, + String nextDate, KQTimesArrayComInfo kqTimesArrayComInfo,Map eventMap, + int index,Map result) { + KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo(); + String overtimePoint = Util.null2String(kqSettingsComInfo.getMain_val("overtime_point"),"0"); + boolean needPointCut = true; + if("1".equals(overtimePoint)){ + needPointCut = false; + } + + Map signMap = Maps.newHashMap(); + KQFormatSignData kqFormatSignData = new KQFormatSignData(); + List lsCheckInfo = new ArrayList<>(); + Map checkInfo = null; + String base_sql = ""; + RecordSet rs = new RecordSet(); + String dbtype = rs.getDBType(); + + int has_cut_point = Util.getIntValue(Util.null2String(result.get("has_cut_point"))); + String cut_point = Util.null2String(result.get("cut_point")); + + int pre_has_cut_point = Util.getIntValue(Util.null2String(result.get("pre_has_cut_point"))); + String pre_cut_point = Util.null2String(result.get("pre_cut_point")); + int lsWorkTime_size = Util.getIntValue(Util.null2String(result.get("lsWorkTime_size"))); + + List> sqlConditions = kqFormatSignData.getCanSignInfo(signTimeScope,kqDate,preDate,nextDate,kqTimesArrayComInfo); + base_sql = kqFormatSignData.signSignSql(rs); + + if(sqlConditions != null && !sqlConditions.isEmpty()){ + for (int i = 0; i < sqlConditions.size(); i++) { + Map sqlMap = sqlConditions.get(i); + String sql = ""; + String orderSql = ""; + int idx = 0; + String signBeginDateTime = Util.null2String(sqlMap.get("signBeginDateTime")); + String signEndDateTime = Util.null2String(sqlMap.get("signEndDateTime")); + if(index == lsWorkTime_size-1 && i == sqlConditions.size()-1){ + //最后一次的打卡范围会被打卡临界点给修改 + if(needPointCut && has_cut_point == 1){ + String cut_point_datettime = nextDate+" "+cut_point+":59"; + signEndDateTime = cut_point_datettime; + } + } + if(index == 0 && i == 0){ + //第一次的打卡范围会被打卡临界点给修改 + if(needPointCut && pre_has_cut_point == 1){ + String cut_point_datettime = kqDate+" "+pre_cut_point+":00"; + signBeginDateTime = cut_point_datettime; + } + } + String type = Util.null2String(sqlMap.get("type")); + if(type.length() > 0){ + if("signoff".equalsIgnoreCase(type)){ + orderSql = " order by signdate desc, signtime desc "; + }else if("signin".equalsIgnoreCase(type)){ + orderSql = " order by signdate asc, signtime asc "; + } + if("oracle".equalsIgnoreCase(dbtype)){ + sql = "select * from ("+base_sql+" "+orderSql+") a where rownum=1"; + }else if("mysql".equalsIgnoreCase(dbtype)){ + sql = "select * from ("+base_sql+" "+orderSql+") a limit 0,1"; + } + else if("postgresql".equalsIgnoreCase(dbtype)){ + sql = "select * from ("+base_sql+" "+orderSql+") a limit 1 offset 0"; + } + else if("sqlserver".equalsIgnoreCase(dbtype)){ + sql = "select top 1 * from ("+base_sql+") a "+" "+orderSql; + }else{ + sql = "select * from ("+base_sql+" "+orderSql+") a where rownum=1"; + } + }else{ + orderSql = " order by signdate asc, signtime asc "; + sql = base_sql+" "+orderSql; + } + rs.executeQuery(sql, userId, signBeginDateTime, signEndDateTime); + String work_card_sql = "index:"+index+":idx:"+idx+"|sql:"+sql+"|resourceid|"+userId+"|signBeginDateTime|"+signBeginDateTime+"|signEndDateTime|"+signEndDateTime; + + eventMap.put("工作日打卡sql|work_card_sql_"+index, work_card_sql); + eventMap.put("工作日打卡sql结果|work_card_sql_getCounts_"+index, rs.getCounts()); + while (rs.next()) { + String signId = Util.null2String(rs.getString("id")); + String signdate = Util.null2String(rs.getString("signdate")); + String signtime = Util.null2String(rs.getString("signtime")); + + checkInfo = new HashMap<>(); + checkInfo.put("signId", signId);//签到签退标识 + checkInfo.put("signDate", signdate);//签到签退日期 + checkInfo.put("signTime", signtime);//签到签退时间 + checkInfo.put("type", type);//是否有打卡归属,type有值就是有打卡归属 + idx++; + if(type.length() > 0){ + if("signin".equalsIgnoreCase(type)){ + checkInfo.put("signType", "1"); + lsCheckInfo.add(checkInfo); + }else { + checkInfo.put("signType", "2"); + lsCheckInfo.add(checkInfo); + } + }else{ + if(idx==1){//第一条算签到 + checkInfo.put("signType", "1"); + lsCheckInfo.add(checkInfo); + }else if(idx==rs.getCounts()){//最后一条算签退 + checkInfo.put("signType", "2"); + lsCheckInfo.add(checkInfo); + } + } + } + } + } + if(lsCheckInfo != null && !lsCheckInfo.isEmpty()){ + if(lsCheckInfo.size() == 1){ + Map checkInfoMap = (Map) lsCheckInfo.get(0); + String type = Util.null2String(checkInfoMap.get("type")); + if("signin".equalsIgnoreCase(type)){ + signMap.put("signindate", checkInfoMap.get("signDate")); + signMap.put("signintime", checkInfoMap.get("signTime")); + signMap.put("signoutdate", workTimeScope.getBeginTimeAcross()?nextDate:kqDate); + signMap.put("signouttime", kqTimesArrayComInfo.turn48to24Time(workTimeScope.getBeginTime())+":00"); + }else if("signoff".equalsIgnoreCase(type)){ + signMap.put("signindate", workTimeScope.getEndTimeAcross()?nextDate:kqDate); + signMap.put("signintime", kqTimesArrayComInfo.turn48to24Time(workTimeScope.getEndTime())+":00"); + signMap.put("signoutdate", checkInfoMap.get("signDate")); + signMap.put("signouttime", checkInfoMap.get("signTime")); + }else{ + signMap.put("signindate", checkInfoMap.get("signDate")); + signMap.put("signintime", checkInfoMap.get("signTime")); + signMap.put("signoutdate", workTimeScope.getBeginTimeAcross()?nextDate:kqDate); + signMap.put("signouttime", kqTimesArrayComInfo.turn48to24Time(workTimeScope.getBeginTime())+":00"); + } + }else{ + Map begin_signMap = (Map) lsCheckInfo.get(0); + Map end_signMap = (Map) lsCheckInfo.get(lsCheckInfo.size()-1); + signMap.put("signindate", begin_signMap.get("signDate")); + signMap.put("signintime", begin_signMap.get("signTime")); + signMap.put("signoutdate", end_signMap.get("signDate")); + signMap.put("signouttime", end_signMap.get("signTime")); + } + } + return signMap; + } + + /** + * 获取已经生成过的加班数据 + * @param resourceid + * @param belongdate + * @param hasOverTimeList + */ + private void getHasOverTimeData(String resourceid, String belongdate,List> hasOverTimeList) { + RecordSet rs = new RecordSet(); + + String sql = " select * from kq_flow_overtime where resourceid = ? and belongdate = ? "; + rs.executeQuery(sql,resourceid,belongdate); + while (rs.next()){ + String requestid =rs.getString("requestid"); + String fromdate =rs.getString("fromdate"); + String fromtime =rs.getString("fromtime"); + String todate =rs.getString("todate"); + String totime =rs.getString("totime"); + String duration_min =Util.null2String(rs.getString("duration_min")); + String flow_dataid =Util.null2String(rs.getString("flow_dataid")); + String ori_belongdate =Util.null2String(rs.getString("ori_belongdate")); + //流程+打卡的时候,存的对应的流程数据 + String fromdate_flow =rs.getString("fromdatedb"); + String fromtime_flow =rs.getString("fromtimedb"); + String todate_flow =rs.getString("todatedb"); + String totime_flow =rs.getString("totimedb"); + Map hasOverTimeMap = Maps.newHashMap(); + hasOverTimeMap.put("resourceid", resourceid); + hasOverTimeMap.put("belongdate", belongdate); + hasOverTimeMap.put("requestid", requestid); + hasOverTimeMap.put("fromdate", fromdate); + hasOverTimeMap.put("fromtime", fromtime); + hasOverTimeMap.put("todate", todate); + hasOverTimeMap.put("totime", totime); + hasOverTimeMap.put("fromdate_flow", fromdate_flow); + hasOverTimeMap.put("fromtime_flow", fromtime_flow); + hasOverTimeMap.put("todate_flow", todate_flow); + hasOverTimeMap.put("totime_flow", totime_flow); + hasOverTimeMap.put("duration_min", duration_min); + hasOverTimeMap.put("flow_dataid", flow_dataid); + hasOverTimeMap.put("ori_belongdate", ori_belongdate); + + hasOverTimeList.add(hasOverTimeMap); + } + } + + /** + * 根据人和日期获取加班规则里的信息 + * @param resourceid + * @param fromDate + * @param toDate + * @param dateFormatter + * @param changeTypeMap + * @param overRulesDetailMap + * @param restTimeMap + * @param computingModeMap + */ + public void getOverTimeDataMap(String resourceid, String fromDate, String toDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap,Map> restTimeMap,Map computingModeMap){ + + LocalDate localFromDate = LocalDate.parse(fromDate); + LocalDate localToDate = LocalDate.parse(toDate); + LocalDate preFromDate = localFromDate.minusDays(2); + LocalDate nextToDate = localToDate.plusDays(1); + long betweenDays = nextToDate.toEpochDay() - preFromDate.toEpochDay(); + for (int i = 0; i <= betweenDays; i++) { + LocalDate curLocalDate = preFromDate.plusDays(i); + String splitDate = curLocalDate.format(dateFormatter); + KQOvertimeRulesBiz.getOverTimeData(resourceid, splitDate,changeTypeMap,overRulesDetailMap,restTimeMap,computingModeMap); + } + } + + public void logOvertimeMap(Map overtimeLogMap,Object params, String keys){ + if(overtimeLogMap != null){ + overtimeLogMap.put(keys, params); + } + } + + /** + * 判断是否开启了调休 + * @param kqOvertimeRulesDetailEntity + * @param overtime_type + * @return + */ + public int getPaidLeaveEnable(KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity, + String overtime_type) { + int paidLeaveEnable = -1; + if (kqOvertimeRulesDetailEntity != null){ + paidLeaveEnable = kqOvertimeRulesDetailEntity.getPaidLeaveEnable(); + paidLeaveEnable = paidLeaveEnable == 1?1:0; + } + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + if(2 == paidLeaveEnableType){ +// logOvertimeMap(overtimeLogMap, overtime_type, flow_cross_key+"|关联调休与否来自于流程选择,加班类型下拉框值|overtime_type"); + if("0".equalsIgnoreCase(overtime_type)){ + paidLeaveEnable = 1; + }else if("1".equalsIgnoreCase(overtime_type)){ + paidLeaveEnable = 0; + }else{ + paidLeaveEnable = 0; + } + } + return paidLeaveEnable; + } + + + /** + * 清掉之前的加班和调休,重新生成 + * @param resourceid + * @param belongdate + * @param overtimeLogMap + * @param splitDate + */ + public void clearOvertimeTX(String resourceid, String belongdate, + Map overtimeLogMap, String splitDate) { + List all_tiaoxiuidList = Lists.newArrayList(); + String all_tiaoxiuids = ""; + RecordSet rs = new RecordSet(); + String sql = "select * from kq_flow_overtime where resourceid = ? and belongdate=? and ori_belongdate=? "; + rs.executeQuery(sql,resourceid, belongdate,splitDate); + while (rs.next()){ + String tiaoxiuid = Util.null2String(rs.getString("tiaoxiuid"),""); + if(tiaoxiuid.length() > 0 && Util.getIntValue(tiaoxiuid) > 0){ + all_tiaoxiuids += ","+tiaoxiuid; + all_tiaoxiuidList.add(tiaoxiuid); + } + } + logOvertimeMap(overtimeLogMap, all_tiaoxiuids, "需要重新生成的调休|all_tiaoxiuids"); + if(all_tiaoxiuids.length() > 0){ + all_tiaoxiuids = all_tiaoxiuids.substring(1); + + Map tiaoxiuamountMap = Maps.newLinkedHashMap(); + String selSql = "select * from kq_balanceofleave where "+Util.getSubINClause(all_tiaoxiuids, "id", "in"); + rs.executeQuery(selSql); + while (rs.next()){ + String id = rs.getString("id"); + String tiaoxiuamount = rs.getString("tiaoxiuamount"); + tiaoxiuamountMap.put(id, tiaoxiuamount); + } + if(!tiaoxiuamountMap.isEmpty()){ + logOvertimeMap(overtimeLogMap, tiaoxiuamountMap, "先记录下之前的加班生成的调休数据|tiaoxiuamountMap"); + } + String tiaoxiuidis0 = ""; + String delSql0 = "select * from kq_balanceofleave where "+Util.getSubINClause(all_tiaoxiuids, "id", "in")+" and " + + " baseamount =0 and extraamount=0 and usedamount=0 and baseamount2=0 and extraamount2=0 and usedamount2=0 "; + if(rs.getDBType().equalsIgnoreCase("oracle")) { + delSql0 = "select * from kq_balanceofleave where "+Util.getSubINClause(all_tiaoxiuids, "id", "in")+" and " + + " nvl(baseamount,0) =0 and nvl(extraamount,0)=0 and nvl(usedamount,0)=0 and nvl(baseamount2,0)=0 " + + " and nvl(extraamount2,0)=0 and nvl(usedamount2,0)=0 "; + }else if((rs.getDBType()).equalsIgnoreCase("mysql")){ + delSql0 = "select * from kq_balanceofleave where "+Util.getSubINClause(all_tiaoxiuids, "id", "in")+" and " + + " ifnull(baseamount,0) =0 and ifnull(extraamount,0)=0 and ifnull(usedamount,0)=0 and ifnull(baseamount2,0)=0 " + + " and ifnull(extraamount2,0)=0 and ifnull(usedamount2,0)=0 "; + }else { + delSql0 = "select * from kq_balanceofleave where "+Util.getSubINClause(all_tiaoxiuids, "id", "in")+" and " + + " isnull(baseamount,0) =0 and isnull(extraamount,0)=0 and isnull(usedamount,0)=0 and isnull(baseamount2,0)=0 " + + " and isnull(extraamount2,0)=0 and isnull(usedamount2,0)=0 "; + } + rs.executeQuery(delSql0); + while (rs.next()){ + String tiaoxiuid = Util.null2String(rs.getString("id"),""); + if(tiaoxiuid.length() > 0 && Util.getIntValue(tiaoxiuid) > 0){ + tiaoxiuidis0 += ","+tiaoxiuid; + all_tiaoxiuidList.remove(tiaoxiuid); + } + } + String delSql = ""; + if(tiaoxiuidis0.length() > 0){ + delSql = "delete from kq_balanceofleave where "+Util.getSubINClause(tiaoxiuidis0, "id", "in"); + boolean flag= rs.executeUpdate(delSql); + if (!flag) { + kqLog.info("加班流程删除之前的调休数据失败:数据库更新失败" ); + } + } + String clearSql = ""; + boolean isclearOk = false; + if(!all_tiaoxiuidList.isEmpty()){ + String clear_tiaoxiuids = all_tiaoxiuidList.stream().collect(Collectors.joining(",")); + clearSql = "update kq_balanceofleave set tiaoxiuamount=0.0, update_time=? where "+Util.getSubINClause(clear_tiaoxiuids, "id", "in"); + isclearOk = rs.executeUpdate(clearSql,KQDateUtil.getUpdateTimeStamp()); + } + + String delUsageSql = "delete from kq_usagehistory where "+Util.getSubINClause(all_tiaoxiuids, "balanceofleaveid", "in"); + boolean isdelUsageOk = rs.executeUpdate(delUsageSql); + Map logSqlMap = Maps.newLinkedHashMap(); + logSqlMap.put("tiaoxiuidis0",tiaoxiuidis0); + logSqlMap.put("all_tiaoxiuidList",all_tiaoxiuidList); + logSqlMap.put("delSql",delSql); + logSqlMap.put("clearSql",clearSql); + logSqlMap.put("isclearOk",isclearOk); + logSqlMap.put("delUsageSql",delUsageSql); + logSqlMap.put("isdelUsageOk",isdelUsageOk); + logOvertimeMap(overtimeLogMap, logSqlMap, "需要重新生成的调休对应的信息|logSqlMap"); + } + String delSql = "delete from kq_flow_overtime where resourceid = ? and belongdate=? and ori_belongdate=? "; + boolean isDelOk = rs.executeUpdate(delSql,resourceid, belongdate,splitDate); + String delSqlLog = delSql+":resourceid:"+resourceid+":belongdate:"+belongdate+":splitDate:"+splitDate+":isDelOk:"+isDelOk; + logOvertimeMap(overtimeLogMap, delSqlLog, "删除加班中间表数据|delSql"); + + } + /** + * 加班单位 + * @param d_mins + * @return + */ + public double getD_MinsByUnit(double d_mins) { + Map map = KQOvertimeRulesBiz.getMinimumUnitAndConversion(); + if(!map.isEmpty()){ + double conversionMins = 0.0; + int minimumUnit = Util.getIntValue(Util.null2String(map.get("minimumUnit")),-1); + int overtimeConversion = Util.getIntValue(Util.null2String(map.get("overtimeConversion")),-1); + if(5 == minimumUnit || 6 == minimumUnit){ + int halfHourInt = 30; + int wholeHourInt = 60; + if(5 == minimumUnit){ + conversionMins = getConversionMins(halfHourInt,d_mins,overtimeConversion); + }else { + conversionMins = getConversionMins(wholeHourInt,d_mins,overtimeConversion); + } + return conversionMins; + } + } + return d_mins; + } + + /** + * 根据转换规则得到转换后的加班时长 + * @param halfHourInt + * @param d_mins + * @param overtimeConversion + * @return + */ + public double getConversionMins(int halfHourInt, double d_mins, int overtimeConversion) { + double conversionMins = 0.0; + int step = (int) (d_mins/halfHourInt); + double leftMins = d_mins - halfHourInt*step; + //半小时 + if(1 == overtimeConversion){ +// 四舍五入 + if(leftMins >= halfHourInt/2){ + conversionMins = halfHourInt*step+halfHourInt; + }else{ + conversionMins = halfHourInt*step; + } + }else if(2 == overtimeConversion){ +// 向上取整 + if(leftMins > 0){ + conversionMins = halfHourInt*step+halfHourInt; + }else{ + conversionMins = halfHourInt*step; + } + }else if(3 == overtimeConversion){ +// 向下取整 + if(leftMins < halfHourInt){ + conversionMins = halfHourInt*step; + }else{ + conversionMins = halfHourInt*step; + } + } + return conversionMins; + } +}