From 17c7199b9651589395b027e5e910abca9e20c3a7 Mon Sep 17 00:00:00 2001 From: shilei <798989044@qq.com> Date: Tue, 19 Mar 2024 16:19:49 +0800 Subject: [PATCH] =?UTF-8?q?#WEAVER-HANSANG=5FPROD-1#=20=20=E5=91=A8?= =?UTF-8?q?=E6=9C=AB=E7=8F=AD=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/engine/kq/biz/KQFormatData.java | 985 ++++++ src/com/engine/kq/biz/KQOverTimeFlowBiz.java | 848 +++++ .../engine/kq/biz/KQOverTimeRuleCalBiz.java | 2798 +++++++++++++++++ .../kq/biz/KQShiftManagementComInfo.java | 759 +++++ .../engine/kq/biz/KQShiftManagementRedis.java | 299 ++ src/com/engine/kq/biz/KQWorkTime.java | 418 +++ .../chain/cominfo/ShiftInfoCominfoBean.java | 519 +++ .../biz/chain/cominfo/WorkShiftComIndex.java | 37 + .../cmd/attendanceButton/PunchButtonCmd.java | 618 ++++ .../GetShiftManagementBaseFormCmd.java | 424 +++ .../SaveShiftManagementBaseFormCmd.java | 489 +++ src/com/engine/kq/entity/WorkTimeEntity.java | 136 + .../kq/util/KQDurationCalculatorUtil.java | 631 ++++ 13 files changed, 8961 insertions(+) create mode 100644 src/com/engine/kq/biz/KQFormatData.java create mode 100644 src/com/engine/kq/biz/KQOverTimeFlowBiz.java create mode 100644 src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java create mode 100644 src/com/engine/kq/biz/KQShiftManagementComInfo.java create mode 100644 src/com/engine/kq/biz/KQShiftManagementRedis.java create mode 100644 src/com/engine/kq/biz/KQWorkTime.java create mode 100644 src/com/engine/kq/biz/chain/cominfo/ShiftInfoCominfoBean.java create mode 100644 src/com/engine/kq/biz/chain/cominfo/WorkShiftComIndex.java create mode 100644 src/com/engine/kq/cmd/attendanceButton/PunchButtonCmd.java create mode 100644 src/com/engine/kq/cmd/shiftmanagement/GetShiftManagementBaseFormCmd.java create mode 100644 src/com/engine/kq/cmd/shiftmanagement/SaveShiftManagementBaseFormCmd.java create mode 100644 src/com/engine/kq/entity/WorkTimeEntity.java create mode 100644 src/com/engine/kq/util/KQDurationCalculatorUtil.java diff --git a/src/com/engine/kq/biz/KQFormatData.java b/src/com/engine/kq/biz/KQFormatData.java new file mode 100644 index 0000000..e4972ad --- /dev/null +++ b/src/com/engine/kq/biz/KQFormatData.java @@ -0,0 +1,985 @@ +package com.engine.kq.biz; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.cloudstore.dev.api.util.Util_DataMap; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.cmd.attendanceButton.ButtonStatusEnum; +import com.engine.kq.entity.KQShiftRuleEntity; +import com.engine.kq.entity.TimeScopeEntity; +import com.engine.kq.entity.TimeSignScopeEntity; +import com.engine.kq.entity.WorkTimeEntity; +import com.engine.kq.enums.FlowReportTypeEnum; +import com.engine.kq.log.KQLog; +import com.engine.kq.util.UtilKQ; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.googlecode.aviator.AviatorEvaluator; +import com.googlecode.aviator.Expression; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang3.StringUtils; +import weaver.common.DateUtil; +import weaver.conn.BatchRecordSet; +import weaver.conn.RecordSet; +import weaver.file.Prop; +import weaver.general.BaseBean; +import weaver.general.InitServer; +import weaver.general.Util; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 考勤数据格式化 + */ +public class KQFormatData extends BaseBean { + private String today = DateUtil.getCurrentDate(); + private KQLog kqLog = new KQLog(); + private boolean writeLog = false; + private LinkedHashMap logInfo = new LinkedHashMap<>(); + + /*** + * 该方法不允许直接调用 + * @param userId + * @param kqDate + * @return + */ + public Map formatKqDate(String userId, String kqDate) { + List> lsParam = new ArrayList<>(); + //非工作日处理 + List nonlsParam = null; + Map resultMap = new HashMap<>(); + BatchRecordSet bRs = new BatchRecordSet(); + KQGroupComInfo kqGroupComInfo = new KQGroupComInfo(); + RecordSet rs = new RecordSet(); + String sql = ""; + try { + kqLog.info("formatKqDate in userId=" + userId + "kqDate==" + kqDate); + if (DateUtil.timeInterval(kqDate, today) < 0) {//今天之后的无需处理 + kqLog.info("今天之后的无需处理的数据:resourceid=="+userId+"kqdate=="+kqDate+"today=="+today); + return resultMap; + } + String uuid = UUID.randomUUID().toString(); + KQFormatFreeData kqFormatFreeData = new KQFormatFreeData(); + KQWorkTime kqWorkTime = new KQWorkTime(); + kqWorkTime.setIsFormat(true); + String kqDateNext = DateUtil.addDate(kqDate, 1); + + KQFlowDataBiz kqFlowDataBiz = new KQFlowDataBiz.FlowDataParamBuilder().resourceidParam(userId).fromDateParam(kqDate).toDateParam(kqDateNext).build(); + Map workFlowInfo = new HashMap<>();//userid|date--工作流程 + kqFlowDataBiz.getAllFlowData(workFlowInfo,false); + WorkTimeEntity workTime = kqWorkTime.getWorkTime(userId, kqDate); + kqLog.info("userId:"+userId+":kqDate:"+kqDate+":formatKqDate workTime=" + JSONObject.toJSONString(workTime)+"::uuid::"+uuid); + kqLog.info("userId:"+userId+":kqDate:"+kqDate+":formatKqDate workFlowInfo=" + JSONObject.toJSONString(workFlowInfo)+"::uuid::"+uuid); + + if(this.writeLog) { + logInfo.put("userId",userId); + logInfo.put("kqDate",kqDate); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(16253,weaver.general.ThreadVarLanguage.getLang())+"",workTime); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(126871,weaver.general.ThreadVarLanguage.getLang())+"",workFlowInfo); + } + + new KQFormatBiz().delFormatData(userId, kqDate); + + String excludecount = Util.null2String(kqGroupComInfo.getExcludecount(workTime.getGroupId()));//是否参与考勤报表统计 + if (workTime.getIsExclude()) {//无需考勤人员没有异常状态 + if(!excludecount.equals("1")){ + kqLog.info("无需考勤人员没有异常状态 workTime.getIsExclude()="+workTime.getIsExclude()+"excludecount=="+excludecount); + return resultMap; + } + } + if( Util.null2String(workTime.getGroupId()).length()==0){ + //没有考勤组不需格式化 + return resultMap; + } + if (workTime == null || (workTime.getWorkMins() == 0 && workTime.getRestShift() != 1)) { + kqLog.info("workTime == null || workTime.getWorkMins() == 0 插入空记录"); + nonlsParam = new ArrayList<>(); + formatNonWork(userId, kqDate,nonlsParam,workTime, workFlowInfo); + + if(!nonlsParam.isEmpty()){ + sql = " insert into kq_format_detail(resourceid,kqdate,groupid,serialnumber,signindate,signintime,signinid,signoutdate,signouttime,signoutid,leaveMins,leaveinfo,evectionMins,outMins)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + rs.executeUpdate(sql, nonlsParam); + + sql = " insert into kq_format_total(resourceid,kqdate,subcompanyid,departmentid,jobtitle,groupid,serialid,workdays," + + " workmins,attendancedays,attendancemins,signdays,signmins,belate,belatemins,gravebelate,gravebelatemins,leaveeearly,leaveearlymins," + + " graveleaveearly,graveleaveearlymins,absenteeism,absenteeismmins,forgotcheck, forgotcheckMins,leaveMins,evectionMins,outMins)" + + " select a.resourceid,kqdate,b.subcompanyid1,b.departmentid,b.jobtitle,groupid,serialid," + + " case when sum(workmins)>0 then 1 end as workdays, sum(workmins) as workmins," + + " 0 as attendancedays, sum(attendanceMins) as attendanceMins," + + " 0 as signdays, sum(signmins) as signmins," + + " sum(case when belatemins> 0 then 1 else 0 end) as belate,sum(belatemins) as belatemins," + + " sum(case when graveBeLateMins> 0 then 1 else 0 end) as graveBeLate,sum(graveBeLateMins) as graveBeLateMins," + + " sum(case when leaveearlymins> 0 then 1 else 0 end) as leaveearly,sum(leaveearlymins) as leaveearlymins," + + " sum(case when graveLeaveEarlyMins> 0 then 1 else 0 end) as graveLeaveEarly,sum(graveLeaveEarlyMins) as graveLeaveEarlyMins," + + " sum(case when absenteeismmins> 0 then 1 else 0 end) as absenteeism,sum(absenteeismmins) as absenteeismmins," + + " sum(case when forgotcheckmins> 0 then 1 else 0 end) as forgotcheck,sum(forgotcheckmins) as forgotcheckmins, " + + " sum(leaveMins) as leaveMins, sum(evectionMins) as evectionMins, sum(outMins) as outMins" + + " from kq_format_detail a, hrmresource b" + + " where a.resourceid = b.id and resourceid =? and kqdate=?" + + " group by resourceid,kqdate,b.subcompanyid1,b.departmentid,b.jobtitle,groupid,serialid,workmins"; + rs.executeUpdate(sql, userId, kqDate); + } + }else{ + Map definedFieldInfo = new KQFormatBiz().getDefinedField(); + String definedField = ""; + String definedParam = ""; + String definedParamSum = ""; + if (workTime.getKQType().equals("3")) {//自由工时 + lsParam.addAll(kqFormatFreeData.format(userId, kqDate, workFlowInfo)); + } else { + definedField = Util.null2String(definedFieldInfo.get("definedField")); + definedParam = Util.null2String(definedFieldInfo.get("definedParam")); + definedParamSum = Util.null2String(definedFieldInfo.get("definedParamSum")); + lsParam.addAll(format(userId, kqDate, workTime, workFlowInfo,uuid)); + } + + if (lsParam.size() > 0) { + sql = " insert into kq_format_detail( " + + " resourceid,kqdate,groupid,serialid,serialnumber,workbegindate,workbegintime,workenddate,workendtime,workmins," + + " signindate,signintime,signinid,signoutdate,signouttime,signoutid,signMins," + + " attendanceMins,belatemins,graveBeLateMins,leaveearlymins,graveLeaveEarlyMins,absenteeismmins,forgotcheckMins," + + " leaveMins,leaveinfo,evectionMins,outMins,forgotbeginworkcheckmins,otherinfo"+(definedField.length()>0?","+definedField+"":"")+") " + + " values(?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?,?,?,?"+(definedField.length()>0?","+definedParam+"":"")+")"; + for (int i = 0; i < lsParam.size(); i++) { + List param = lsParam.get(i); + boolean isok = rs.executeUpdate(sql, param); + kqLog.info("插入记录:userId:"+userId+":kqDate:"+kqDate+":param:"+JSON.toJSONString(param)+":isok:"+isok+"::uuid::"+uuid); + } + + sql = " insert into kq_format_total(resourceid,kqdate,subcompanyid,departmentid,jobtitle,groupid,serialid,workdays,workmins," + + " attendancedays,attendancemins,signdays,signmins,belate,belatemins,gravebelate,gravebelatemins,leaveeearly,leaveearlymins,graveleaveearly," + + " graveleaveearlymins,absenteeism,absenteeismmins,forgotcheck,forgotcheckmins," + + " leaveMins,evectionMins,outMins,forgotbeginworkcheck,forgotbeginworkcheckmins"+(definedField.length()>0?","+definedField+"":"")+") " + + " select a.resourceid,kqdate,b.subcompanyid1,b.departmentid,b.jobtitle,groupid,serialid," + + " case when sum(workmins)>0 then 1 end as workdays, sum(workmins) as workmins," + + " cast(sum(attendanceMins)AS decimal(10, 2))/sum(workmins) as attendancedays, sum(attendanceMins) as attendanceMins," + + " cast(sum(signmins)AS decimal(10, 2))/sum(workmins) as signdays, sum(signmins) as signmins," + + " sum(case when belatemins> 0 then 1 else 0 end) as belate,sum(belatemins) as belatemins," + + " sum(case when graveBeLateMins> 0 then 1 else 0 end) as graveBeLate,sum(graveBeLateMins) as graveBeLateMins," + + " sum(case when leaveearlymins> 0 then 1 else 0 end) as leaveearly,sum(leaveearlymins) as leaveearlymins," + + " sum(case when graveLeaveEarlyMins> 0 then 1 else 0 end) as graveLeaveEarly,sum(graveLeaveEarlyMins) as graveLeaveEarlyMins, " + + " sum(case when absenteeismmins> 0 then 1 else 0 end) as absenteeism,sum(absenteeismmins) as absenteeismmins," + + " sum(case when forgotcheckmins> 0 then 1 else 0 end) as forgotcheck,sum(forgotcheckmins) as forgotcheckmins,sum(leaveMins) as leaveMins," + + " sum(evectionMins) as evectionMins,sum(outMins) as outMins, " + + " sum(case when forgotbeginworkcheckmins> 0 then 1 else 0 end) as forgotbeginworkcheck,sum(forgotbeginworkcheckmins) as forgotbeginworkcheckmins " + + (definedField.length()>0?","+definedParamSum+"":"")+ + " from kq_format_detail a, hrmresource b" + + " where a.resourceid = b.id and resourceid = ? and kqdate=?" + + " group by resourceid,kqdate,b.subcompanyid1,b.departmentid,b.jobtitle,groupid,serialid"; + rs.executeUpdate(sql, userId, kqDate); + } + } + }catch (Exception e) { + kqLog.info("KQFormatData失败:userId:"+userId+":kqDate:"+kqDate); + sql = " insert into kq_format_pool (resourceid, kqdate) values (?,?)"; + rs.executeUpdate(sql, userId, kqDate); + writeLog(e); + kqLog.info(e); + } + return resultMap; + } + + public List> format(String userId, String kqDate, WorkTimeEntity workTime, + Map workFlowInfo, String uuid) { + List> lsParam = new ArrayList<>(); + List params = null; + try { + KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo(); + String nosign_is_absent = Util.null2String(kqSettingsComInfo.getMain_val("nosign_is_absent"),"1"); + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + KQFormatShiftRule kqFormatShiftRule = new KQFormatShiftRule(); + String preDate = DateUtil.addDate(kqDate, -1);//上一天日期 + String nextDate = DateUtil.addDate(kqDate, 1);//下一天日期 + String dateKey = userId + "|" + kqDate; + String nextDateKey = userId + "|" + nextDate; + ArrayList hostIps = InitServer.getRealIp(); + kqLog.info("format in >>>>>userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + boolean oneSign = false; + List lsSignTime = new ArrayList<>(); + List lsWorkTime = new ArrayList<>(); + List lsRestTime = new ArrayList<>(); + List workFlow = null; + + int workminsNew = 0; + if (workTime != null) { + lsSignTime = workTime.getSignTime();//允许打卡时间 + lsWorkTime = workTime.getWorkTime();//工作时间 + lsRestTime = workTime.getRestTime();//休息时段时间 + oneSign = lsWorkTime!=null&&lsWorkTime.size()==1; + workminsNew = workTime.getWorkMins(); + } + + int[] dayMins = new int[2880];//一天所有分钟数 + Arrays.fill(dayMins, -1); + for (int i = 0; lsWorkTime != null && i < lsWorkTime.size(); i++) { + params = new ArrayList<>(); + TimeScopeEntity signTimeScope = lsSignTime.get(i); + TimeScopeEntity workTimeScope = lsWorkTime.get(i); + TimeScopeEntity restTimeScope = lsRestTime.isEmpty()?null:lsRestTime.get(i); + 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(); + int workMins = workTimeScope.getWorkMins(); + + String workBeginDate = workBenginTimeAcross ? nextDate : kqDate; + String workEndDate = workEndTimeAcross ? nextDate : kqDate; + + Arrays.fill(dayMins, workBeginIdx, workEndIdx, 1);//工作时段标识 1 + + int beginIdx = 0; + int endIdx = 0; + int checkIn = 0; + int checkOut = 0; + String signInId = ""; + String signInDate = ""; + String signInTime = ""; + String signOutId = ""; + String signOutDate = ""; + String signOutTime = ""; + int earlyInMins = 0;//早到分钟数 + int lateOutMins = 0;//晚走分钟数 + int signMins = 0;//签到签退时长 + int tmpAttendanceMins = 0;//出勤分钟数(流程抵扣来的) + int attendanceMins = 0; + int beLateMins = 0; + int graveBeLateMins = 0; + int leaveEarlyMins = 0; + int graveLeaveEarlyMins = 0; + int absenteeismMins = 0; + int leaveMins = 0;//请假时长 + Map leaveInfo = new HashMap<>();//请假信息 + Map otherinfo = new HashMap<>();//存一些用得到的信息 + int evectionMins = 0;//出差时长 + int outMins = 0;//公出时长 + int otherMins = 0;//异常流程时长 + int forgotCheckMins = 0; + int forgotBeginWorkCheckMins = 0;//上班漏签 + int signInTimeIndx = -1; + int flowSignInTimeIndx = -1; + int signInTimeOutdx = -1; + //用来计算实际打卡时长用的 + int signInTimeIndx4Sign = -1; + int signInTimeOutdx4Sign = -1; + + String signBeginDateTime = signTimeScope.getBeginTimeAcross() ? nextDate : kqDate; + if(signTimeScope.isBeginTimePreAcross()){ + signBeginDateTime = preDate; + } + signBeginDateTime+=" "+kqTimesArrayComInfo.turn48to24Time(signTimeScope.getBeginTime())+":00"; + String signEndDateTime = signTimeScope.getEndTimeAcross() ? nextDate : kqDate; + + signEndDateTime+=" "+kqTimesArrayComInfo.turn48to24Time(signTimeScope.getEndTime())+":59"; + + String workBeginDateTime = workTimeScope.getBeginTimeAcross() ? nextDate : kqDate; + workBeginDateTime+=" "+kqTimesArrayComInfo.turn48to24Time(workTimeScope.getBeginTime())+":00"; + String workEndDateTime = workTimeScope.getEndTimeAcross() ? nextDate : kqDate; + workEndDateTime+=" "+kqTimesArrayComInfo.turn48to24Time(workTimeScope.getEndTime())+":00"; + + kqLog.info("signBeginDateTime" + signBeginDateTime+"::userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + kqLog.info("signEndDateTime" + signEndDateTime+"::userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + kqLog.info("workBeginDateTime" + workBeginDateTime+"::userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + kqLog.info("workEndDateTime" + workEndDateTime+"::userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + + Map shifRuleMap = Maps.newHashMap(); + if(oneSign){ + //个性化设置只支持一天一次上下班 + ShiftInfoBean shiftInfoBean = new ShiftInfoBean(); + shiftInfoBean.setSplitDate(kqDate); + shiftInfoBean.setShiftRuleMap(workTime.getShiftRuleInfo()); + shiftInfoBean.setSignTime(lsSignTime); + shiftInfoBean.setWorkTime(lsWorkTime); + List logList = Lists.newArrayList(); + KQShiftRuleInfoBiz.getShiftRuleInfo(shiftInfoBean, userId, shifRuleMap,logList); + if(!shifRuleMap.isEmpty()){ + if(!logList.isEmpty()){ + otherinfo.put("logList", logList); + } + otherinfo.put("shiftRule", shifRuleMap); + 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); + } + } + } + kqLog.info("个性化之后 signBeginDateTime" + signBeginDateTime); + kqLog.info("个性化之后 signEndDateTime" + signEndDateTime); + kqLog.info("个性化之后 workBeginDateTime" + workBeginDateTime); + kqLog.info("个性化之后 workEndDateTime" + workEndDateTime); + } + List lsCheckInfo = new KQFormatSignData().getSignInfo(userId,signTimeScope,workTimeScope,kqDate,preDate,nextDate,kqTimesArrayComInfo,hostIps,uuid); + kqLog.info("lsCheckInfo" + JSONObject.toJSONString(lsCheckInfo)+"::userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + if(this.writeLog) { + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005297,weaver.general.ThreadVarLanguage.getLang())+"",signBeginDateTime); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005298,weaver.general.ThreadVarLanguage.getLang())+"",signEndDateTime); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(1940,weaver.general.ThreadVarLanguage.getLang())+"",workBeginDateTime); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005299,weaver.general.ThreadVarLanguage.getLang())+"",workEndDateTime); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005300,weaver.general.ThreadVarLanguage.getLang())+"",lsCheckInfo); + } + for (int j = 0; lsCheckInfo != null && j < lsCheckInfo.size(); j++) { + Map checkInfo = (Map) lsCheckInfo.get(j); + String signStatus = Util.null2String(checkInfo.get("signStatus")); + String signId = Util.null2String(checkInfo.get("signId")); + String signDate = Util.null2String(checkInfo.get("signDate")); + String signTime = Util.null2String(checkInfo.get("signTime")); + String deduct_signintime = Util.null2String(checkInfo.get("deduct_signintime")); + String deduct_signofftime = Util.null2String(checkInfo.get("deduct_signofftime")); + String flow_signInTime = ""; + String flow_signOutTime = ""; + if(kqDate.compareTo(signDate) < 0)endIdx+=1440; + if (signTime.length() > 8) { + signTime = signTime.substring(0, 8); + } + if (checkInfo.get("signType").equals("1")) {//签到 + checkIn++; + //如果流程抵扣存在,打卡时长也存在,那么相互比较得到出勤时长和打卡时长 暂不这样处理,还是按照漏签的逻辑来处理 + if(signTime.length() > 0){ + signInTimeIndx4Sign = kqTimesArrayComInfo.getArrayindexByTimes(signTime); + } + signInId = signId; + signInDate = signDate; + signInTime = signTime; + signInTimeIndx = kqTimesArrayComInfo.getArrayindexByTimes(signInTime); + if(deduct_signintime.length() > 0){ + if(signTime.length() > 0){ + if(deduct_signintime.compareTo(signTime) < 0){ + flow_signInTime = deduct_signintime; + } + }else{ + flow_signInTime = deduct_signintime; + } + } + if(flow_signInTime.length() > 0){ + flowSignInTimeIndx = kqTimesArrayComInfo.getArrayindexByTimes(flow_signInTime); + } + if(kqDate.compareTo(signDate) < 0) { + signInTimeIndx += 1440; + flowSignInTimeIndx += 1440; + }else if(kqDate.compareTo(signDate) > 0){ + signInTimeIndx -= 1440; + signInTimeIndx = signInTimeIndx < 0 ? 0 : signInTimeIndx; + flowSignInTimeIndx -= 1440; + flowSignInTimeIndx = flowSignInTimeIndx < 0 ? 0 : flowSignInTimeIndx; + } + if(oneSign){ + if(workBeginIdx>signInTimeIndx) { + earlyInMins = workBeginIdx-signInTimeIndx; + } + } + } else if (checkInfo.get("signType").equals("2")) {//签退 + checkOut++; + //如果流程抵扣存在,打卡时长也存在,那么相互比较得到出勤时长和打卡时长 暂不这样处理,还是按照漏签的逻辑来处理 + if(signTime.length() > 0){ + signInTimeOutdx4Sign = kqTimesArrayComInfo.getArrayindexByTimes(signTime); + } + signOutId = signId; + signOutDate = signDate; + signOutTime = signTime; + signInTimeOutdx = kqTimesArrayComInfo.getArrayindexByTimes(signOutTime); + if(deduct_signofftime.length() > 0){ + if(signTime.length() > 0){ + if(deduct_signofftime.compareTo(signTime) > 0){ + flow_signOutTime = deduct_signofftime; + } + }else{ + flow_signOutTime = deduct_signofftime; + } + } + if(flow_signOutTime.length() > 0){ + signInTimeOutdx = kqTimesArrayComInfo.getArrayindexByTimes(flow_signOutTime); + } + if(kqDate.compareTo(signDate) < 0){ + signInTimeOutdx+=1440; + }else if(kqDate.compareTo(signDate) > 0){ + signInTimeOutdx -= 1440; + signInTimeOutdx = signInTimeOutdx < 0 ? 0 : signInTimeOutdx; + } + if(oneSign){ + if(signInTimeOutdx>workEndIdx) { + lateOutMins = signInTimeOutdx-workEndIdx; + } + } + } + if (checkInfo.get("signType").equals("1")) {//签到 + if(signTime.length() > 0){ + String signMinTime = signTime.substring(0,5)+":00"; + endIdx = kqTimesArrayComInfo.getArrayindexByTimes(signTime); + if(signTime.compareTo(signMinTime) > 0){ + //如果签到时间是带秒的且是迟到,那么签到时间多一秒和多一分钟是一样的 + endIdx += 1; + signInTimeIndx = signInTimeIndx + 1;//如果是带秒的打卡数据不应该影响流程抵扣的数据的下标 + } + if(kqDate.compareTo(signDate) < 0){ + endIdx+=1440; + }else if(kqDate.compareTo(signDate) > 0){ + endIdx -= 1440; + endIdx = endIdx < 0 ? 0 : endIdx; + } + if (endIdx > workBeginIdx) { + if(flow_signInTime.length() > 0){ + if(flowSignInTimeIndx > workBeginIdx){ + //增加一个判断,流程抵扣打卡如果开启了并且有抵扣上班打卡,那么也就不是迟到了 + Arrays.fill(dayMins, workBeginIdx, endIdx, 2);//迟到时段标识 2 + } + }else{ + Arrays.fill(dayMins, workBeginIdx, endIdx, 2);//迟到时段标识 2 + } + } + } + } else if (checkInfo.get("signType").equals("2")) {//签退 + if(signTime.length() > 0){ + beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(signTime); + if(StringUtils.isNotBlank(signDate) && signDate.compareTo(kqDate) > 0){ + beginIdx+=1440; + }else if(kqDate.compareTo(signDate) > 0){ + beginIdx -= 1440; + beginIdx = beginIdx < 0 ? 0 : beginIdx; + } + if (workEndIdx > beginIdx) { + if(flow_signOutTime.length() > 0){ + if (workEndIdx > signInTimeOutdx) { + //增加一个判断,流程抵扣打卡如果开启了并且有抵扣下班打卡,那么也就不是早退了 + Arrays.fill(dayMins, beginIdx, workEndIdx, 3);//早退时段标识 3 + } + }else{ + + Arrays.fill(dayMins, beginIdx, workEndIdx, 3);//早退时段标识 3 + } + } + } + } + } + + //打卡时长=签退时间-签到时间(有签到签退才计算) + if(checkIn==1&&checkOut==1){ + if(signInTimeIndx4Sign > -1 && signInTimeOutdx4Sign > -1){ + if(DateUtil.dayDiff(signInDate,signOutDate)==0){//同一天签到和签退 + signMins=signInTimeOutdx4Sign - signInTimeIndx4Sign; + }else if(DateUtil.dayDiff(signInDate,signOutDate)==1) {//第一天签到,第二天签退 + if(signInTimeOutdx4Sign workBeginIdx) { + Arrays.fill(dayMins, workBeginIdx, workEndIdx, 4);//旷工时段标识 4 + } + } + + if (checkOut == 0 && checkIn > 0) {//漏签(有签到无签退) + if(signInTimeIndx > -1){ + if (workEndIdx > signInTimeIndx) { + //漏签就是从本次时段内的打卡到下班点 + //上班漏签应该是从签到到签到结束时间,不过这里可以不用管,只是一个次数 + Arrays.fill(dayMins, signInTimeIndx, workEndIdx, 6);//上班漏签时段标识 6 + } else { + //签到晚于本次时段结束时间,也算漏签 + forgotCheckMins++; + } + }else if(flowSignInTimeIndx > -1){ + if (workEndIdx > flowSignInTimeIndx) { + //漏签就是从本次时段内的打卡到下班点 + //上班漏签应该是从签到到签到结束时间,不过这里可以不用管,只是一个次数 + Arrays.fill(dayMins, flowSignInTimeIndx, workEndIdx, 6);//上班漏签时段标识 6 + } else { + //签到晚于本次时段结束时间,也算漏签 + forgotCheckMins++; + } + } + } + + if (checkIn == 0 && checkOut > 0) {//漏签(有签退无签到) + if(signInTimeOutdx > 0){ + if(workBeginIdx < signInTimeOutdx) { + //下班漏签应该是从签退到签退开始时间,不过这里可以不用管,只是一个次数 + Arrays.fill(dayMins, workBeginIdx, signInTimeOutdx, 66);//下班漏签时段标识 66,66呼应前面的漏签的6 + }else{ + //这种数据理论上不会存在,也记下吧 + forgotBeginWorkCheckMins++; + } + } + } + + if (workFlowInfo.get(dateKey) != null) { + workFlow = (List) workFlowInfo.get(dateKey); + } + + for (int j = 0; workFlow != null && j < workFlow.size(); j++) { + Map data = (Map) workFlow.get(j); + String flowType = Util.null2String(data.get("flowtype")); + String newLeaveType = Util.null2String(data.get("newleavetype")); + String signtype = Util.null2String(data.get("signtype")); + String serial = Util.null2String(data.get("serial")); + String requestId = Util.null2String(data.get("requestId")); + beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(Util.null2String(data.get("begintime"))); + endIdx = kqTimesArrayComInfo.getArrayindexByTimes(Util.null2String(data.get("endtime"))); + if (beginIdx >= endIdx) { + continue; + } + + if(flowType.equals(FlowReportTypeEnum.EVECTION.getFlowType())){ + Arrays.fill(dayMins, beginIdx, endIdx, 7);//出差抵扣时段标识 7 + }else if(flowType.equals(FlowReportTypeEnum.OUT.getFlowType())){ + Arrays.fill(dayMins, beginIdx, endIdx, 8);//公出抵扣时段标识 8 + }else if(flowType.equalsIgnoreCase(FlowReportTypeEnum.LEAVE.getFlowType())){ + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, 5);//流程抵扣时段标识 5 + int tmpBeginIdx = beginIdx; + int tmpEndIdx = endIdx; + Integer val = 0; + if(leaveInfo.get(newLeaveType)==null){ + leaveInfo.put(newLeaveType,val); + }else{ + val = (Integer) leaveInfo.get(newLeaveType); + } + + if(beginIdxworkEndIdx)tmpEndIdx=endIdx; + if(tmpEndIdx>tmpBeginIdx){ + leaveInfo.put(newLeaveType,val+(tmpEndIdx-tmpBeginIdx)); + } + } + }else{ + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, 99);//异常流程抵扣时段标识99 + } + } + } + + + if (workEndTimeAcross && false) {//跨天需要加入一天的流程 + workFlow = null; + if (workFlowInfo.get(nextDateKey) != null) { + workFlow = (List) workFlowInfo.get(nextDateKey); + } + + for (int j = 0; workFlow != null && j < workFlow.size(); j++) { + Map data = (Map) workFlow.get(j); + String flowType = Util.null2String(data.get("flowtype")); + beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(Util.null2String(data.get("begintime")))+1440; + endIdx = kqTimesArrayComInfo.getArrayindexByTimes(Util.null2String(data.get("endtime")))+1440; + if(endIdx>=2880){ + endIdx = 2880; + } + if(flowType.equals(FlowReportTypeEnum.EVECTION.getFlowType())){ + Arrays.fill(dayMins, beginIdx, endIdx, 7);//出差抵扣时段标识 7 + }else if(flowType.equals(FlowReportTypeEnum.OUT.getFlowType())){ + Arrays.fill(dayMins, beginIdx, endIdx, 8);//公出抵扣时段标识 8 + }else if(flowType.equalsIgnoreCase(FlowReportTypeEnum.LEAVE.getFlowType())){ + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, 5);//流程抵扣时段标识 5 + + } + }else{ + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, 99);//异常流程抵扣时段标识99 + } + } + } + } + + if (restTimeScope!=null) { + String restBeginTime = Util.null2String(restTimeScope.getBeginTime()); + String restEndTime = Util.null2String(restTimeScope.getEndTime()); + beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(restBeginTime); + endIdx = kqTimesArrayComInfo.getArrayindexByTimes(restEndTime); + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, -1);//休息时间 + workMins = workMins-(endIdx-beginIdx); + } + } + + for (int j = workBeginIdx; j < workEndIdx; j++) { + switch (dayMins[j]) { + case 1: + tmpAttendanceMins++; + break; + case 2: + beLateMins++; + break; + case 3: + leaveEarlyMins++; + break; + case 4: + absenteeismMins++; + break; + case 5: + leaveMins++; + break; + case 6: + forgotCheckMins++; + break; + case 7: + evectionMins++; + break; + case 8: + outMins++; + break; + case 66: + forgotBeginWorkCheckMins++; + break; + case 99: + otherMins++; + break; + default: + break; + } + } + + if(forgotCheckMins == 1 && beLateMins==0 && tmpAttendanceMins==0){//forgotCheckMins==1表示下班后漏签,不是迟到,流程已完全抵扣异常 + forgotCheckMins = 0; + } + + KQShiftRuleEntity kqShiftRuleEntity = new KQShiftRuleEntity(); + kqShiftRuleEntity.setUserId(userId); + kqShiftRuleEntity.setKqDate(kqDate); + kqShiftRuleEntity.setBelatemins(beLateMins); + kqShiftRuleEntity.setLeaveearlymins(leaveEarlyMins); + kqShiftRuleEntity.setAbsenteeismmins(absenteeismMins); + kqShiftRuleEntity.setForgotcheckmins(forgotCheckMins); + kqShiftRuleEntity.setForgotBeginWorkCheckMins(forgotBeginWorkCheckMins); + kqShiftRuleEntity.setEarlyInMins(earlyInMins); + kqShiftRuleEntity.setLateOutMins(lateOutMins); + kqLog.info("人性化规则处理前数据" + JSONObject.toJSONString(kqShiftRuleEntity)); + if(this.writeLog) { + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005301,weaver.general.ThreadVarLanguage.getLang())+"",kqShiftRuleEntity); + } + //人性化规则 + kqShiftRuleEntity = kqFormatShiftRule.doShiftRule(workTime,kqShiftRuleEntity); + kqLog.info("人性化规则处理后数据" + JSONObject.toJSONString(kqShiftRuleEntity)); + if(this.writeLog) { + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005302,weaver.general.ThreadVarLanguage.getLang())+"",kqShiftRuleEntity); + } + beLateMins = kqShiftRuleEntity.getBelatemins(); + graveBeLateMins = kqShiftRuleEntity.getGravebelatemins(); + leaveEarlyMins = kqShiftRuleEntity.getLeaveearlymins(); + graveLeaveEarlyMins = kqShiftRuleEntity.getGraveleaveearlymins(); + absenteeismMins = kqShiftRuleEntity.getAbsenteeismmins(); + forgotCheckMins = kqShiftRuleEntity.getForgotcheckmins(); + forgotBeginWorkCheckMins = kqShiftRuleEntity.getForgotBeginWorkCheckMins(); + + boolean beforeBegin = !new KQFormatBiz().needCal(workBeginDate,workBeginTime); + if(beforeBegin) {//还未到上班时间,不用计算任何状态 + kqLog.writeLog("还未到上班时间,不用计算任何状态"); + beLateMins = 0; + graveBeLateMins = 0; + leaveEarlyMins = 0; + graveLeaveEarlyMins = 0; + absenteeismMins = 0; + forgotCheckMins = 0; + forgotBeginWorkCheckMins = 0; + }else if(!new KQFormatBiz().needCal(workEndDate,workEndTime)) {//还未到下班时间 + kqLog.writeLog("还未到上班时间"); + leaveEarlyMins = 0; + graveLeaveEarlyMins = 0; + forgotCheckMins = 0; + } + + if (workminsNew == 0 || workTime.getIsExclude()) {//无需考勤人员没有异常状态 + beLateMins = 0; + graveBeLateMins = 0; + leaveEarlyMins = 0; + graveLeaveEarlyMins = 0; + absenteeismMins = 0; + forgotCheckMins = 0; + forgotBeginWorkCheckMins = 0; + } + + //计算实际出勤时间(出差公出算出勤)=应出勤-旷工-请假-迟到-早退 + attendanceMins = workMins - absenteeismMins-leaveMins-beLateMins-graveBeLateMins-leaveEarlyMins-graveLeaveEarlyMins; + // 如果没有开启"漏签是否算实际出勤"开关,则漏签不算实际出勤时长 + if("0".equals(nosign_is_absent)) { + attendanceMins = attendanceMins-forgotCheckMins-forgotBeginWorkCheckMins; + } + if(workminsNew == 0) { + attendanceMins = 0; + workMins = 0; + } + if(beforeBegin || attendanceMins < 0) {//还未到上班时间,不用计算任何状体 + attendanceMins = 0; + } + kqLog.info("实际出勤计算公式" + "实际出勤=应出勤- 旷工-请假-迟到-早退 userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + kqLog.info("实际出勤计算结果" + attendanceMins + "=" + workMins + "- " + absenteeismMins + "-" + leaveMins + "-" + (beLateMins + graveBeLateMins) + "-" + (leaveEarlyMins - graveLeaveEarlyMins)+" userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); + if(this.writeLog) { + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005303,weaver.general.ThreadVarLanguage.getLang())+"",""+weaver.systeminfo.SystemEnv.getHtmlLabelName(130566,weaver.general.ThreadVarLanguage.getLang())+"="+weaver.systeminfo.SystemEnv.getHtmlLabelName(132056,weaver.general.ThreadVarLanguage.getLang())+"- "+weaver.systeminfo.SystemEnv.getHtmlLabelName(20085,weaver.general.ThreadVarLanguage.getLang())+"-"+weaver.systeminfo.SystemEnv.getHtmlLabelName(670,weaver.general.ThreadVarLanguage.getLang())+"-"+weaver.systeminfo.SystemEnv.getHtmlLabelName(20081,weaver.general.ThreadVarLanguage.getLang())+"-"+weaver.systeminfo.SystemEnv.getHtmlLabelName(20082,weaver.general.ThreadVarLanguage.getLang())+""); + logInfo.put(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005304,weaver.general.ThreadVarLanguage.getLang())+"",attendanceMins+"="+workMins+"- "+absenteeismMins+"-"+leaveMins+"-"+(beLateMins+graveBeLateMins)+"-"+(leaveEarlyMins-graveLeaveEarlyMins)); + } + //判断当天考勤状态 +// if (beLateMins > 0) { +// status = ButtonStatusEnum.BELATE.getStatusCode(); +// } else if (leaveEarlyMins > 0) { +// status = ButtonStatusEnum.LEAVEERALY.getStatusCode(); +// } else if (absenteeismMins > 0) { +// status = ButtonStatusEnum.ABSENT.getStatusCode(); +// } else if (forgotCheckMins > 0) { +// status = ButtonStatusEnum.NOSIGN.getStatusCode(); +// } else { +// status = ButtonStatusEnum.NORMAL.getStatusCode(); +// } + + String groupid = Util.null2String(workTime.getGroupId()); + String serialid = Util.null2String(workTime.getSerialId()); + + params.add(userId); + params.add(kqDate); + params.add(groupid.length() == 0 ? null : groupid); + params.add(serialid.length() == 0 ? null : serialid); + params.add(i); + params.add(workBeginDate); + params.add(kqTimesArrayComInfo.turn48to24Time(ori_workBeginTime)); + params.add(workEndDate); + params.add(kqTimesArrayComInfo.turn48to24Time(ori_workEndTime)); + params.add(workMins); + params.add(signInDate); + params.add(signInTime); + params.add(signInId.length() == 0 ? null : signInId); + params.add(signOutDate); + params.add(signOutTime); + params.add(signOutId.length() == 0 ? null : signOutId); + kqLog.info("format in >>>>>userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid + +":signInDate:"+signInDate+":signInTime::"+signInTime+":signOutDate:"+signOutDate+":signOutTime::"+signOutTime); + params.add(signMins); + params.add(attendanceMins); + params.add(beLateMins); + params.add(graveBeLateMins); + params.add(leaveEarlyMins); + params.add(graveLeaveEarlyMins); + params.add(absenteeismMins); + params.add(forgotCheckMins); + params.add(leaveMins); + params.add(JSONObject.toJSONString(leaveInfo)); + params.add(evectionMins); + params.add(outMins); + params.add(forgotBeginWorkCheckMins); + params.add(JSONObject.toJSONString(otherinfo)); + + Map definedFieldInfo = new KQFormatBiz().getDefinedField(); + String[] definedFields = Util.splitString(Util.null2String(definedFieldInfo.get("definedField")),","); + KQReportFieldComInfo kqReportFieldComInfo = new KQReportFieldComInfo(); + for (int tmpIdx = 0; tmpIdx env = new HashMap<>(); + String keyname = ""; + while (matcher.find()) { + String key = matcher.group(0); + keyname = key.substring(2, key.length() - 1).trim(); + expression = matcher.replaceAll(keyname); + env.put(keyname, keyname.equals("beLateMins")?beLateMins:leaveEarlyMins); + } + Expression compiledExp = AviatorEvaluator.compile(expression,true); + String value = Util.null2String(compiledExp.execute(env)); + params.add(value); + if(value.equals("1")) { + params.add(keyname.equals("beLateMins") ? beLateMins : leaveEarlyMins); + }else{ + params.add("0"); + } + } + kqLog.info("format in >>>>>userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid + +":params:"+JSON.toJSONString(params)); + lsParam.add(params); + } + } catch (Exception e) { + writeLog(e); + kqLog.info(e); + } + return lsParam; + } + + public void setWriteLog(boolean writeLog) { + this.writeLog = writeLog; + } + + public Map getLogInfo() { + return logInfo; + } + + public void formatDateByKQDate(String kqdate) { + KQFormatBiz kqFormatBiz = new KQFormatBiz(); + kqFormatBiz.formatDateByKQDate(kqdate); + } + + public void formatDateByGroupId(String groupid, String kqdate) { + KQFormatBiz kqFormatBiz = new KQFormatBiz(); + kqFormatBiz.formatDateByGroupId(groupid, kqdate); + } + + public void formatDate(String resourceid, String kqdate) { + KQFormatBiz kqFormatBiz = new KQFormatBiz(); + kqFormatBiz.formatDate(resourceid, kqdate); + } + + public void delFormatData(String resourceid, String kqdate) { + KQFormatBiz kqFormatBiz = new KQFormatBiz(); + kqFormatBiz.delFormatData(resourceid, kqdate); + } + + /** + * 非工作日格式化考勤报表 + * @param userId + * @param kqDate + * @param nonlsParam + * @param workTime + * @param workFlowInfo + */ + public void formatNonWork(String userId, String kqDate, List nonlsParam, WorkTimeEntity workTime, Map workFlowInfo) { + String signInId = ""; + String signInDate = ""; + String signInTime = ""; + String signOutId = ""; + String signOutDate = ""; + String signOutTime = ""; + int beginIdx = 0; + int endIdx = 0; + int leaveMins = 0;//请假时长 + Map leaveInfo = new HashMap<>();//请假信息 + int evectionMins = 0;//出差时长 + int outMins = 0;//公出时长 + int otherMins = 0;//异常流程时长 + int[] dayMins = new int[2880];//一天所有分钟数 + List workFlow = null; + String dateKey = userId + "|" + kqDate; + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + + String preDate = DateUtil.addDate(kqDate, -1);//上一天日期 + String nextDate = DateUtil.addDate(kqDate, 1);//下一天日期 + WorkTimeEntity pre_workTime = new KQWorkTime().getWorkTime(userId, 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(userId, nextDate); + List next_lsSignTime = new ArrayList<>(); + + if (next_workTime != null) { + next_lsSignTime = next_workTime.getSignTime();//允许打卡时间 + next_lsSignTime = next_lsSignTime != null ? next_lsSignTime : new ArrayList<>(); + } + + List lsCheckInfo = new KQFormatSignData().getNonWorkSignInfo(userId,preDate,kqDate,pre_lsSignTime,next_lsSignTime); + + for (int j = 0; lsCheckInfo != null && j < lsCheckInfo.size(); j++) { + Map checkInfo = (Map) lsCheckInfo.get(j); + String signStatus = Util.null2String(checkInfo.get("signStatus")); + String signId = Util.null2String(checkInfo.get("signId")); + String signDate = Util.null2String(checkInfo.get("signDate")); + String signTime = Util.null2String(checkInfo.get("signTime")); + if (checkInfo.get("signType").equals("1")) {//签到 + signInId = signId; + signInDate = signDate; + signInTime = signTime; + } else if (checkInfo.get("signType").equals("2")) {//签退 + signOutId = signId; + signOutDate = signDate; + signOutTime = signTime; + } + } + + if (workFlowInfo.get(dateKey) != null) { + workFlow = (List) workFlowInfo.get(dateKey); + } + + for (int j = 0; workFlow != null && j < workFlow.size(); j++) { + Map data = (Map) workFlow.get(j); + String flowType = Util.null2String(data.get("flowtype")); + String newLeaveType = Util.null2String(data.get("newleavetype")); + beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(Util.null2String(data.get("begintime"))); + endIdx = kqTimesArrayComInfo.getArrayindexByTimes(Util.null2String(data.get("endtime"))); + if(flowType.equals(FlowReportTypeEnum.EVECTION.getFlowType())){ + Arrays.fill(dayMins, beginIdx, endIdx, 7);//出差抵扣时段标识 7 + }else if(flowType.equals(FlowReportTypeEnum.OUT.getFlowType())){ + Arrays.fill(dayMins, beginIdx, endIdx, 8);//公出抵扣时段标识 8 + }else if(flowType.equalsIgnoreCase(FlowReportTypeEnum.LEAVE.getFlowType())){ + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, 5);//流程抵扣时段标识 5 + int tmpBeginIdx = beginIdx; + int tmpEndIdx = endIdx; + Integer val = 0; + if(leaveInfo.get(newLeaveType)==null){ + leaveInfo.put(newLeaveType,val); + }else{ + val = (Integer) leaveInfo.get(newLeaveType); + } + if(tmpEndIdx>tmpBeginIdx){ + leaveInfo.put(newLeaveType,val+(tmpEndIdx-tmpBeginIdx)); + } + } + }else{ + if (endIdx > beginIdx) { + Arrays.fill(dayMins, beginIdx, endIdx, 99);//异常流程抵扣时段标识99 + } + } + } + + for (int j = 0; j < 2880; j++) { + switch (dayMins[j]) { + case 5: + leaveMins++; + break; + case 7: + evectionMins++; + break; + case 8: + outMins++; + break; + case 99: + otherMins++; + break; + default: + break; + } + } + + nonlsParam.add(userId); + nonlsParam.add(kqDate); + nonlsParam.add(workTime.getGroupId()); + nonlsParam.add(0); + nonlsParam.add(signInDate); + nonlsParam.add(signInTime); + nonlsParam.add(signInId.length() == 0 ? null : signInId); + nonlsParam.add(signOutDate); + nonlsParam.add(signOutTime); + nonlsParam.add(signOutId.length() == 0 ? null : signOutId); + nonlsParam.add(leaveMins); + nonlsParam.add(JSONObject.toJSONString(leaveInfo)); + nonlsParam.add(evectionMins); + nonlsParam.add(outMins); + } +} diff --git a/src/com/engine/kq/biz/KQOverTimeFlowBiz.java b/src/com/engine/kq/biz/KQOverTimeFlowBiz.java new file mode 100644 index 0000000..72501f9 --- /dev/null +++ b/src/com/engine/kq/biz/KQOverTimeFlowBiz.java @@ -0,0 +1,848 @@ +package com.engine.kq.biz; + +import com.alibaba.fastjson.JSONObject; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.entity.KQOvertimeRulesDetailEntity; +import com.engine.kq.log.KQLog; +import com.engine.kq.util.KQDurationCalculatorUtil; +import com.engine.kq.wfset.bean.OvertimeBalanceTimeBean; +import com.engine.kq.wfset.bean.SplitBean; +import com.engine.kq.wfset.util.KQFlowUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.springframework.beans.BeanUtils; +import weaver.common.StringUtil; +import weaver.general.Util; +import weaver.hrm.User; + +/** + * 加班流程 非工作时长计算 重新搞一把 + * 现在是根据归属来拆分流程 + */ +public class KQOverTimeFlowBiz { + private KQLog kqLog = new KQLog(); + + /** + * 之前的加班拆分是根据每一天进行拆分的,但是我们是有个默认归属的,就是上班前是属于前一天的,再加上这次标准改造,加了临界点, + * 加班的拆分改造一下,改成和请假拆分一样,根据归属区间来拆分 + * 未设置加班归属的逻辑是 + * 工作日A-工作日B ,从工作日A的上班时间往后加24小时,都算工作日A的加班区间 + * 工作日A-非工作日,从工作日A的上班时间往后加24小时,都算工作日A的加班区间 + * 非工作日-工作日A,从非工作日的0点到工作日A的上班前,都属于非工作日的区间 + * + * 计算加班逻辑很特殊, + * 需要知道昨日,今日和明日的类型,是工作日还是非工作日 + * @param splitBean + * @param splitBeans + */ + public void getSplitDurationBean_new(SplitBean splitBean,List splitBeans) { + try{ + long a = System.currentTimeMillis(); + + double oneDayHour = KQFlowUtil.getOneDayHour(splitBean.getDurationTypeEnum(),""); + int workmins = (int)(oneDayHour * 60); + String resourceid = splitBean.getResourceId(); + String fromDate = splitBean.getFromdatedb(); + String toDate = splitBean.getTodatedb(); + String overtime_type = splitBean.getOvertime_type(); + + User tmp_user = User.getUser(Util.getIntValue(resourceid), 0); + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + + LocalDate localFromDate = LocalDate.parse(fromDate); + LocalDate localToDate = LocalDate.parse(toDate); + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + LocalDate preFromDate = localFromDate.minusDays(1); + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + + KQOvertimeRulesBiz kqOvertimeRulesBiz = new KQOvertimeRulesBiz(); + KQOverTimeRuleCalBiz kqOverTimeRuleCalBiz = new KQOverTimeRuleCalBiz(); + Map changeTypeMap = Maps.newHashMap(); + Map overRulesDetailMap = Maps.newHashMap(); + Map> restTimeMap = Maps.newHashMap(); + Map computingModeMap = Maps.newHashMap(); + kqOverTimeRuleCalBiz.getOverTimeDataMap(resourceid, fromDate, toDate, dateFormatter,changeTypeMap,overRulesDetailMap,restTimeMap,computingModeMap); + + if(overRulesDetailMap.isEmpty()){ + return; + } + String fromTime = splitBean.getFromtimedb(); + String toTime = splitBean.getTotimedb(); + long betweenDays = localToDate.toEpochDay() - preFromDate.toEpochDay(); + //默认是从加班开始日期的前一天开始计算 需要特殊处理的就三个情况,i=0的时候,i=1的时候就是加班流程开始日期那一天,i=最后一天就是加班流程结束日期那一天 + for (int i = 0; i <= betweenDays; i++) { + SplitBean overSplitBean = new SplitBean(); + //然后把bean重新赋值下,根据拆分后的时间 + BeanUtils.copyProperties(splitBean, overSplitBean); + + //从加班流程开始的前一天开始算归属 + LocalDate curLocalDate = preFromDate.plusDays(i); + String splitDate = curLocalDate.format(dateFormatter); + String preSplitDate = LocalDate.parse(splitDate).minusDays(1).format(dateFormatter); + LocalDate nextLocalDate = curLocalDate.plusDays(1); + String nextSplitDate = nextLocalDate.format(dateFormatter); + String change_key = splitDate+"_"+resourceid; + String pre_change_key = preSplitDate+"_"+resourceid; + String next_change_key = nextSplitDate+"_"+resourceid; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + int preChangeType = Util.getIntValue(""+changeTypeMap.get(pre_change_key),-1); + int next_changeType = Util.getIntValue(""+changeTypeMap.get(next_change_key),-1); + + boolean shouldAcross = false; + String changeType_key = splitDate+"_"+changeType; + String preChangeType_key = preSplitDate+"_"+preChangeType; + String nextChangeType_key = nextSplitDate+"_"+next_changeType; + if(!computingModeMap.containsKey(changeType_key)){ + continue; + } + int computingMode = computingModeMap.get(changeType_key); + if(computingMode == 3){ + //如果是纯打卡为主的不生成加班 + continue; + } + + int[] initArrays = kqTimesArrayComInfo.getInitArr(); + //当前日期的加班分割点 分割点都是次日的 + String overtime_cut_point = ""; + int before_startTime = 0; + int startTime = 0; + int curMins = 0 ; + //排除休息类型 + int restTimeType = -1; + String next_beginwork_time = ""; + String cur_beginwork_time = ""; + String serialid = ""; + boolean isRestshift_next = false; + boolean isRestshift = false; + String tmp_next_beginwork_time = ""; + String tmp_cur_beginwork_time = ""; + //需要知道明日的类型:如果今天是工作日的话,那么今天的加班临界点可能和明日的上班时间冲突,需要知道明日的上班时间进行比较, + // 如果今天是休息日,那么明天如果是工作日的话,默认规则下,明天的上班前都是属于今天的加班区间 + if(next_changeType == 2){ + ShiftInfoBean next_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceid, nextSplitDate, false); + if(next_shiftInfoBean != null){ + List workLongTimeIndex = next_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,next_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + next_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + } + } + + //休息日有开发的休息班次,单独搞下 + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",next_changeType="+next_changeType); + if(next_changeType == 3){ + if(null != tmp_user){ + ShiftInfoBean next_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(tmp_user, nextSplitDate, false,true,false); + if(next_shiftInfoBean != null){ + int tmp_serialid = StringUtil.parseToInt(next_shiftInfoBean.getSerialid(), 0); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(tmp_serialid)), 0); +// kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",tmp_serialid="+ tmp_serialid+",restShift="+ restShift); + if(tmp_serialid > 0 && restShift == 1) { + isRestshift_next = true; + } + + List workLongTimeIndex = next_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,next_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + tmp_next_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",tmp_next_beginwork_time="+ tmp_next_beginwork_time+",isRestshift_next="+ isRestshift_next); + } + } + } + +// kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",changeType="+changeType); + if(changeType == 2){ + ShiftInfoBean cur_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceid, splitDate, false); + if(cur_shiftInfoBean != null){ + List workLongTimeIndex = cur_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,cur_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + cur_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + } + } + + //休息日有开发的休息班次,单独搞下 + if(changeType == 3){ +// kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",tmp_user="+tmp_user); + if(null != tmp_user){ + ShiftInfoBean tmp_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(tmp_user, splitDate,false,true,false); +// kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",tmp_shiftInfoBean="+ JSONObject.toJSONString(tmp_shiftInfoBean)); + if(tmp_shiftInfoBean != null){ + int tmp_serialid = StringUtil.parseToInt(tmp_shiftInfoBean.getSerialid(), 0); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(tmp_serialid)), 0); +// kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",tmp_serialid="+ tmp_serialid+",restShift="+ restShift); + if(tmp_serialid > 0 && restShift == 1) { + isRestshift = true; + } + + List workLongTimeIndex = tmp_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,tmp_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + tmp_cur_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",tmp_cur_beginwork_time="+ tmp_cur_beginwork_time+",isRestshift="+ isRestshift); + } + } + } + boolean needSplitByTime = false; +// 按照加班时长转调休的 时长设置 + List timepointList = null; + List overtimeBalanceTimeBeans = Lists.newArrayList(); + KQOvertimeRulesDetailEntity curKqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + if(curKqOvertimeRulesDetailEntity != null){ + int has_cut_point = curKqOvertimeRulesDetailEntity.getHas_cut_point(); + before_startTime = curKqOvertimeRulesDetailEntity.getBefore_startTime(); + int overtimeEnable = curKqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + continue; + } + if(has_cut_point != 1){ + before_startTime = -1; + } + startTime = curKqOvertimeRulesDetailEntity.getStartTime(); + restTimeType = curKqOvertimeRulesDetailEntity.getRestTimeType(); + int paidLeaveEnable = kqOverTimeRuleCalBiz.getPaidLeaveEnable(curKqOvertimeRulesDetailEntity,overtime_type); + needSplitByTime = kqOverTimeRuleCalBiz.getNeedSplitByTime(curKqOvertimeRulesDetailEntity,paidLeaveEnable); + if(needSplitByTime){ + int ruleDetailid = curKqOvertimeRulesDetailEntity.getId(); + Map> balanceTimethDetailMap = kqOvertimeRulesBiz.getBalanceTimeDetailMap(ruleDetailid); + if(balanceTimethDetailMap != null && !balanceTimethDetailMap.isEmpty()){ + timepointList = balanceTimethDetailMap.get("timepointList"); + } + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",has_cut_point="+ has_cut_point+",changeType="+ changeType+",isRestshift="+ isRestshift+",isRestshift_next="+ isRestshift_next); + if(has_cut_point == 0){ + if(changeType == 2){ + overtime_cut_point = cur_beginwork_time; + }else { + if(changeType == 3){ + if(isRestshift){ + overtime_cut_point = tmp_cur_beginwork_time; + } + + /** + * 测试过程中有连续排很多休息班次的情况,比如今天休息班次是09:00-18:00,明天休息班次是12:00-22:00,导致计算次日的加班时长会受这个上班时间12:00的影响导致加班时长计算不准 + * 先全部按开始日期的所在的休息班次的上班时间来为分界点,下面的代码逻辑先注释 + * + if(isRestshift_next && overtime_cut_point.length() > 0 && tmp_next_beginwork_time.length() > 0){ + int next_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(tmp_next_beginwork_time); + int overtime_cut_point_index = kqTimesArrayComInfo.getArrayindexByTimes(overtime_cut_point); + if(overtime_cut_point_index > next_beginwork_time_index){ + overtime_cut_point = next_beginwork_time; + } + } + */ + + } + + if(next_beginwork_time.length() > 0){ + overtime_cut_point = next_beginwork_time; + } + } + }else{ + overtime_cut_point = curKqOvertimeRulesDetailEntity.getCut_point(); + if(next_beginwork_time.length() > 0){ + int next_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(next_beginwork_time); + int overtime_cut_point_index = kqTimesArrayComInfo.getArrayindexByTimes(overtime_cut_point); + if(overtime_cut_point_index > next_beginwork_time_index){ + overtime_cut_point = next_beginwork_time; + } + } + } + if(overtime_cut_point.length() == 0){ + overtime_cut_point = "00:00"; + } + }else{ + continue; + } + int fromTime_index = 0; + int toTime_index = 0; + kqLog.info(i+"resourceid="+resourceid+",splitDate="+splitDate+",overtime_cut_point11="+ overtime_cut_point); + if(i == 0){ + //i=0就是加班开始日期的前一天,只有当加班临界点超过了加班流程开始时间的话,i=0才会有可能计算出时长 + if(overtime_cut_point.compareTo(fromTime) > 0){ + fromTime_index = kqTimesArrayComInfo.getArrayindexByTimes(kqTimesArrayComInfo.turn24to48Time(fromTime)); + toTime_index = kqTimesArrayComInfo.getArrayindexByTimes(kqTimesArrayComInfo.turn24to48Time(overtime_cut_point)); + if(fromDate.equalsIgnoreCase(toDate)){ + //如果开始日期和结束日期是同一天,还需要比较流程的结束时间和归属点的大小 + int oriTotime_index = kqTimesArrayComInfo.getArrayindexByTimes(kqTimesArrayComInfo.turn24to48Time(toTime)); + if(toTime_index > oriTotime_index){ + toTime_index = oriTotime_index; + } + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",fromTime_index="+ fromTime_index+",toTime_index="+ toTime_index); + Arrays.fill(initArrays, fromTime_index, toTime_index, 0); +// 1-节假日、2-工作日、3-休息日 + if(changeType == 1){ + handle_changeType_1(initArrays,overRulesDetailMap,nextChangeType_key,next_changeType,next_beginwork_time); + }else if(changeType == 2){ + boolean isok = handle_changeType_2(initArrays, resourceid, splitDate, before_startTime, startTime, fromTime_index,kqTimesArrayComInfo,splitBean, + toTime_index); + serialid = splitBean.getSerialid(); + if(!isok){ + continue; + } + }else if(changeType == 3){ + handle_changeType_3(initArrays,overRulesDetailMap,nextChangeType_key,next_changeType,next_beginwork_time); + } + if(restTimeType == 1){ + //如果排除设置的休息时间 + handle_resttime(restTimeMap,changeType_key,kqTimesArrayComInfo,shouldAcross,initArrays); + } + curMins = kqTimesArrayComInfo.getCnt(initArrays, fromTime_index,toTime_index,0); + if(restTimeType == 2){ + //如果排除休息时间是扣除时长 + curMins = handle_restlength(curMins,restTimeMap,changeType_key); + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",curMins="+ curMins); + }else{ + continue; + } + }else{ + //除了i=0的情况,其他的每一天都是要获取一下昨日的临界点的 + String pre_overtime_cut_point = get_pre_overtime_cut_point(overRulesDetailMap,preChangeType_key,resourceid,preSplitDate,splitDate,preChangeType,kqTimesArrayComInfo,splitBean,changeType); + if(changeType == 2){ + //如果今天是工作日,昨日的打卡归属会受到今日的上班前开始加班分钟数的影响 + int cur_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(cur_beginwork_time); + if(before_startTime > -1){ + int pre_overtime_cut_point_index = kqTimesArrayComInfo.getArrayindexByTimes(pre_overtime_cut_point); + int before_cur_beginwork_time_index = cur_beginwork_time_index - before_startTime; + } + } + //计算区间加班开始日期和加班结束日期这两天都是要特殊处理的 + fromTime_index = kqTimesArrayComInfo.getArrayindexByTimes(pre_overtime_cut_point); + if(i == 1){ + if(fromTime.compareTo(pre_overtime_cut_point) > 0){ + fromTime_index = kqTimesArrayComInfo.getArrayindexByTimes(fromTime); + } + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",betweenDays="+ betweenDays); + if(i == betweenDays){ + toTime_index = kqTimesArrayComInfo.getArrayindexByTimes(toTime); + }else{ + toTime_index = kqTimesArrayComInfo.turn24to48TimeIndex(kqTimesArrayComInfo.getArrayindexByTimes(overtime_cut_point)); +// kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",toTime_index22="+ toTime_index); + if(tmp_next_beginwork_time.length() > 0){ + int overtime_cut_point_index = kqTimesArrayComInfo.getArrayindexByTimes(overtime_cut_point); + int next_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(tmp_next_beginwork_time); + //如果临界点都已经超过第二天上班的开始时间了,要相应的缩短成第二天上班时间 + if(overtime_cut_point_index > next_beginwork_time_index){ + toTime_index = kqTimesArrayComInfo.turn24to48TimeIndex(next_beginwork_time_index); + } + } + if(next_beginwork_time.length() > 0){ + int overtime_cut_point_index = kqTimesArrayComInfo.getArrayindexByTimes(overtime_cut_point); + int next_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(next_beginwork_time); + //如果临界点都已经超过第二天上班的开始时间了,要相应的缩短成第二天上班时间 + if(overtime_cut_point_index > next_beginwork_time_index){ + toTime_index = kqTimesArrayComInfo.turn24to48TimeIndex(next_beginwork_time_index); + } + } + if(i == betweenDays-1){ + int ori_totime_index = kqTimesArrayComInfo.turn48to24TimeIndex(toTime_index); + int last_toTime_index = kqTimesArrayComInfo.getArrayindexByTimes(toTime); + if(ori_totime_index > last_toTime_index){ + toTime_index = kqTimesArrayComInfo.turn24to48TimeIndex(last_toTime_index); + } + } + } + System.out.println(i+":betweenDays:"+betweenDays+":fromTime_index:"+fromTime_index+":toTime_index:"+toTime_index+":changeType:"+changeType); + + if(fromTime_index > toTime_index){ + continue; + } + Arrays.fill(initArrays, fromTime_index, toTime_index, 0); + + if(changeType == 1){ + handle_changeType_1(initArrays, overRulesDetailMap, nextChangeType_key, next_changeType, + next_beginwork_time); + }else if(changeType == 2){ + serialid = splitBean.getSerialid(); + boolean isok = handle_changeType_2(initArrays, resourceid, splitDate, before_startTime, startTime, fromTime_index, + kqTimesArrayComInfo, splitBean, toTime_index); + if(!isok){ + continue; + } + }else if(changeType == 3){ + handle_changeType_3(initArrays, overRulesDetailMap, nextChangeType_key, next_changeType, + overtime_cut_point); + } + if(restTimeType == 1) { + //如果排除设置的休息时间 + handle_resttime(restTimeMap, changeType_key, kqTimesArrayComInfo, shouldAcross,initArrays); + } + curMins = kqTimesArrayComInfo.getCnt(initArrays, fromTime_index,toTime_index,0); + + if(restTimeType == 2){ + //如果排除休息时间是扣除时长 + curMins = handle_restlength(curMins,restTimeMap,changeType_key); + } + kqLog.info(i+">>>resourceid="+resourceid+",splitDate="+splitDate+",curMins111="+ curMins); + } + int minimumUnit = curKqOvertimeRulesDetailEntity.getMinimumLen(); + if(curMins < minimumUnit){ + continue; + } + if(needSplitByTime){ + kqOverTimeRuleCalBiz.get_overtimeBalanceTimeBeans(timepointList,overtimeBalanceTimeBeans,kqTimesArrayComInfo,initArrays,toTime_index,fromTime_index,0); + + if(overtimeBalanceTimeBeans != null && !overtimeBalanceTimeBeans.isEmpty()){ + String bean_cross_fromtime = kqTimesArrayComInfo.getTimesByArrayindex(fromTime_index); + String bean_cross_totime = kqTimesArrayComInfo.getTimesByArrayindex(toTime_index); + for(int timeIndex = 0 ; timeIndex < overtimeBalanceTimeBeans.size() ;timeIndex++) { + OvertimeBalanceTimeBean overtimeBalanceTimeBean = overtimeBalanceTimeBeans.get(timeIndex); + String timePointStart = overtimeBalanceTimeBean.getTimepoint_start(); + String timePointEnd = overtimeBalanceTimeBean.getTimepoint_end(); + boolean isNeedTX = overtimeBalanceTimeBean.isNeedTX(); + int timePointStart_index = kqTimesArrayComInfo.getArrayindexByTimes(timePointStart); + int timePointEnd_index = kqTimesArrayComInfo.getArrayindexByTimes(timePointEnd); + if(timePointStart_index > fromTime_index){ + bean_cross_fromtime = kqTimesArrayComInfo.getTimesByArrayindex(timePointStart_index); + }else{ + bean_cross_fromtime = kqTimesArrayComInfo.getTimesByArrayindex(fromTime_index); + } + if(timePointEnd_index < toTime_index){ + bean_cross_totime = kqTimesArrayComInfo.getTimesByArrayindex(timePointEnd_index); + }else{ + bean_cross_totime = kqTimesArrayComInfo.getTimesByArrayindex(toTime_index); + } + int timepoint_mins = overtimeBalanceTimeBean.getTimepoint_mins(); + if(isNeedTX){ + if(timepoint_mins > 0){ + overSplitBean = new SplitBean(); + //然后把bean重新赋值下,根据拆分后的时间 + BeanUtils.copyProperties(splitBean, overSplitBean); + overSplitBean.setChangeType(changeType); + overSplitBean.setPreChangeType(preChangeType); + overSplitBean.setOneDayHour(oneDayHour); + overSplitBean.setWorkmins(workmins); + overSplitBean.setComputingMode(computingMode+""); + overSplitBean.setChangeType(changeType); + overSplitBean.setFromDate(splitDate); + overSplitBean.setFromTime(bean_cross_fromtime); + overSplitBean.setToDate(splitDate); + overSplitBean.setToTime(bean_cross_totime); + overSplitBean.setBelongDate(splitDate); + overSplitBean.setD_Mins(timepoint_mins); + overSplitBean.setOvertimeBalanceTimeBeans(overtimeBalanceTimeBeans); + overSplitBean.setSerialid(serialid); + getDurationByRule(overSplitBean); + splitBeans.add(overSplitBean); + } + } + } + } + }else{ + curMins = (int) kqOverTimeRuleCalBiz.getD_MinsByUnit(curMins); + overSplitBean.setChangeType(changeType); + overSplitBean.setPreChangeType(preChangeType); + overSplitBean.setOneDayHour(oneDayHour); + overSplitBean.setWorkmins(workmins); + overSplitBean.setComputingMode(computingMode+""); + overSplitBean.setChangeType(changeType); + overSplitBean.setFromDate(splitDate); + overSplitBean.setFromTime(kqTimesArrayComInfo.getTimesByArrayindex(fromTime_index)); + overSplitBean.setToDate(splitDate); + overSplitBean.setToTime(kqTimesArrayComInfo.getTimesByArrayindex(toTime_index)); + overSplitBean.setBelongDate(splitDate); + overSplitBean.setD_Mins(curMins); + overSplitBean.setOvertimeBalanceTimeBeans(overtimeBalanceTimeBeans); + overSplitBean.setSerialid(serialid); + getDurationByRule(overSplitBean); + splitBeans.add(overSplitBean); + } + } + + long b = System.currentTimeMillis(); + System.out.println("::"+(b-a)); + + }catch (Exception e){ + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + } + } + + + /** + * 被个性化设置处理下 得到实际的上下班时间 + * @param workLongTimeIndex + * @param real_workLongTimeIndex + * @param shiftInfoBean + * @param kqTimesArrayComInfo + * @param splitBean + */ + public void get_real_workLongTimeIndex(List workLongTimeIndex, + List real_workLongTimeIndex, + ShiftInfoBean shiftInfoBean, KQTimesArrayComInfo kqTimesArrayComInfo, + SplitBean splitBean) { + + //list带数组,这里要深拷贝 + for(int[] tmp : workLongTimeIndex){ + int[] real_tmp = new int[tmp.length]; + System.arraycopy(tmp, 0, real_tmp, 0, tmp.length); + real_workLongTimeIndex.add(real_tmp); + } + if(real_workLongTimeIndex.size() == 1){ + //个性化设置只支持一次打卡的 + KQShiftRuleInfoBiz kqShiftRuleInfoBiz = new KQShiftRuleInfoBiz(); + kqShiftRuleInfoBiz.rest_workLongTimeIndex(shiftInfoBean,splitBean,real_workLongTimeIndex,kqTimesArrayComInfo,null); + } + + } + + /** + * 获取一下昨日的临界点 + * @param overRulesDetailMap + * @param preChangeType_key + * @param resourceid + * @param preSplitDate + * @param splitDate + * @param preChangeType + * @param kqTimesArrayComInfo + * @param splitBean + * @param changeType + * @return + */ + private String get_pre_overtime_cut_point( + Map overRulesDetailMap, + String preChangeType_key, String resourceid, String preSplitDate, String splitDate, + int preChangeType, KQTimesArrayComInfo kqTimesArrayComInfo, + SplitBean splitBean, int changeType) { + + String pre_overtime_cut_point = ""; + KQOvertimeRulesDetailEntity preKqOvertimeRulesDetailEntity = overRulesDetailMap.get(preChangeType_key); + if(preKqOvertimeRulesDetailEntity != null){ + int has_cut_point = preKqOvertimeRulesDetailEntity.getHas_cut_point(); + if(has_cut_point == 0){ + if(preChangeType == 2){ + ShiftInfoBean pre_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceid, preSplitDate, false); + if(pre_shiftInfoBean != null){ + List workLongTimeIndex = pre_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + 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 { + String next_beginwork_time = ""; + //单独搞下开发的休息班次 + if(preChangeType == 3){ + ShiftInfoBean pre_shiftInfoBean = KQDurationCalculatorUtil.getWorkTimeNew(resourceid, preSplitDate, false); + if(pre_shiftInfoBean != null){ + int serialid = StringUtil.parseToInt(pre_shiftInfoBean.getSerialid(), 0); + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(serialid)), 0); + if(serialid > 0 && restShift == 1) { + List workLongTimeIndex = pre_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + 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]); + } + } + } + +// ShiftInfoBean next_shiftInfoBean = KQDurationCalculatorUtil.getWorkTimeNew(resourceid, splitDate, false); +// if(next_shiftInfoBean != null){ +// int serialid = StringUtil.parseToInt(next_shiftInfoBean.getSerialid(), 0); +// KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); +// int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(serialid)), 0); +// if(serialid > 0 && restShift == 1) { +// List workLongTimeIndex = next_shiftInfoBean.getWorkLongTimeIndex(); +// List real_workLongTimeIndex = Lists.newArrayList(); +// get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,next_shiftInfoBean,kqTimesArrayComInfo,splitBean); +// +// if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ +// next_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); +// } +// } +// } + } + + if(changeType == 2){ + ShiftInfoBean next_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceid, splitDate, false); + if(next_shiftInfoBean != null){ + List workLongTimeIndex = next_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,next_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + next_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + } + } + if(next_beginwork_time.length() > 0){ + pre_overtime_cut_point = next_beginwork_time; + } + } + }else{ + pre_overtime_cut_point = preKqOvertimeRulesDetailEntity.getCut_point(); + } + if(pre_overtime_cut_point.length() == 0){ + pre_overtime_cut_point = "00:00"; + } + } + return pre_overtime_cut_point; + } + + /** + * 处理节假日的加班 + * @param initArrays + * @param overRulesDetailMap + * @param nextChangeType_key + * @param next_changeType + * @param next_beginwork_time + */ + public void handle_changeType_1(int[] initArrays, + Map overRulesDetailMap, + String nextChangeType_key, int next_changeType, String next_beginwork_time){ + KQOvertimeRulesDetailEntity nextKqOvertimeRulesDetailEntity = overRulesDetailMap.get(nextChangeType_key); +// if(nextKqOvertimeRulesDetailEntity != null){ +// if(next_changeType == 2){ +// //如果明日是工作日 工作日如果设置了上班前分钟,会导致加班归属被设置的分钟数给切断,上班前某些部分属于今天不属于昨日 +// int overtimeEnable = nextKqOvertimeRulesDetailEntity.getOvertimeEnable(); +// if(overtimeEnable == 1){ +// KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); +// int before_startTime = nextKqOvertimeRulesDetailEntity.getBefore_startTime(); +// int has_cut_point = nextKqOvertimeRulesDetailEntity.getHas_cut_point(); +// if(has_cut_point != 1){ +// before_startTime = -1; +// } +// int next_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(next_beginwork_time); +// if(before_startTime > -1){ +// int before_next_beginwork_time_index = next_beginwork_time_index - before_startTime; +// if(before_next_beginwork_time_index > 0 && before_next_beginwork_time_index < next_beginwork_time_index){ +// before_next_beginwork_time_index = kqTimesArrayComInfo.turn24to48TimeIndex(before_next_beginwork_time_index); +// next_beginwork_time_index = kqTimesArrayComInfo.turn24to48TimeIndex(next_beginwork_time_index); +// Arrays.fill(initArrays, before_next_beginwork_time_index,next_beginwork_time_index,-1); +// } +// } +// } +// } +// } + } + + /** + * 排除休息时间 现在工作日,节假日和休息日都可以设置排除休息时间 + * @param restTimeMap + * @param changeType_key + * @param kqTimesArrayComInfo + * @param shouldAcross + * @param initArrays + */ + public void handle_resttime(Map> restTimeMap, String changeType_key, KQTimesArrayComInfo kqTimesArrayComInfo, boolean shouldAcross, int[] initArrays) { + + if(restTimeMap.containsKey(changeType_key)){ + List restTimeList = restTimeMap.get(changeType_key); + //再把休息时间填充上去 + if(!restTimeList.isEmpty()){ + 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]); +// if(shouldAcross && restEnd == 1439){ + if(restEnd == 1439){ + //针对跨天的休息时段单独处理排除掉23:59-00:00的时间 + restEnd = 1440; + } + int hasRestMins = kqTimesArrayComInfo.getCnt(initArrays, restStart,restEnd,0); + if(hasRestMins == 0) { + restStart = kqTimesArrayComInfo.turn24to48TimeIndex(restStart); + restEnd = kqTimesArrayComInfo.turn24to48TimeIndex(restEnd); + } + Arrays.fill(initArrays, restStart, restEnd, 1); + } + } + } + } + } + + /** + * 排除休息时长 根据加班时长排除指定时长 + * @param curMins + * @param restTimeMap + * @param changeType_key + * @return + */ + public int handle_restlength(int curMins, Map> restTimeMap, String changeType_key) { + if(restTimeMap.containsKey(changeType_key)) { + List restTimeList = restTimeMap.get(changeType_key); + //再把休息时间填充上去 + if (!restTimeList.isEmpty()) { + for(int k = restTimeList.size()-1 ; k >= 0 ; k--) { + String[] restTimes = restTimeList.get(k); + if (restTimes.length == 2) { + //overlength 是满多少小时 cutlength是减去多少小时 + double overlength = Util.getDoubleValue(restTimes[0],-1); + double cutlength = Util.getDoubleValue(restTimes[1],-1); + if(overlength > -1 && cutlength > -1){ + double min_overlength = overlength * 60; + double min_cutlength = cutlength * 60; + if(curMins >= min_overlength){ + curMins = (int) (curMins-min_cutlength); + break; + } + } + } + } + + } + } + return curMins; + } + + /** + * 处理工作日的加班 + * @param initArrays + * @param resourceid + * @param splitDate + * @param before_startTime + * @param startTime + * @param fromTime_index + * @param kqTimesArrayComInfo + * @param splitBean + * @param toTime_index + * @return + */ + public boolean handle_changeType_2(int[] initArrays, String resourceid, String splitDate, + int before_startTime, int startTime, int fromTime_index, + KQTimesArrayComInfo kqTimesArrayComInfo, SplitBean splitBean, int toTime_index){ + + boolean isok = true; + ShiftInfoBean cur_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceid, splitDate, false); + if(cur_shiftInfoBean != null){ + splitBean.setSerialid(cur_shiftInfoBean.getSerialid()); + List workLongTimeIndex = cur_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,cur_shiftInfoBean,kqTimesArrayComInfo,splitBean); + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + int all_firstworktime = 0; + int all_lastworktime = 0; + boolean need_middle_time = false; + for(int k = 0 ; k < real_workLongTimeIndex.size() ; k++){ + int workLongTimeStartIndex = real_workLongTimeIndex.get(k)[0]; + int workLongTimeEndIndex = real_workLongTimeIndex.get(k)[1]; + if(k == 0){ + if(before_startTime > -1){ + int before_workLongTimeStartIndex = workLongTimeStartIndex-before_startTime; + if(before_workLongTimeStartIndex > 0){ + //从前一天的加班归属点到今天的上班前开始加班点,这段时间属于两不靠。需要排除 + if(fromTime_index < before_workLongTimeStartIndex){ + Arrays.fill(initArrays, fromTime_index,before_workLongTimeStartIndex,-1); + } + } + } + all_firstworktime = workLongTimeStartIndex; + } + if(k == real_workLongTimeIndex.size()-1){ + if(startTime > -1){ + int after_workLongTimeEndIndex = workLongTimeEndIndex+startTime; + if(workLongTimeEndIndex < after_workLongTimeEndIndex){ + Arrays.fill(initArrays, workLongTimeEndIndex,after_workLongTimeEndIndex,-1); + } + } + all_lastworktime = workLongTimeEndIndex; + } + if(!need_middle_time){ + //目前标准加班,一天多次打卡的话是不算中间时间的,只算上班前和下班后的加班 + }else{ + //这个里面是可以算一天多次打卡的话是中间时间的 + Arrays.fill(initArrays, workLongTimeStartIndex,workLongTimeEndIndex,1); + } + } + if(!need_middle_time){ + Arrays.fill(initArrays, all_firstworktime,all_lastworktime,1); + } + List restLongTimeIndex = cur_shiftInfoBean.getRestLongTimeIndex(); + if(restLongTimeIndex != null && !restLongTimeIndex.isEmpty()){ + for (int k = 0; k < restLongTimeIndex.size(); k++) { + //休息时段填充2 + Arrays.fill(initArrays, restLongTimeIndex.get(k)[0], restLongTimeIndex.get(k)[1], 2); + } + } + }else { + System.out.println("error"); + isok = false; + } + }else { + System.out.println("error"); + isok = false; + } + + return isok; + } + /** + * 处理休息日的加班 + * @param restTimeMap + * @param initArrays + * @param overRulesDetailMap + * @param nextChangeType_key + * @param next_changeType + * @param next_beginwork_time + */ + public void handle_changeType_3(int[] initArrays, + Map overRulesDetailMap, + String nextChangeType_key, int next_changeType, String next_beginwork_time){ + KQOvertimeRulesDetailEntity nextKqOvertimeRulesDetailEntity = overRulesDetailMap.get(nextChangeType_key); +// if(nextKqOvertimeRulesDetailEntity != null){ +// if(next_changeType == 2){ +// //如果明日是工作日 工作日如果设置了上班前分钟,会导致加班归属被设置的分钟数给切断,上班前某些部分属于今天不属于昨日 +// int overtimeEnable = nextKqOvertimeRulesDetailEntity.getOvertimeEnable(); +// if(overtimeEnable == 1){ +// KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); +// int before_startTime = nextKqOvertimeRulesDetailEntity.getBefore_startTime(); +// int has_cut_point = nextKqOvertimeRulesDetailEntity.getHas_cut_point(); +// if(has_cut_point != 1){ +// before_startTime = -1; +// } +// int next_beginwork_time_index = kqTimesArrayComInfo.getArrayindexByTimes(next_beginwork_time); +// if(before_startTime > -1){ +// int before_next_beginwork_time_index = next_beginwork_time_index - before_startTime; +// if(before_next_beginwork_time_index > 0 && before_next_beginwork_time_index < next_beginwork_time_index){ +// before_next_beginwork_time_index = kqTimesArrayComInfo.turn24to48TimeIndex(before_next_beginwork_time_index); +// next_beginwork_time_index = kqTimesArrayComInfo.turn24to48TimeIndex(next_beginwork_time_index); +// Arrays.fill(initArrays, before_next_beginwork_time_index,next_beginwork_time_index,-1); +// } +// } +// } +// } +// } + } + + public void getDurationByRule(SplitBean splitBean) { + double D_Mins = splitBean.getD_Mins(); + int workmins = splitBean.getWorkmins(); + String durationrule = splitBean.getDurationrule(); + if("3".equalsIgnoreCase(durationrule) || "5".equalsIgnoreCase(durationrule) + || "6".equalsIgnoreCase(durationrule)){ + double d_hour = D_Mins/60.0; + splitBean.setDuration(KQDurationCalculatorUtil.getDurationRound5(""+d_hour)); + }else if("1".equalsIgnoreCase(durationrule)){ + double d_day = D_Mins/workmins; + splitBean.setDuration(KQDurationCalculatorUtil.getDurationRound5(""+d_day)); + } + } +} diff --git a/src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java b/src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java new file mode 100644 index 0000000..3a494ff --- /dev/null +++ b/src/com/engine/kq/biz/KQOverTimeRuleCalBiz.java @@ -0,0 +1,2798 @@ +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.KQUsageHistoryEntity; +import com.engine.kq.entity.TimeScopeEntity; +import com.engine.kq.entity.WorkTimeEntity; +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.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.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.stream.Collectors; +import weaver.common.DateUtil; +import weaver.conn.RecordSet; +import weaver.general.Util; + +/** + * 根据加班规则计算加班和调休数据 + * 主要是针对 流程+打卡 打卡 这几种方式 + */ +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 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; + String change_key = splitDate + "_" + resourceid; + int changeType = Util.getIntValue("" + changeTypeMap.get(change_key), -1); + String changeType_key = splitDate + "_" + changeType; + int computingMode = Util.getIntValue(""+computingModeMap.get(changeType_key),-1); + if(computingMode == 2){ +// 需审批,以打卡为准,但是不能超过审批时长 + doComputingMode2(resourceid,splitDate,dateFormatter,changeTypeMap,overRulesDetailMap,restTimeMap, + computingModeMap,kqTimesArrayComInfo,uuid); + } + if(computingMode == 3){ +// 无需审批,根据打卡时间计算加班时长 + doComputingMode3(resourceid,splitDate,dateFormatter,changeTypeMap,overRulesDetailMap,restTimeMap, + computingModeMap,kqTimesArrayComInfo,uuid); + } + if(computingMode == 4){ +// 需审批,以打卡为准,取流程和打卡的交集 + doComputingMode4(resourceid,splitDate,dateFormatter,changeTypeMap,overRulesDetailMap,restTimeMap, + computingModeMap,kqTimesArrayComInfo,uuid); + } + } + 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){ + //假期类型的缓存类 + 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) + " 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) + " 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) + " 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 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)); + if (!flag) { + kqLog.info("刷新加班流程数据失败:数据库更新失败" ); + return; + } + } + + } + + /** + * 需审批,以打卡为准,取流程和打卡的交集 + * @param resourceid + * @param splitDate + * @param dateFormatter + * @param changeTypeMap + * @param overRulesDetailMap + * @param restTimeMap + * @param computingModeMap + * @param kqTimesArrayComInfo + * @param main_uuid + */ + private void doComputingMode4(String resourceid, String splitDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap, + Map> restTimeMap, Map computingModeMap, + KQTimesArrayComInfo kqTimesArrayComInfo, String main_uuid) 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(); + Map lsCheckInfoMaps = Maps.newLinkedHashMap(); + //获取加班打卡数据 + getOverTimeCardDataMap(resourceid, splitDate, splitDate, dateFormatter,kqTimesArrayComInfo,overRulesDetailMap,changeTypeMap,lsCheckInfoMaps,eventMap); + + if(lsCheckInfoMaps.isEmpty()){ + logOvertimeMap(overtimeLogMap, "没有打卡数据", "打卡和上下班数据|KQOvertimeCardBean"); + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode4|对应的加班流程数据|key|"+key); + return; + } + RecordSet rs = new RecordSet(); + + 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]; + + 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; + 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"); + continue; + } + int overtimeEnable = kqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + String overtimeEnableInfo = "overtimeEnable:"+overtimeEnable; + logOvertimeMap(overtimeLogMap, overtimeEnableInfo, mapKey+"|"+"未开启加班规则|overtimeEnable"); + continue; + } + + 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); + 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; + } + + 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); +// 本来下面的这个地方是处理重复流程的问题,比如提了两个流程19-20,19-21,那么这俩流程相互交叉的话也只能生成2个小时,但是后来讨论 +// 流程直接的重复校验就通过开那个校验规则了,每一个流程都是和打卡的比较,所以一个是1一个是2.总共3 +// List> hasOverTimeList = Lists.newArrayList(); +// getHasOverTimeData(resourceid,realSplitDate,hasOverTimeList); +// logOvertimeMap(overtimeLogMap, hasOverTimeList, flow_key+"|是否已经生成过加班,返回已经生成过加班的区间|hasOverTimeList"); +// if(hasOverTimeList != null && !hasOverTimeList.isEmpty()){ +// for(int p = 0 ; p < hasOverTimeList.size(); p++){ +// Map hasOverTimeMap = hasOverTimeList.get(p); +// +// String fromdate_flow = Util.null2String(hasOverTimeMap.get("fromdate_flow")); +// String fromtime_flow = Util.null2String(hasOverTimeMap.get("fromtime_flow")); +// String todate_flow = Util.null2String(hasOverTimeMap.get("todate_flow")); +// String totime_flow = Util.null2String(hasOverTimeMap.get("totime_flow")); +// int has_flow_fromIndex = kqTimesArrayComInfo.getArrayindexByTimes(fromtime_flow); +// int has_totime_flow = kqTimesArrayComInfo.getArrayindexByTimes(totime_flow); +// //把重复的流程给去掉,覆盖成-1 +// Arrays.fill(initArrays_flow, has_flow_fromIndex, has_totime_flow,-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"); + + String cross_fromtime = kqTimesArrayComInfo.getTimesByArrayindex(flow_cross_fromtime_index); + String cross_totime = kqTimesArrayComInfo.getTimesByArrayindex(flow_cross_totime_index); + String cross_fromdate = realSplitDate; + String cross_todate = realSplitDate; + + boolean needSplitByTime = false; + if(needSplitByTime){ + // 按照加班时长转调休的 时长设置 这个逻辑如果后面要开启来可以直接用的 + List timepointList = null; + if(kqOvertimeRulesDetailEntity != null){ + timepointList = get_timepointList(kqOvertimeRulesDetailEntity); + logOvertimeMap(overtimeLogMap, timepointList, flow_cross_key+"|如果要生成调休且是根据时间区间来转调休,返回对应的时间区间|timepointList"); + } + + List overtimeBalanceTimeBeans = Lists.newArrayList(); + if(timepointList != null && !timepointList.isEmpty()){ + int[] time_initArrays = kqTimesArrayComInfo.getInitArr(); + for(int t = flow_cross_fromtime_index;t < flow_cross_totime_index; t++){ + time_initArrays[t] = initArrays_flow[t]; + } + get_overtimeBalanceTimeBeans(timepointList,overtimeBalanceTimeBeans,kqTimesArrayComInfo,time_initArrays,flow_cross_totime_index,flow_cross_fromtime_index,2); + } + String overtimeBalanceTimeBeansLogInfo = ""; + if(overtimeBalanceTimeBeans == null || overtimeBalanceTimeBeans.isEmpty()){ + }else{ + overtimeBalanceTimeBeansLogInfo = JSON.toJSONString(overtimeBalanceTimeBeans); + } + logOvertimeMap(overtimeLogMap, overtimeBalanceTimeBeansLogInfo, flow_cross_key+"|如果要生成调休且是根据时间区间来转调休,返回对应的时间区间对应的时长|overtimeBalanceTimeBeans"); + + if(overtimeBalanceTimeBeans != null && !overtimeBalanceTimeBeans.isEmpty()){ + String bean_cross_fromtime = cross_fromtime; + String bean_cross_totime = cross_totime; + for(int timeIndex = 0 ; timeIndex < overtimeBalanceTimeBeans.size() ;timeIndex++){ + OvertimeBalanceTimeBean overtimeBalanceTimeBean = overtimeBalanceTimeBeans.get(timeIndex); + String timePointStart = overtimeBalanceTimeBean.getTimepoint_start(); + String timePointEnd = overtimeBalanceTimeBean.getTimepoint_end(); + boolean isNeedTX = overtimeBalanceTimeBean.isNeedTX(); + int timePointStart_index = kqTimesArrayComInfo.getArrayindexByTimes(timePointStart); + int timePointEnd_index = kqTimesArrayComInfo.getArrayindexByTimes(timePointEnd); + if(timePointStart_index > flow_cross_fromtime_index){ + bean_cross_fromtime = kqTimesArrayComInfo.getTimesByArrayindex(timePointStart_index); + }else{ + bean_cross_fromtime = cross_fromtime; + } + if(timePointEnd_index < flow_cross_totime_index){ + bean_cross_totime = kqTimesArrayComInfo.getTimesByArrayindex(timePointEnd_index); + }else{ + bean_cross_totime = cross_totime; + } + int timepoint_mins = overtimeBalanceTimeBean.getTimepoint_mins(); + if(timepoint_mins == 0){ + continue; + } + mins = timepoint_mins; + } + } + }else{ + } + 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); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + if(2 == paidLeaveEnableType){ + logOvertimeMap(overtimeLogMap, overtime_type, flow_key+"|关联调休与否来自于流程选择,加班类型下拉框值|overtime_type"); + } + + int paidLeaveEnable = getPaidLeaveEnable(kqOvertimeRulesDetailEntity, overtime_type); + //目前不处理按照时间段生成调休 + boolean needSplitByTime = false;//getNeedSplitByTime(kqOvertimeRulesDetailEntity, paidLeaveEnable); + if(needSplitByTime){ + + }else{ + 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)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + signinTime = kqTimesArrayComInfo.turn48to24Time(signinTime); + signoutTime = kqTimesArrayComInfo.turn48to24Time(signoutTime); + if(signinTime.length() == 5){ + signinTime = signinTime+":00"; + } + if(signoutTime.length() == 5){ + signoutTime = signoutTime+":00"; + } + 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); + + 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"); + } + } + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode4|对应的加班流程数据|key|"+key); + + } + + /** + * 得到有效的打卡区间,这个区间肯定已经是去除了上下班时间和休息时间还有重复打卡的部分 + * @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); + } + } + + /** + * 处理加班方式是 无需审批,根据打卡时间计算加班时长 + * @param resourceid + * @param splitDate + * @param dateFormatter + * @param changeTypeMap + * @param overRulesDetailMap + * @param restTimeMap + * @param computingModeMap + * @param kqTimesArrayComInfo + */ + private void doComputingMode3(String resourceid, String splitDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap, + Map> restTimeMap, Map computingModeMap, + KQTimesArrayComInfo kqTimesArrayComInfo, String main_uuid) 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(); + Map lsCheckInfoMaps = Maps.newLinkedHashMap(); + //获取加班打卡数据 + getOverTimeCardDataMap(resourceid, splitDate, splitDate, dateFormatter,kqTimesArrayComInfo,overRulesDetailMap,changeTypeMap,lsCheckInfoMaps, + eventMap); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode3|对应的打卡数据|key|"+key); + + if(lsCheckInfoMaps.isEmpty()){ + logOvertimeMap(overtimeLogMap, "没有打卡数据", "打卡和上下班数据|KQOvertimeCardBean"); + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + return; + } + + 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; + 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"); + continue; + } + int overtimeEnable = kqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + String overtimeEnableInfo = "overtimeEnable:"+overtimeEnable; + logOvertimeMap(overtimeLogMap, overtimeEnableInfo, mapKey+"|"+"未开启加班规则|overtimeEnable"); + continue; + } + if(kqOvertimeCardBean != null){ + + int[] initArrays = kqTimesArrayComInfo.getInitArr(); + Map signinoffMap = buildOvertimeCard(kqOvertimeCardBean, resourceid, realSplitDate, kqTimesArrayComInfo, restTimeMap, changeType_key,initArrays,Lists.newArrayList(),overRulesDetailMap, + true, overtimeLogMap); + 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){ + continue; + } + 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"); + continue; + } + 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(); + int unit = KQOvertimeRulesBiz.getMinimumUnit(); + + int paidLeaveEnable = kqOvertimeRulesDetailEntity.getPaidLeaveEnable(); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + boolean needSplitByTime = false;//getNeedSplitByTime(kqOvertimeRulesDetailEntity, paidLeaveEnable); + if(needSplitByTime){ + // 按照加班时长转调休的 时长设置 + List timepointList = null; + if(kqOvertimeRulesDetailEntity != null){ + timepointList = get_timepointList(kqOvertimeRulesDetailEntity); + logOvertimeMap(overtimeLogMap, timepointList, flow_cross_key+"|如果要生成调休且是根据时间区间来转调休,返回对应的时间区间|timepointList"); + } + + List overtimeBalanceTimeBeans = Lists.newArrayList(); + if(timepointList != null && !timepointList.isEmpty()){ + int[] time_initArrays = kqTimesArrayComInfo.getInitArr(); + for(int t = signinTimeIndex;t < signoutTimeIndex; t++){ + time_initArrays[t] = initArrays[t]; + } + get_overtimeBalanceTimeBeans(timepointList,overtimeBalanceTimeBeans,kqTimesArrayComInfo,time_initArrays,signoutTimeIndex,signinTimeIndex,1); + } + String overtimeBalanceTimeBeansLogInfo = ""; + if(overtimeBalanceTimeBeans == null || overtimeBalanceTimeBeans.isEmpty()){ + }else{ + overtimeBalanceTimeBeansLogInfo = JSON.toJSONString(overtimeBalanceTimeBeans); + } + logOvertimeMap(overtimeLogMap, overtimeBalanceTimeBeansLogInfo, flow_cross_key+"|如果要生成调休且是根据时间区间来转调休,返回对应的时间区间对应的时长|overtimeBalanceTimeBeans"); + + if(overtimeBalanceTimeBeans != null && !overtimeBalanceTimeBeans.isEmpty()){ + String bean_cross_fromtime = signinTime; + String bean_cross_totime = signoutTime; + for(int timeIndex = 0 ; timeIndex < overtimeBalanceTimeBeans.size() ;timeIndex++) { + OvertimeBalanceTimeBean overtimeBalanceTimeBean = overtimeBalanceTimeBeans.get(timeIndex); + String timePointStart = overtimeBalanceTimeBean.getTimepoint_start(); + String timePointEnd = overtimeBalanceTimeBean.getTimepoint_end(); + int timePointStart_index = kqTimesArrayComInfo.getArrayindexByTimes(timePointStart); + int timePointEnd_index = kqTimesArrayComInfo.getArrayindexByTimes(timePointEnd); + if(timePointStart_index > signinTimeIndex){ + bean_cross_fromtime = kqTimesArrayComInfo.getTimesByArrayindex(timePointStart_index); + }else{ + bean_cross_fromtime = signinTime; + } + if(timePointEnd_index < signoutTimeIndex){ + bean_cross_totime = kqTimesArrayComInfo.getTimesByArrayindex(timePointEnd_index); + }else{ + bean_cross_totime = signoutTime; + } + int timepoint_mins = overtimeBalanceTimeBean.getTimepoint_mins(); + if(timepoint_mins == 0){ + continue; + } + mins = timepoint_mins; + otherParam.put("OvertimeBalanceTimeBean", overtimeBalanceTimeBean); + otherParam.put("overtimeLogMap", overtimeLogMap); + String timepoint_key = flow_cross_key+"|调休按照分段计算加班时间("+signinTime+"-"+signoutTime+")"; + otherParam.put("timepoint_key", timepoint_key); + logOvertimeMap(overtimeLogMap, mins, timepoint_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); + } + overtime_uuid = UUID.randomUUID().toString(); + 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)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + 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); + + String overtimeid = get_overtime_uuid(overtime_uuid); + kqEventLogBiz.updateOvertimeId(uuid, overtimeid); + } + } + }else{ + + 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); + } + + 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)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + 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); + + 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"); + } + } + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode3|对应的加班流程数据|key|"+key); + + + } + + /** + * 获取生成的加班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); + } + } + } + + /** + * 处理加班方式是 需审批,以打卡为准,但是不能超过审批时长的加班时长 + * @param resourceid + * @param splitDate + * @param dateFormatter + * @param changeTypeMap + * @param overRulesDetailMap + * @param restTimeMap + * @param computingModeMap + * @param kqTimesArrayComInfo + */ + private void doComputingMode2(String resourceid, String splitDate, + DateTimeFormatter dateFormatter, Map changeTypeMap, + Map overRulesDetailMap, + Map> restTimeMap, Map computingModeMap, + KQTimesArrayComInfo kqTimesArrayComInfo, String main_uuid) 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(); + Map lsCheckInfoMaps = Maps.newLinkedHashMap(); + //获取加班打卡数据 + getOverTimeCardDataMap(resourceid, splitDate, splitDate, dateFormatter,kqTimesArrayComInfo,overRulesDetailMap,changeTypeMap,lsCheckInfoMaps, + eventMap); + + Map> splitBeanMaps = Maps.newHashMap(); + //获取加班流程数据 + getOverTimeFlowData(resourceid,splitDate,splitDate,splitBeanMaps,dateFormatter); + + if(lsCheckInfoMaps.isEmpty()){ + logOvertimeMap(overtimeLogMap, "没有打卡数据", "打卡和上下班数据|KQOvertimeCardBean"); + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode2|对应的加班流程数据|key|"+key); + return; + } + + 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; + 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"); + continue; + } + int overtimeEnable = kqOvertimeRulesDetailEntity.getOvertimeEnable(); + if(overtimeEnable != 1){ + String overtimeEnableInfo = "overtimeEnable:"+overtimeEnable; + logOvertimeMap(overtimeLogMap, overtimeEnableInfo, mapKey+"|"+"未开启加班规则|overtimeEnable"); + continue; + } + + 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"); + continue; + } + 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); + + 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(Map.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); + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + if(2 == paidLeaveEnableType){ + logOvertimeMap(overtimeLogMap, overtime_type, flow_cross_key+"|关联调休与否来自于流程选择,加班类型下拉框值|overtime_type"); + } + + int paidLeaveEnable = getPaidLeaveEnable(kqOvertimeRulesDetailEntity, overtime_type); + boolean needSplitByTime = false;//getNeedSplitByTime(kqOvertimeRulesDetailEntity, paidLeaveEnable); + if(needSplitByTime){ + // 按照加班时长转调休的 时长设置 + List timepointList = null; + if(kqOvertimeRulesDetailEntity != null){ + timepointList = get_timepointList(kqOvertimeRulesDetailEntity); + logOvertimeMap(overtimeLogMap, timepointList, flow_cross_key+"|如果要生成调休且是根据时间区间来转调休,返回对应的时间区间|timepointList"); + } + + List overtimeBalanceTimeBeans = Lists.newArrayList(); + //需要分段根据设置的时间区间来计算加班,这个第二种加班方式有有点冲突,不能做 +// if(timepointList != null && !timepointList.isEmpty()){ +// int[] time_initArrays = kqTimesArrayComInfo.getInitArr(); +// get_overtimeBalanceTimeBeans(timepointList,overtimeBalanceTimeBeans,kqTimesArrayComInfo,time_initArrays,flow_cross_totime_index,2); +// } + }else{ + 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"); + + 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)"+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + 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); + 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"); + } + } + kqEventLogBiz.logDetailOvertimeMap(resourceid,overtimeLogMap,uuid); + kqEventLogBiz.logDetailEvent(resourceid,eventMap,uuid,"doComputingMode2|对应的加班流程数据|key|"+key); + + } + + /** + * 打卡的时长计算,流程+打卡 和纯打卡的可以拿来共用 + * 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) 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(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; + } + int hasRestMins = kqTimesArrayComInfo.getCnt(initArrays, restStart,restEnd,1); + if(hasRestMins == 0) { + restStart = kqTimesArrayComInfo.turn24to48TimeIndex(restStart); + restEnd = kqTimesArrayComInfo.turn24to48TimeIndex(restEnd); + } + if(restStart < restEnd){ + Arrays.fill(initArrays, restStart, restEnd, -2); + } + } + } + }else{ + } + } + } + + boolean isNextDay = false; + clearWorkAndRestTime(resourceid,splitDate,isNextDay,kqTimesArrayComInfo,overtimeLogMap,kqOvertimeRulesDetailEntity,initArrays,signinTimeIndex); + isNextDay = true; + clearWorkAndRestTime(resourceid,DateUtil.addDate(splitDate, 1),isNextDay, kqTimesArrayComInfo, + overtimeLogMap, kqOvertimeRulesDetailEntity, 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 isNextDay 是否是处理处理明日的,如果是true的话,上下班时间和休息时间都要+1440 + * @param kqTimesArrayComInfo + * @param overtimeLogMap + * @param kqOvertimeRulesDetailEntity + * @param initArrays + * @param signinTimeIndex + */ + public void clearWorkAndRestTime(String resourceid, String splitDate, boolean isNextDay, + KQTimesArrayComInfo kqTimesArrayComInfo, + Map overtimeLogMap, + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity, int[] initArrays, + int signinTimeIndex) { + + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTime = kqWorkTime.getWorkTime(resourceid, splitDate); + if (workTime == null || workTime.getWorkMins() == 0) { + }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()); + 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(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(isNextDay){ + begintimeIndex = begintimeIndex + 1440; + endtimeIndex = endtimeIndex + 1440; + if(begintimeIndex >= initArrays.length){ + begintimeIndex = initArrays.length-1; + } + if(endtimeIndex >= initArrays.length){ + endtimeIndex = initArrays.length-1; + } + } + String workTimeLogInfo = "begintime:"+begintime+":endtime:"+endtime+":isNextDay:"+isNextDay; + logOvertimeMap(overtimeLogMap, workTimeLogInfo, "工作日的上下班时间|workTimeLogInfo"); + if(begintimeIndex < endtimeIndex){ + Arrays.fill(initArrays, begintimeIndex, endtimeIndex, -2); + } + if(!isNextDay){ + if(kqOvertimeRulesDetailEntity != null){ + int startTime = kqOvertimeRulesDetailEntity.getStartTime(); + if(startTime > -1){ + int after_endtimeIndex = endtimeIndex + startTime; + if(after_endtimeIndex > endtimeIndex){ + 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 > 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(isNextDay){ + begintimeIndex = begintimeIndex + 1440; + endtimeIndex = endtimeIndex + 1440; + if(begintimeIndex >= initArrays.length){ + begintimeIndex = initArrays.length-1; + } + if(endtimeIndex >= initArrays.length){ + endtimeIndex = initArrays.length-1; + } + } + if(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("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){ + 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]); + } + 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); + } + }else{ + String errorMsg = "前一天是工作日但是前一天的ShiftInfoBean班次获取不到信息"; + eventMap.put("errorMsg", errorMsg); + } + }else { + eventMap.put("changeType", changeType); + if(changeType == 2){ + eventMap.put("firstworkTime", firstworkTime); + if(has_cut_point == 1 && before_startTime > 0){ + firstworkTime = kqTimesArrayComInfo.getTimesByArrayindex(kqTimesArrayComInfo.getArrayindexByTimes(firstworkTime)-before_startTime); + } + //如果前一天是非工作日,今天是工作日的话 + rePutCheckInfoMap(lsCheckInfoMaps, kqOvertimeBean, preKey, key, firstworkTime, splitDate, + eventMap); + }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); + } + } + } + + /** + * 获取打卡数据 + * @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; + String nextChangeType_key = nextSplitDate+"_"+nextChangeType; + + KQOvertimeRulesDetailEntity curKqOvertimeRulesDetailEntity = overRulesDetailMap.get(changeType_key); + KQOvertimeRulesDetailEntity preKqOvertimeRulesDetailEntity = overRulesDetailMap.get(preChangeType_key); + KQOvertimeRulesDetailEntity nextKqOvertimeRulesDetailEntity = 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); + + if (workTime == null || (workTime.getWorkMins() == 0 && workTime.getRestShift() != 1)) { + 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) { + lsSignTime = workTime.getSignTime();//允许打卡时间 + lsWorkTime = workTime.getWorkTime();//工作时间 + result.put("lsWorkTime_size", ""+lsWorkTime.size()); + lsRestTime = workTime.getRestTime();//休息时段时间 + oneSign = lsWorkTime!=null&&lsWorkTime.size()==1; + 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) { + String preDate = DateUtil.addDate(splitDate, -1); + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + + 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){ + //如果签退大于签到 表示打卡跨天 + 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); + curOvertimeBean.setBelongDate(splitDate); + lsCheckInfoMaps.put(key, curOvertimeBean); + + KQOvertimeCardBean nextOvertimeBean = new KQOvertimeCardBean(); + nextOvertimeBean.setSigninDate(nextDate); + nextOvertimeBean.setSigninTime(cut_points); + nextOvertimeBean.setSignoutDate(signoutdate); + nextOvertimeBean.setSignoutTime(signouttime); + nextOvertimeBean.setBelongDate(nextDate); + lsCheckInfoMaps.put(nextkey, nextOvertimeBean); + } + } + } + } + } + + + /** + * 重新把打卡数据按照归属来赋值 + * @param lsCheckInfoMaps + * @param kqOvertimeBean + * @param preKey + * @param key + * @param overtime_cut_point + * @param splitDate + * @param eventMap + */ + public void rePutCheckInfoMap(Map lsCheckInfoMaps, + KQOvertimeCardBean kqOvertimeBean, + String preKey, String key, String overtime_cut_point, String splitDate, + Map eventMap){ + + 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); + } + } + + + /** + * 获取加班流程数据 + * @param resourceid + * @param fromDate + * @param toDate + * @param splitBeanMaps + * @param dateFormatter + */ + public 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(); + 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(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(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(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) { + 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"))); + + //流程抵扣打卡不处理 + Map flow_deduct_card_map = Maps.newHashMap(); + + 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(has_cut_point == 1){ + String cut_point_datettime = nextDate+" "+cut_point+":59"; + signEndDateTime = cut_point_datettime; + } + } + if(index == 0 && i == 0){ + //第一次的打卡范围会被打卡临界点给修改 + if(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", workTimeScope.getBeginTime()+":00"); + }else if("signoff".equalsIgnoreCase(type)){ + signMap.put("signindate", workTimeScope.getEndTimeAcross()?nextDate:kqDate); + signMap.put("signintime", 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", 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 + */ + public 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 resourceId + * @param fromdate + * @param fromtime + * @param todate + * @param totime + * @param changeTypeMap + * @param kqOvertimeRulesDetailEntity + * @param splitBean + * @param restTimeMap + * @param overRulesDetailMap + */ + public List getOvertimeBalanceTimeBean(String resourceId, + String fromdate, String fromtime, String todate, String totime, + Map changeTypeMap, + KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity, SplitBean splitBean, + Map> restTimeMap, + Map overRulesDetailMap){ + KQOverTimeFlowBiz kqOverTimeFlowBiz = new KQOverTimeFlowBiz(); + KQTimesArrayComInfo kqTimesArrayComInfo= new KQTimesArrayComInfo(); + KQOverTimeRuleCalBiz kqOverTimeRuleCalBiz = new KQOverTimeRuleCalBiz(); + int[] initArrays = kqTimesArrayComInfo.getInitArr(); + boolean shouldAcross = false; + int before_startTime = -1; + int startTime = 0; + String change_key = fromdate+"_"+resourceId; + int changeType = Util.getIntValue(""+changeTypeMap.get(change_key),-1); + String changeType_key = fromdate+"_"+changeType; + + String nextSplitDate = DateUtil.addDate(fromdate,1); + String next_change_key = nextSplitDate+"_"+resourceId; + int next_changeType = Util.getIntValue(""+changeTypeMap.get(next_change_key),-1); + String nextChangeType_key = nextSplitDate+"_"+next_changeType; + + String next_beginwork_time = ""; + String serialid = ""; + //需要知道明日的类型:如果今天是工作日的话,那么今天的加班临界点可能和明日的上班时间冲突,需要知道明日的上班时间进行比较, + // 如果今天是休息日,那么明天如果是工作日的话,默认规则下,明天的上班前都是属于今天的加班区间 + if(next_changeType == 2){ + ShiftInfoBean next_shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(resourceId, nextSplitDate, false); + if(next_shiftInfoBean != null){ + List workLongTimeIndex = next_shiftInfoBean.getWorkLongTimeIndex(); + List real_workLongTimeIndex = Lists.newArrayList(); + kqOverTimeFlowBiz.get_real_workLongTimeIndex(workLongTimeIndex,real_workLongTimeIndex,next_shiftInfoBean,kqTimesArrayComInfo,splitBean); + + if(real_workLongTimeIndex != null && !real_workLongTimeIndex.isEmpty()){ + next_beginwork_time = kqTimesArrayComInfo.getTimesByArrayindex(real_workLongTimeIndex.get(0)[0]); + } + } + } + + int fromTime_index = kqTimesArrayComInfo.getArrayindexByTimes(fromtime); + int toTime_index = kqTimesArrayComInfo.getArrayindexByTimes(totime); + Arrays.fill(initArrays, fromTime_index, toTime_index, 0); + if(changeType == 1){ + kqOverTimeFlowBiz.handle_changeType_1(initArrays, overRulesDetailMap, nextChangeType_key, + next_changeType, next_beginwork_time); + }else if(changeType == 2){ + if(kqOvertimeRulesDetailEntity != null){ + before_startTime = kqOvertimeRulesDetailEntity.getBefore_startTime(); + int has_cut_point = kqOvertimeRulesDetailEntity.getHas_cut_point(); + if(has_cut_point != 1){ + before_startTime = -1; + } + startTime = kqOvertimeRulesDetailEntity.getStartTime(); + } + boolean isok = kqOverTimeFlowBiz.handle_changeType_2(initArrays, resourceId, fromdate, before_startTime, startTime, fromTime_index, + kqTimesArrayComInfo, splitBean,toTime_index); + }else if(changeType == 3){ + kqOverTimeFlowBiz.handle_changeType_3(initArrays, overRulesDetailMap, nextChangeType_key, + next_changeType, next_beginwork_time); + } + int restTimeType = -1; + if(kqOvertimeRulesDetailEntity != null){ + restTimeType = kqOvertimeRulesDetailEntity.getRestTimeType(); + } + if(restTimeType == 1){ + //如果排除设置的休息时间 + kqOverTimeFlowBiz.handle_resttime(restTimeMap,changeType_key,kqTimesArrayComInfo,shouldAcross,initArrays); + } + // 按照加班时长转调休的 时长设置 + List timepointList = null; + List overtimeBalanceTimeBeans = Lists.newArrayList(); + if(kqOvertimeRulesDetailEntity != null){ + timepointList = kqOverTimeRuleCalBiz.get_timepointList(kqOvertimeRulesDetailEntity); + } + + if(timepointList != null && !timepointList.isEmpty()){ + kqOverTimeRuleCalBiz.get_overtimeBalanceTimeBeans(timepointList,overtimeBalanceTimeBeans,kqTimesArrayComInfo,initArrays,toTime_index,fromTime_index,0); + } + + return overtimeBalanceTimeBeans; + } + + /** + * 判断是否开启了调休的 按照时间点分段生成调休 + * @param kqOvertimeRulesDetailEntity + * @param paidLeaveEnable + * @return + */ + public boolean getNeedSplitByTime(KQOvertimeRulesDetailEntity kqOvertimeRulesDetailEntity, + int paidLeaveEnable) { + //因为【按加班时长范围设置转调休时长问题】这个方式存在问题,暂不使用 + if(true){ + return false; + } + boolean needSplitByTime = false; + if(paidLeaveEnable == 1){ + int paidLeaveEnableType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableType(); + //如果开启了转调休,并且调休是分段折算的,可以按照分段来显示加班 + if(1 == paidLeaveEnableType){ + int paidLeaveEnableDefaultType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableDefaultType(); + if(paidLeaveEnableDefaultType == 3){ + needSplitByTime = true; + } + }else if(2 == paidLeaveEnableType){ + int paidLeaveEnableFlowType = kqOvertimeRulesDetailEntity.getPaidLeaveEnableFlowType(); + if(paidLeaveEnableFlowType == 3){ + needSplitByTime = true; + } + } + } + return needSplitByTime; + } + + /** + * 判断是否开启了调休 + * @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 where "+Util.getSubINClause(clear_tiaoxiuids, "id", "in"); + isclearOk = rs.executeUpdate(clearSql); + } + + 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; + } +} diff --git a/src/com/engine/kq/biz/KQShiftManagementComInfo.java b/src/com/engine/kq/biz/KQShiftManagementComInfo.java new file mode 100644 index 0000000..0f28c31 --- /dev/null +++ b/src/com/engine/kq/biz/KQShiftManagementComInfo.java @@ -0,0 +1,759 @@ +package com.engine.kq.biz; + +import com.alibaba.fastjson.JSON; +import com.engine.kq.biz.chain.cominfo.HalfShiftComIndex; +import com.engine.kq.biz.chain.cominfo.RestShiftComIndex; +import com.engine.kq.biz.chain.cominfo.ShiftComIndex; +import com.engine.kq.biz.chain.cominfo.ShiftInfoCominfoBean; +import com.engine.kq.biz.chain.cominfo.WorkShiftComIndex; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.cmd.shiftmanagement.toolkit.ShiftManagementToolKit; +import com.engine.kq.entity.TimeScopeEntity; +import com.engine.kq.log.KQLog; +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StringWriter; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import org.apache.commons.lang.math.NumberUtils; +import weaver.cache.CacheBase; +import weaver.cache.CacheColumn; +import weaver.cache.CacheColumnType; +import weaver.cache.CacheItem; +import weaver.cache.CacheMap; +import weaver.cache.PKColumn; +import weaver.conn.RecordSet; +import weaver.general.Util; + +/** + * 班次管理缓存类 + */ +public class KQShiftManagementComInfo extends CacheBase implements Serializable { + /* + * 需要关注 : 如果完全在 initCache 自己定义数据初始化, 这个字段可以不定义 + */ + protected static String TABLE_NAME = ""; + + /* + * 需要关注 : 如果完全在 initCache 自己定义数据初始化,或者不需要指定固定的条件, 这个字段可以不定义 + * sql中的where信息,不要以where开始 + */ + protected static String TABLE_WHERE = null; + + /* + * 需要关注 : 如果完全在 initCache 自己定义数据初始化,或者不需要指定顺序, 这个字段可以不定义 sql中的order + * by信息,不要以order by开始 + * + */ + protected static String TABLE_ORDER = null; + + @PKColumn(type = CacheColumnType.NUMBER) + protected static String PK_NAME = "id"; + + @CacheColumn + protected static int shiftbean; + + @CacheColumn + protected static int color; + + @CacheColumn + protected static int isoffdutyfreecheck; + + @CacheColumn + protected static int shiftonoffworkcount; + + @CacheColumn + protected static int serial; + + @CacheColumn + protected static int isresttimeopen; + + @CacheColumn + protected static int worktime; + + @CacheColumn + protected static int punchsetting; + + @CacheColumn + protected static int cardRemind; + + @CacheColumn + protected static int cardRemOfSignIn; + + @CacheColumn + protected static int minsBeforeSignIn; + + @CacheColumn + protected static int cardRemOfSignOut; + + @CacheColumn + protected static int minsAfterSignOut; + + @CacheColumn + protected static int remindMode; + + @CacheColumn + protected static int remindOnPC; + + @CacheColumn + protected static int rest_shift; + + private KQLog kqLog = new KQLog(); + + @Override + public CacheItem initCache(String key) { + if (key == null || "".equals(key.trim())) { + return null; + } + CacheMap localData = createCacheMap(); + String sql = ""; + kqLog = new KQLog(); + ConcurrentHashMap resourceKQGroups = new ConcurrentHashMap<>(); + //考勤组优先级 + try { + + ConcurrentHashMap shiftInfoBeanMap = new ConcurrentHashMap<>(); + ConcurrentHashMap idMap = new ConcurrentHashMap<>(); + ConcurrentHashMap colorsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap isoffdutyfreechecksMap = new ConcurrentHashMap<>(); + ConcurrentHashMap shiftonoffworkcountsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap serialsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap isresttimeopensMap = new ConcurrentHashMap<>(); + ConcurrentHashMap worktimesMap = new ConcurrentHashMap<>(); + ConcurrentHashMap punchsettingsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap cardRemindMap = new ConcurrentHashMap<>(); + ConcurrentHashMap cardRemOfSignInMap = new ConcurrentHashMap<>(); + ConcurrentHashMap minsBeforeSignInMap = new ConcurrentHashMap<>(); + ConcurrentHashMap cardRemOfSignOutMap = new ConcurrentHashMap<>(); + ConcurrentHashMap minsAfterSignOutMap = new ConcurrentHashMap<>(); + ConcurrentHashMap remindModeMap = new ConcurrentHashMap<>(); + ConcurrentHashMap remindOnPCMap = new ConcurrentHashMap<>(); + ConcurrentHashMap restShiftMap = new ConcurrentHashMap<>(); + RecordSet rs = new RecordSet(); + String getShiftInfo = "select * from kq_ShiftManagement where 1=1 and id="+key+" order by id "; + rs.execute(getShiftInfo); + while(rs.next()){ + String serialid = rs.getString("id"); + String isresttimeopen = rs.getString("isresttimeopen"); + String color = rs.getString("color"); + String shiftonoffworkcount = rs.getString("shiftonoffworkcount"); + String worktime = rs.getString("worktime"); + String serial = rs.getString("serial"); + String punchsetting = "1"; + String isoffdutyfreecheck = rs.getString("isoffdutyfreecheck"); + String cardRemind = rs.getString("cardRemind"); + String cardRemOfSignIn = rs.getString("cardRemOfSignIn"); + String minsBeforeSignIn = rs.getString("minsBeforeSignIn"); + String cardRemOfSignOut = rs.getString("cardRemOfSignOut"); + String minsAfterSignOut = rs.getString("minsAfterSignOut"); + String remindMode = rs.getString("remindMode"); + String remindOnPC = rs.getString("remindOnPC"); + String halfcalrule = rs.getString("halfcalrule"); + halfcalrule = Util.null2String(halfcalrule).length() == 0 ? "0" : halfcalrule; + String halfcalpoint = rs.getString("halfcalpoint"); + String halfcalpoint2cross = rs.getString("halfcalpoint2cross"); + String restShift = rs.getString("rest_shift"); + + getShiftInfoBean(serialid,isresttimeopen,worktime,punchsetting,shiftInfoBeanMap,halfcalrule,halfcalpoint,halfcalpoint2cross,restShift); + + idMap.put(serialid, serialid); + colorsMap.put(serialid, color); + isoffdutyfreechecksMap.put(serialid, isoffdutyfreecheck); + shiftonoffworkcountsMap.put(serialid, shiftonoffworkcount); + serialsMap.put(serialid, serial); + isresttimeopensMap.put(serialid, isresttimeopen); + worktimesMap.put(serialid, worktime); + punchsettingsMap.put(serialid, punchsetting); + cardRemindMap.put(serialid,cardRemind); + cardRemOfSignInMap.put(serialid,cardRemOfSignIn); + minsBeforeSignInMap.put(serialid,minsBeforeSignIn); + cardRemOfSignOutMap.put(serialid,cardRemOfSignOut); + minsAfterSignOutMap.put(serialid,minsAfterSignOut); + remindModeMap.put(serialid,remindMode); + remindOnPCMap.put(serialid,remindOnPC); + restShiftMap.put(serialid,restShift); + } + + + if(shiftInfoBeanMap.size()>0){ + CacheItem cacheItem = createCacheItem(); + Iterator> iterator = shiftInfoBeanMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String id = entry.getKey(); + Object value = entry.getValue(); + cacheItem.set(PK_INDEX, id); + cacheItem.set(shiftbean, value); + cacheItem.set(isoffdutyfreecheck, isoffdutyfreechecksMap.get(id)); + cacheItem.set(shiftonoffworkcount, shiftonoffworkcountsMap.get(id)); + cacheItem.set(serial, serialsMap.get(id)); + cacheItem.set(isresttimeopen, isresttimeopensMap.get(id)); + cacheItem.set(worktime, worktimesMap.get(id)); + cacheItem.set(punchsetting, punchsettingsMap.get(id)); + cacheItem.set(cardRemind,cardRemindMap.get(id)); + cacheItem.set(cardRemOfSignIn,cardRemOfSignInMap.get(id)); + cacheItem.set(minsBeforeSignIn,minsBeforeSignInMap.get(id)); + cacheItem.set(cardRemOfSignOut,cardRemOfSignOutMap.get(id)); + cacheItem.set(minsAfterSignOut,minsAfterSignOutMap.get(id)); + cacheItem.set(remindMode,remindModeMap.get(id)); + cacheItem.set(remindOnPC,remindOnPCMap.get(id)); + cacheItem.set(rest_shift,restShiftMap.get(id)); + modifyCacheItem(id, cacheItem); + } + return cacheItem; + } + } catch (Exception e) { + kqLog.info(e); + } + return null; + } + + @Override + public CacheMap initCache() { + CacheMap localData = createCacheMap(); + String sql = ""; + kqLog = new KQLog(); + ConcurrentHashMap resourceKQGroups = new ConcurrentHashMap<>(); + //考勤组优先级 + try { + + ConcurrentHashMap shiftInfoBeanMap = new ConcurrentHashMap<>(); + ConcurrentHashMap idMap = new ConcurrentHashMap<>(); + ConcurrentHashMap colorsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap isoffdutyfreechecksMap = new ConcurrentHashMap<>(); + ConcurrentHashMap shiftonoffworkcountsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap serialsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap isresttimeopensMap = new ConcurrentHashMap<>(); + ConcurrentHashMap worktimesMap = new ConcurrentHashMap<>(); + ConcurrentHashMap punchsettingsMap = new ConcurrentHashMap<>(); + ConcurrentHashMap cardRemindMap = new ConcurrentHashMap<>(); + ConcurrentHashMap cardRemOfSignInMap = new ConcurrentHashMap<>(); + ConcurrentHashMap minsBeforeSignInMap = new ConcurrentHashMap<>(); + ConcurrentHashMap cardRemOfSignOutMap = new ConcurrentHashMap<>(); + ConcurrentHashMap minsAfterSignOutMap = new ConcurrentHashMap<>(); + ConcurrentHashMap remindModeMap = new ConcurrentHashMap<>(); + ConcurrentHashMap remindOnPCMap = new ConcurrentHashMap<>(); + ConcurrentHashMap restShiftMap = new ConcurrentHashMap<>(); + RecordSet rs = new RecordSet(); + String getShiftInfo = "select * from kq_ShiftManagement where 1=1 order by id "; + rs.execute(getShiftInfo); + while(rs.next()){ + String serialid = rs.getString("id"); + String isresttimeopen = rs.getString("isresttimeopen"); + String color = rs.getString("color"); + String shiftonoffworkcount = rs.getString("shiftonoffworkcount"); + String worktime = rs.getString("worktime"); + String serial = rs.getString("serial"); + String punchsetting = "1"; + String isoffdutyfreecheck = rs.getString("isoffdutyfreecheck"); + String cardRemind = rs.getString("cardRemind"); + String cardRemOfSignIn = rs.getString("cardRemOfSignIn"); + String minsBeforeSignIn = rs.getString("minsBeforeSignIn"); + String cardRemOfSignOut = rs.getString("cardRemOfSignOut"); + String minsAfterSignOut = rs.getString("minsAfterSignOut"); + String remindMode = rs.getString("remindMode"); + String remindOnPC = rs.getString("remindOnPC"); + String halfcalrule = rs.getString("halfcalrule"); + halfcalrule = Util.null2String(halfcalrule).length() == 0 ? "0" : halfcalrule; + String halfcalpoint = rs.getString("halfcalpoint"); + String halfcalpoint2cross = rs.getString("halfcalpoint2cross"); + String restShift = rs.getString("rest_shift"); + + getShiftInfoBean(serialid,isresttimeopen,worktime,punchsetting,shiftInfoBeanMap,halfcalrule,halfcalpoint,halfcalpoint2cross,restShift); + + idMap.put(serialid, serialid); + colorsMap.put(serialid, color); + isoffdutyfreechecksMap.put(serialid, isoffdutyfreecheck); + shiftonoffworkcountsMap.put(serialid, shiftonoffworkcount); + serialsMap.put(serialid, serial); + isresttimeopensMap.put(serialid, isresttimeopen); + worktimesMap.put(serialid, worktime); + punchsettingsMap.put(serialid, punchsetting); + cardRemindMap.put(serialid,cardRemind); + cardRemOfSignInMap.put(serialid,cardRemOfSignIn); + minsBeforeSignInMap.put(serialid,minsBeforeSignIn); + cardRemOfSignOutMap.put(serialid,cardRemOfSignOut); + minsAfterSignOutMap.put(serialid,minsAfterSignOut); + remindModeMap.put(serialid,remindMode); + remindOnPCMap.put(serialid,remindOnPC); + restShiftMap.put(serialid,restShift); + } + + + if(shiftInfoBeanMap.size()>0){ + Iterator> iterator = shiftInfoBeanMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String id = entry.getKey(); + Object value = entry.getValue(); + CacheItem cacheItem = createCacheItem(); + cacheItem.set(PK_INDEX, id); + cacheItem.set(shiftbean, value); + cacheItem.set(isoffdutyfreecheck, isoffdutyfreechecksMap.get(id)); + cacheItem.set(shiftonoffworkcount, shiftonoffworkcountsMap.get(id)); + cacheItem.set(serial, serialsMap.get(id)); + cacheItem.set(isresttimeopen, isresttimeopensMap.get(id)); + cacheItem.set(worktime, worktimesMap.get(id)); + cacheItem.set(punchsetting, punchsettingsMap.get(id)); + cacheItem.set(cardRemind,cardRemindMap.get(id)); + cacheItem.set(cardRemOfSignIn,cardRemOfSignInMap.get(id)); + cacheItem.set(minsBeforeSignIn,minsBeforeSignInMap.get(id)); + cacheItem.set(cardRemOfSignOut,cardRemOfSignOutMap.get(id)); + cacheItem.set(minsAfterSignOut,minsAfterSignOutMap.get(id)); + cacheItem.set(remindMode,remindModeMap.get(id)); + cacheItem.set(remindOnPC,remindOnPCMap.get(id)); + cacheItem.set(rest_shift,restShiftMap.get(id)); + modifyCacheItem(id, cacheItem); + localData.put(id, cacheItem); + } + } + } catch (Exception e) { + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + } + return localData; + } + + public String getId(){ + return (String)getRowValue(PK_INDEX); + } + + public String getColor() { return (String)getRowValue(color); } + + public String getColor(String key) + { + return (String)getValue(color,key); + } + + public String getIsoffdutyfreecheck() { return (String)getRowValue(isoffdutyfreecheck); } + + public String getIsoffdutyfreecheck(String key) + { + return (String)getValue(isoffdutyfreecheck,key); + } + + public String getShiftonoffworkcounts() { return (String)getRowValue(shiftonoffworkcount); } + + public String getShiftonoffworkcounts(String key) + { + return (String)getValue(shiftonoffworkcount,key); + } + + public String getSerial() { return (String)getRowValue(serial); } + + public String getSerial(String key) + { + return (String)getValue(serial,key); + } + + public String getIsresttimeopen() { return (String)getRowValue(isresttimeopen); } + + public String getIsresttimeopen(String key) + { + return (String)getValue(isresttimeopen,key); + } + + public String getWorktime() { return (String)getRowValue(worktime); } + + public String getWorktime(String key) + { + return (String)getValue(worktime,key); + } + + public String getPunchsetting() { + return (String) getRowValue(punchsetting); + } + + public String getPunchsetting(String key) { + return (String) getValue(punchsetting, key); + } + + public String getCardRemind() { + return (String) getRowValue(cardRemind); + } + + public String getCardRemind(String key) { + return (String) getValue(cardRemind,key); + } + + public String getCardRemOfSignIn() { + return (String) getRowValue(cardRemOfSignIn); + } + + public String getCardRemOfSignIn(String key) { + return (String) getValue(cardRemOfSignIn, key); + } + + public String getMinsBeforeSignIn() { + return (String) getRowValue(minsBeforeSignIn); + } + + public String getMinsBeforeSignIn(String key) { + return (String) getValue(minsBeforeSignIn, key); + } + + public String getCardRemOfSignOut() { + return (String) getRowValue(cardRemOfSignOut); + } + + public String getCardRemOfSignOut(String key) { + return (String) getValue(cardRemOfSignOut, key); + } + + public String getMinsAfterSignOut() { + return (String) getRowValue(minsAfterSignOut); + } + + public String getMinsAfterSignOut(String key) { + return (String) getValue(minsAfterSignOut, key); + } + + public String getRemindMode() { + return (String) getRowValue(remindMode); + } + + public String getRemindMode(String key) { + return (String) getValue(remindMode, key); + } + + public String getRemindOnPC() { + return (String) getRowValue(remindOnPC); + } + + public String getRemindOnPC(String key) { + return (String) getValue(remindOnPC, key); + } + + public String getRestShift() { + return (String) getRowValue(rest_shift); + } + + public String getRestShift(String key) { + return (String) getValue(rest_shift, key); + } + + private void getShiftInfoBean(String serialid, String isresttimeopen, String worktime, + String punchsettings, + ConcurrentHashMap serialMap, + String halfcalrule,String halfcalpoint,String halfcalpoint2cross, String restShift) throws Exception { + + Map workTimeMap = new HashMap<>(); + int workmins = 0; + List workTimes = Collections.synchronizedList(new ArrayList<>()); + List restTimes = Collections.synchronizedList(new ArrayList<>()); + KQShiftOnOffWorkSectionComInfo kqShiftOnOffWorkSectionComInfo = new KQShiftOnOffWorkSectionComInfo(); + KQShiftRestTimeSectionComInfo kqShiftRestTimeSectionComInfo = new KQShiftRestTimeSectionComInfo(); + + workTimes = kqShiftOnOffWorkSectionComInfo.getWorkSectionTimes(serialid); + if(workTimes != null && !workTimes.isEmpty()){ + if("1".equalsIgnoreCase(isresttimeopen)) { + //如果开启了才去判断 + restTimes = kqShiftRestTimeSectionComInfo.getRestSectionTimes(serialid); + } + if(NumberUtils.isNumber(worktime)){ + if(worktime.indexOf('.') == -1){ + workmins = Util.getIntValue(worktime,0); + }else { + worktime = worktime.substring(0,worktime.indexOf('.')); + workmins = Util.getIntValue(worktime,0); + } + + }else{ + workmins = 0; + kqLog.info("班次有问题,serialid:"+serialid+"工作时长为:"+worktime); + } + workTimeMap.put("workTime", workTimes); + workTimeMap.put("restTime", restTimes); + workTimeMap.put("serialid", serialid); + //工作时长分钟数 + workTimeMap.put("workmins", workmins+""); + workTimeMap.put("punchsettings", punchsettings); + workTimeMap.put("isresttimeopen", isresttimeopen); + workTimeMap.put("halfcalrule", halfcalrule); + workTimeMap.put("halfcalpoint", halfcalpoint); + workTimeMap.put("halfcalpoint2cross", halfcalpoint2cross); + workTimeMap.put("restShift", restShift.equals("1") ? "1" : "0"); + + ShiftInfoCominfoBean shiftInfoCominfoBean = setShiftInfoBean(workTimeMap); + serialMap.put(serialid, shiftInfoCominfoBean); + } + + } + + private ShiftInfoCominfoBean setShiftInfoBean(Map workTimeMap) throws Exception { + + ShiftComIndex workComIndex = new WorkShiftComIndex(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005306,weaver.general.ThreadVarLanguage.getLang())+"",workTimeMap); + ShiftComIndex restComIndex = new RestShiftComIndex(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005307,weaver.general.ThreadVarLanguage.getLang())+"",workTimeMap); + ShiftComIndex halfComIndex = new HalfShiftComIndex(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005308,weaver.general.ThreadVarLanguage.getLang())+"",workTimeMap); + //创建执行链 + //前一天的都执行完了,去获取当天工作时段,再执行半天的规则 + workComIndex.setDuration(restComIndex); + //执行完了半天的规则,再最后判断休息的时段 + restComIndex.setDuration(halfComIndex); + + ShiftInfoCominfoBean shiftInfoCominfoBean = new ShiftInfoCominfoBean(); + + workComIndex.handleDuration(shiftInfoCominfoBean); + return shiftInfoCominfoBean; + } + + /** + * 考勤按钮 + * @param workdate + * @param serialidInfo + * @param containYesterday + * @return + */ + public Map getWorkButton(String workdate,Map serialidInfo, boolean containYesterday){ + Map shiftMap = new HashMap<>(); + + //考勤按钮还是走缓存 + KQShiftManagementRedis kqShiftManagementRedis = new KQShiftManagementRedis(); + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if(serialidInfo != null && !serialidInfo.isEmpty()){ + LocalDate preLocalDate = LocalDate.parse(workdate); + String preSplitDate = ""; + preLocalDate = preLocalDate.minusDays(1); + preSplitDate = preLocalDate.format(dateFormatter); + String serialid = Util.null2String(serialidInfo.get(workdate)); + String preSerialid = Util.null2String(serialidInfo.get(preSplitDate)); + if(containYesterday){ + if(Util.getIntValue(preSerialid) > 0){ + ShiftInfoCominfoBean pre_shiftInfoCominfoBean = kqShiftManagementRedis.getShiftInfoBean(preSerialid); + List timelineList = pre_shiftInfoCominfoBean.getTimelineList(); + if(timelineList!=null && !timelineList.isEmpty()){ + shiftMap.put("pre_timelineList", timelineList); + } + shiftMap.put("pre_isAcross", pre_shiftInfoCominfoBean.getIsAcross()); + shiftMap.put("pre_allWorkTime", pre_shiftInfoCominfoBean.getAllWorkTime()); + shiftMap.put("pre_allAcrossWorkTime", pre_shiftInfoCominfoBean.getAllAcrossWorkTime()); + shiftMap.put("pre_signTime", pre_shiftInfoCominfoBean.getSignWorkTime()); + shiftMap.put("pre_restTime", pre_shiftInfoCominfoBean.getRestAcrossLongTime()); + } + } + if(Util.getIntValue(serialid) > 0){ + ShiftInfoCominfoBean cur_shiftInfoCominfoBean = kqShiftManagementRedis.getShiftInfoBean(serialid); + Map shiftRuleMap = ShiftManagementToolKit.getShiftRuleInfo(serialid,false); + List timelineList = cur_shiftInfoCominfoBean.getTimelineList(); + if(timelineList!=null && !timelineList.isEmpty()){ + shiftMap.put("timelineList", timelineList); + } + shiftMap.put("isAcross", cur_shiftInfoCominfoBean.getIsAcross()); + shiftMap.put("allWorkTime", cur_shiftInfoCominfoBean.getAllWorkTime()); + shiftMap.put("allAcrossWorkTime", cur_shiftInfoCominfoBean.getAllAcrossWorkTime()); + shiftMap.put("signTime", cur_shiftInfoCominfoBean.getSignWorkTime()); + shiftMap.put("restTime", cur_shiftInfoCominfoBean.getRestAcrossLongTime()); + if(shiftRuleMap != null && !shiftRuleMap.isEmpty()){ + shiftMap.put("shiftRuleMap", shiftRuleMap); + } + } + } + + return shiftMap; + } + + /** + * 流程计算用的 + * @param workdate + * @param serialidInfo + * @param containYesterday + * @return + * shiftInfoBean 每一天内含有的班次都拆分出来,包含昨天班次在今天的时段0-24小时制的 + * shiftLongInfoBean 当天的班次数据,0-48小时制度的 + */ + public Map getWorkDuration(String workdate,Map serialidInfo,boolean containYesterday){ + + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + Map dateWorkTimeMap = new HashMap<>(); + LocalDate preLocalDate = LocalDate.parse(workdate); + String preSplitDate = ""; + preLocalDate = preLocalDate.minusDays(1); + preSplitDate = preLocalDate.format(dateFormatter); + if(serialidInfo != null && !serialidInfo.isEmpty()){ + String preSerialid = Util.null2String(serialidInfo.get(preSplitDate)); + String serialid = Util.null2String(serialidInfo.get(workdate)); + ShiftInfoBean shiftInfoBean = new ShiftInfoBean(); + shiftInfoBean.setPreSplitDate(preSplitDate); + shiftInfoBean.setSplitDate(workdate); + shiftInfoBean.setD_Mins(0.0); + shiftInfoBean.setPreSerialid(preSerialid); + shiftInfoBean.setSerialid(serialid); + if(containYesterday){ + if(Util.getIntValue(serialid) > 0 || Util.getIntValue(preSerialid) > 0){ + fillShiftInfoBean(shiftInfoBean, preSerialid, serialid); + dateWorkTimeMap.put("shiftInfoBean", shiftInfoBean); + } + }else{ + if(Util.getIntValue(serialid) > 0){ + fillShiftInfoBean(shiftInfoBean, preSerialid, serialid); + dateWorkTimeMap.put("shiftInfoBean", shiftInfoBean); + } + } + } + + return dateWorkTimeMap; + } + + /** + * 根据班次id获取对应日期的上下班时间+休息时间 + * @param workdate + * @param serialidInfo + * @return + */ + public Map getWorkTimeMap(String workdate,Map serialidInfo){ + + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + Map dateWorkTimeMap = new HashMap<>(); + LocalDate preLocalDate = LocalDate.parse(workdate); + String preSplitDate = ""; + preLocalDate = preLocalDate.minusDays(1); + preSplitDate = preLocalDate.format(dateFormatter); + if(serialidInfo != null && !serialidInfo.isEmpty()){ + String preSerialid = Util.null2String(serialidInfo.get(preSplitDate)); + String serialid = Util.null2String(serialidInfo.get(workdate)); + getShiftInfoBeanMap(dateWorkTimeMap,preSerialid, serialid); + } + + return dateWorkTimeMap; + } + + /** + * 根据考勤报表需要的 返回相应格式的数据 + * @param dateWorkTimeMap + * @param preSerialid + * @param serialid + */ + private void getShiftInfoBeanMap(Map dateWorkTimeMap,String preSerialid, String serialid) { + ShiftInfoCominfoBean cur_shiftInfoCominfoBean = getShiftInfoCominfoBean(serialid); + + if(cur_shiftInfoCominfoBean != null){ + dateWorkTimeMap.put("restTime",cur_shiftInfoCominfoBean.getRestAcrossLongTime()); + dateWorkTimeMap.put("workTime",cur_shiftInfoCominfoBean.getWorkAcrossLongTime()); + dateWorkTimeMap.put("workMins",cur_shiftInfoCominfoBean.getWorkmins()); + dateWorkTimeMap.put("isAcross",cur_shiftInfoCominfoBean.getIsAcross()); + dateWorkTimeMap.put("signTime", cur_shiftInfoCominfoBean.getSignWorkTime()); + } + } + + /** + * 每次获取的话都需要获取昨天和今天的班次数据 + * @param shiftInfoBean + * @param preSerialid 昨天的班次 + * @param serialid 今天的班次 + */ + private void fillShiftInfoBean(ShiftInfoBean shiftInfoBean,String preSerialid,String serialid){ + ShiftInfoCominfoBean pre_shiftInfoCominfoBean = getShiftInfoCominfoBean(preSerialid); + ShiftInfoCominfoBean cur_shiftInfoCominfoBean = getShiftInfoCominfoBean(serialid); + Map pre_shiftRuleMap = ShiftManagementToolKit.getShiftRuleInfo(preSerialid,false); + Map shiftRuleMap = ShiftManagementToolKit.getShiftRuleInfo(serialid,false); + + //把前一个班次的填充好 + if(pre_shiftInfoCominfoBean != null){ + shiftInfoBean.setPreWorkIndex(pre_shiftInfoCominfoBean.getPreWorkTimeIndex()); + shiftInfoBean.setPreWorkAcrossIndex(pre_shiftInfoCominfoBean.getWorkAcrossTimeIndex()); + shiftInfoBean.setPreWorkMinsAcrossIndex(pre_shiftInfoCominfoBean.getWorkPunchMins()); + shiftInfoBean.setPreRestIndex(pre_shiftInfoCominfoBean.getPreRestTimeIndex()); + shiftInfoBean.setPreHalfWorkIndex(pre_shiftInfoCominfoBean.getHalfWorkIndex()); + shiftInfoBean.setPreWorkmins(pre_shiftInfoCominfoBean.getWorkmins()); + shiftInfoBean.setPreAllWorkTime(pre_shiftInfoCominfoBean.getAllWorkTime()); + shiftInfoBean.setPreAllAcrossWorkTime(pre_shiftInfoCominfoBean.getAllAcrossWorkTime()); + shiftInfoBean.setPreAllRestTime(pre_shiftInfoCominfoBean.getAllRestTime()); + shiftInfoBean.setPreAllAcrossRestTime(pre_shiftInfoCominfoBean.getAllAcrossRestTime()); + shiftInfoBean.setPreSerialid(preSerialid); + shiftInfoBean.setIsPreAcross(pre_shiftInfoCominfoBean.getIsAcross()); + shiftInfoBean.setShiftRuleMap(pre_shiftRuleMap); + } + + //把当前班次的填充好 + if(cur_shiftInfoCominfoBean != null){ + shiftInfoBean.setWorkIndex(cur_shiftInfoCominfoBean.getWorkTimeIndex()); + shiftInfoBean.setWorkAcrossIndex(cur_shiftInfoCominfoBean.getWorkAcrossTimeIndex()); + shiftInfoBean.setWorkMinsAcrossIndex(cur_shiftInfoCominfoBean.getWorkPunchMins()); + shiftInfoBean.setRestIndex(cur_shiftInfoCominfoBean.getRestTimeIndex()); + shiftInfoBean.setHalfWorkIndex(cur_shiftInfoCominfoBean.getHalfWorkIndex()); + shiftInfoBean.setWorkmins(cur_shiftInfoCominfoBean.getWorkmins()); + shiftInfoBean.setAllWorkTime(cur_shiftInfoCominfoBean.getAllWorkTime()); + shiftInfoBean.setAllAcrossWorkTime(cur_shiftInfoCominfoBean.getAllAcrossWorkTime()); + shiftInfoBean.setAllRestTime(cur_shiftInfoCominfoBean.getAllRestTime()); + shiftInfoBean.setAllAcrossRestTime(cur_shiftInfoCominfoBean.getAllAcrossRestTime()); + shiftInfoBean.setAllLongWorkTime(cur_shiftInfoCominfoBean.getAllLongWorkTime()); + shiftInfoBean.setRestLongTimeIndex(cur_shiftInfoCominfoBean.getRestLongTimeIndex()); + shiftInfoBean.setWorkLongTimeIndex(cur_shiftInfoCominfoBean.getWorkLongTimeIndex()); + shiftInfoBean.setIsAcross(cur_shiftInfoCominfoBean.getIsAcross()); + shiftInfoBean.setSerialid(serialid); + shiftInfoBean.setShiftRuleMap(shiftRuleMap); + + if(cur_shiftInfoCominfoBean.getWorkAcrossLongTime() != null){ + List workTime1 = cur_shiftInfoCominfoBean.getWorkAcrossLongTime().stream().collect(Collectors.toList()); + List lsWorkTime = new KQWorkTime().formatTimeScope(workTime1, false); + shiftInfoBean.setWorkTime(lsWorkTime); + } + if(cur_shiftInfoCominfoBean.getSignWorkTime() != null){ + List signTime1 = cur_shiftInfoCominfoBean.getSignWorkTime().stream().collect(Collectors.toList()); + List lsSignTime = new KQWorkTime().formatTimeScope(signTime1, true); + shiftInfoBean.setSignTime(lsSignTime); + } + shiftInfoBean.setHalfcalrule(cur_shiftInfoCominfoBean.getHalfcalrule()); + shiftInfoBean.setHalfcalpoint(cur_shiftInfoCominfoBean.getHalfcalpoint()); + shiftInfoBean.setHalfcalpoint2cross(cur_shiftInfoCominfoBean.getHalfcalpoint2cross()); + shiftInfoBean.setWorkAcrossTime(cur_shiftInfoCominfoBean.getWorkAcrossTime()); + shiftInfoBean.setEachWorkMins(cur_shiftInfoCominfoBean.getEachWorkMins()); + } + } + + public void removeShiftManagementCache(){ + KQShiftRestTimeSectionComInfo kqShiftRestTimeSectionComInfo = new KQShiftRestTimeSectionComInfo(); + KQShiftOnOffWorkSectionComInfo kqShiftOnOffWorkSectionComInfo = new KQShiftOnOffWorkSectionComInfo(); + kqShiftRestTimeSectionComInfo.removeShiftRestTimeSectionCache(); + kqShiftOnOffWorkSectionComInfo.removeShiftWorkSectionCache(); + super.removeCache(); + //改用redis和staticobj的方式 + KQShiftManagementRedis kqShiftManagementRedis = new KQShiftManagementRedis(); + kqShiftManagementRedis.resetShiftValWithRedis(); + } + + /** + * 根据班次获取shiftInfoCominfoBean + * @param serialid + * @return + */ + public ShiftInfoCominfoBean getShiftInfoCominfoBean(String serialid){ +// Object object = getObjValue(shiftbean, serialid); +// if(object != null){ +// return (ShiftInfoCominfoBean) object; +// }else{ +// return null; +// } + //改用redis和staticobj的方式 + KQShiftManagementRedis kqShiftManagementRedis = new KQShiftManagementRedis(); + return kqShiftManagementRedis.getShiftInfoBeanMapBySql(serialid); + } + + /** + * 根据人员和日期获取shiftInfoCominfoBean + * @param workdate + * @param serialidInfo + * @return + */ + public ShiftInfoCominfoBean getShiftInfoCominfoBean(String workdate,Map serialidInfo){ + ShiftInfoCominfoBean shiftInfoCominfoBean = null; + if(serialidInfo != null && !serialidInfo.isEmpty()){ + String serialid = Util.null2String(serialidInfo.get(workdate)); + if(Util.getIntValue(serialid) > 0){ + shiftInfoCominfoBean = getShiftInfoCominfoBean(serialid); + } + } + return shiftInfoCominfoBean; + } + +} diff --git a/src/com/engine/kq/biz/KQShiftManagementRedis.java b/src/com/engine/kq/biz/KQShiftManagementRedis.java new file mode 100644 index 0000000..5f8916c --- /dev/null +++ b/src/com/engine/kq/biz/KQShiftManagementRedis.java @@ -0,0 +1,299 @@ +package com.engine.kq.biz; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.cloudstore.dev.api.util.Util_DataCache; +import com.engine.kq.biz.chain.cominfo.HalfShiftComIndex; +import com.engine.kq.biz.chain.cominfo.RestShiftComIndex; +import com.engine.kq.biz.chain.cominfo.ShiftComIndex; +import com.engine.kq.biz.chain.cominfo.ShiftInfoCominfoBean; +import com.engine.kq.biz.chain.cominfo.WorkShiftComIndex; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.cmd.shiftmanagement.toolkit.ShiftManagementToolKit; +import com.engine.kq.entity.TimeScopeEntity; +import com.engine.kq.log.KQLog; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StringWriter; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import org.apache.commons.lang.math.NumberUtils; +import weaver.cache.CacheBase; +import weaver.cache.CacheColumn; +import weaver.cache.CacheColumnType; +import weaver.cache.CacheItem; +import weaver.cache.CacheMap; +import weaver.cache.PKColumn; +import weaver.cluster.CacheManager; +import weaver.cluster.CacheMessage; +import weaver.conn.RecordSet; +import weaver.email.MailReciveStatusUtils; +import weaver.email.domain.AccountStautsBean; +import weaver.general.BaseBean; +import weaver.general.StaticObj; +import weaver.general.Util; + +/** + * 班次管理缓存类 改成用redis的 + */ +public class KQShiftManagementRedis { + public static final String KQ_SHIFT_COMINFO_STATUS = "KQ_SHIFT_COMINFO_STATUS"; + + private static final BaseBean baseBean = new BaseBean(); + + /** + * 是否是E9 radis缓存方案。false:未启用radis。true:使用radis。 + */ + public static boolean isNewSession = false; + + /** + * 非集群,单节点服务器部署时,账号接收状态量获取方法。(线程安全的) + */ + public static ConcurrentHashMap KQ_SHIFT_COMINFO_STATUS_MAP = new ConcurrentHashMap(); + + // 初始化执行 + static { + useNewSessionMode(); + } + + /** + * 判断是否开启redis缓存。 + */ + public static void useNewSessionMode() { + String status = Util.null2String(baseBean.getPropValue("weaver_new_session", "status")).trim(); + isNewSession = "1".equals(status); + } + + private KQLog kqLog = new KQLog(); + + public void getShiftInfoBean(String serialid, String isresttimeopen, String worktime, + String punchsettings, + ConcurrentHashMap shiftInfoBeanMap, + String halfcalrule,String halfcalpoint,String halfcalpoint2cross) throws Exception { + getShiftInfoBean(serialid, isresttimeopen, worktime, punchsettings, shiftInfoBeanMap, halfcalrule, halfcalpoint, halfcalpoint2cross, "0"); + } + + public void getShiftInfoBean(String serialid, String isresttimeopen, String worktime, + String punchsettings, + ConcurrentHashMap shiftInfoBeanMap, + String halfcalrule,String halfcalpoint,String halfcalpoint2cross, String restShift) throws Exception { + + Map workTimeMap = new HashMap<>(); + int workmins = 0; + List workTimes = Collections.synchronizedList(new ArrayList<>()); + List restTimes = Collections.synchronizedList(new ArrayList<>()); + KQShiftOnOffWorkSectionComInfo kqShiftOnOffWorkSectionComInfo = new KQShiftOnOffWorkSectionComInfo(); + KQShiftRestTimeSectionComInfo kqShiftRestTimeSectionComInfo = new KQShiftRestTimeSectionComInfo(); + + workTimes = kqShiftOnOffWorkSectionComInfo.getWorkSectionTimes(serialid); + if(workTimes != null && !workTimes.isEmpty()){ + if("1".equalsIgnoreCase(isresttimeopen)) { + //如果开启了才去判断 + restTimes = kqShiftRestTimeSectionComInfo.getRestSectionTimes(serialid); + } + if(NumberUtils.isNumber(worktime)){ + if(worktime.indexOf('.') == -1){ + workmins = Util.getIntValue(worktime,0); + }else { + worktime = worktime.substring(0,worktime.indexOf('.')); + workmins = Util.getIntValue(worktime,0); + } + + }else{ + workmins = 0; + kqLog.info("班次有问题,serialid:"+serialid+"工作时长为:"+worktime); + } + workTimeMap.put("workTime", workTimes); + workTimeMap.put("restTime", restTimes); + workTimeMap.put("serialid", serialid); + //工作时长分钟数 + workTimeMap.put("workmins", workmins+""); + workTimeMap.put("punchsettings", punchsettings); + workTimeMap.put("isresttimeopen", isresttimeopen); + workTimeMap.put("halfcalrule", halfcalrule); + workTimeMap.put("halfcalpoint", halfcalpoint); + workTimeMap.put("halfcalpoint2cross", halfcalpoint2cross); + workTimeMap.put("restShift", restShift.equals("1") ? "1" : "0"); + + ShiftInfoCominfoBean shiftInfoCominfoBean = setShiftInfoBean(workTimeMap); + shiftInfoBeanMap.put(serialid, shiftInfoCominfoBean); + } + + } + + public ShiftInfoCominfoBean setShiftInfoBean(Map workTimeMap) throws Exception { + + ShiftComIndex workComIndex = new WorkShiftComIndex(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005306,weaver.general.ThreadVarLanguage.getLang())+"",workTimeMap); + ShiftComIndex restComIndex = new RestShiftComIndex(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005307,weaver.general.ThreadVarLanguage.getLang())+"",workTimeMap); + ShiftComIndex halfComIndex = new HalfShiftComIndex(""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005308,weaver.general.ThreadVarLanguage.getLang())+"",workTimeMap); + //创建执行链 + //前一天的都执行完了,去获取当天工作时段,再执行半天的规则 + workComIndex.setDuration(restComIndex); + //执行完了半天的规则,再最后判断休息的时段 + restComIndex.setDuration(halfComIndex); + + ShiftInfoCominfoBean shiftInfoCominfoBean = new ShiftInfoCominfoBean(); + + workComIndex.handleDuration(shiftInfoCominfoBean); + return shiftInfoCominfoBean; + } + + public ConcurrentHashMap getShiftInfoBeanMap() { + ConcurrentHashMap shiftInfoBeanMap = new ConcurrentHashMap<>(); + kqLog = new KQLog(); + try { + + RecordSet rs = new RecordSet(); + String getShiftInfo = "select * from kq_ShiftManagement where 1=1 order by id "; + rs.executeQuery(getShiftInfo); + while(rs.next()){ + String serialid = rs.getString("id"); + try { + String isresttimeopen = rs.getString("isresttimeopen"); + String worktime = rs.getString("worktime"); + String punchsetting = "1"; + String halfcalrule = rs.getString("halfcalrule"); + halfcalrule = Util.null2String(halfcalrule).length() == 0 ? "0" : halfcalrule; + String halfcalpoint = rs.getString("halfcalpoint"); + String halfcalpoint2cross = rs.getString("halfcalpoint2cross"); + String restShift = rs.getString("rest_shift"); + getShiftInfoBean(serialid,isresttimeopen,worktime,punchsetting,shiftInfoBeanMap,halfcalrule,halfcalpoint,halfcalpoint2cross,restShift); + } catch (Exception e) { + kqLog.info("班次缓存报错:getShiftInfoBeanMap:serialid:"+serialid); + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + } + } + + } catch (Exception e) { + kqLog.info("班次缓存报错:getShiftInfoBeanMap:"); + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + } + return shiftInfoBeanMap; + } + + + public ShiftInfoCominfoBean getShiftInfoBeanMapBySql(String serialid) { + ConcurrentHashMap shiftInfoBeanMap = new ConcurrentHashMap<>(); + kqLog = new KQLog(); + try { + RecordSet rs = new RecordSet(); + String getShiftInfo = "select * from kq_ShiftManagement where 1=1 and id=? order by id "; + rs.executeQuery(getShiftInfo,serialid); + if(rs.next()){ + String isresttimeopen = rs.getString("isresttimeopen"); + String worktime = rs.getString("worktime"); + String punchsetting = "1"; + String halfcalrule = rs.getString("halfcalrule"); + halfcalrule = Util.null2String(halfcalrule).length() == 0 ? "0" : halfcalrule; + String halfcalpoint = rs.getString("halfcalpoint"); + String halfcalpoint2cross = rs.getString("halfcalpoint2cross"); + String restShift = rs.getString("rest_shift"); + getShiftInfoBean(serialid,isresttimeopen,worktime,punchsetting,shiftInfoBeanMap,halfcalrule,halfcalpoint,halfcalpoint2cross,restShift); + } + if(shiftInfoBeanMap.containsKey(serialid)){ + return shiftInfoBeanMap.get(serialid); + } + + } catch (Exception e) { + kqLog.info("班次缓存报错:getShiftInfoBeanMapBySql:"); + StringWriter errorsWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(errorsWriter)); + kqLog.info(errorsWriter.toString()); + } + return null; + } + + /** + * 三套缓存,redis staticobj 和当前本身自制的map + * 把缓存数据重置下 + */ + public void resetShiftValWithRedis(){ + boolean isCluster = StaticObj.getInstance().isCluster(); + Map shiftInfoBeanMap = getShiftInfoBeanMap(); + if(isCluster) { + if(isNewSession) { + try { + Util_DataCache.setObjValWithRedis(KQ_SHIFT_COMINFO_STATUS, shiftInfoBeanMap); + } catch (IOException e) { + baseBean.writeLog(e); + StaticObj staticObj = StaticObj.getInstance(); + staticObj.putObject(KQ_SHIFT_COMINFO_STATUS, shiftInfoBeanMap); + sendNotificationToCache(CacheManager.ACTION_UPDATE, KQ_SHIFT_COMINFO_STATUS); + } + }else{ + StaticObj staticObj = StaticObj.getInstance(); + staticObj.putObject(KQ_SHIFT_COMINFO_STATUS, shiftInfoBeanMap); + sendNotificationToCache(CacheManager.ACTION_UPDATE, KQ_SHIFT_COMINFO_STATUS); + } + } else { + KQ_SHIFT_COMINFO_STATUS_MAP.put(KQ_SHIFT_COMINFO_STATUS, shiftInfoBeanMap); + } + } + + public ShiftInfoCominfoBean getShiftInfoBean(String serialid){ + ShiftInfoCominfoBean shiftInfoCominfoBean = null; + Map shiftInfoBeanMap = getShiftBeanMapValWithRedis(); + if(shiftInfoBeanMap == null){ + resetShiftValWithRedis(); + shiftInfoBeanMap = getShiftBeanMapValWithRedis(); + } + if(shiftInfoBeanMap != null && shiftInfoBeanMap.containsKey(serialid)){ + shiftInfoCominfoBean = shiftInfoBeanMap.get(serialid); + } + return shiftInfoCominfoBean; + } + + public Map getShiftBeanMapValWithRedis() { + Map shiftInfoBeanMap = null; + boolean isCluster = StaticObj.getInstance().isCluster(); + + if(isCluster) { // 判断是否是集群环境。true 是集群,false非集群 + if(isNewSession){ + try { + if(Util_DataCache.containsKeyWithRedis(KQ_SHIFT_COMINFO_STATUS)) { + shiftInfoBeanMap = (Map) Util_DataCache.getObjValWithRedis(KQ_SHIFT_COMINFO_STATUS); + } + }catch (Exception e){ + StaticObj staticObj = StaticObj.getInstance(); + shiftInfoBeanMap = (Map) staticObj.getObject(KQ_SHIFT_COMINFO_STATUS); + } + }else{ + StaticObj staticObj = StaticObj.getInstance(); + shiftInfoBeanMap = (Map) staticObj.getObject(KQ_SHIFT_COMINFO_STATUS); + } + } else { + shiftInfoBeanMap = (Map) KQ_SHIFT_COMINFO_STATUS_MAP.get(KQ_SHIFT_COMINFO_STATUS); + } + return shiftInfoBeanMap; + } + + /** + * 通知其他集群环境其他节点进行更新等操作. + * @param optType + * @param cacheKey + */ + public static void sendNotificationToCache(String optType, String cacheKey) { + StaticObj staticObj = StaticObj.getInstance(); + if(staticObj.isCluster()) { + CacheMessage msg = new CacheMessage(); + msg.setAction(optType); + msg.setCacheType(cacheKey); + staticObj.sendNotification(msg); + } + } +} diff --git a/src/com/engine/kq/biz/KQWorkTime.java b/src/com/engine/kq/biz/KQWorkTime.java new file mode 100644 index 0000000..88c18da --- /dev/null +++ b/src/com/engine/kq/biz/KQWorkTime.java @@ -0,0 +1,418 @@ +package com.engine.kq.biz; + +import com.alibaba.fastjson.JSON; +import com.engine.kq.biz.chain.cominfo.ShiftInfoCominfoBean; +import com.engine.kq.cmd.shiftmanagement.toolkit.ShiftManagementToolKit; +import com.engine.kq.entity.KQGroupEntity; +import com.engine.kq.entity.TimeScopeEntity; +import com.engine.kq.entity.TimeSignScopeEntity; +import com.engine.kq.entity.WorkTimeEntity; +import com.engine.kq.log.KQLog; +import weaver.common.DateUtil; +import weaver.common.StringUtil; +import weaver.conn.RecordSet; +import weaver.general.BaseBean; +import weaver.general.Util; +import weaver.hrm.resource.ResourceComInfo; + +import java.util.*; + +public class KQWorkTime extends BaseBean { + private KQLog kqLog = new KQLog(); + private boolean isFormat = false; + + public WorkTimeEntity getWorkTime(String userId) { + return getWorkTime(userId, null); + } + + /** + * 判断是否是工作日 + * @param userId + * @param workdate + * @return + */ + public boolean isWorkDay(String userId, String workdate) { + boolean isWorkDay = false; + if(!KQHolidaySetBiz.isHoliday(userId,workdate)) {//不是节假日,且有班次 + Map serialInfo = getSerialInfo( userId, workdate, false); + if(!serialInfo.isEmpty()){ + if(Util.null2String(serialInfo.get("kqType")).equals("3")){ + Map result = (Map) serialInfo.get(workdate); + if(result!=null && result.size()>0 && Util.null2String(result.get("signStart")).length()>0 && Util.null2String(result.get("workMins")).length()>0){ + isWorkDay = true; + } + }else{ + int serialid = Util.getIntValue(Util.null2String(serialInfo.get(workdate)), 0); + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(serialid)), 0); + isWorkDay = restShift == 1 ? false : serialid > 0; + } + } + } + return isWorkDay; + } + + public Map getWorkButton(String userId, String workdate, boolean containYesterday) { + Map result = new HashMap<>(); + try { + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + Map serialInfo = getSerialInfo(userId, workdate, containYesterday, true); + kqLog.info("考勤组获取成员所在的班次 getWorkButton:serialInfo:"+ serialInfo); + String kqType = Util.null2String(serialInfo.get("kqType")); + if(serialInfo!=null&&serialInfo.size()>0){ + if("3".equalsIgnoreCase(kqType)){ + //自由班制的单独处理 + result = (Map) serialInfo.get(workdate); + if(result != null && !result.isEmpty()){ + result.put("isfree", "1"); + }else{ + result = new HashMap<>(); + } + }else{ + result = kQShiftManagementComInfo.getWorkButton(workdate,serialInfo,containYesterday); + kqLog.info("考勤组获取成员所在的班次 getWorkButton:result:"+ JSON.toJSONString(result)); + } + } + } catch (Exception e) { + writeLog(e); + } + return result; + } + + /** + * + * 获取今天所含班次的考勤时间(包含今天和昨天的) + * @param userId + * @param workdate + * @param containYesterday + * @param isLog 是否记录日志 + * @return + */ + public Map getWorkDuration(String userId, String workdate,boolean containYesterday,boolean isLog) { + Map result = new HashMap<>(); + try { + Map workTimeMap = null; + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + Map serialInfo = getSerialInfo(userId, workdate, true); + if(isLog){ + kqLog.info("考勤组获取成员所在的班次 getWorkDuration:"+serialInfo); + } + if(serialInfo!=null&&serialInfo.size()>0){ + String kqType = Util.null2String(serialInfo.get("kqType")); + if("3".equalsIgnoreCase(kqType)){ + //自由班制的单独处理 + result = (Map) serialInfo.get(workdate); + if(result != null && !result.isEmpty()){ + result.put("isfree", "1"); + }else{ + result = new HashMap<>(); + } + }else{ + workTimeMap = kQShiftManagementComInfo.getWorkDuration(workdate,serialInfo,containYesterday); + if(workTimeMap!=null){ + if(isLog) { + kqLog.info( + "考勤组获取成员所在的班次 getWorkDuration:workTimeMap:" + JSON.toJSONString(workTimeMap)); + } + result.put("shiftInfoBean",workTimeMap.get("shiftInfoBean")); + } + } + } + } catch (Exception e) { + writeLog(e); + } + return result; + } + + /** + * 获取今天所含班次的考勤时间(包含今天和昨天的) + * @param userId + * @param workdate + * @param containYesterday + * @return + */ + public Map getWorkDuration(String userId, String workdate,boolean containYesterday) { + return getWorkDuration(userId,workdate,containYesterday,true); + } + + /** + * 获取今天所含班次的考勤时间(今天的) + * @param userId + * @param workdate + * @return + */ + public ShiftInfoCominfoBean getShiftInfoCominfoBean(String userId, String workdate) { + ShiftInfoCominfoBean shiftInfoCominfoBean = null; + try { + Map workTimeMap = null; + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + Map serialInfo = getSerialInfo(userId, workdate, false); + + if(serialInfo!=null&&serialInfo.size()>0){ + shiftInfoCominfoBean = kQShiftManagementComInfo.getShiftInfoCominfoBean(workdate,serialInfo); + } + } catch (Exception e) { + writeLog(e); + } + return shiftInfoCominfoBean; + } + + /** + * 获取考勤时间 + * @param userId + * @param workdate + * @return + */ + public WorkTimeEntity getWorkTime(String userId, String workdate) { + WorkTimeEntity workTimeEntity = new WorkTimeEntity(); + try { + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + ShiftManagementToolKit shiftManagementToolKit = new ShiftManagementToolKit(); + Map serialInfo = getSerialInfo(userId, workdate, false, true); + workTimeEntity.setIsExclude(Util.null2String(serialInfo.get("isExclude")).equals("1")); + workTimeEntity.setGroupId(Util.null2String(serialInfo.get("groupId"))); + if(serialInfo!=null&&serialInfo.size()>0) { + String kqType = Util.null2String(serialInfo.get("kqType")); + if(kqType.equals("3")){ + Map map = (Map)serialInfo.get(workdate); + workTimeEntity.setGroupId(Util.null2String(serialInfo.get("groupId"))); + workTimeEntity.setGroupName(Util.null2String(serialInfo.get("groupName"))); + workTimeEntity.setKQType(Util.null2String(kqType)); + workTimeEntity.setIsExclude(Util.null2String(serialInfo.get("isExclude")).equals("1")); + if(map!=null) { + workTimeEntity.setSignStart(Util.null2String(map.get("signStart"))); + workTimeEntity.setWorkMins(Util.getIntValue(Util.null2String(map.get("workMins")))); + workTimeEntity.setCalmethod(Util.null2String(map.get("calmethod"))); + } + workTimeEntity.setRestShift(0); + }else{ + int serialid = Util.getIntValue(Util.null2String(serialInfo.get(workdate)), 0); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(serialid)), 0); + if(kqType.equals("1") && KQHolidaySetBiz.isHoliday(userId,workdate)) restShift = 1; + workTimeEntity.setRestShift(restShift); + if (serialid > 0){ + Map dateWorkTimeMap = kQShiftManagementComInfo.getWorkTimeMap(workdate, serialInfo); + workTimeEntity.setGroupId(Util.null2String(serialInfo.get("groupId"))); + workTimeEntity.setGroupName(Util.null2String(serialInfo.get("groupName"))); + workTimeEntity.setKQType(kqType); + workTimeEntity.setSerialId(""+serialid); + workTimeEntity.setRestTime(formatTimeScope((List)dateWorkTimeMap.get("restTime"),false)); + workTimeEntity.setShiftRuleInfo(ShiftManagementToolKit.getShiftRuleInfo(""+serialid,true)); + workTimeEntity.setSignTime(formatTimeScope((List)dateWorkTimeMap.get("signTime"),false)); + workTimeEntity.setWorkTime(formatTimeScope((List)dateWorkTimeMap.get("workTime"),true)); + if(restShift != 1) { + workTimeEntity.setWorkMins(Util.getIntValue(Util.null2String(dateWorkTimeMap.get("workMins")))); + } + workTimeEntity.setIsAcross(Util.null2String(dateWorkTimeMap.get("isAcross"))); + } + } + } + } catch (Exception e) { + writeLog(e); + } + return workTimeEntity; + } + + public List formatTimeScope(List timeScope, boolean needWorkMins){ + List timeScopes = new ArrayList<>(); + KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo(); + TimeScopeEntity timeScopeEntity = null; + for(int i=0;timeScope!=null && i obj = (Map)timeScope.get(i); + String bengintime_end = Util.null2String(obj.get("bengintime_end")); + String bengintime_end_across = Util.null2String(obj.get("bengintime_end_across")); + String endtime_start = Util.null2String(obj.get("endtime_start")); + String endtime_start_across = Util.null2String(obj.get("endtime_start_across")); + String bengintime_pre_across = Util.null2String(obj.get("bengintime_pre_across")); + timeScopeEntity = new TimeScopeEntity(); + timeScopeEntity.setBeginTime(Util.null2String(obj.get("bengintime"))); + timeScopeEntity.setBeginTimeAcross(Util.null2String(obj.get("bengintime_across")).equals("1"));//标记是否跨天 + timeScopeEntity.setEndTime(Util.null2String(obj.get("endtime"))); + timeScopeEntity.setEndTimeAcross(Util.null2String(obj.get("endtime_across")).equals("1"));//标记是否跨天 + timeScopeEntity.setBeginTimePreAcross("1".equalsIgnoreCase(bengintime_pre_across)); + + if(needWorkMins) { + int workBeginIdx = kqTimesArrayComInfo.getArrayindexByTimes(timeScopeEntity.getBeginTime()); + int workEndIdx = kqTimesArrayComInfo.getArrayindexByTimes(timeScopeEntity.getEndTime()); + timeScopeEntity.setWorkMins(workEndIdx - workBeginIdx); + } + if((bengintime_end != null && bengintime_end.length() >0) || (endtime_start != null && endtime_start.length() > 0)){ + TimeSignScopeEntity timeSignScopeEntity = new TimeSignScopeEntity(); + timeSignScopeEntity.setBeginTimeEnd(bengintime_end); + timeSignScopeEntity.setBeginTimeEndAcross("1".equalsIgnoreCase(bengintime_end_across)); + timeSignScopeEntity.setEndTimeStart(endtime_start); + timeSignScopeEntity.setEndTimeStartAcross("1".equalsIgnoreCase(endtime_start_across)); + timeSignScopeEntity.setBeginTimePreAcross("1".equalsIgnoreCase(bengintime_pre_across)); + timeScopeEntity.setTimeSignScopeEntity(timeSignScopeEntity); + } + timeScopes.add(timeScopeEntity); + } + return timeScopes; + } + + /** + * 获取当天班次 + * @param userId + * @param workdate + * @return + */ + public String getSerialIds(String userId, String workdate) { + Map serialInfo = getSerialInfo( userId, workdate, false); + return serialInfo!=null?Util.null2String(serialInfo.get(workdate)):""; + } + + /** + * 获取班次信息 获取顺序 工作日调整、排班、固定班和周期班 + * @param userId + * @param workdate + * @param containYesterday + * @return + */ + public Map getSerialInfo(String userId, String workdate, boolean containYesterday) { + return getSerialInfo(userId, workdate, containYesterday, false); + } + + public Map getSerialInfo(String userId, String workdate, boolean containYesterday, boolean includeHoliday) { + Map serialInfo = new HashMap<>(); + String preworkdate = ""; + try { + KQGroupMemberComInfo groupMemberComInfo = new KQGroupMemberComInfo(); + groupMemberComInfo.setIsFormat(this.isFormat); + KQFixedSchedulceComInfo kqFixedSchedulceComInfo = new KQFixedSchedulceComInfo(); + kqFixedSchedulceComInfo.setFormat(this.isFormat); + KQShiftScheduleComInfo kqShiftScheduleComInfo = new KQShiftScheduleComInfo(); + kqShiftScheduleComInfo.setFormat(this.isFormat); + KQGroupEntity kqGroupEntity = groupMemberComInfo.getUserKQGroupInfo(userId,workdate); + ResourceComInfo resourceComInfo = new ResourceComInfo(); + + preworkdate = DateUtil.addDate(workdate,-1); + if(containYesterday){ + Map pre_serialInfo = getSerialInfo(userId, preworkdate, false, includeHoliday); + if(pre_serialInfo != null && !pre_serialInfo.isEmpty()){ + if(pre_serialInfo.containsKey(preworkdate)){ + serialInfo.put(preworkdate,pre_serialInfo.get(preworkdate));//获取前一天的班次 + } + } + } + + if(kqGroupEntity==null){//不在考勤组内 + return serialInfo; + } + + + //无需考勤人员需要计算考勤时间,但不计算异常状态 +// if (("," + kqGroupEntity.getExcludeid() + ",").indexOf("," + userId + ",")>-1) {//排除人员无需计算考勤时间 +// return serialInfo; +// } + + if (("," + kqGroupEntity.getExcludeid() + ",").indexOf("," + userId + ",")>-1) {//排除人员无需计算考勤时间 + serialInfo.put("isExclude","1"); + } + + String begindate = Util.null2String(resourceComInfo.getCreatedate(userId)).trim(); + String companyStartDate = Util.null2String(resourceComInfo.getCompanyStartDate(userId)).trim(); + if(companyStartDate.length()!=10){ + companyStartDate = ""; + } + if(companyStartDate.length()>0 && companyStartDate.indexOf("-")>0){ + begindate=companyStartDate; + } + if(begindate.length()>0 && DateUtil.compDate(begindate,workdate)<0 ){//人员入职日期前无需计算考勤,如果没有入职日期,已创建日期为准 +// kqLog.writeLog("getSerialInfo 入职日期不满足条件:userId:"+userId+":workdate:"+workdate+":companyStartDate:"+companyStartDate+":begindate:"+begindate+":DateUtil.compDate(begindate,workdate):"+DateUtil.compDate(begindate,workdate)); + return serialInfo; + } + + String endDate = Util.null2String(resourceComInfo.getEndDate(userId)); + + String status = Util.null2String(resourceComInfo.getStatus(userId)); + if(status.equals("0")||status.equals("1")||status.equals("2")||status.equals("3")){ + //在职 + }else{ + //其他状态 + if(endDate.length()>0 && DateUtil.compDate(endDate,workdate)>0){//人员合同结束日期无需计算考勤 +// kqLog.writeLog("getSerialInfo 人员合同结束日期不满足条件:userId:"+userId+":workdate:"+workdate+":endDate:"+endDate+":status:"+status+":DateUtil.compDate(endDate,workdate):"+DateUtil.compDate(endDate,workdate)); + return serialInfo; + } + } + + String groupid = kqGroupEntity.getId(); + String groupname = kqGroupEntity.getGroupname(); + String kqtype = kqGroupEntity.getKqtype(); + int dayOfweek = DateUtil.getWeek(workdate)-1; + int preDayOfweek = DateUtil.getWeek(preworkdate)-1; + boolean preDayIsHoliday = KQHolidaySetBiz.isHoliday(userId,preworkdate); + boolean isHoliday = KQHolidaySetBiz.isHoliday(userId,workdate); + String serialid = ""; + + if(!kqtype.equals("2")){//处理调配工作日(除排班外) + if(KQHolidaySetBiz.getChangeType(groupid,preworkdate)==2){ + preDayOfweek = KQHolidaySetBiz.getRelatedDay(userId,preworkdate); + } + + if(KQHolidaySetBiz.getChangeType(groupid,workdate)==2){ + dayOfweek = KQHolidaySetBiz.getRelatedDay(userId,workdate); + } + } + serialInfo.put("groupId",groupid); + serialInfo.put("groupName",groupname); + serialInfo.put("kqType",kqtype); + serialInfo.put("isHoliday",isHoliday); + if(includeHoliday) isHoliday = false; + + if (kqtype.equals("1")) {//固定班 +// if(containYesterday && !serialInfo.containsKey(preworkdate)) { +// serialid = Util.null2String(kqFixedSchedulceComInfo.getSerialid(groupid,preDayOfweek)); +// if(!preDayIsHoliday&&serialid.length()>0 && Util.getIntValue(serialid) > 0){ +// serialInfo.put(preworkdate,serialid);//获取前一天的班次 +// } +// } + if(!serialInfo.containsKey(workdate)){ + serialid = Util.null2String(kqFixedSchedulceComInfo.getSerialid(groupid,dayOfweek)); + if( !isHoliday&&serialid.length()>0 && Util.getIntValue(serialid) > 0){ + serialInfo.put(workdate, serialid);//获取当天的班次 + } + } + } else if (kqtype.equals("2")) {//排班 + //先取排班设置里的班次 +// serialid = Util.null2String(kqShiftScheduleComInfo.getSerialId(userId,preworkdate)); +// if(containYesterday && serialid.length()>0 && !preDayIsHoliday && Util.getIntValue(serialid) > 0){ +// serialInfo.put(preworkdate,Util.null2String(kqShiftScheduleComInfo.getSerialId(userId,preworkdate)));//获取前一天的班次 +// } + serialid = Util.null2String(kqShiftScheduleComInfo.getSerialId(userId,workdate)); + if(serialid.length()>0 && !isHoliday && Util.getIntValue(serialid) > 0){ + serialInfo.put(workdate,Util.null2String(kqShiftScheduleComInfo.getSerialId(userId,workdate)));//获取当天的班次 + } + } else if (kqtype.equals("3")) {//自由班 + List weekDay = Util.splitString2List(kqGroupEntity.getWeekday(), ","); + String signStart = Util.null2String(kqGroupEntity.getSignstart());//签到开始时间 + int workMins = Util.getIntValue(Util.getIntValues(""+Util.getDoubleValue(Util.null2String(kqGroupEntity.getWorkhour()))*60));//工作时长 + if(signStart.length()>0 && workMins>0) { + String calmethod = Util.null2s(kqGroupEntity.getCalmethod(),"1"); + Map map = null; + if (weekDay.contains(""+preDayOfweek) && !preDayIsHoliday) {//前一天 + map = new HashMap<>(); + map.put("signStart", signStart); + map.put("workMins", workMins); + map.put("calmethod", calmethod); + serialInfo.put(preworkdate, map); + } + if (weekDay.contains(""+dayOfweek) && !isHoliday) {//当前天 + map = new HashMap<>(); + map.put("signStart", signStart); + map.put("workMins", workMins); + map.put("calmethod", calmethod); + serialInfo.put(workdate, map); + } + } + } + } catch (Exception e) { + writeLog(e); + } + return serialInfo; + } + + + public void setIsFormat(boolean isFormat){ + this.isFormat = isFormat; + } +} \ No newline at end of file diff --git a/src/com/engine/kq/biz/chain/cominfo/ShiftInfoCominfoBean.java b/src/com/engine/kq/biz/chain/cominfo/ShiftInfoCominfoBean.java new file mode 100644 index 0000000..e55f900 --- /dev/null +++ b/src/com/engine/kq/biz/chain/cominfo/ShiftInfoCominfoBean.java @@ -0,0 +1,519 @@ +package com.engine.kq.biz.chain.cominfo; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + */ +public class ShiftInfoCominfoBean implements Serializable { + + + private static final long serialVersionUID = -1735765502081116461L; + + /** + * 当前班次如果是作为前一个班次存在,跨到次日的工作时段 + */ + private List preWorkTime; + + /** + * 当前班次作为当前班次存在,在0-24小时内的工作时段 + */ + private List workTime; + + /** + * 当前班次作为当前班次存在,如果存在跨天的话,包含跨天的工作时段,显示成0-24小时的 + */ + private List workAcrossTime; + + + /** + * 当前班次如果是作为前一个班次存在,跨到次日的工作时段 + */ + private List preWorkTimeIndex; + + /** + * 当前班次作为当前班次存在,在0-24小时内的工作时段 + */ + private List workTimeIndex; + + /** + * 当前班次作为当前班次存在,在0-48小时内的工作时段下标 + */ + private List workLongTimeIndex; + + /** + * 当前班次作为当前班次存在,在0-48小时内的工作时段下标 + */ + private List restLongTimeIndex; + + /** + * 存储所有的工作时间 48小时制休息时段 + */ + private List allLongWorkTime; + + /** + * 当前班次作为当前班次存在,如果存在跨天的话,包含跨天的工作时段,显示成0-24小时的 + */ + private List workAcrossTimeIndex; + + /** + * 考勤报表用的 48小时制工作时段 + */ + private List> workAcrossLongTime; + + /** + * 当天打卡时段时间:多少分钟可以开始签到签退的 + */ + private List workPunchMins; + + /** + * 当前班次如果是作为前一个班次存在,跨到次日的休息时段 + */ + private List preRestTime; + + /** + * 当前班次作为当前班次存在,在0-24小时内的休息时段 + */ + private List restTime; + + /** + * 当前班次作为当前班次存在,如果存在跨r天的话,包含跨天的休息时段,显示成0-24小时的 + */ + private List restAcrossTime; + /** + * 当前班次如果是作为前一个班次存在,跨到次日的休息时段 + */ + private List preRestTimeIndex; + + /** + * 当前班次作为当前班次存在,在0-24小时内的休息时段 + */ + private List restTimeIndex; + + /** + * 当前班次作为当前班次存在,如果存在跨r天的话,包含跨天的休息时段,显示成0-24小时的 + */ + private List restAcrossTimeIndex; + + /** + * 考勤报表用的 48小时制休息时段 + */ + private List> restAcrossLongTime; + + /** + * 要返回的半天规则时间区间对应的数组下标 + * 这里有值的话是三个,最早的开始时间 中间时间 最晚的下班时间 + */ + private List halfWorkTime; + + /** + * 要返回的半天规则时间区间对应的数组下标 + * 这里有值的话是三个,最早的开始时间 中间时间 最晚的下班时间 + */ + private List halfWorkIndex; + + /** + * 存储所有的工作时间 + */ + private List allWorkTime; + + /** + * 存储所有的跨天时间 + */ + private List allAcrossWorkTime; + /** + * 存储所有的休息时间 + */ + private List allRestTime; + + /** + * 存储所有的休息时间 + */ + private List allAcrossRestTime; + + /** + * 存储每一段工作时段内的工作时长 + */ + private List eachWorkMins; + + /** + * 工作时长 + */ + private int workmins; + + /** + * 当前日期的班次 + */ + private String serialid; + + /** + * 判断当前班次是否存在跨天 + */ + private String isAcross; + + /** + * 半天计算规则 + */ + private String halfcalrule; + + /** + * 自定义 半天计算规则 时间点 + */ + private String halfcalpoint; + + private String halfcalpoint2cross; + + private List timelineList; + + /** + * 允许签到签退的时段范围 + */ + private List> signWorkTime; + + /** + * 存储所有的工作时间是否跨天 和allWorkTime对应 + */ + private List allWorkTimeisAcross; + + private String uuid = ""; + + private String restShift; + + public ShiftInfoCominfoBean() { + + this.preWorkTime = new ArrayList<>(); + this.workTime = new ArrayList<>(); + this.workAcrossTime = new ArrayList<>(); + this.preWorkTimeIndex = new ArrayList<>(); + this.workTimeIndex = new ArrayList<>(); + this.workAcrossTimeIndex = new ArrayList<>(); + this.workAcrossLongTime = new ArrayList<>(); + this.workPunchMins = new ArrayList<>(); + this.preRestTime = new ArrayList<>(); + this.restTime = new ArrayList<>(); + this.restAcrossTime = new ArrayList<>(); + this.preRestTimeIndex = new ArrayList<>(); + this.restTimeIndex = new ArrayList<>(); + this.restAcrossTimeIndex = new ArrayList<>(); + this.restAcrossLongTime = new ArrayList<>(); + this.halfWorkTime = new ArrayList<>(); + this.allWorkTime = new ArrayList<>(); + this.allAcrossWorkTime = new ArrayList<>(); + this.allRestTime = new ArrayList<>(); + this.allAcrossRestTime = new ArrayList<>(); + this.eachWorkMins = new ArrayList<>(); + this.workmins = 0; + this.serialid = ""; + this.isAcross = "0"; + this.halfcalrule = "0"; + this.halfWorkIndex = new ArrayList<>(); + + this.timelineList = new ArrayList<>(); + + this.workLongTimeIndex = new ArrayList<>(); + this.restLongTimeIndex = new ArrayList<>(); + this.allLongWorkTime = new ArrayList<>(); + this.signWorkTime = new ArrayList<>(); + this.allWorkTimeisAcross = new ArrayList<>(); + this.uuid = UUID.randomUUID().toString(); + this.halfcalpoint = "0"; + this.halfcalpoint2cross = "0"; + this.restShift = "0"; + } + + public List getPreWorkTime() { + return preWorkTime; + } + + public void setPreWorkTime(List preWorkTime) { + this.preWorkTime = preWorkTime; + } + + public List getWorkTime() { + return workTime; + } + + public void setWorkTime(List workTime) { + this.workTime = workTime; + } + + public List getWorkAcrossTime() { + return workAcrossTime; + } + + public void setWorkAcrossTime(List workAcrossTime) { + this.workAcrossTime = workAcrossTime; + } + + public List> getWorkAcrossLongTime() { + return workAcrossLongTime; + } + + public void setWorkAcrossLongTime( + List> workAcrossLongTime) { + this.workAcrossLongTime = workAcrossLongTime; + } + + public List getWorkPunchMins() { + return workPunchMins; + } + + public void setWorkPunchMins(List workPunchMins) { + this.workPunchMins = workPunchMins; + } + + public List getHalfWorkTime() { + return halfWorkTime; + } + + public void setHalfWorkTime(List halfWorkTime) { + this.halfWorkTime = halfWorkTime; + } + + public int getWorkmins() { + return workmins; + } + + public void setWorkmins(int workmins) { + this.workmins = workmins; + } + + public String getSerialid() { + return serialid; + } + + public void setSerialid(String serialid) { + this.serialid = serialid; + } + + public List getAllWorkTime() { + return allWorkTime; + } + + public void setAllWorkTime(List allWorkTime) { + this.allWorkTime = allWorkTime; + } + + public List getAllAcrossWorkTime() { + return allAcrossWorkTime; + } + + public void setAllAcrossWorkTime(List allAcrossWorkTime) { + this.allAcrossWorkTime = allAcrossWorkTime; + } + + public List getRestTime() { + return restTime; + } + + public void setRestTime(List restTime) { + this.restTime = restTime; + } + + public String getIsAcross() { + return isAcross; + } + + public void setIsAcross(String isAcross) { + this.isAcross = isAcross; + } + + public List getPreRestTime() { + return preRestTime; + } + + public void setPreRestTime(List preRestTime) { + this.preRestTime = preRestTime; + } + + public List getRestAcrossTime() { + return restAcrossTime; + } + + public void setRestAcrossTime(List restAcrossTime) { + this.restAcrossTime = restAcrossTime; + } + + public List> getRestAcrossLongTime() { + return restAcrossLongTime; + } + + public void setRestAcrossLongTime( + List> restAcrossLongTime) { + this.restAcrossLongTime = restAcrossLongTime; + } + + public List getAllRestTime() { + return allRestTime; + } + + public void setAllRestTime(List allRestTime) { + this.allRestTime = allRestTime; + } + + public List getAllAcrossRestTime() { + return allAcrossRestTime; + } + + public void setAllAcrossRestTime(List allAcrossRestTime) { + this.allAcrossRestTime = allAcrossRestTime; + } + + public List getEachWorkMins() { + return eachWorkMins; + } + + public void setEachWorkMins(List eachWorkMins) { + this.eachWorkMins = eachWorkMins; + } + + public List getPreWorkTimeIndex() { + return preWorkTimeIndex; + } + + public void setPreWorkTimeIndex(List preWorkTimeIndex) { + this.preWorkTimeIndex = preWorkTimeIndex; + } + + public List getWorkTimeIndex() { + return workTimeIndex; + } + + public void setWorkTimeIndex(List workTimeIndex) { + this.workTimeIndex = workTimeIndex; + } + + public List getWorkAcrossTimeIndex() { + return workAcrossTimeIndex; + } + + public void setWorkAcrossTimeIndex(List workAcrossTimeIndex) { + this.workAcrossTimeIndex = workAcrossTimeIndex; + } + + public List getPreRestTimeIndex() { + return preRestTimeIndex; + } + + public void setPreRestTimeIndex(List preRestTimeIndex) { + this.preRestTimeIndex = preRestTimeIndex; + } + + public List getRestTimeIndex() { + return restTimeIndex; + } + + public void setRestTimeIndex(List restTimeIndex) { + this.restTimeIndex = restTimeIndex; + } + + public List getRestAcrossTimeIndex() { + return restAcrossTimeIndex; + } + + public void setRestAcrossTimeIndex(List restAcrossTimeIndex) { + this.restAcrossTimeIndex = restAcrossTimeIndex; + } + + public List getHalfWorkIndex() { + return halfWorkIndex; + } + + public void setHalfWorkIndex(List halfWorkIndex) { + this.halfWorkIndex = halfWorkIndex; + } + + public List getTimelineList() { + return timelineList; + } + + public void setTimelineList(List timelineList) { + this.timelineList = timelineList; + } + + public List getWorkLongTimeIndex() { + return workLongTimeIndex; + } + + public void setWorkLongTimeIndex(List workLongTimeIndex) { + this.workLongTimeIndex = workLongTimeIndex; + } + + public List getRestLongTimeIndex() { + return restLongTimeIndex; + } + + public void setRestLongTimeIndex(List restLongTimeIndex) { + this.restLongTimeIndex = restLongTimeIndex; + } + + public List getAllLongWorkTime() { + return allLongWorkTime; + } + + public void setAllLongWorkTime(List allLongWorkTime) { + this.allLongWorkTime = allLongWorkTime; + } + + public List> getSignWorkTime() { + return signWorkTime; + } + + public void setSignWorkTime( + List> signWorkTime) { + this.signWorkTime = signWorkTime; + } + + public List getAllWorkTimeisAcross() { + return allWorkTimeisAcross; + } + + public void setAllWorkTimeisAcross(List allWorkTimeisAcross) { + this.allWorkTimeisAcross = allWorkTimeisAcross; + } + + public String getHalfcalrule() { + return halfcalrule; + } + + public void setHalfcalrule(String halfcalrule) { + this.halfcalrule = halfcalrule; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getHalfcalpoint() { + return halfcalpoint; + } + + public void setHalfcalpoint(String halfcalpoint) { + this.halfcalpoint = halfcalpoint; + } + + public String getHalfcalpoint2cross() { + return halfcalpoint2cross; + } + + public void setHalfcalpoint2cross(String halfcalpoint2cross) { + this.halfcalpoint2cross = halfcalpoint2cross; + } + + public String getRestShift() { + return restShift; + } + + public void setRestShift(String restShift) { + this.restShift = restShift; + } +} + diff --git a/src/com/engine/kq/biz/chain/cominfo/WorkShiftComIndex.java b/src/com/engine/kq/biz/chain/cominfo/WorkShiftComIndex.java new file mode 100644 index 0000000..f00e88c --- /dev/null +++ b/src/com/engine/kq/biz/chain/cominfo/WorkShiftComIndex.java @@ -0,0 +1,37 @@ +package com.engine.kq.biz.chain.cominfo; + +import java.util.List; +import java.util.Map; + +import weaver.common.StringUtil; +import weaver.general.Util; + +/** + * 规则时段计算规则 + */ +public class WorkShiftComIndex extends ShiftComIndex { + + public WorkShiftComIndex(String name,Map workTimeMap){ + super(name,workTimeMap); + } + + @Override + public void handleDuration(ShiftInfoCominfoBean shiftInfoCominfoBean) throws Exception { + + handleWorkTime(shiftInfoCominfoBean); + this.success.handleDuration(shiftInfoCominfoBean); + } + + private void handleWorkTime(ShiftInfoCominfoBean shiftInfoCominfoBean) throws Exception { + List workTimes = (List)workTimeMap.get("workTime"); + int workmins = Util.getIntValue(Util.null2String(workTimeMap.get("workmins"))); + shiftInfoCominfoBean.setWorkmins(workmins); + String serialid = Util.null2String(workTimeMap.get("serialid")); + shiftInfoCominfoBean.setSerialid(serialid); + shiftInfoCominfoBean.setRestShift(StringUtil.vString(workTimeMap.get("restShift"), "0")); + + setWorkDuration(workTimes, shiftInfoCominfoBean); + + } + +} diff --git a/src/com/engine/kq/cmd/attendanceButton/PunchButtonCmd.java b/src/com/engine/kq/cmd/attendanceButton/PunchButtonCmd.java new file mode 100644 index 0000000..9609dc1 --- /dev/null +++ b/src/com/engine/kq/cmd/attendanceButton/PunchButtonCmd.java @@ -0,0 +1,618 @@ +package com.engine.kq.cmd.attendanceButton; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.cloudstore.dev.api.util.EMManager; +import com.engine.common.biz.AbstractCommonCommand; +import com.engine.common.entity.BizLogContext; +import com.engine.core.interceptor.CommandContext; +import com.engine.kq.biz.KQShiftManagementComInfo; +import com.engine.kq.biz.KQCardLogBiz; +import com.engine.kq.biz.KQFormatBiz; +import com.engine.kq.biz.KQGroupBiz; +import com.engine.kq.biz.KQGroupMemberComInfo; +import com.engine.kq.biz.KQLoactionComInfo; +import com.engine.kq.biz.KQShiftRuleInfoBiz; +import com.engine.kq.biz.KQTimesArrayComInfo; +import com.engine.kq.biz.KQWorkTime; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.entity.KQGroupEntity; +import com.engine.kq.entity.WorkTimeEntity; +import com.engine.kq.log.KQLog; +import com.engine.kq.timer.KQQueue; +import com.engine.kq.timer.KQTaskBean; +import com.engine.kq.util.KQDurationCalculatorUtil; +import com.engine.kq.wfset.util.SplitActionUtil; +import com.google.common.collect.Maps; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.servlet.http.HttpServletRequest; +import weaver.common.DateUtil; +import weaver.common.StringUtil; +import weaver.conn.RecordSet; +import weaver.dateformat.DateTransformer; +import weaver.dateformat.TimeZoneVar; +import weaver.general.Util; +import weaver.hrm.User; +import weaver.systeminfo.SystemEnv; + +/** + * 考勤的 签到签退 + */ +public class PunchButtonCmd extends AbstractCommonCommand> { + public KQLog kqLog = new KQLog(); + private HttpServletRequest request; + private Map logMap = Maps.newHashMap(); + private Map workTimeEntityLogMap = Maps.newHashMap(); + + public PunchButtonCmd(HttpServletRequest request,Map params, User user) { + this.request = request; + this.user = user; + this.params = params; + } + + @Override + public Map execute(CommandContext commandContext) { + Map retmap = new HashMap(); + try{ + insertSign(retmap); + + }catch (Exception e) { + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + writeLog(e); + } + kqLog.info(user.getLastname()+":PunchButtonCmd:retmap:"+retmap); + KQCardLogBiz.logCardInfo(user.getUID()+"", logMap, workTimeEntityLogMap, "punchButton"); + + return retmap; + } + + /** + * 检验ip是否在考勤组设置的范围要求内 + * @param ismobile + */ + private boolean checkIsInIp(String ismobile) { +// if("1".equalsIgnoreCase(ismobile)){ +// return true; +// } + KQGroupBiz kqGroupBiz = new KQGroupBiz(); + String clientAddress = Util.getIpAddr(request); + kqLog.info("PunchButtonCmd:clientAddress:"+clientAddress); + return kqGroupBiz.getIsInScopeV4V6(user.getUID()+"", clientAddress,ismobile); + } + + public void insertSign(Map retmap) throws Exception{ + logMap.put("lastname", user.getLastname()); + logMap.put("params", params); + kqLog.info(user.getLastname()+":PunchButtonCmd:params:"+params); + RecordSet rs = new RecordSet(); + String deviceInfo = Util.null2String(params.get("deviceInfo")); + JSONObject jsonObject = null; + if(deviceInfo.length() > 0){ + jsonObject = JSON.parseObject(deviceInfo); + JSONObject jsonObject1 = new JSONObject(); + Set> jsonSet = jsonObject.entrySet(); + for(Entry js : jsonSet){ + String key = js.getKey(); + String value = Util.null2String(js.getValue()); + jsonObject1.put(key, value); + } + if(!jsonObject1.isEmpty()){ + deviceInfo = jsonObject1.toJSONString(); + } + } + //应上班 工作时间点 + String time = Util.null2String(params.get("time")); + //应上班 工作时间 带日期 + String datetime = Util.null2String(params.get("datetime")); + //允许打卡时段 带日期 + String signSectionTime = Util.null2String(params.get("signSectionTime")); + //上传照片 + String attachment = Util.null2String(params.get("fileids")); + + //打卡所属worksection的对应的点 + String type = Util.null2String(params.get("type")); + //所属打卡日期 + String belongdate = Util.null2String(params.get("belongdate")); + belongdate = belongdate.length() == 0 ? DateUtil.getCurrentDate() : belongdate; + String islastsign = Util.null2String(params.get("islastsign")); + String isfirstsign = Util.null2String(params.get("isfirstsign")); + + String workmins = Util.null2String(params.get("workmins")); + //针对非工作时段 签退的时候记录的签到数据 用于计算加班 + String signInTime4Out = Util.null2String(params.get("signInTime4Out")); + //允许打卡的范围 + String signsection = Util.null2String(params.get("signSection")); + + //手机打卡部分 + String longitude = Util.null2String(params.get("longitude")); + String latitude = Util.null2String(params.get("latitude")); + double d_longitude = Util.getDoubleValue(longitude); + double d_latitude = Util.getDoubleValue(latitude); + if(d_latitude <= 0){ + latitude = ""; + } + if(d_longitude <= 0){ + longitude = ""; + } + //wifi用的 + String mac = Util.null2String(params.get("mac")); + String sid = Util.null2String(params.get("sid")); + String addr = Util.null2String(params.get("position")); + String ismobile = Util.null2String(params.get("ismobile")); + //区分是来自于钉钉还是EM7 + String browser = Util.null2String(params.get("browser")); + //自由班制处理 + String isfree = Util.null2String(Util.null2String(params.get("isfree")),"0"); + + //上班打卡 允许最晚打卡时间 + String signSectionEndTime = Util.null2String(params.get("signSectionEndTime")); + //下班打卡 允许最早打卡时间 + String signSectionBeginTime = Util.null2String(params.get("signSectionBeginTime")); + + String locationshowaddress = Util.null2String(params.get("locationshowaddress")); + if(locationshowaddress.equals("1")){//记录统一地址 + String locationid = Util.null2String(params.get("locationid"));//办公地点id + if(locationid.length()>0){//如果开启统一显示,就用配置的地址 + KQLoactionComInfo kqLoactionComInfo = new KQLoactionComInfo(); + addr = kqLoactionComInfo.getLocationname(locationid); + } + } + + DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss"); + LocalTime localTime = LocalTime.now(); + String signTime =localTime.format(dateTimeFormatter); + String signDate = LocalDate.now().format(dateFormatter); + + String timeZone = Util.null2String(TimeZoneVar.getTimeZone(),""); + //处理多时区 + String timeZoneConversion = Util.null2String(new weaver.general.BaseBean().getPropValue("weaver_timezone_conversion","timeZoneConversion")).trim(); + logMap.put("timeZoneConversion", timeZoneConversion); + if("1".equals(timeZoneConversion)) { + DateTransformer dateTransformer=new DateTransformer(); + String[] zone_localTime = dateTransformer.getLocaleDateAndTime(signDate,signTime); + kqLog.info(user.getLastname()+":TimeZoneVar.getTimeZone():"+TimeZoneVar.getTimeZone()+":zone_localTime:"+JSON.toJSONString(zone_localTime)); + if(zone_localTime != null && zone_localTime.length == 2){ + signDate = zone_localTime[0]; + signTime = zone_localTime[1]; + } + } + + int userId = user.getUID(); + String userType = user.getLogintype(); + String signType = "on".equalsIgnoreCase(type) ? "1" : "2"; + String clientAddress = Util.getIpAddr(request); + boolean isInIp = checkIsInIp(ismobile); + logMap.put("clientAddress", clientAddress); + + if(!isInIp){ + retmap.put("message", SystemEnv.getHtmlLabelName(20157,user.getLanguage())); + retmap.put("isInIp", "0"); + } + String isInCom = isInIp ? "1" : "0"; + + //是否是考勤例外人员 + boolean isExclude = false; + + KQGroupMemberComInfo kqGroupMemberComInfo = new KQGroupMemberComInfo(); + KQWorkTime kqWorkTime = new KQWorkTime(); + WorkTimeEntity workTimeEntity = kqWorkTime.getWorkTime(user.getUID()+"", signDate); + String userinfo = "#userid#"+user.getUID()+"#getUserSubCompany1#"+user.getUserSubCompany1()+"#getUserSubCompany1#"+user.getUserDepartment() + +"#getJobtitle#"+user.getJobtitle(); + workTimeEntityLogMap.put("resourceid", userinfo); + workTimeEntityLogMap.put("splitDate", signDate); + workTimeEntityLogMap.put("workTimeEntity", workTimeEntity); + String groupid = workTimeEntity.getGroupId(); + logMap.put("groupid", groupid); + KQGroupEntity kqGroupEntity = kqGroupMemberComInfo.getUserKQGroupInfo(user.getUID()+""); + String kqGroupEntityInfo = kqGroupEntity != null ? JSON.toJSONString(kqGroupEntity): ""; + logMap.put("kqGroupEntityInfo", kqGroupEntityInfo); + if (kqGroupEntity != null && ("," + kqGroupEntity.getExcludeid() + ",").indexOf("," + user.getUID() + ",")>-1) {//排除人员无需计算考勤时间 + isExclude = true; + } + + String[] signsections = signsection.split("#"); + if(!"1".equalsIgnoreCase(isfree)){ + if(signsections != null && signsections.length == 2){ + //判断是未签到直接签退 + String signedMsg = signedMsg(userId+"", signType, user,signsections,signSectionBeginTime,signSectionEndTime); + if(signedMsg.length() > 0){ + retmap.put("status", "1"); + retmap.put("message", signedMsg); + isInCom = "0"; + } + } + } + + String datetime_timezone = signDate+" "+signTime; + LocalDateTime nowDateTime = LocalDateTime.parse(datetime_timezone,fullFormatter); + kqLog.info("timeZone:"+timeZone+":signDate:"+signDate+":signTime:"+signTime+":nowDateTime:"+nowDateTime); + + if("1".equalsIgnoreCase(signType) && signSectionTime.length() > 0 ){ + LocalDateTime startWorkDateTime = LocalDateTime.parse(signSectionTime,fullFormatter); + if(nowDateTime.isBefore(startWorkDateTime)){ + Duration duration = Duration.between(nowDateTime, startWorkDateTime); + retmap.put("status", "1"); + retmap.put("message", ""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005326,weaver.general.ThreadVarLanguage.getLang())+""+duration.toMinutes()+""+weaver.systeminfo.SystemEnv.getHtmlLabelName(15049,weaver.general.ThreadVarLanguage.getLang())+""); + isInCom = "0"; + } + + }else if("2".equalsIgnoreCase(signType) && signSectionTime.length() > 0 ){ + LocalDateTime endWorkDateTime = LocalDateTime.parse(signSectionTime,fullFormatter); + if(nowDateTime.isAfter(endWorkDateTime)){ + Duration duration = Duration.between(endWorkDateTime, nowDateTime); + retmap.put("status", "1"); + retmap.put("message", ""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005327,weaver.general.ThreadVarLanguage.getLang())+""+duration.toMinutes()+""+weaver.systeminfo.SystemEnv.getHtmlLabelName(15049,weaver.general.ThreadVarLanguage.getLang())+""); + isInCom = "0"; + } + } + + //记录下是来自于E9的pc端签到 + String signfrom = "e9pc"; + if("1".equalsIgnoreCase(ismobile)){ + signfrom = "e9mobile"; + boolean needLocationRange = false; + boolean needWifiRange = false; + boolean isLocationRange = false; + boolean isWifiRange = false; + KQGroupBiz kqGroupBiz = new KQGroupBiz(); + Map locationMap = kqGroupBiz.checkLocationScope(userId+"",longitude,latitude); + logMap.put("locationMap", locationMap); + String locationNeedCheck = Util.null2String(locationMap.get("needCheck")); + boolean locationInScope = Boolean.parseBoolean(Util.null2String(locationMap.get("inScope"))); + if("1".equalsIgnoreCase(locationNeedCheck)){ + needLocationRange = true; + if(locationInScope){ + isLocationRange = true; + } + } + String wifiNeedCheck = ""; + Map wifiMap = kqGroupBiz.checkWifiScope(userId+"", sid, mac); + logMap.put("wifiMap", wifiMap); + wifiNeedCheck = Util.null2String(wifiMap.get("needCheck")); + boolean wifiInScope = Boolean.parseBoolean(Util.null2String(wifiMap.get("inScope"))); + if("1".equalsIgnoreCase(wifiNeedCheck)){ + needWifiRange = true; + if(wifiInScope){ + isWifiRange = true; + } + } + if(needLocationRange){ + if(isLocationRange){ + }else{ + if(needWifiRange){ + if(isWifiRange){ + }else{ + //地理位置开启,而且不在范围内,且开启wifi验证,不在范围内 + retmap.put("message", SystemEnv.getHtmlLabelName(507524, user.getLanguage())); + isInCom = "0"; + } + }else { + //地理位置开启,而且不在范围内,且未开启wifi验证 + retmap.put("message", SystemEnv.getHtmlLabelName(500510, user.getLanguage())); + isInCom = "0"; + } + } + }else{ + if(needWifiRange) { + if (isWifiRange) { + } else { + //地理位置未开启,且开启wifi验证,不在范围内 + retmap.put("message", SystemEnv.getHtmlLabelName(507524, user.getLanguage())); + isInCom = "0"; + } + } + } + + if("DingTalk".equalsIgnoreCase(browser)){ + signfrom = "DingTalk"; + }else if("Wechat".equalsIgnoreCase(browser)){ + signfrom = "Wechat"; + String weChat_deviceid = Util.null2String(request.getSession().getAttribute(EMManager.DeviceId)); + logMap.put("weChat_deviceid", weChat_deviceid); + kqLog.info("EMManager.DeviceId:"+EMManager.DeviceId+":weChat_deviceid:"+weChat_deviceid); + if(weChat_deviceid.length() > 0){ + //微信打卡的设备号需要单独处理 + if(jsonObject != null){ + jsonObject.put("deviceId", weChat_deviceid); + }else{ + jsonObject = new JSONObject(); + jsonObject.put("deviceId", weChat_deviceid); + } + if(!jsonObject.isEmpty()){ + deviceInfo = jsonObject.toJSONString(); + } + } + } + } + String signStatus = ""; + + if(!"1".equalsIgnoreCase(isfree) && datetime.length() > 0){ + signStatus = getSignStatus(signType,datetime,user.getUID()+"",belongdate,nowDateTime); + logMap.put("signStatus", signStatus); + } + + if(isExclude){ + signStatus = ButtonStatusEnum.NORMAL.getStatusCode(); + } + + String punchSql = "insert into HrmScheduleSign(userId,userType,signType,signDate,signTime,clientAddress,isInCom,timeZone,belongdate,signfrom,longitude,latitude,addr,deviceInfo) "+ + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + boolean isOk = rs.executeUpdate(punchSql,userId,userType,signType,signDate,signTime,clientAddress,isInCom, + timeZone,belongdate,signfrom,longitude,latitude,addr,deviceInfo); + if(!isOk){ + retmap.put("status", "1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + return ; + } + logMap.put("punchSql", punchSql); + logMap.put("punchSql_isOk", isOk); + kqLog.info(user.getLastname()+":PunchButtonCmd:punchSql:"+punchSql+":isOk:"+isOk); + + //打卡提醒处理 + String remindSql = "insert into hrmschedulesign_remind(userId,signType,signDate,signTime,belongdate) values(?,?,?,?,?)"; + isOk = rs.executeUpdate(remindSql, userId,signType,signDate,signTime,belongdate); + kqLog.info(user.getLastname()+":PunchButtonCmd:remindSql:"+remindSql+":isOk:"+isOk); + + //同步更新考勤数据到考勤报表 + new KQFormatBiz().formatDate(""+userId,(belongdate.length() == 0 ? DateUtil.getCurrentDate() : belongdate)); + //点击签退的时候,可能存在加班数据生成的情况 + if("2".equalsIgnoreCase(signType)){ + if("1".equalsIgnoreCase(islastsign)){ + List tasks = new ArrayList<>(); + List after_tasks = new ArrayList<>(); + SplitActionUtil.pushOverTimeTasks(belongdate, belongdate, ""+userId,tasks); + if(!tasks.isEmpty()){ + for(KQTaskBean kqTaskBean : tasks){ + after_tasks.add(kqTaskBean); + } + } + logMap.put("after_tasks", after_tasks); + if(!after_tasks.isEmpty()){ + KQQueue.writeTasks(after_tasks); + } + } + } + if("1".equalsIgnoreCase(signType)){ + if("1".equalsIgnoreCase(isfirstsign)){ + List tasks = new ArrayList<>(); + List before_tasks = new ArrayList<>(); + SplitActionUtil.pushOverTimeTasks(belongdate, belongdate, ""+userId,tasks); + if(!tasks.isEmpty()){ + for(KQTaskBean kqTaskBean : tasks){ + kqTaskBean.setTasktype("punchcard"); + before_tasks.add(kqTaskBean); + } + } + logMap.put("before_tasks", before_tasks); + if(!before_tasks.isEmpty()){ + KQQueue.writeTasks(before_tasks); + } + } + } + + String reSignStatus = reSignStatus(user.getUID()+"",signType,nowDateTime,belongdate); + if(Util.null2String(reSignStatus,"").length() > 0){ + signStatus = reSignStatus; + } + + retmap.put("status", "1"); + retmap.put("signdate", signDate); + retmap.put("signtime", signTime); + retmap.put("kqstatus", signStatus); + + if(!"1".equalsIgnoreCase(signStatus) && !"2".equalsIgnoreCase(signStatus)){ + if("".equalsIgnoreCase(Util.null2String(retmap.get("message")))){ + retmap.put("success", "1"); + retmap.put("message", SystemEnv.getHtmlLabelName(512596,weaver.general.Util.getIntValue(user.getLanguage()))); + } + } + logMap.put("retmap", retmap); + } + + public String reSignStatus(String userid, String signType, LocalDateTime nowDateTime, + String workdate) { + String signStatus = ""; + + String shift_begindateworktime = ""; + String shift_enddateworktime = ""; + ShiftInfoBean shiftInfoBean = KQDurationCalculatorUtil.getWorkTime(userid, workdate,false); + if(shiftInfoBean == null){ + return signStatus; + } + //休息班次打卡去掉迟到、早退的打卡异常提醒 + int serialid = StringUtil.parseToInt(shiftInfoBean.getSerialid(), 0); + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(serialid)), 0); + if(serialid <= 0 || restShift == 1) { + return "-1"; + } + + Map shifRuleMap = Maps.newHashMap(); + KQShiftRuleInfoBiz.getShiftRuleInfo(shiftInfoBean,userid,shifRuleMap); + KQTimesArrayComInfo arrayComInfo = new KQTimesArrayComInfo(); + if(!shifRuleMap.isEmpty()) { + DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String datetime = ""; + if (shifRuleMap.containsKey("shift_beginworktime")) { + String shift_beginworktime = Util.null2String(shifRuleMap.get("shift_beginworktime")); + if (shift_beginworktime.length() > 0) { + int shift_beginworktime_index = -1; + shift_beginworktime_index = arrayComInfo.getArrayindexByTimes(shift_beginworktime); + datetime = workdate+" "+shift_beginworktime+":00"; + if(shift_beginworktime_index >= 1440){ + //跨天了 + datetime = DateUtil.addDate(workdate, 1)+" "+arrayComInfo.turn48to24Time(shift_beginworktime)+":00"; + } + } + } + if (shifRuleMap.containsKey("shift_endworktime")) { + String shift_endworktime = Util.null2String(shifRuleMap.get("shift_endworktime")); + if (shift_endworktime.length() > 0) { + int shift_endworktime_index = -1; + shift_endworktime_index = arrayComInfo.getArrayindexByTimes(shift_endworktime); + datetime = workdate+" "+shift_endworktime+":00"; + if(shift_endworktime_index >= 1440) { + //跨天了 + datetime = DateUtil.addDate(workdate, 1)+" "+arrayComInfo.turn48to24Time(shift_endworktime)+":00"; + } + } + } + + if (datetime.length() > 0) { + if("1".equalsIgnoreCase(signType)) { + LocalDateTime startWorkDateTime = LocalDateTime.parse(datetime, fullFormatter); + //打卡时间比上班时间晚,迟到了 + if (nowDateTime.isAfter(startWorkDateTime)) { + signStatus = ButtonStatusEnum.BELATE.getStatusCode(); + } else { + signStatus = ButtonStatusEnum.NORMAL.getStatusCode(); + } + } else if ("2".equalsIgnoreCase(signType)) { + LocalDateTime endWorkDateTime = LocalDateTime.parse(datetime, fullFormatter); + //签退的话 + if (nowDateTime.isBefore(endWorkDateTime)) { + signStatus = ButtonStatusEnum.LEAVEERALY.getStatusCode(); + } else { + signStatus = ButtonStatusEnum.NORMAL.getStatusCode(); + } + } else { + writeLog(user.getLastname() + nowDateTime + ":竟然没有传:" + signType); + return ""; + } + } + } + return signStatus; + } + + /** + * 上班前打卡目前是 视作前一天的跨天加班 + * @param resourceid + * @param pre_splitDate + * @param signtime + * @param pre_bengintime + * @param signdate + */ + public void doBeforeAcrossOvertime(String resourceid,String pre_splitDate,String signtime,String pre_bengintime,String signdate) { + + KQTaskBean kqTaskBean = new KQTaskBean(); + kqTaskBean.setResourceId(resourceid); + kqTaskBean.setTaskDate(pre_splitDate); + kqTaskBean.setLastWorkTime(signtime); + if(pre_bengintime.length() == 5){ + kqTaskBean.setTaskSignTime(pre_bengintime+":00"); + }else{ + kqTaskBean.setTaskSignTime(pre_bengintime); + } + kqTaskBean.setSignDate(signdate); + kqTaskBean.setSignEndDate(signdate); + kqTaskBean.setTimesource("before"); + KQQueue.writeTask(kqTaskBean); + } + + /** + * 校验是否已经签到过 + * @param userid + * @param signtype + * @param curUser + * @param signsections + * @param signSectionBeginTime 下班打卡 允许最早打卡时间 + * @param signSectionEndTime 上班打卡 允许最晚打卡时间 + * @return + */ + public String signedMsg(String userid, String signtype, User curUser, String[] signsections, + String signSectionBeginTime, String signSectionEndTime) throws Exception{ + String signedMsg = ""; + RecordSet rs = new RecordSet(); + boolean hasSigned = false; + String onSignSectionTime = signsections[0]; + String offSignSectionTime = signsections[1]; + if(onSignSectionTime.length() > 0 && offSignSectionTime.length() > 0){ + String hasSign = "select 1 from hrmschedulesign where 1 = 1 and isInCom = '1' and userid = ? "; + + StringBuffer sql = new StringBuffer(); + if(rs.getDBType().equals("oracle")||rs.getDBType().equals("postgresql")){ + sql.append(" AND signDate||' '||signTime>=? "); + sql.append(" AND signDate||' '||signTime<=? "); + }else if(rs.getDBType().equals("mysql")){ + sql.append(" AND concat(signDate,' ',signTime)>=? "); + sql.append(" AND concat(signDate,' ',signTime)<=? "); + }else{ + sql.append(" AND signDate+' '+signTime>=? "); + sql.append(" AND signDate+' '+signTime<=? "); + } + hasSign += sql.toString(); + rs.executeQuery(hasSign, userid,onSignSectionTime,offSignSectionTime); + if(rs.next()){ + hasSigned = true; + } + if("1".equalsIgnoreCase(signtype)){ + if(signSectionBeginTime.length() > 0 || signSectionEndTime.length() > 0){ + }else{ + if(hasSigned){ + signedMsg = SystemEnv.getHtmlLabelName(129706, curUser.getLanguage()); + } + } + }else if("2".equalsIgnoreCase(signtype)){ + if(signSectionBeginTime.length() > 0 || signSectionEndTime.length() > 0){ + }else{ + if(!hasSigned){ + signedMsg = SystemEnv.getHtmlLabelName(501301, curUser.getLanguage()); + } + } + } + } + return signedMsg; + } + /** + * 在签到签退的时候先根据打卡数据 + * 粗步 得到打卡状态 正常,迟到,早退 + * @return + */ + public String getSignStatus(String signType, String datetime, String userid, String workdate, + LocalDateTime nowDateTime) { + DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String signStatus = ""; + + //签到的话 + if("1".equalsIgnoreCase(signType)){ + LocalDateTime startWorkDateTime = LocalDateTime.parse(datetime,fullFormatter); + //打卡时间比上班时间晚,迟到了 + if(nowDateTime.isAfter(startWorkDateTime)){ + signStatus = ButtonStatusEnum.BELATE.getStatusCode(); + }else{ + signStatus = ButtonStatusEnum.NORMAL.getStatusCode(); + } + }else if("2".equalsIgnoreCase(signType)){ + LocalDateTime endWorkDateTime = LocalDateTime.parse(datetime,fullFormatter); + //签退的话 + if(nowDateTime.isBefore(endWorkDateTime)){ + signStatus = ButtonStatusEnum.LEAVEERALY.getStatusCode(); + }else{ + signStatus = ButtonStatusEnum.NORMAL.getStatusCode(); + } + }else{ + writeLog(user.getLastname()+nowDateTime+":竟然没有传:"+signType); + return ""; + } + return signStatus; + } + + @Override + public BizLogContext getLogContext() { + return null; + } + +} diff --git a/src/com/engine/kq/cmd/shiftmanagement/GetShiftManagementBaseFormCmd.java b/src/com/engine/kq/cmd/shiftmanagement/GetShiftManagementBaseFormCmd.java new file mode 100644 index 0000000..f6ec2fe --- /dev/null +++ b/src/com/engine/kq/cmd/shiftmanagement/GetShiftManagementBaseFormCmd.java @@ -0,0 +1,424 @@ +package com.engine.kq.cmd.shiftmanagement; + +import com.api.browser.bean.SearchConditionItem; +import com.api.browser.bean.SearchConditionOption; +import com.api.hrm.bean.HrmFieldBean; +import com.api.hrm.util.HrmFieldSearchConditionComInfo; +import com.engine.common.biz.AbstractCommonCommand; +import com.engine.common.entity.BizLogContext; +import com.engine.core.interceptor.CommandContext; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import weaver.conn.RecordSet; +import weaver.general.Util; +import weaver.hrm.HrmUserVarify; +import weaver.hrm.User; +import weaver.hrm.company.SubCompanyComInfo; +import weaver.hrm.moduledetach.ManageDetachComInfo; +import weaver.systeminfo.SystemEnv; +import weaver.systeminfo.systemright.CheckSubCompanyRight; + +/** + * 获取班次管理基本信息表单 + * @author pzy + * + */ +public class GetShiftManagementBaseFormCmd extends AbstractCommonCommand>{ + + public GetShiftManagementBaseFormCmd(Map params, User user) { + this.user = user; + this.params = params; + } + + @Override + public BizLogContext getLogContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map execute(CommandContext commandContext) { + Map retmap = new HashMap(); + List> grouplist = new ArrayList>(); + Map groupitem = null; + List itemlist = null; + RecordSet rs = new RecordSet(); + RecordSet rs1 = new RecordSet(); + String sql = ""; + try { + if(!HrmUserVarify.checkUserRight("KQClass:Management",user)) { + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(2012, user.getLanguage())); + return retmap; + } + CheckSubCompanyRight newCheck=new CheckSubCompanyRight(); + ManageDetachComInfo manageDetachComInfo = new ManageDetachComInfo(); + boolean hrmdetachable = manageDetachComInfo.isUseHrmManageDetach();//是否开启了人力资源模块的管理分权 + String hrmdftsubcomid = manageDetachComInfo.getHrmdftsubcomid();//分权默认分部 + + SubCompanyComInfo sc = new SubCompanyComInfo(); + String _id = Util.null2String(params.get("id")); + String subcompanyid = Util.null2String(params.get("subcompanyid")); + boolean isEdit = false; + + List workSectionList = new ArrayList<>(); + Map groupSectionMaps = new HashMap<>();//分组用的map + Map sectionMaps = new HashMap<>(); + Map sectionMap = new HashMap<>(); + + //现在休息时段还是只能设置一个的,对于以后可能出现的多个休息时段预留这个map + List restSectionsList = new ArrayList<>(); + Map restSectionsMap = new HashMap<>(); + + String[] fields = new String[]{"serial,125818,1,1","subcompanyid,141,3,169","shiftonoffworkcount,388563,5,3","punchsettings,388564,4,1", + "rest_shift,536771,4,2", + "isresttimeopen,388565,4,2","restbeigin,388566,3,19","restend,388567,3,19","halfcalrule,513090,5,1","cardRemind,507833,4,2","cardRemOfSignIn,507835,5,1", + "minsBeforeSignIn,510106,1,2","cardRemOfSignOut,507837,5,1","minsAfterSignOut,510108,1,2","remindMode,501471,5,3","remindOnPC,513233,4,2", + "isoffdutyfreecheck,388568,4,2","halfcalpoint,513145,3,19","halfcalpoint2cross,513090,5,1"}; + + Map shiftValMap = new HashMap<>(); + if(_id.length() > 0){ + String getShiftInfo = "select * from kq_ShiftManagement where (isdelete is null or isdelete <> '1') and id = ?"; + rs.executeQuery(getShiftInfo, _id); + if(rs.next()){ + for(int i = 0 ; i < fields.length ; i++){ + String[] tmpField = Util.null2String(fields[i]).split(","); + String fieldname = tmpField[0]; + String fieldvalue = rs.getString(fieldname); + if("shiftonoffworkcount".equalsIgnoreCase(fieldname) || + "punchsettings".equalsIgnoreCase(fieldname) || + "cardRemOfSignIn".equalsIgnoreCase(fieldname) || + "cardRemOfSignOut".equalsIgnoreCase(fieldname) || + "remindMode".equalsIgnoreCase(fieldname)){ + fieldvalue = Util.null2s(fieldvalue, "1"); + }else if("isresttimeopen".equalsIgnoreCase(fieldname) || + "halfcalrule".equalsIgnoreCase(fieldname) || + "cardRemind".equalsIgnoreCase(fieldname) || + "minsAfterSignOut".equalsIgnoreCase(fieldname) || + "remindOnPC".equalsIgnoreCase(fieldname) || + "isoffdutyfreecheck".equalsIgnoreCase(fieldname) || + "halfcalpoint".equalsIgnoreCase(fieldname) || + "halfcalpoint2cross".equalsIgnoreCase(fieldname)|| + "rest_shift".equalsIgnoreCase(fieldname)){ + fieldvalue = Util.null2s(fieldvalue, "0"); + }else if("minsBeforeSignIn".equalsIgnoreCase(fieldname)){ + fieldvalue = Util.null2s(fieldvalue, "10"); + }else if("subcompanyid".equalsIgnoreCase(fieldname)){ + subcompanyid = fieldvalue; + } + shiftValMap.put(fieldname, fieldvalue); + } + } + + String getWorkSections = "select * from kq_ShiftOnOffWorkSections where (isdelete is null or isdelete <> '1') and serialid = ? order by record "; + rs.executeQuery(getWorkSections, _id); + while(rs.next()){ + String record = rs.getString("record"); + if(record.length() == 0) { + continue; + } + + String onoffworktype = Util.null2String(rs.getString("onoffworktype")); + String across = Util.null2String(rs.getString("across")); + String times = Util.null2String(rs.getString("times")); + String mins = Util.null2String(rs.getString("mins")); + String mins_next = Util.null2String(rs.getString("mins_next")); + sectionMap = new HashMap<>(); + sectionMaps = new HashMap<>(); + sectionMap.put("across", across); + sectionMap.put("times", times); + sectionMap.put("mins", mins); + sectionMap.put("mins_next", mins_next); + sectionMaps.put(onoffworktype, sectionMap); + if(groupSectionMaps.get(record) != null){ + List tmpSections = (List) groupSectionMaps.get(record); + ((Map)tmpSections.get(tmpSections.size()-1)).putAll(sectionMaps); + }else{ + sectionMaps.put("record", record); + workSectionList.add(sectionMaps); + groupSectionMaps.put(record, workSectionList); + } + } + + String getRestSections = "select * from kq_ShiftRestTimeSections where (isdelete is null or isdelete <> '1') and serialid = ? "; + rs.executeQuery(getRestSections, _id); + while(rs.next()){ + String resttype = Util.null2String(rs.getString("resttype")); + String across = Util.null2String(rs.getString("across")); + String times = Util.null2String(rs.getString("time")); + restSectionsMap = new HashMap<>(); + restSectionsMap.put("resttype", resttype); + restSectionsMap.put("time", times); + restSectionsMap.put("across", across); + restSectionsList.add(restSectionsMap); + if("start".equalsIgnoreCase(resttype)){ + shiftValMap.put("restbeigin", times); + }else if("end".equalsIgnoreCase(resttype)){ + shiftValMap.put("restend", times); + } + } + isEdit = true; + } + + //班次名称 所属机构(开启分权有所属机构) 一天内上下班次数 打卡时段是否开启 排除休息时间是否开启 休息开始时间 休息结束时间 允许下班不打卡 + HrmFieldBean hrmFieldBean = null; + + HrmFieldSearchConditionComInfo hrmFieldSearchConditionComInfo = new HrmFieldSearchConditionComInfo(); + SearchConditionItem searchConditionItem = null; + List options = new ArrayList(); + + groupitem = new HashMap(); + + itemlist = new ArrayList(); + for (int j = 0; j < fields.length; j++) { + options = new ArrayList(); + String[] tmpField = Util.null2String(fields[j]).split(","); + String fieldname = tmpField[0]; + String beanVal = Util.null2String(shiftValMap.get(fieldname)); + hrmFieldBean = new HrmFieldBean(); + hrmFieldBean.setFieldname(fieldname); + hrmFieldBean.setFieldlabel(tmpField[1]); + hrmFieldBean.setFieldhtmltype(tmpField[2]); + hrmFieldBean.setType(tmpField[3]); + hrmFieldBean.setIsFormField(true); + + if("serial".equalsIgnoreCase(tmpField[0]) || "restbeigin".equalsIgnoreCase(tmpField[0]) || "restend".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setViewAttr(3); + hrmFieldBean.setRules("required|string"); + } + if("shiftonoffworkcount".equalsIgnoreCase(tmpField[0]) || "restbeigin".equalsIgnoreCase(tmpField[0]) || "restend".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setRules("required|string"); + if(!isEdit){ + if("restbeigin".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setFieldvalue("12:00"); + } + if("restend".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setFieldvalue("13:00"); + } + } + } +// if("color".equalsIgnoreCase(tmpField[0])){ +// hrmFieldBean.setTip(SystemEnv.getHtmlLabelName(389509, user.getLanguage())); +// } + if(!isEdit){ + if("isresttimeopen".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setFieldvalue("0"); + } + if("isoffdutyfreecheck".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setFieldvalue("0"); + } + if("punchsettings".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setFieldvalue("1"); + } +// if("color".equalsIgnoreCase(tmpField[0])){ +// hrmFieldBean.setFieldvalue("#000"); +// } + if("cardRemOfSignIn".equals(hrmFieldBean.getFieldname())){ + beanVal = "1"; + } + if("minsBeforeSignIn".equals(hrmFieldBean.getFieldname())){ + beanVal = "10"; + } + if("cardRemOfSignOut".equals(hrmFieldBean.getFieldname())){ + beanVal = "1"; + } + if("minsAfterSignOut".equals(hrmFieldBean.getFieldname())){ + beanVal = "0"; + } + if("remindMode".equals(hrmFieldBean.getFieldname())){ + beanVal = "1"; + } + if("halfcalrule".equals(hrmFieldBean.getFieldname())){ + hrmFieldBean.setFieldvalue("0"); + } + if("halfcalpoint2cross".equals(hrmFieldBean.getFieldname())){ + hrmFieldBean.setFieldvalue("0"); + } + if("rest_shift".equals(hrmFieldBean.getFieldname())){ + hrmFieldBean.setFieldvalue("0"); + } + } + + if("shiftonoffworkcount".equals(tmpField[0])){ + SearchConditionOption SearchConditionOption_1 = new SearchConditionOption("1",SystemEnv.getHtmlLabelName(388569, user.getLanguage())); + SearchConditionOption SearchConditionOption_2 = new SearchConditionOption("2",SystemEnv.getHtmlLabelName(388570, user.getLanguage())); + SearchConditionOption SearchConditionOption_3 = new SearchConditionOption("3",SystemEnv.getHtmlLabelName(388571, user.getLanguage())); + if(isEdit){ + if("1".equalsIgnoreCase(beanVal)){ + SearchConditionOption_1.setSelected(true); + }else if("2".equalsIgnoreCase(beanVal)){ + SearchConditionOption_2.setSelected(true); + }else if("3".equalsIgnoreCase(beanVal)){ + SearchConditionOption_3.setSelected(true); + } + }else{ + SearchConditionOption_1.setSelected(true); + } + options.add(SearchConditionOption_1); + options.add(SearchConditionOption_2); + options.add(SearchConditionOption_3); + hrmFieldBean.setSelectOption(options); + } + if(isEdit){ + hrmFieldBean.setFieldvalue(beanVal); + } + if("subcompanyid".equals(tmpField[0])){ + if(hrmdetachable){ + hrmFieldBean.setViewAttr(3); + hrmFieldBean.setRules("required|string"); + String defaultSubcompanyid = ""; + int[] subcomids = newCheck.getSubComByUserRightId(user.getUID(),"KQClass:Management",0); + ManageDetachComInfo detachComInfo = new ManageDetachComInfo(); + if(detachComInfo.isUseHrmManageDetach()){ + defaultSubcompanyid = detachComInfo.getHrmdftsubcomid(); + }else{ + rs.executeProc("SystemSet_Select",""); + if(rs.next()){ + if(subcompanyid.length()==0||subcompanyid.equals("0")){ + defaultSubcompanyid = Util.null2String(rs.getString("dftsubcomid")); + } + } + } + + boolean hasRight = false; + for (int i = 0; subcomids!=null&& i < subcomids.length; i++) { + if((""+subcomids[i]).equals(defaultSubcompanyid)){ + hasRight = true; + break; + } + } + + if(!hasRight){ + defaultSubcompanyid = ""; + } + //表示左侧分部树选择了 + if(Util.getIntValue(Util.null2String(subcompanyid)) > 0){ + hrmFieldBean.setFieldvalue(subcompanyid); + }else{ + hrmFieldBean.setFieldvalue(defaultSubcompanyid); + } + + }else{ + //不开启分权的话,不显示分部 + continue; + } + } + if("punchsettings".equalsIgnoreCase(tmpField[0])){ + hrmFieldBean.setFieldvalue("1"); + } + searchConditionItem = hrmFieldSearchConditionComInfo.getSearchConditionItem(hrmFieldBean, user); + if("shiftonoffworkcount".equals(tmpField[0])){ +// searchConditionItem.setHelpfulTip(SystemEnv.getHtmlLabelName(388574, user.getLanguage())); + } + if("isoffdutyfreecheck".equals(tmpField[0])){ + searchConditionItem.setHelpfulTip(SystemEnv.getHtmlLabelName(388573, user.getLanguage())); + } + if(hrmdetachable && "subcompanyid".equals(tmpField[0])){ + searchConditionItem.getBrowserConditionParam().getDataParams().put("rightStr", "KQClass:Management"); + searchConditionItem.getBrowserConditionParam().getCompleteParams().put("rightStr", "KQClass:Management"); + } + if("cardRemOfSignIn".equals(hrmFieldBean.getFieldname())){ + List optionsList = new ArrayList(); + optionsList.add(new SearchConditionOption("0", SystemEnv.getHtmlLabelName(19782, user.getLanguage()), "0".equals(beanVal))); + optionsList.add(new SearchConditionOption("1", SystemEnv.getHtmlLabelName(510106, user.getLanguage()), "1".equals(beanVal))); + searchConditionItem.setOptions(optionsList); + searchConditionItem.setValue(beanVal); + } + if("minsBeforeSignIn".equals(hrmFieldBean.getFieldname())||"minsAfterSignOut".equals(hrmFieldBean.getFieldname())){ + searchConditionItem.setValue(beanVal); + searchConditionItem.setMin("0"); + searchConditionItem.setViewAttr(3); + searchConditionItem.setRules("required|integer"); + } + if("cardRemOfSignOut".equals(hrmFieldBean.getFieldname())){ + List optionsList = new ArrayList(); + optionsList.add(new SearchConditionOption("0", SystemEnv.getHtmlLabelName(19782, user.getLanguage()), "0".equals(beanVal))); + optionsList.add(new SearchConditionOption("1", SystemEnv.getHtmlLabelName(510108, user.getLanguage()), "1".equals(beanVal))); + searchConditionItem.setOptions(optionsList); + searchConditionItem.setValue(beanVal); + } + if("remindMode".equals(hrmFieldBean.getFieldname())){ + List optionsList = new ArrayList(); + optionsList.add(new SearchConditionOption("1", SystemEnv.getHtmlLabelName(383607, user.getLanguage()), "1".equals(beanVal))); + optionsList.add(new SearchConditionOption("2", SystemEnv.getHtmlLabelName(18845, user.getLanguage()), "2".equals(beanVal))); + optionsList.add(new SearchConditionOption("3", SystemEnv.getHtmlLabelName(17586, user.getLanguage()), "3".equals(beanVal))); + searchConditionItem.setOptions(optionsList); + searchConditionItem.setValue(beanVal); + } + if("halfcalrule".equals(hrmFieldBean.getFieldname())){ + List optionsList = new ArrayList(); + optionsList.add(new SearchConditionOption("0", SystemEnv.getHtmlLabelName(513091, user.getLanguage()), "0".equals(beanVal))); + optionsList.add(new SearchConditionOption("1", SystemEnv.getHtmlLabelName(513092, user.getLanguage()), "1".equals(beanVal))); + searchConditionItem.setOptions(optionsList); + } + if("halfcalpoint2cross".equals(hrmFieldBean.getFieldname())){ + List optionsList = new ArrayList(); + optionsList.add(new SearchConditionOption("0", SystemEnv.getHtmlLabelName(509159, user.getLanguage()), "0".equals(beanVal))); + optionsList.add(new SearchConditionOption("1", SystemEnv.getHtmlLabelName(388785, user.getLanguage()), "1".equals(beanVal))); + searchConditionItem.setOptions(optionsList); + } + searchConditionItem.setColSpan(1); + + itemlist.add(searchConditionItem); + } + groupitem.put("items", itemlist); + grouplist.add(groupitem); + int operatelevel = -1; + if(hrmdetachable){ + if(subcompanyid.length()>0 && !subcompanyid.equalsIgnoreCase("0")){ + CheckSubCompanyRight checkSubCompanyRight = new CheckSubCompanyRight(); + operatelevel=checkSubCompanyRight.ChkComRightByUserRightCompanyId(user.getUID(),"KQClass:Management",Util.getIntValue(subcompanyid,-1)); + } + }else{ + operatelevel = 2; + } + if(!isEdit){ + operatelevel = 2; + } + + if(user.getUID() == 1){ + operatelevel = 2; + } + if(operatelevel > 0){ + retmap.put("canAdd", true); + }else{ + retmap.put("canAdd", false); + } + retmap.put("status", "1"); + retmap.put("condition", grouplist); + retmap.put("workSections", workSectionList); + retmap.put("restTimeSections", restSectionsList); + if(shift_24()){ + retmap.put("shift_24", "1"); + }else{ + retmap.put("shift_24", "0"); + } + retmap.put("id", _id); + } catch (Exception e) { + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + writeLog(e); + } + return retmap; + } + + /** + * 班次是否放开24小时制 + * @return + */ + public boolean shift_24() { + boolean shift_24 = false; + RecordSet rs = new RecordSet(); + String settingSql = "select * from KQ_SETTINGS where main_key='shift_24'"; + rs.executeQuery(settingSql); + if(rs.next()){ + String main_val = rs.getString("main_val"); + if("1".equalsIgnoreCase(main_val)){ + shift_24 = true; + } + } + return shift_24; + } +} diff --git a/src/com/engine/kq/cmd/shiftmanagement/SaveShiftManagementBaseFormCmd.java b/src/com/engine/kq/cmd/shiftmanagement/SaveShiftManagementBaseFormCmd.java new file mode 100644 index 0000000..8c2ba9e --- /dev/null +++ b/src/com/engine/kq/cmd/shiftmanagement/SaveShiftManagementBaseFormCmd.java @@ -0,0 +1,489 @@ +package com.engine.kq.cmd.shiftmanagement; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.engine.common.biz.AbstractCommonCommand; +import com.engine.common.biz.SimpleBizLogger; +import com.engine.common.constant.BizLogSmallType4Hrm; +import com.engine.common.constant.BizLogType; +import com.engine.common.entity.BizLogContext; +import com.engine.core.interceptor.CommandContext; +import com.engine.kq.biz.KQConfigComInfo; +import com.engine.kq.biz.KQGroupBiz; +import com.engine.kq.biz.KQGroupComInfo; +import com.engine.kq.biz.KQShiftManagementComInfo; +import com.engine.kq.biz.KQShiftOnOffWorkSectionComInfo; +import com.engine.kq.biz.KQShiftRestTimeSectionComInfo; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.UUID; +import weaver.common.StringUtil; +import weaver.conn.RecordSet; +import weaver.conn.RecordSetTrans; +import weaver.general.Util; +import weaver.hrm.HrmUserVarify; +import weaver.hrm.Reminder.KQAutoCardTask; +import weaver.hrm.User; +import weaver.hrm.common.database.dialect.DbDialectFactory; +import weaver.hrm.common.database.dialect.IDbDialectSql; +import weaver.systeminfo.SystemEnv; + +/** + * 保存班次管理基本信息表单 + * @author pzy + * + */ +public class SaveShiftManagementBaseFormCmd extends AbstractCommonCommand>{ + + private SimpleBizLogger logger; + + public SaveShiftManagementBaseFormCmd() { + } + + public SaveShiftManagementBaseFormCmd(Map params, User user) { + this.user = user; + this.params = params; + this.logger = new SimpleBizLogger(); + BizLogContext logContext = new BizLogContext(); + logContext.setDateObject(new Date()); + logContext.setLogType(BizLogType.HRM_ENGINE); + logContext.setBelongType(BizLogSmallType4Hrm.HRM_ENGINE_SHIFTMANAGER); + logContext.setLogSmallType(BizLogSmallType4Hrm.HRM_ENGINE_SHIFTMANAGER); + logContext.setParams(params); + logger.setUser(user);//当前操作人 + if(params != null && params.containsKey("data")){ + String datas = Util.null2String(params.get("data")); + JSONObject jsonObj = JSON.parseObject(datas); + String serialid = Util.null2String(jsonObj.get("id")); + + if(serialid.length() > 0){ + String mainSql = " select * from kq_ShiftManagement where id= "+serialid +" "; + logger.setMainSql(mainSql);//主表sql + logger.setMainPrimarykey("id");//主日志表唯一key + logger.setMainTargetNameColumn("serial"); + + SimpleBizLogger.SubLogInfo subLogInfo1 = logger.getNewSubLogInfo(); + String subSql1 = "select * from kq_ShiftOnOffWorkSections where serialid="+serialid; + subLogInfo1.setSubTargetNameColumn("times"); + subLogInfo1.setGroupId("0"); //所属分组, 按照groupid排序显示在详情中, 不设置默认按照add的顺序。 + subLogInfo1.setSubGroupNameLabel(27961); //在详情中显示的分组名称,不设置默认显示明细x + subLogInfo1.setSubSql(subSql1); + logger.addSubLogInfo(subLogInfo1); + + SimpleBizLogger.SubLogInfo subLogInfo = logger.getNewSubLogInfo(); + String subSql = " select * from kq_ShiftRestTimeSections where serialid = "+serialid; + subLogInfo.setSubSql(subSql); + subLogInfo.setSubTargetNameColumn("time"); + subLogInfo.setGroupId("1"); //所属分组, 按照groupid排序显示在详情中, 不设置默认按照add的顺序。 + subLogInfo.setSubGroupNameLabel(505603); //在详情中显示的分组名称,不设置默认显示明细x + logger.addSubLogInfo(subLogInfo); + logger.before(logContext); + } + } + + } + + @Override + public BizLogContext getLogContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getLogContexts() { + return logger.getBizLogContexts(); + } + + /** + * 获取日志对象的名称 + * @param id + * @param para2 + * @return + */ + public String getTargetName(String id,String para2){ + try { + return para2; + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + @Override + public Map execute(CommandContext commandContext) { + Map retmap = new HashMap(); + String datas = Util.null2String(params.get("data")); + JSONObject jsonObj = JSON.parseObject(datas); + String serialid = Util.null2String(jsonObj.get("id")); + if(!HrmUserVarify.checkUserRight("KQClass:Management",user)) { + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(2012, user.getLanguage())); + return retmap; + } + + try{ + if(serialid.length() > 0){ + edit(retmap,jsonObj); + }else{ + add(retmap,jsonObj); + } + KQShiftManagementComInfo kqShiftManagementComInfo = new KQShiftManagementComInfo(); + kqShiftManagementComInfo.removeShiftManagementCache(); + + if(retmap.containsKey("id")){ + KQConfigComInfo kqConfigComInfo = new KQConfigComInfo(); + String auto_card_cominfo = Util.null2String(kqConfigComInfo.getValue("auto_card_cominfo"),"0"); + if("1".equalsIgnoreCase(auto_card_cominfo)){ + String serial_id = Util.null2String(retmap.get("id")); + KQGroupBiz kqGroupBiz = new KQGroupBiz(); + List groupList = kqGroupBiz.getGroupIdByUesedSerialId(serial_id); + KQGroupComInfo kqGroupComInfo = new KQGroupComInfo(); + if(!groupList.isEmpty()){ + for(String groupId : groupList){ + String auto_checkin = kqGroupComInfo.getAuto_checkin(groupId); + String auto_checkout = kqGroupComInfo.getAuto_checkout(groupId); + if("1".equalsIgnoreCase(auto_checkout) || "1".equalsIgnoreCase(auto_checkin)){ + //当前班次存在自动打卡设置,修改班次后,不影响当天的自动打卡时间,变更后的班次自动打卡需要第二天才起作用 + retmap.put("message", "当前班次存在自动打卡设置,修改班次后,不影响当天的自动打卡时间,变更后的班次自动打卡需要第二天才起作用"); + break; + } + } + } + } + } + + }catch (Exception e){ + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + writeLog(e); + } + + return retmap; + } + + /** + * 编辑班次基本信息 + * @param retmap + * @param jsonObj + */ + public void edit(Map retmap,JSONObject jsonObj) throws Exception{ + RecordSetTrans rst = new RecordSetTrans(); + rst.setAutoCommit(true); + RecordSet rs = new RecordSet(); + String serialid = Util.null2String(jsonObj.get("id")); + String serial = Util.null2String(jsonObj.get("serial"));//班次名称 + String subcompanyid = Util.null2o(Util.null2String(jsonObj.get("subcompanyid"))); + int rest_shift = StringUtil.parseToInt(jsonObj.getString("rest_shift"),0);//休息班 + String shiftOnOffWorkCount = Util.null2o(Util.null2String(jsonObj.get("shiftonoffworkcount")));//一天内上下班次数 + String punchSettings = "1";//打卡时段是否开启 1表示开启 + String isOffDutyFreeCheck = Util.null2o(Util.null2String(jsonObj.get("isoffdutyfreecheck")));//允许下班不打卡 1表示开启 + String isRestTimeOpen = Util.null2o(Util.null2String(jsonObj.get("isresttimeopen")));//排除休息时间是否开启 1表示开启 + String worktime = Util.null2o(Util.null2String(jsonObj.get("worktime")));//工作时长 +// String color = Util.null2o(Util.null2String(jsonObj.get("color")));//工作时长 + String color = "#000"; + String cardRemind = Util.null2s(jsonObj.getString("cardRemind"),"0");//是否开启打卡提醒:0-不开启、1-开启。默认不开启 + String cardRemOfSignIn = Util.null2s(jsonObj.getString("cardRemOfSignIn"),"1");//上班打卡提醒:0-不提醒、1-自定义提前提醒分钟数。默认为1 + String minsBeforeSignIn = Util.null2s(jsonObj.getString("minsBeforeSignIn"),"10");//自定义提前提醒分钟数。默认10分钟 + String cardRemOfSignOut = Util.null2s(jsonObj.getString("cardRemOfSignOut"),"1");//下班打卡提醒:0-不提醒、1-自定义延后提醒分钟数。默认为1 + String minsAfterSignOut = Util.null2s(jsonObj.getString("minsAfterSignOut"),"0");//自定义延后提醒分钟数。默认0分钟 + String remindMode = Util.null2s(jsonObj.getString("remindMode"),"1");//提醒方式:1-消息中心提醒、2-邮件提醒、3-短信提醒。默认消息中心提醒 + String remindOnPC = Util.null2s(jsonObj.getString("remindOnPC"),"0");//登陆PC端弹窗提醒:0-不开启、1-开启 + + String halfcalrule = Util.null2s(jsonObj.getString("halfcalrule"),"0");//半天计算规则 + String halfcalpoint = Util.null2s(jsonObj.getString("halfcalpoint"),"");//半天分界点 + String halfcalpoint2cross = Util.null2s(jsonObj.getString("halfcalpoint2cross"),"0");//当日 + + + if(duplicationCheck(serial,serialid)){ + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(389019,user.getLanguage())); + return ; + } + String[] works = new String[]{"start","end"}; + JSONArray workSections = (JSONArray)jsonObj.get("workSections"); + checkRule(retmap,workSections,works); + + if(!retmap.isEmpty()){ + return ; + } + + String mainSql = "update kq_ShiftManagement set serial=?,subcompanyid=?,shiftonoffworkcount=?,punchsettings=?,isoffdutyfreecheck=?,isresttimeopen=?,worktime=?,color=?," + + "cardRemind=? ,cardRemOfSignIn=? ,minsBeforeSignIn=? ,cardRemOfSignOut=? ,minsAfterSignOut=? ,remindMode=? ,remindOnPC=?,halfcalrule=?,halfcalpoint=?,halfcalpoint2cross=?,rest_shift= ? where id = ? "; + + boolean isUpdated = rst.executeUpdate(mainSql, serial,subcompanyid,shiftOnOffWorkCount,punchSettings,isOffDutyFreeCheck,isRestTimeOpen,worktime,color, + cardRemind ,cardRemOfSignIn ,minsBeforeSignIn ,cardRemOfSignOut ,minsAfterSignOut ,remindMode ,remindOnPC,halfcalrule,halfcalpoint,halfcalpoint2cross,rest_shift,serialid); + + if(isUpdated){ + //对于休息时间和工作时间,直接删除后重新创建 + String delRestSql = "delete from kq_ShiftRestTimeSections where serialid = ? "; + rs = new RecordSet(); + rst.executeUpdate(delRestSql, serialid); + String delWorkSql = "delete from kq_ShiftOnOffWorkSections where serialid = ? "; + rs = new RecordSet(); + rst.executeUpdate(delWorkSql, serialid); + + //休息时间 resttype:start开始时间,end结束时间 + JSONArray restTimeSections = (JSONArray)jsonObj.get("restTimeSections"); + //工作时间 across是否跨天,1表示跨天;beginMin上班前分钟数开始签到,endMin下班后分钟数停止签退;times具体上下班时间;onOffWorkType:start开始时间,end结束时间 + + String restSql = "insert into kq_ShiftRestTimeSections(serialid,resttype,time,across) values(?,?,?,?)"; + int restCount = restTimeSections.size(); + rs = new RecordSet(); + for(int i = 0 ; i < restCount ; i++){ + JSONObject jsonRest = ((JSONObject)restTimeSections.get(i)); + String time=Util.null2String(jsonRest.get("time")); + String resttype=Util.null2String(jsonRest.get("resttype")); + String across=Util.null2String(jsonRest.get("across")); + rst.executeUpdate(restSql, serialid,resttype,time,across); + } + rs = new RecordSet(); + String workSql = "insert into kq_ShiftOnOffWorkSections(serialid,across,mins,times,onoffworktype,record,mins_next) values(?,?,?,?,?,?,?)"; + int workCount = workSections.size(); + for(int i = 0 ; i < workCount ; i++){ + JSONObject jsonWork = ((JSONObject)workSections.get(i)); + String record = Util.null2String(jsonWork.get("record")); + for(int j = 0 ; j < works.length ; j++){ + String onOffWorkType=works[j]; + JSONObject inWork=(JSONObject)jsonWork.get(onOffWorkType); + String across=Util.null2String(inWork.get("across")); + String mins = Util.null2s(Util.null2String(inWork.get("mins")),"0"); + String times=Util.null2String(inWork.get("times")); + String mins_next=Util.null2String(inWork.get("mins_next")); + rst.executeUpdate(workSql, serialid,across,mins,times,onOffWorkType,record,mins_next); + } + } + retmap.put("id", serialid); + retmap.put("status", "1"); + retmap.put("message", SystemEnv.getHtmlLabelName(18758, user.getLanguage())); + }else{ + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + } + + } + + /** + * 新增班次基本信息 + * @param retmap + * @param jsonObj + */ + public void add(Map retmap,JSONObject jsonObj) throws Exception{ + RecordSetTrans rst = new RecordSetTrans(); + rst.setAutoCommit(true); + RecordSet rs = new RecordSet(); + String subcompanyid = Util.null2o(Util.null2String(jsonObj.get("subcompanyid"))); + int rest_shift = StringUtil.parseToInt(jsonObj.getString("rest_shift"),0);//休息班 + String serial = Util.null2String(jsonObj.get("serial"));//班次名称 + String shiftOnOffWorkCount = Util.null2o(Util.null2String(jsonObj.get("shiftonoffworkcount")));//一天内上下班次数 + String punchSettings = "1";//打卡时段是否开启 1表示开启 + String isOffDutyFreeCheck = Util.null2o(Util.null2String(jsonObj.get("isoffdutyfreecheck")));//允许下班不打卡 1表示开启 + String isRestTimeOpen = Util.null2o(Util.null2String(jsonObj.get("isresttimeopen")));//排除休息时间是否开启 1表示开启 + String worktime = Util.null2o(Util.null2String(jsonObj.get("worktime")));//工作时长 +// String color = Util.null2o(Util.null2String(jsonObj.get("color")));//工作时长 + String color = "#000"; + String uuid = UUID.randomUUID().toString();//uuid供查询使用 + String cardRemind = Util.null2s(jsonObj.getString("cardRemind"),"0");//是否开启打卡提醒:0-不开启、1-开启。默认不开启 + String cardRemOfSignIn = Util.null2s(jsonObj.getString("cardRemOfSignIn"),"1");//上班打卡提醒:0-不提醒、1-自定义提前提醒分钟数。默认为1 + String minsBeforeSignIn = Util.null2s(jsonObj.getString("minsBeforeSignIn"),"10");//自定义提前提醒分钟数。默认10分钟 + String cardRemOfSignOut = Util.null2s(jsonObj.getString("cardRemOfSignOut"),"1");//下班打卡提醒:0-不提醒、1-自定义延后提醒分钟数。默认为1 + String minsAfterSignOut = Util.null2s(jsonObj.getString("minsAfterSignOut"),"0");//自定义延后提醒分钟数。默认0分钟 + String remindMode = Util.null2s(jsonObj.getString("remindMode"),"1");//提醒方式:1-消息中心提醒、2-邮件提醒、3-短信提醒。默认消息中心提醒 + String remindOnPC = Util.null2s(jsonObj.getString("remindOnPC"),"0");//登陆PC端弹窗提醒:0-不开启、1-开启 + + String halfcalrule = Util.null2s(jsonObj.getString("halfcalrule"),"0");//半天计算规则 + String halfcalpoint = Util.null2s(jsonObj.getString("halfcalpoint"),"");//半天分界点 + String halfcalpoint2cross = Util.null2s(jsonObj.getString("halfcalpoint2cross"),"0");//当日 + + if(duplicationCheck(serial,"")){ + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(389019,user.getLanguage())); + return ; + } + //工作时间 across是否跨天,1表示跨天;beginMin上班前分钟数开始签到,endMin下班后分钟数停止签退;times具体上下班时间;onOffWorkType:start开始时间,end结束时间 + + JSONArray workSections = (JSONArray)jsonObj.get("workSections"); + String[] works = new String[]{"start","end"}; + checkRule(retmap,workSections,works); + + if(!retmap.isEmpty()){ + return ; + } + //color改为前台获取 +// String color = getRandomColor(); + boforeLog(uuid); + + String mainSql = "insert into kq_ShiftManagement(serial,subcompanyid,shiftonoffworkcount,punchsettings,isoffdutyfreecheck,isresttimeopen,worktime,uuid,color," + + "cardRemind ,cardRemOfSignIn ,minsBeforeSignIn ,cardRemOfSignOut ,minsAfterSignOut ,remindMode ,remindOnPC,halfcalrule,halfcalpoint,halfcalpoint2cross,rest_shift)" + + " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + boolean isUpdated = rst.executeUpdate(mainSql, serial,subcompanyid,shiftOnOffWorkCount,punchSettings,isOffDutyFreeCheck,isRestTimeOpen,worktime,uuid,color, + cardRemind ,cardRemOfSignIn ,minsBeforeSignIn ,cardRemOfSignOut ,minsAfterSignOut ,remindMode ,remindOnPC,halfcalrule,halfcalpoint,halfcalpoint2cross,rest_shift); + + if(isUpdated){ + int serialid = 0; + String idSql = "select id from kq_ShiftManagement where uuid=? and (isdelete is null or isdelete <> '1') "; + rs = new RecordSet(); + rs.executeQuery(idSql,uuid); + if(rs.next()) { + serialid = rs.getInt("id"); + } + + if(serialid > 0){ + + //休息时间 resttype:start开始时间,end结束时间 + JSONArray restTimeSections = (JSONArray)jsonObj.get("restTimeSections"); + + String restSql = "insert into kq_ShiftRestTimeSections(serialid,resttype,time,across) values(?,?,?,?)"; + int restCount = restTimeSections.size(); + rs = new RecordSet(); + for(int i = 0 ; i < restCount ; i++){ + JSONObject jsonRest = ((JSONObject)restTimeSections.get(i)); + String time=Util.null2String(jsonRest.get("time")); + String resttype=Util.null2String(jsonRest.get("resttype")); + String across=Util.null2String(jsonRest.get("across")); + rst.executeUpdate(restSql, serialid,resttype,time,across); + } + rs = new RecordSet(); + String workSql = "insert into kq_ShiftOnOffWorkSections(serialid,across,mins,times,onoffworktype,record,mins_next) values(?,?,?,?,?,?,?)"; + int workCount = workSections.size(); + for(int i = 0 ; i < workCount ; i++){ + JSONObject jsonWork = ((JSONObject)workSections.get(i)); + String record = Util.null2String(jsonWork.get("record")); + for(int j = 0 ; j < works.length ; j++){ + String onOffWorkType=works[j]; + JSONObject inWork=(JSONObject)jsonWork.get(onOffWorkType); + String across=Util.null2String(inWork.get("across")); + String mins = Util.null2s(Util.null2String(inWork.get("mins")),"1"); + String times=Util.null2String(inWork.get("times")); + String mins_next=Util.null2String(inWork.get("mins_next")); + rst.executeUpdate(workSql, serialid,across,mins,times,onOffWorkType,record,mins_next); + } + } + retmap.put("status", "1"); + retmap.put("id", serialid); + retmap.put("message", SystemEnv.getHtmlLabelName(18758, user.getLanguage())); + }else{ + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + } + }else{ + retmap.put("status", "-1"); + retmap.put("message", SystemEnv.getHtmlLabelName(382661,user.getLanguage())); + } + } + + private void checkRule(Map retmap, + JSONArray workSections, String[] works) { + for(int i = 0 ; i < workSections.size() ; i++) { + JSONObject jsonWork = ((JSONObject) workSections.get(i)); + for(int j = 0 ; j < works.length ; j++){ + String onOffWorkType=works[j]; + JSONObject inWork=(JSONObject)jsonWork.get(onOffWorkType); + String mins = Util.null2String(inWork.get("mins")); + if(mins.length() == 0 || Util.getIntValue(mins) == 0){ + retmap.put("status", "-1"); + retmap.put("message", ""+weaver.systeminfo.SystemEnv.getHtmlLabelName(10005343,weaver.general.ThreadVarLanguage.getLang())+""); + break; + } + } + } + } + + /** + * 判断是否重名 + * @param serial + * @param serialid 为空表示新增 + * @return + */ + private boolean duplicationCheck(String serial,String serialid){ + boolean isDuplicated = false; + RecordSet rs = new RecordSet(); + String checkSql = "select 1 from kq_ShiftManagement where serial=? and (isdelete is null or isdelete <> '1') "; + if(serialid.length() > 0){ + checkSql += " and id != "+serialid; + } + rs.executeQuery(checkSql, Util.null2s(serial, "").trim()); + if(rs.next()){ + isDuplicated = true; + } + return isDuplicated; + } + + /** + * 生成随机的颜色 + * @return + */ + private String getRandomColor(){ + + RecordSet rs = new RecordSet(); + List colorLists = new ArrayList<>(); + String hasSameColor = "select color from kq_ShiftManagement group by color "; + rs.executeQuery(hasSameColor); + while (rs.next()){ + colorLists.add(rs.getString("color")); + } + + String color = ""; + Random random = null; + + int i = 0 ; +// while(true){ +// random = new Random(); +// //颜色就要深色的 +// String[] colors = new String[]{"0","1","2","3","4","5","6"}; +// int not_r = random.nextInt(16); +// int not_g = random.nextInt(16); +// int not_b = random.nextInt(16); +// int not_r1 = random.nextInt(16); +// int not_g1 = random.nextInt(16); +// int not_b1 = random.nextInt(16); +// color = "#"+colors[not_r]+colors[not_g]+colors[not_b]+colors[not_r1]+colors[not_g1]+colors[not_b1]; +// //以防死锁 +// if(i > 1000){ +// break; +// } +// if(!colorLists.contains(color)){ +// break; +// } +// i++; +// } + + return color; + } + + public void boforeLog(String uuid){ + BizLogContext logContext = new BizLogContext(); + logContext.setDateObject(new Date()); + logContext.setLogType(BizLogType.HRM_ENGINE); + logContext.setBelongType(BizLogSmallType4Hrm.HRM_ENGINE_SHIFTMANAGER); + logContext.setLogSmallType(BizLogSmallType4Hrm.HRM_ENGINE_SHIFTMANAGER); + logContext.setParams(params); + + String log_mainSql = " select * from kq_ShiftManagement where uuid in('"+uuid+"')"; + logger.setMainSql(log_mainSql);//主表sql + logger.setMainPrimarykey("id");//主日志表唯一key + logger.setMainTargetNameColumn("serial"); + + SimpleBizLogger.SubLogInfo subLogInfo1 = logger.getNewSubLogInfo(); + String subSql1 = "select * from kq_ShiftOnOffWorkSections where serialid in (select id from kq_ShiftManagement where uuid in('"+uuid+"'))" ; + subLogInfo1.setSubTargetNameColumn("times"); + subLogInfo1.setGroupId("0"); //所属分组, 按照groupid排序显示在详情中, 不设置默认按照add的顺序。 + subLogInfo1.setSubGroupNameLabel(27961); //在详情中显示的分组名称,不设置默认显示明细x + subLogInfo1.setSubSql(subSql1); + logger.addSubLogInfo(subLogInfo1); + + SimpleBizLogger.SubLogInfo subLogInfo = logger.getNewSubLogInfo(); + String subSql = " select * from kq_ShiftRestTimeSections where serialid in (select id from kq_ShiftManagement where uuid in('"+uuid+"'))" ; + subLogInfo.setSubSql(subSql); + subLogInfo.setSubTargetNameColumn("time"); + subLogInfo.setGroupId("1"); //所属分组, 按照groupid排序显示在详情中, 不设置默认按照add的顺序。 + subLogInfo.setSubGroupNameLabel(505603); //在详情中显示的分组名称,不设置默认显示明细x + logger.addSubLogInfo(subLogInfo); + logger.before(logContext); + } +} diff --git a/src/com/engine/kq/entity/WorkTimeEntity.java b/src/com/engine/kq/entity/WorkTimeEntity.java new file mode 100644 index 0000000..b358c44 --- /dev/null +++ b/src/com/engine/kq/entity/WorkTimeEntity.java @@ -0,0 +1,136 @@ +package com.engine.kq.entity; + +import java.util.List; +import java.util.Map; + +/*** + * 工作时间 + */ +public class WorkTimeEntity { + private String groupId;//所属考勤组 + private String groupName;//所属考勤组 + private String kqType;//考勤类型 + private String serialId;//班次 + private Map shiftRuleInfo;//班次人性化规则 + private List signTime;//允许打卡时间 + private List workTime;//工作时间 + private List restTime;//休息时间 + private int workMins;//工作时长 + private String isAcross;//是否跨天 + private String signstart;//自由工时开始打卡时间 + private boolean isExclude;//无需考勤人员 + private String calmethod;//自由班制计算方式 + private int restShift; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public String getKQType() { + return kqType; + } + + public void setKQType(String kqType) { + this.kqType = kqType; + } + + public String getSerialId() { + return serialId; + } + + public void setSerialId(String serialId) { + this.serialId = serialId; + } + + public Map getShiftRuleInfo() { + return shiftRuleInfo; + } + + public void setShiftRuleInfo(Map shiftRuleInfo) { + this.shiftRuleInfo = shiftRuleInfo; + } + + public List getWorkTime() { + return workTime; + } + + public void setWorkTime(List workTime) { + this.workTime = workTime; + } + + public List getRestTime() { + return restTime; + } + + public void setRestTime(List restTime) { + this.restTime = restTime; + } + + public int getWorkMins() { + return workMins; + } + + public void setWorkMins(int workMins) { + this.workMins = workMins; + } + + public String getIsAcross() { + return isAcross; + } + + public void setIsAcross(String isAcross) { + this.isAcross = isAcross; + } + + public String getSignStart() { + return signstart; + } + + public void setSignStart(String signstart) { + this.signstart = signstart; + } + + public List getSignTime() { + return signTime; + } + + public void setSignTime(List signTime) { + this.signTime = signTime; + } + + public boolean getIsExclude() { + return isExclude; + } + + public void setIsExclude(boolean isExclude) { + this.isExclude = isExclude; + } + + public String getCalmethod() { + return calmethod; + } + + public void setCalmethod(String calmethod) { + this.calmethod = calmethod; + } + +public int getRestShift() { + return restShift; +} + +public void setRestShift(int restShift) { + this.restShift = restShift; +} +} diff --git a/src/com/engine/kq/util/KQDurationCalculatorUtil.java b/src/com/engine/kq/util/KQDurationCalculatorUtil.java new file mode 100644 index 0000000..b9c8418 --- /dev/null +++ b/src/com/engine/kq/util/KQDurationCalculatorUtil.java @@ -0,0 +1,631 @@ +package com.engine.kq.util; + +import com.engine.kq.biz.KQLeaveRulesBiz; +import com.engine.kq.biz.KQLeaveRulesComInfo; +import com.engine.kq.biz.KQShiftManagementComInfo; +import com.engine.kq.biz.KQWorkTime; +import com.engine.kq.biz.chain.cominfo.ShiftInfoCominfoBean; +import com.engine.kq.biz.chain.duration.NonDayUnitSplitChain; +import com.engine.kq.biz.chain.duration.NonHalfUnitSplitChain; +import com.engine.kq.biz.chain.duration.NonHourUnitSplitChain; +import com.engine.kq.biz.chain.duration.NonWholeUnitSplitChain; +import com.engine.kq.biz.chain.duration.NonWorkDurationChain; +import com.engine.kq.biz.chain.duration.WorkDayUnitSplitChain; +import com.engine.kq.biz.chain.duration.WorkDurationChain; +import com.engine.kq.biz.chain.duration.WorkHalfUnitSplitChain; +import com.engine.kq.biz.chain.duration.WorkHourUnitSplitChain; +import com.engine.kq.biz.chain.duration.WorkWholeUnitSplitChain; +import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; +import com.engine.kq.enums.DurationTypeEnum; +import com.engine.kq.log.KQLog; +import com.engine.kq.wfset.bean.SplitBean; +import com.engine.kq.wfset.util.KQFlowUtil; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import weaver.common.StringUtil; +import weaver.general.BaseBean; +import weaver.general.Util; +import weaver.hrm.User; +import weaver.hrm.report.schedulediff.HrmScheduleDiffUtil; + +public class KQDurationCalculatorUtil extends BaseBean { + private KQLog kqLog = new KQLog(); + + private final String resourceid; + private String fromDate; + private String toDate; + private String fromTime; + private String toTime; + private String newLeaveType; + /** + * 获取最小计算单位 + * 1-按天计算 + * 2-按半天计算 + * 3-按小时计算 + * 4-按整天计算 + */ + private String durationrule; + /** + * 1-按工作日计算计算时长 + * 2-按自然日计算计算时长 + */ + private String computingMode; + + /** + * 加班类型 + */ + private String overtime_type; + + private DurationTypeEnum durationTypeEnum; + + //外部类的构造函数 + private KQDurationCalculatorUtil(DurationParamBuilder build){ + this.resourceid = build.resourceid; + this.fromDate = build.fromDate; + this.toDate = build.toDate; + this.fromTime = build.fromTime; + this.toTime = build.toTime; + this.newLeaveType = build.newLeaveType; + this.durationrule = build.durationrule; + this.computingMode = build.computingMode; + this.durationTypeEnum = build.durationTypeEnum; + this.overtime_type = build.overtime_type; + } + + /** + * 根据人和指定的日期获取办公时段 + * @param resourceid + * @param date + * @param containYesterday + * @return + */ + public static ShiftInfoBean getWorkTime(String resourceid, String date,boolean containYesterday){ + User user = User.getUser(Util.getIntValue(resourceid), 0); + if(user == null){ + return null; + } + return getWorkTime(user, date,containYesterday); + } + + public static ShiftInfoBean getWorkTimeNew(String resourceid, String date,boolean containYesterday){ + User user = User.getUser(Util.getIntValue(resourceid), 0); + if(user == null){ + return null; + } + return getWorkTime(user, date, containYesterday, true, false); + } + + /** + * 不记录日志的,流程的超时提醒日志太大 + * @param resourceid + * @param date + * @param containYesterday + * @param isLog + * @return + */ + public static ShiftInfoBean getWorkTime(String resourceid, String date,boolean containYesterday,boolean isLog){ + User user = User.getUser(Util.getIntValue(resourceid), 0); + if(user == null){ + return null; + } + return getWorkTime(user, date,containYesterday,isLog); + } + + public static ShiftInfoCominfoBean getShiftInfoCominfoBean(String resourceid, String date){ + KQWorkTime kqWorkTime = new KQWorkTime(); + Map kqWorkTimeMap = new HashMap<>(); + ShiftInfoCominfoBean shiftInfoCominfoBean = kqWorkTime.getShiftInfoCominfoBean(resourceid, date); + return shiftInfoCominfoBean; + } + + /** + * 直接根据user来获取 + * @param user + * @param date + * @param containYesterday + * @param isLog + * @return + */ + public static ShiftInfoBean getWorkTime(User user, String date,boolean containYesterday,boolean isLog){ + return getWorkTime(user, date, containYesterday, isLog, true); + } + + public static ShiftInfoBean getWorkTime(User user, String date,boolean containYesterday,boolean isLog, boolean isUsedRestShift){ + KQWorkTime kqWorkTime = new KQWorkTime(); + Map kqWorkTimeMap = new HashMap<>(); + kqWorkTimeMap = kqWorkTime.getWorkDuration(""+user.getUID(), date,containYesterday,isLog); + boolean isfree = "1".equalsIgnoreCase(Util.null2String(kqWorkTimeMap.get("isfree"))); + if(isfree){ + ShiftInfoBean shiftInfoBean = new ShiftInfoBean(); + shiftInfoBean.setIsfree(true); + String signStart = Util.null2String(kqWorkTimeMap.get("signStart")); + String workMins = Util.null2String(kqWorkTimeMap.get("workMins")); + shiftInfoBean.setFreeSignStart(signStart); + shiftInfoBean.setFreeWorkMins(workMins); + shiftInfoBean.setSplitDate(date); + if(signStart.length() > 0 && workMins.length() > 0){ + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm"); + LocalTime signLocalTime = LocalTime.parse(signStart, dateTimeFormatter); + shiftInfoBean.setFreeSignEnd(signLocalTime.plusMinutes(Util.getIntValue(workMins)).format(dateTimeFormatter)); + shiftInfoBean.setFreeSignMiddle(signLocalTime.plusMinutes(Util.getIntValue(workMins)/2).format(dateTimeFormatter)); + } + + return shiftInfoBean; + }else{ + if(kqWorkTimeMap.get("shiftInfoBean") != null){ + ShiftInfoBean shiftInfoBean = (ShiftInfoBean)kqWorkTimeMap.get("shiftInfoBean"); + if(isUsedRestShift) { + int serialid = Util.getIntValue(Util.null2String(shiftInfoBean.getSerialid()), 0); + KQShiftManagementComInfo kQShiftManagementComInfo = new KQShiftManagementComInfo(); + int restShift = StringUtil.parseToInt(kQShiftManagementComInfo.getRestShift(String.valueOf(serialid)), 0); + if(restShift == 1) { + return null; + } + } + return shiftInfoBean; + }else{ + return null; + } + } + } + + /** + * 直接根据user来获取 + * @param user + * @param date + * @param containYesterday + * @return + */ + public static ShiftInfoBean getWorkTime(User user, String date,boolean containYesterday){ + return getWorkTime(user, date, containYesterday, true); + } + + public static Map getWorkButton(String resourceid, String date, boolean containYesterday){ + User user = User.getUser(Util.getIntValue(resourceid), 0); + return getWorkButton(user,date,containYesterday); + } + + public static Map getWorkButton(User user, String date, boolean containYesterday){ + KQWorkTime kqWorkTime = new KQWorkTime(); + Map kqWorkTimeMap = new HashMap<>(); + kqWorkTimeMap = kqWorkTime.getWorkButton(""+user.getUID(), date,containYesterday); + + return kqWorkTimeMap; + } + + /** + * 根据传入的用户和时段返回非工作时长 + * @return + */ + public Map getNonWorkDuration(){ + + Map durationMap = new HashMap<>(); + try{ + double D_Duration = 0.0; + double Min_Duration = 0.0; + //公众假日加班时长 + double D_Pub_Duration = 0.0; + double D_Pub_Mins = 0.0; + //工作日加班时长 + double D_Work_Duration = 0.0; + double D_Work_Mins = 0.0; + //休息日加班时长 + double D_Rest_Duration = 0.0; + double D_Rest_Mins = 0.0; + + SplitBean splitBean = new SplitBean(); + splitBean.setFromDate(fromDate); + splitBean.setFromTime(fromTime); + splitBean.setToDate(toDate); + splitBean.setToTime(toTime); + splitBean.setResourceId(resourceid); + splitBean.setFromdatedb(fromDate); + splitBean.setTodatedb(toDate); + splitBean.setFromtimedb(fromTime); + splitBean.setTotimedb(toTime); + splitBean.setDurationrule(durationrule); + splitBean.setComputingMode(computingMode); + splitBean.setDurationTypeEnum(DurationTypeEnum.OVERTIME); + splitBean.setOvertime_type(overtime_type); + + List splitBeans = new ArrayList<>(); + + NonWorkDurationChain hourUnitSplitChain = new NonHourUnitSplitChain(splitBeans); + NonWorkDurationChain dayUnitSplitChain = new NonDayUnitSplitChain(splitBeans); + NonWorkDurationChain halfUnitSplitChain = new NonHalfUnitSplitChain(splitBeans); + NonWorkDurationChain wholeUnitSplitChain = new NonWholeUnitSplitChain(splitBeans); + + //设置执行链 + hourUnitSplitChain.setDurationChain(dayUnitSplitChain); + dayUnitSplitChain.setDurationChain(halfUnitSplitChain); + halfUnitSplitChain.setDurationChain(wholeUnitSplitChain); + //把初始数据设置进去 + hourUnitSplitChain.handleDuration(splitBean); + + //每一天的流程时长都在这里了,搞吧 + for(SplitBean sb : splitBeans){ +// * 1-公众假日、2-工作日、3-休息日 + int changeType = sb.getChangeType(); + double durations = Util.getDoubleValue(sb.getDuration(), 0.0); + double durationMins = sb.getD_Mins(); + if(1 == changeType){ + D_Pub_Duration += durations; + D_Pub_Mins += durationMins; + } + if(2 == changeType){ + D_Work_Duration += durations; + D_Work_Mins += durationMins; + } + if(3 == changeType){ + D_Rest_Duration += durations; + D_Rest_Mins += durationMins; + } + } + Min_Duration = D_Pub_Mins+D_Work_Mins+D_Rest_Mins; + + if("3".equalsIgnoreCase(durationrule) || "5".equalsIgnoreCase(durationrule) || "6".equalsIgnoreCase(durationrule)){ + double d_hour = Min_Duration/60.0; + durationMap.put("duration", KQDurationCalculatorUtil.getDurationRound(""+d_hour)); + }else { + double oneDayHour = KQFlowUtil.getOneDayHour(DurationTypeEnum.OVERTIME,""); + double d_day = Min_Duration/(oneDayHour * 60); + durationMap.put("duration", KQDurationCalculatorUtil.getDurationRound(""+d_day)); + } + + durationMap.put("min_duration", KQDurationCalculatorUtil.getDurationRound(""+Min_Duration)); + + }catch (Exception e){ + e.printStackTrace(); + } + return durationMap; + } + + /** + * 根据传入的用户和时段返回工作时长 + * @return + */ + public Map getWorkDuration(){ + + Map durationMap = new HashMap<>(); + try{ + if(!isValidate(fromDate,toDate,fromTime,toTime)){ + durationMap.put("duration", "0.0"); + return durationMap; + } + if(durationTypeEnum != DurationTypeEnum.COMMON_CAL){ + kqLog.info("getWorkDuration:"+durationTypeEnum.getDurationType()+":fromDate:"+fromDate+":toDate:"+toDate+":fromTime:"+fromTime+":toTime:"+toTime+":durationrule:"+durationrule+":computingMode:"+computingMode); + } + //如果是加班 + if(durationTypeEnum ==DurationTypeEnum.OVERTIME){ + return getNonWorkDuration(); + } + //时长 + double D_Duration = 0.0; + //分钟数 + double Min_Duration = 0.0; + + SplitBean splitBean = new SplitBean(); + splitBean.setFromDate(fromDate); + splitBean.setFromTime(fromTime); + splitBean.setToDate(toDate); + splitBean.setToTime(toTime); + splitBean.setResourceId(resourceid); + splitBean.setFromdatedb(fromDate); + splitBean.setTodatedb(toDate); + splitBean.setFromtimedb(fromTime); + splitBean.setTotimedb(toTime); + splitBean.setDurationrule(durationrule); + splitBean.setDurationTypeEnum(durationTypeEnum); + splitBean.setComputingMode(computingMode); + splitBean.setNewLeaveType(newLeaveType); + if("2".equalsIgnoreCase(computingMode)){ + double oneDayHour = KQFlowUtil.getOneDayHour(durationTypeEnum,newLeaveType); + splitBean.setOneDayHour(oneDayHour); + if(durationTypeEnum == DurationTypeEnum.LEAVE){ + //只有自然日 请假才有这个排除节假日、休息日的功能 + splitBean.setFilterholidays(KQLeaveRulesBiz.getFilterHolidays(splitBean.getNewLeaveType())); + } + } + if(durationTypeEnum ==DurationTypeEnum.LEAVE || durationTypeEnum ==DurationTypeEnum.LEAVEBACK){ + if(newLeaveType.length() > 0){ + KQLeaveRulesComInfo kqLeaveRulesComInfo = new KQLeaveRulesComInfo(); + String conversion = kqLeaveRulesComInfo.getConversion(newLeaveType); + splitBean.setConversion(conversion); + } + } + + List splitBeans = new ArrayList<>(); + + WorkDurationChain hourUnitSplitChain = new WorkHourUnitSplitChain(splitBeans); + WorkDurationChain dayUnitSplitChain = new WorkDayUnitSplitChain(splitBeans); + WorkDurationChain halfUnitSplitChain = new WorkHalfUnitSplitChain(splitBeans); + WorkDurationChain wholeUnitSplitChain = new WorkWholeUnitSplitChain(splitBeans); + + //设置执行链 + hourUnitSplitChain.setDurationChain(dayUnitSplitChain); + dayUnitSplitChain.setDurationChain(halfUnitSplitChain); + halfUnitSplitChain.setDurationChain(wholeUnitSplitChain); + //把初始数据设置进去 + hourUnitSplitChain.handleDuration(splitBean); + + //每一天的流程时长都在这里了,搞吧 + for(SplitBean sb : splitBeans){ + double durations = Util.getDoubleValue(sb.getDuration(), 0.0); + double min_durations = sb.getD_Mins(); + D_Duration += durations; + Min_Duration += min_durations; + } + + durationMap.put("duration", KQDurationCalculatorUtil.getDurationRound(""+D_Duration)); + durationMap.put("min_duration", KQDurationCalculatorUtil.getDurationRound(""+Min_Duration)); + + }catch (Exception e){ + e.printStackTrace(); + } + return durationMap; + } + + /** + * 校验是传入的参数数据是否正常 + * @return false 表示数据有误 + */ + private boolean isValidate(String fromDate,String toDate,String fromTime,String toTime) { + + if(fromDate.length() == 0 || toDate.length() == 0){ + return false; + } + if(fromTime.length() == 0 || toTime.length() == 0){ + return false; + } + + DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + String fromDateTime = fromDate+" "+fromTime+":00"; + String toDateTime = toDate+" "+toTime+":00"; + + LocalDateTime localFromDateTime = LocalDateTime.parse(fromDateTime,fullFormatter); + LocalDateTime localToDateTime = LocalDateTime.parse(toDateTime,fullFormatter); + + if(localFromDateTime.isAfter(localToDateTime) || localFromDateTime.isEqual(localToDateTime)){ + return false; + } + return true; + } + + /** + * 得到排除非工作时间的时长 + * @param fromDate + * @param fromTime + * @param toDate + * @param toTime + * @param resourceid + * @return + */ + public Map getTotalWorkingDurations(String fromDate,String fromTime,String toDate,String toTime,String resourceid){ + KQDurationCalculatorUtil kqDurationCalculatorUtil =new KQDurationCalculatorUtil.DurationParamBuilder(resourceid). + fromDateParam(fromDate).toDateParam(toDate).fromTimeParam(fromTime).toTimeParam(toTime).durationRuleParam("1") + .computingModeParam("1").durationTypeEnumParam(DurationTypeEnum.COMMON_CAL).build(); + + Map durationMap = kqDurationCalculatorUtil.getWorkDuration(); + return durationMap; + } + + /** + * 得到排除非工作时间的天数 + * @param fromDate + * @param fromTime + * @param toDate + * @param toTime + * @param resourceid + * @return + */ + public String getTotalWorkingDays(String fromDate,String fromTime,String toDate,String toTime,String resourceid){ + Map durationMap = getTotalWorkingDurations(fromDate,fromTime,toDate,toTime,resourceid); + + String duration4day = Util.null2s(Util.null2String(durationMap.get("duration")),"0"); + return KQDurationCalculatorUtil.getDurationRound(duration4day); + } + + /** + * 得到排除非工作时间的小时 + * @param fromDate + * @param fromTime + * @param toDate + * @param toTime + * @param resourceid + * @return + */ + public String getTotalWorkingHours(String fromDate,String fromTime,String toDate,String toTime,String resourceid){ + Map durationMap = getTotalWorkingDurations(fromDate,fromTime,toDate,toTime,resourceid); + String duration4min = Util.null2s(Util.null2String(durationMap.get("min_duration")),"0"); + double duration4hour = Util.getDoubleValue(duration4min)/60.0; + + return KQDurationCalculatorUtil.getDurationRound(duration4hour+""); + } + + /** + * 得到排除非工作时间的分钟 + * @param fromDate + * @param fromTime + * @param toDate + * @param toTime + * @param resourceid + * @return + */ + public String getTotalWorkingMins(String fromDate,String fromTime,String toDate,String toTime,String resourceid){ + Map durationMap = getTotalWorkingDurations(fromDate,fromTime,toDate,toTime,resourceid); + String duration4min = Util.null2s(Util.null2String(durationMap.get("min_duration")),"0"); + + return KQDurationCalculatorUtil.getDurationRound(duration4min+""); + } + + /** + * 得到非工作时间的天数 + * @param fromDate + * @param fromTime + * @param toDate + * @param toTime + * @param resourceid + * @return + */ + public String getTotalNonWorkingDays(String fromDate,String fromTime,String toDate,String toTime,String resourceid){ + KQDurationCalculatorUtil kqDurationCalculatorUtil =new KQDurationCalculatorUtil.DurationParamBuilder(resourceid). + fromDateParam(fromDate).toDateParam(toDate).fromTimeParam(fromTime).toTimeParam(toTime).computingModeParam("1"). + durationRuleParam("1").durationTypeEnumParam(DurationTypeEnum.OVERTIME).build(); + Map durationMap = kqDurationCalculatorUtil.getNonWorkDuration(); + + String duration = Util.null2String(durationMap.get("duration")); + return KQDurationCalculatorUtil.getDurationRound(duration); + } + + /** + * 得到非工作时间的小时 + * @param fromDate + * @param fromTime + * @param toDate + * @param toTime + * @param resourceid + * @return + */ + public String getTotalNonWorkingHours(String fromDate,String fromTime,String toDate,String toTime,String resourceid){ + KQDurationCalculatorUtil kqDurationCalculatorUtil =new KQDurationCalculatorUtil.DurationParamBuilder(resourceid). + fromDateParam(fromDate).toDateParam(toDate).fromTimeParam(fromTime).toTimeParam(toTime).computingModeParam("1"). + durationRuleParam("3").durationTypeEnumParam(DurationTypeEnum.OVERTIME).build(); + Map durationMap = kqDurationCalculatorUtil.getNonWorkDuration(); + + String duration = Util.null2String(durationMap.get("duration")); + return KQDurationCalculatorUtil.getDurationRound(duration); + } + + /** + * 考勤通用精度 2 + * @param duration + * @return + */ + public static String getDurationRound(String duration){ + if(HrmScheduleDiffUtil.isFromFlow()){ + return Util.round(duration,5) ; + } + return Util.round(duration, 2); + } + + /** + * 考勤流程中间表精度 5 + * @param duration + * @return + */ + public static String getDurationRound5(String duration){ + return Util.round(duration, 5); + } + + /** + * 针对可能存在的多种参数类型 创建参数静态内部类Builder + */ + public static class DurationParamBuilder { + + //必选变量 人员看怎么都是需要的 + private final String resourceid; + + //可选变量 + private String fromDate = ""; + private String toDate = ""; + private String fromTime = ""; + private String toTime = ""; + /** + * 请假用的请假类型 + */ + private String newLeaveType = ""; + /** + * 单位 + * 1-按天出差 + * 2-按半天出差 + * 3-按小时出差 + * 4-按整天出差 + */ + private String durationrule = ""; + /** + * 时长计算方式 + * 1-按照工作日计算请假时长 + * 2-按照自然日计算请假时长 + */ + private String computingMode = ""; + + /** + * 加班类型 + */ + private String overtime_type = ""; + + /** + * 哪种类型的时长计算,请假还是出差还是公出还是加班 + */ + private DurationTypeEnum durationTypeEnum; + + public DurationParamBuilder(String resourceid) { + this.resourceid = resourceid; + //初始化的时候需要把其他参数先清空下 + this.fromDate = ""; + this.toDate = ""; + this.fromTime = ""; + this.toTime = ""; + this.newLeaveType = ""; + this.durationrule = ""; + this.computingMode = ""; + this.overtime_type = ""; + } + + //成员方法返回其自身,所以可以链式调用 + public DurationParamBuilder fromDateParam(final String fromDate) { + this.fromDate = fromDate; + return this; + } + + public DurationParamBuilder toDateParam(final String toDate) { + this.toDate = toDate; + return this; + } + + public DurationParamBuilder fromTimeParam(final String fromTime) { + this.fromTime = fromTime; + return this; + } + + public DurationParamBuilder toTimeParam(final String toTime) { + this.toTime = toTime; + return this; + } + + public DurationParamBuilder newLeaveTypeParam(final String newLeaveType) { + this.newLeaveType = newLeaveType; + return this; + } + + public DurationParamBuilder durationRuleParam(final String durationrule) { + this.durationrule = durationrule; + return this; + } + public DurationParamBuilder computingModeParam(final String computingMode) { + this.computingMode = computingMode; + return this; + } + public DurationParamBuilder overtime_typeParam(final String overtime_type) { + this.overtime_type = overtime_type; + return this; + } + public DurationParamBuilder durationTypeEnumParam(final DurationTypeEnum durationTypeEnum) { + this.durationTypeEnum = durationTypeEnum; + return this; + } + + //Builder的build方法,返回外部类的实例 + public KQDurationCalculatorUtil build() { + return new KQDurationCalculatorUtil(this); + } + } + +}