package com.engine.kq.biz; import cn.hutool.core.convert.Convert; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.engine.jc.kq.AbnormalOvertimeRemind; import com.engine.kq.bean.KQRepeatBean; import com.engine.kq.biz.chain.shiftinfo.ShiftInfoBean; import com.engine.kq.entity.KQShiftRuleEntity; import com.engine.kq.entity.TimeScopeEntity; import com.engine.kq.entity.WorkTimeEntity; import com.engine.kq.enums.FlowReportTypeEnum; import com.engine.kq.jucailin.genid.IdGenerator; import com.engine.kq.log.KQLog; import com.engine.kq.util.KQLockAttendaUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.googlecode.aviator.AviatorEvaluator; import com.googlecode.aviator.Expression; import org.apache.commons.collections.CollectionUtils; 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.io.PrintWriter; import java.io.StringWriter; import java.sql.Timestamp; 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<>(); private static final String LOCK_DEGREE = Util.null2String(Prop.getPropValue("kqLockAttenda", "LOCK_DEGREE")); public Map formatKqDateByLock(String userId, String kqDate, int formatType) { Map resultMap = new HashMap<>(); //-1: 其他; 11:右键重新计算考勤数据; 12: 考勤自动和手动同步;13:钉钉同步或者导入; 14:云桥考勤同步 15: 考勤导入;16:排班更新 //17:考勤流程;18testkq.jsp直接触发的;19:考勤设置升级;20:计划任务执行。 //①在途的考勤流程可以正常提交归档报表能统计,管理员干预归档的流程报表能统计。 //②关账不影响考勤导入打卡数据,正常的打卡数据进入报表,导入、同步。 //③其他操作报表更新控制不生效,比如重新计算考勤,自动计算考勤。 // if (LOCK_DEGREE.equals("0")&&new KQLockAttendaUtil().checkLockStatus(userId, kqDate)) { // kqLog.info("锁定程度强控:人员考勤数据已被锁定,"+"userId:"+userId+":kqDate:"+kqDate+";formatType="+formatType); // if(formatType==12||formatType==13||formatType==14||formatType==15||formatType==17){ // return formatKqDate(userId, kqDate); // } // return resultMap; // } //最新确认逻辑:弱控只控制流程在锁定范围内不能提交,其他都可以重新计算考勤报表。 return formatKqDate(userId, kqDate); } /*** * 该方法不允许直接调用 * @param userId * @param kqDate * @return */ public Map formatKqDate(String userId, String kqDate) { //考勤报表增加锁定功能:弱控 //1、考勤流程控制,请假、出差、公出、补卡、加班、销假、考勤变更新建的流程不能提交,在途的流程可以正常提交归档报表能统计,管理员干预归档的流程报表能统计。 //2、关账不影响考勤导入打卡数据,正常的打卡数据进入报表。 //3、强控就是前2点锁定日期后也不能进入报表了 List> lsParam = new ArrayList<>(); boolean isKqReportHalfOpen = "1".equals(new KQSettingsComInfo().getMain_val("kq_report_half")); //非工作日处理 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; } // 强控 if (LOCK_DEGREE.equals("1")&&new KQLockAttendaUtil().checkLockStatus(userId, kqDate)) { kqLog.info("锁定程度强控:人员考勤数据已被锁定,"+"userId:"+userId+":kqDate:"+kqDate); 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 != null && workTime.getWorkMins() == 0 && workTime.getNonWorkShift() != 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,day_type,create_time,update_time,id,flowinfo)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; rs.executeUpdate(sql, nonlsParam); Long id = IdGenerator.generate(); String baseField = ""; if ("mysql".equalsIgnoreCase(rs.getDBType())){ baseField = "sysdate(),sysdate(),"+id; }else if ("oracle".equalsIgnoreCase(rs.getDBType())){ baseField = "SYSDATE,SYSDATE,"+id; }else if ("postgresql".equalsIgnoreCase(rs.getDBType())){ baseField = "now(),now(),"+id; }else{ baseField = "GETDATE(),GETDATE(),"+id; } 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,create_time,update_time,id)" + " 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,"; // if(isKqReportHalfOpen) { // sql+=" sum((on_absenteeismmins+off_absenteeismmins)) as absenteeism,sum(absenteeismmins) as absenteeismmins,"; // } else { sql+=" sum(case when absenteeismmins> 0 then 1 else 0 end) as absenteeism,sum(absenteeismmins) as absenteeismmins,"; // } sql+=" 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," +baseField+ " 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 = ""; String convertAttendDay = workTime != null ? Util.null2s(workTime.getConvertAttendDay(),"1.0") : "1.0"; 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) { if (rs.getDBType().equals("postgresql")) { 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+"":"")+",day_type,create_time,update_time,id,flowinfo,on_absenteeismmins,off_absenteeismmins) " + " values(?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?,?,?,?"+(definedField.length()>0?","+definedParam+"":"")+",?,?::timestamp,?::timestamp,?,?,?,?)"; }else{ 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+"":"")+",day_type,create_time,update_time,id,flowinfo,on_absenteeismmins,off_absenteeismmins) " + " 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); } String attendancedaysF = " (cast(sum(attendanceMins)AS decimal(10, 2))*"+Util.getDoubleValue(convertAttendDay)+")/sum(workmins) as attendancedays, sum(attendanceMins) as attendanceMins, "; String workF = " case when sum(workmins)>0 then "+convertAttendDay+" end as workdays, sum(workmins) as workmins,"; String belateminsF = " sum(case when belatemins> 0 then 1 else 0 end) as belate,sum(belatemins) as belatemins,"; String graveBeLateMinsF = " sum(case when graveBeLateMins> 0 then 1 else 0 end) as graveBeLate,sum(graveBeLateMins) as graveBeLateMins,"; String leaveearlyminsF = " sum(case when leaveearlymins> 0 then 1 else 0 end) as leaveearly,sum(leaveearlymins) as leaveearlymins,"; String graveLeaveEarlyMinsF = " sum(case when graveLeaveEarlyMins> 0 then 1 else 0 end) as graveLeaveEarly,sum(graveLeaveEarlyMins) as graveLeaveEarlyMins, "; String absenteeismminsF = " sum(case when absenteeismmins> 0 then 1 else 0 end) as absenteeism,sum(absenteeismmins) as absenteeismmins, "; String forgotcheckminsF = " sum(case when forgotcheckmins> 0 then 1 else 0 end) as forgotcheck,sum(forgotcheckmins) as forgotcheckmins,"; String forgotbeginworkcheckminsF = " sum(case when forgotbeginworkcheckmins> 0 then 1 else 0 end) as forgotbeginworkcheck,sum(forgotbeginworkcheckmins) as forgotbeginworkcheckmins "; String signF = " cast(sum(signmins)AS decimal(10, 2))/sum(workmins) as signdays, sum(signmins) as signmins,"; String onoffAbsenteeismminsF= " sum(case when on_absenteeismmins> 0 then 1 else 0 end) as on_absenteeismmins,sum(case when off_absenteeismmins> 0 then 1 else 0 end) as off_absenteeismmins "; if(1 == workTime.getNonWorkShift()){ attendancedaysF = " 0 as attendancedays, 0 as attendanceMins, "; workF = " 0 as workdays, 0 as workmins,"; belateminsF = " 0 as belate,0 as belatemins,"; graveBeLateMinsF = " 0 as graveBeLate,0 as graveBeLateMins,"; leaveearlyminsF = " 0 as leaveearly,0 as leaveearlymins,"; graveLeaveEarlyMinsF = " 0 as graveLeaveEarly,0 as graveLeaveEarlyMins, "; absenteeismminsF = " 0 as absenteeism,0 as absenteeismmins,"; forgotcheckminsF = " 0 as forgotcheck,0 as forgotcheckmins,"; forgotbeginworkcheckminsF = " 0 as forgotbeginworkcheck,0 as forgotbeginworkcheckmins "; signF = " 0 as signdays, 0 as signmins,"; onoffAbsenteeismminsF = " 0 as on_absenteeismmins, 0 as off_absenteeismmins "; } Long id = IdGenerator.generate(); String baseField = ""; if ("mysql".equalsIgnoreCase(rs.getDBType())){ baseField = " now(),now(),"+id; }else if ("oracle".equalsIgnoreCase(rs.getDBType())){ baseField = " sysdate,sysdate,"+id; }else if ("postgresql".equalsIgnoreCase(rs.getDBType())){ baseField = " now(),now(),"+id; }else{ baseField = " getdate(),getdate(),"+id; } 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+"":"")+",create_time,update_time,id,on_absenteeismmins,off_absenteeismmins) " + " select a.resourceid,kqdate,b.subcompanyid1,b.departmentid,b.jobtitle,groupid,serialid," + workF + attendancedaysF + signF + belateminsF + graveBeLateMinsF + leaveearlyminsF + graveLeaveEarlyMinsF + absenteeismminsF + forgotcheckminsF+ " sum(leaveMins) as leaveMins," + " sum(evectionMins) as evectionMins,sum(outMins) as outMins, " + forgotbeginworkcheckminsF + (definedField.length()>0?","+definedParamSum+"":"")+","+baseField+","+onoffAbsenteeismminsF+ " 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); } } // 晶测考勤二开 判断加班异常 AbnormalOvertimeRemind.remind(Convert.toInt(userId, 0), kqDate); }catch (Exception e) { kqLog.info("考勤重算报错:KQFormatData.Exception:"); StringWriter errorsWriter = new StringWriter(); e.printStackTrace(new PrintWriter(errorsWriter)); kqLog.info(errorsWriter.toString()); } return resultMap; } public List> format(String userId, String kqDate, WorkTimeEntity workTime, Map workFlowInfo, String uuid) { List> lsParam = new ArrayList<>(); List params = null; HashMap middleMap = new HashMap<>(); try { KQRepeatLengthContext.clear(); KQRepeatLengthContext.removeRepeatBeanLink(); KQRepeatLengthContext.removeRepeatBeanLinkRange(); Timestamp date = new Timestamp(System.currentTimeMillis()); KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo(); String nosign_is_absent = Util.null2String(kqSettingsComInfo.getMain_val("nosign_is_absent"),"1"); //默认不开启半天的特殊规则,如果开启,那么只要是半天的单位,并且申请考勤流程半天,那么实际出勤就是0.5天,不考虑迟到和早退。当天旷工的情况需要考虑,即如果另外半天是旷工,那么实际出勤自然也是0 String is_half = Util.null2String(kqSettingsComInfo.getMain_val("is_half"),"0"); String early_one_mins = Util.null2String(kqSettingsComInfo.getMain_val("early_one_mins"),"0"); 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(); boolean oneSign = false; List lsSignTime = new ArrayList<>(); List lsWorkTime = new ArrayList<>(); List lsRestTime = new ArrayList<>(); List workFlow = null; int restShift = 0; int signoutOnlyoff = 0; if (workTime != null) { lsSignTime = workTime.getSignTime();//允许打卡时间 lsWorkTime = workTime.getWorkTime();//工作时间 lsRestTime = workTime.getRestTime();//休息时段时间 oneSign = lsWorkTime!=null&&lsWorkTime.size()==1; restShift = workTime.getNonWorkShift(); signoutOnlyoff = workTime.getSignoutOnlyoff(); } kqLog.info("format in >>>>>userId" + userId + "kqDate==" + kqDate+":restShift:"+restShift+":signoutOnlyoff:"+signoutOnlyoff+":hostIps:"+hostIps+":uuid::"+uuid); if(this.writeLog) { logInfo.put("signoutOnlyoff",signoutOnlyoff); } //哺乳假 请假时长 int repeatLeaveMins = 0; //所有的请假时长 int allLeaveMins = 0; String repeatKey = userId+"_"+kqDate; String keyRepeat = userId + "|" + kqDate+"|repeat"; if (workFlowInfo.get(keyRepeat) != null) { List workFlowRepeat = (List) workFlowInfo.get(keyRepeat); repeatLeaveMins = handleRepeatWorkFlowInfo(workFlowRepeat,repeatKey); } int[] dayMins = new int[2880];//一天所有分钟数 Arrays.fill(dayMins, -1); //处理半天班次冲销问题 int[] dayMinsNew = new int[2880];//一天所有分钟数 Arrays.fill(dayMinsNew, -1); int workMins4leave = 0; int middleMins = 0;//班次的半天时长 int middleMins_final = 0;//班次的半天时长 int shiftNums = lsWorkTime == null ? 0 : lsWorkTime.size(); // 一天4次打卡单独做判断,如果是上午下班打卡和下午上班打卡时间重叠,那么上午的下班卡取最早的,下午的上班卡取最晚的。用shiftCount是否等于-1判断,-1就走标准不重叠。2就表示重叠走新的逻辑 int shiftCount = lsWorkTime == null ? 0 : lsWorkTime.size(); int shiftI = 0; String signEndDateTimeZero = ""; for (int i = 0; lsWorkTime != null && i < lsWorkTime.size(); i++) { shiftI = i; TimeScopeEntity signTimeScope = lsSignTime.get(i); TimeScopeEntity workTimeScope = lsWorkTime.get(i); 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"; if (shiftCount == 2 && shiftI == 0) { signEndDateTimeZero = signEndDateTime; } if (shiftCount == 2 && shiftI == 1) { shiftCount = signBeginDateTime.compareTo(signEndDateTimeZero) <= 0 ? shiftCount : -1; } 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; if(lsRestTime != null && !lsRestTime.isEmpty()){ for(int k = 0 ; k < lsRestTime.size(); k++){ TimeScopeEntity restTimeScope = lsRestTime.get(k); if (restTimeScope!=null) { String restBeginTime = Util.null2String(restTimeScope.getBeginTime()); String restEndTime = Util.null2String(restTimeScope.getEndTime()); int beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(restBeginTime); int endIdx = kqTimesArrayComInfo.getArrayindexByTimes(restEndTime); if (endIdx > beginIdx) { Arrays.fill(dayMinsNew, beginIdx, endIdx, -11);//休息时间 } } } int all_rest_cnt = kqTimesArrayComInfo.getCnt(dayMinsNew, workBeginIdx, workEndIdx, -11); if(all_rest_cnt >= 0){ workMins = workMins-(all_rest_cnt); } } workMins4leave += workMins; } middleMins = workMins4leave>0?workMins4leave/2:0; middleMins_final = middleMins; int split_time_index = middleMins_final; // 半天时间index,用于考勤汇总报表区分上下午 if(oneSign) { List halfWorkIndex = workTime.getHalfWorkIndex(); if(halfWorkIndex != null && !halfWorkIndex.isEmpty()) { int[] halfWorkIndexs = halfWorkIndex.get(0); split_time_index = halfWorkIndexs[1];//半天的时间 } } for (int i = 0; lsWorkTime != null && i < lsWorkTime.size(); i++) { shiftI = 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 on_absenteeismMins = 0; int off_absenteeismMins = 0; int leaveMins = 0;//请假时长 Map leaveInfo = new HashMap<>();//请假信息 Map otherinfo = new HashMap<>();//存一些用得到的信息 Map flowinfo = 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 (1 != restShift) { if(oneSign){ //个性化设置只支持一天一次上下班 ShiftInfoBean shiftInfoBean = new ShiftInfoBean(); shiftInfoBean.setSplitDate(kqDate); shiftInfoBean.setShiftRuleMap(workTime.getShiftRuleInfo()); shiftInfoBean.setSignTime(lsSignTime); shiftInfoBean.setWorkTime(lsWorkTime); shiftInfoBean.setSignoutOnlyoff(signoutOnlyoff); 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(this.writeLog) { logInfo.put("before.workEndIdx",workEndIdx); } 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); } } if(this.writeLog) { logInfo.put("after.workEndIdx",workEndIdx); } List lsCheckInfo = new KQFormatSignData().getSignInfo(userId,signTimeScope,workTimeScope,kqDate,preDate,nextDate,kqTimesArrayComInfo,hostIps,uuid,shiftCount,shiftI,signoutOnlyoff); 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(this.writeLog) { logInfo.put(j+">>>signInTime",signInTime); logInfo.put(j+">>>signInTimeIndx",signInTimeIndx); logInfo.put(j+">>>kqDate",kqDate+"|"+signDate); } 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; } } 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(this.writeLog) { logInfo.put(j+".signTime",signDate+"|"+signTime); logInfo.put(j+".beginIdx",beginIdx); logInfo.put(j+".workEndIdx",workEndIdx); } 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); } boolean isHandle1 = false; boolean isHandle2 = false; List flowList = Lists.newArrayList(); 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 durationrule = Util.null2String(data.get("durationrule")); String ishalf = Util.null2String(data.get("ishalf")); double duration = Util.getDoubleValue(Util.null2String(data.get("duration"))); if(flowType.equalsIgnoreCase(FlowReportTypeEnum.LEAVE.getFlowType())){ duration = Util.getDoubleValue(Util.null2String(data.get(newLeaveType))); } String serial = Util.null2String(data.get("serial")); String requestId = Util.null2String(data.get("requestId")); String begintime = Util.null2String(data.get("begintime")); String endtime = Util.null2String(data.get("endtime")); beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(begintime); endIdx = kqTimesArrayComInfo.getArrayindexByTimes(endtime); String leavetypeKey = repeatKey+"_"+newLeaveType; List kqRepeatBeans = KQRepeatLengthContext.getKQRepeatBean(leavetypeKey); if(CollectionUtils.isNotEmpty(kqRepeatBeans)){ Long allCnt = 0L; for (int k = 0; k < kqRepeatBeans.size(); k++) { KQRepeatBean kqRepeatBean = kqRepeatBeans.get(k); Long repeatLate = kqRepeatBean.getRepeatLate(); Long repeatEarly = kqRepeatBean.getRepeatEarly(); allCnt += ((repeatLate != null && repeatLate > 0) ? repeatLate : 0L)+ ((repeatEarly != null && repeatEarly > 0) ? repeatEarly : 0L); } if(leaveInfo.get(newLeaveType)==null){ leaveInfo.put(newLeaveType,allCnt.intValue()); }else{ Integer val = (Integer) leaveInfo.get(newLeaveType); leaveInfo.put(newLeaveType,val+allCnt); } continue; } if (beginIdx >= endIdx) { continue; } Map flowMap = Maps.newHashMap(); flowMap.put("newLeaveType", newLeaveType); flowMap.put("begintime", begintime); flowMap.put("endtime", endtime); List> flowMapList = Lists.newArrayList(); if(flowinfo.containsKey(flowType)){ List> tmpFlowMapList = (List>) flowinfo.get(flowType); tmpFlowMapList.add(flowMap); }else{ flowMapList.add(flowMap); flowinfo.put(flowType, flowMapList); } int middleIdx = (workBeginIdx+workEndIdx)/2;//工作时段标识 1 if(flowType.equals(FlowReportTypeEnum.EVECTION.getFlowType())){ if("2".equals(durationrule) && "true".equals(ishalf)){ isHandle2 = true; } Arrays.fill(dayMins, beginIdx, endIdx, 7);//出差抵扣时段标识 7 }else if(flowType.equals(FlowReportTypeEnum.OUT.getFlowType())){ if("2".equals(durationrule) && "true".equals(ishalf)){ isHandle2 = true; } Arrays.fill(dayMins, beginIdx, endIdx, 8);//公出抵扣时段标识 8 }else if(flowType.equalsIgnoreCase(FlowReportTypeEnum.LEAVE.getFlowType())){ if("2".equals(durationrule) && "true".equals(ishalf)){ isHandle1 = true; } if (endIdx > beginIdx) { Arrays.fill(dayMins, beginIdx, endIdx, 5);//流程抵扣时段标识 5 int tmpBeginIdx = beginIdx; int tmpEndIdx = endIdx; Integer val = 0; if(beginIdx>=workEndIdx){ continue; } if(endIdx<=workBeginIdx){ continue; } 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(lsRestTime != null && !lsRestTime.isEmpty()){ for(int k = 0 ; k < lsRestTime.size(); k++){ TimeScopeEntity restTimeScope = lsRestTime.get(k); 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, -11);//休息时间 } } } int all_rest_cnt = kqTimesArrayComInfo.getCnt(dayMins, workBeginIdx, workEndIdx, -11); if(all_rest_cnt >= 0){ workMins = workMins-(all_rest_cnt); } } for (int j = workBeginIdx; j < workEndIdx; j++) { switch (dayMins[j]) { case 1: tmpAttendanceMins++; break; case 2: beLateMins++; break; case 3: leaveEarlyMins++; break; case 4: if(j attendRepeatBeans = KQRepeatLengthContext.getKQRepeatBean(repeatKey); if(beLateMins > 0){ beLateMins = (int) handleRepeatLength(attendRepeatBeans, beLateMins, "late"); } if(leaveEarlyMins > 0){ leaveEarlyMins = (int) handleRepeatLength(attendRepeatBeans, leaveEarlyMins, "early"); } boolean isAmAbsent = false; boolean isPmAbsent = false; if(on_absenteeismMins > 0){ //如果没有个性化的旷工,那就是全天旷工 isAmAbsent = true; } if(off_absenteeismMins > 0) { isPmAbsent = true; } 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); kqShiftRuleEntity.setAMAbsent(isAmAbsent); kqShiftRuleEntity.setPMAbsent(isPmAbsent); kqShiftRuleEntity.setNosign_is_absent(nosign_is_absent); kqShiftRuleEntity.setSignInTime(signInTime); kqShiftRuleEntity.setSignOutTime(signOutTime); kqShiftRuleEntity.setEarly_one_mins(early_one_mins); 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(); int shiftOn_absenteeismMins = Util.getIntValue(kqShiftRuleEntity.getOn_absenteeismMins()); if(shiftOn_absenteeismMins > 0) { on_absenteeismMins = shiftOn_absenteeismMins; } int shiftOff_absenteeismMins = Util.getIntValue(kqShiftRuleEntity.getOff_absenteeismMins()); if(shiftOff_absenteeismMins > 0) { off_absenteeismMins = shiftOff_absenteeismMins; } boolean isondutyfreecheck =false; boolean isoffdutyfreecheck =false; Map model_ShiftRule = kqFormatShiftRule.getModel_ShiftRule(i, workTime.getSerialId()); Iterator iter = model_ShiftRule.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String key = Util.null2String(entry.getKey()); String value = Util.null2String(entry.getValue()); if(key.equals("start")&&value.equals("1")){ isondutyfreecheck = true; } if(key.equals("end")&&value.equals("1")){ isoffdutyfreecheck = true; } } 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; isAmAbsent = false; isPmAbsent = false; on_absenteeismMins = 0; off_absenteeismMins = 0; }else if(!new KQFormatBiz().needCal(workEndDate,workEndTime)) {//还未到下班时间 kqLog.writeLog("还未到上班时间"); leaveEarlyMins = 0; graveLeaveEarlyMins = 0; forgotCheckMins = 0; isPmAbsent = false; off_absenteeismMins = 0; } if (1 == restShift || workTime.getIsExclude()) {//休息日班次或者无需考勤人员没有异常状态 beLateMins = 0; graveBeLateMins = 0; leaveEarlyMins = 0; graveLeaveEarlyMins = 0; absenteeismMins = 0; forgotCheckMins = 0; forgotBeginWorkCheckMins = 0; isAmAbsent = false; isPmAbsent = false; on_absenteeismMins = 0; off_absenteeismMins = 0; } if (1 == restShift) {//非工作日班次連打卡時長和出勤时长也不給了 workMins = 0; signMins = 0; isAmAbsent = false; isPmAbsent = false; on_absenteeismMins = 0; off_absenteeismMins = 0; } //允许下班不打卡 ,如果上班也没有打卡,那么算上班旷工0.5天 if (isoffdutyfreecheck) { if (checkIn == 0) {//(无签到),就会有上班漏签,如果有下班卡,那么上班漏签 if(forgotBeginWorkCheckMins==0&&absenteeismMins>0){ forgotBeginWorkCheckMins= absenteeismMins ; } } absenteeismMins = 0; forgotCheckMins = 0; off_absenteeismMins = 0; } //允许上班不打卡,如果下班也没有打卡,那么算漏签 if(isondutyfreecheck){ if (checkOut == 0) {//(无签退) if(forgotCheckMins==0&&absenteeismMins>0){ forgotCheckMins= absenteeismMins ; } } absenteeismMins = 0; forgotBeginWorkCheckMins = 0; on_absenteeismMins = 0; } if(isondutyfreecheck&&isoffdutyfreecheck){ absenteeismMins = 0; forgotCheckMins = 0; forgotBeginWorkCheckMins = 0; on_absenteeismMins = 0; off_absenteeismMins = 0; } int repeatLeaveTime = (int) getRepeatLeaveTime(); if(repeatLeaveTime > 0){ leaveMins = leaveMins+repeatLeaveTime; } //计算实际出勤时间(出差公出算出勤)=应出勤-旷工-请假-迟到-早退 attendanceMins = workMins - absenteeismMins-leaveMins-beLateMins-graveBeLateMins-leaveEarlyMins-graveLeaveEarlyMins; if(this.writeLog) { logInfo.put("is_half",is_half); logInfo.put("shiftNums",shiftNums); logInfo.put("isHandle2",isHandle2); logInfo.put("isHandle1",isHandle1); logInfo.put("workMins"+i,workMins); logInfo.put("absenteeismMins"+i,absenteeismMins); logInfo.put("middleMins"+i,middleMins); } //如果开启半天特殊处理的,请假是需要扣除0.5天 //说明没有打卡的情况,因为有打卡肯定是有迟到、早退、漏签这些异常的,不考虑迟到算旷工,早退算旷工的情况 //只处理1天1次,和1天2次的情况,因为1天3次的中间点可能在第二段,需要考虑有没有打卡,以及有打卡第三次是否需要处理等情况,和上下午半天的概念不太适用 if("1".equals(is_half)){ boolean absentFlag_1 = false;//请假, boolean absentFlag_2 = false;//公出或出差 if(isHandle1 || isHandle2){ if(absenteeismMins>0 && !(beLateMins >0||graveBeLateMins > 0||leaveEarlyMins > 0||graveLeaveEarlyMins > 0||forgotCheckMins > 0||forgotBeginWorkCheckMins >0)){ if(isHandle1){ absentFlag_1 = true;//可以理解为是1天3次和1天1次的情况,因为1天2次的情况,如果有旷工,那么另外半天才是有请假, } if(isHandle2){ absentFlag_2 = true;//可以理解为是1天3次和1天1次的情况,因为1天2次的情况,如果有旷工,那么另外半天才是有公出或者出差 } } } if(this.writeLog) { logInfo.put("tmp_absenteeismMins"+i,absenteeismMins); logInfo.put("absentFlag_1"+i,absentFlag_1); logInfo.put("absentFlag_2"+i,absentFlag_2); } /*1次---上午3小时,下午5小时 上午公出,下午旷工 上午公出,下午打卡 上午旷工,下午公出 上午打卡,下午公出 2次---上午3小时,下午5小时 上午公出,下午旷工--需处理实际出勤、旷工时长 上午公出,下午打卡--需处理实际出勤 上午旷工,下午公出--需处理实际出勤、旷工时长 上午打卡,下午公出--需处理实际出勤 */ if(isHandle2){ if(shiftNums ==1){ absenteeismMins = absentFlag_2?middleMins_final:0; attendanceMins = workMins - absenteeismMins; }else if(shiftNums == 2){ if(workMins>middleMins_final && middleMins_final>0){ absenteeismMins = (absenteeismMins > middleMins_final)?middleMins_final:((absentFlag_2||outMins>0||evectionMins>0)?Math.abs(workMins - middleMins_final):0); absenteeismMins = (i==1 && middleMap.get("attendanceMins0")>0)?(absentFlag_2?absenteeismMins:0):absenteeismMins;//上午打卡3小时,下午公出5小时,下午的就不要显示旷工1小时了 } attendanceMins = workMins - absenteeismMins; } } if(this.writeLog) { logInfo.put("absenteeismMins_1"+i,absenteeismMins); logInfo.put("attendanceMins_1"+i,attendanceMins); } /*1次---上午3小时,下午5小时 上午请假,下午旷工 上午请假,下午打卡 上午旷工,下午请假 上午打卡,下午请假 2次---上午3小时,下午5小时 上午请假,下午旷工--需处理实际出勤、旷工时长 上午请假,下午打卡--需处理实际出勤 上午旷工,下午请假--需处理实际出勤、旷工时长 上午打卡,下午请假--需处理实际出勤 */ if(isHandle1){ if(shiftNums == 1){ absenteeismMins = absentFlag_1?middleMins_final:0; attendanceMins = workMins - absenteeismMins - (leaveMins>0?middleMins_final:(absentFlag_1?(workMins - middleMins_final):0)); }else if(shiftNums == 2){ if(workMins>middleMins_final && middleMins_final>0){ absenteeismMins = (absenteeismMins > middleMins_final)?middleMins_final:((absentFlag_1||leaveMins>0)?Math.abs(workMins - middleMins_final):0); absenteeismMins = (i==1 && middleMap.get("attendanceMins0")>0)?0:absenteeismMins;//上午打卡3小时,下午请假5小时,下午的就不要显示旷工1小时了 } attendanceMins = workMins - absenteeismMins - (leaveMins>0?middleMins_final:(absentFlag_1?Math.abs(workMins - middleMins_final):0)); attendanceMins = attendanceMins>middleMins_final?middleMins_final:attendanceMins;//上午请假3小时,下午打卡5小时 }else if(shiftNums == 3){//比如一天三次上下班,那么中间点在第二次上下班区间 // if(workMins>middleMins && middleMins>0){ // absenteeismMins = (absenteeismMins > middleMins_final)?middleMins_final:((absentFlag_1||leaveMins>0)?(workMins - middleMins):0); // absenteeismMins = (i>=1 && middleMap.get("attendanceMins"+(i-1))>0)?0:absenteeismMins; // } // attendanceMins = workMins - absenteeismMins - (leaveMins>0?middleMins_final:(absentFlag_1?Math.abs(workMins - middleMins_final):0)); // attendanceMins = attendanceMins>middleMins_final?middleMins_final:attendanceMins;//上午请假3小时,下午打卡5小时 // if(workMins < middleMins){//客户可能是一天2次,或者3次,那么workmins有可能是小于半天的请假时间 // middleMins = middleMins-workMins; // }else { // middleMins = 0; // } } if(absenteeismMins > middleMins_final){//客户可能是一天2次,或者3次 absenteeismMins = middleMins_final; } } middleMap.put("attendanceMins"+i,attendanceMins); middleMap.put("absenteeismMins"+i,absenteeismMins); middleMap.put("workMins"+i,workMins); middleMap.put("leaveMins"+i,leaveMins); middleMap.put("outMins"+i,outMins); middleMap.put("evectionMins"+i,evectionMins); middleMap.put("isHandle1"+i,isHandle1?1:0); middleMap.put("isHandle2"+i,isHandle2?1:0); middleMap.put("absentFlag_1"+i,absentFlag_1?1:0);//1表示有旷工 middleMap.put("absentFlag_2"+i,absentFlag_2?1:0);//1表示有旷工 } // 如果没有开启"漏签是否算实际出勤"开关,则漏签不算实际出勤时长 if("0".equals(nosign_is_absent)) { attendanceMins = attendanceMins-forgotCheckMins-forgotBeginWorkCheckMins; } if(beforeBegin || attendanceMins < 0) {//还未到上班时间,不用计算任何状体 attendanceMins = 0; } /** * 汇总报表的日历显示是有旷工就不显示漏签了,如果这里还统计漏签,张总表示日历也需要修改,改不动了 * 在处理完实际出勤之后,将漏签还原 */ String nosign_ishandle = Util.null2String(kqShiftRuleEntity.getNosign_ishandle()); if("1".equals(nosign_ishandle)){ forgotCheckMins = 0; }else if("2".equals(nosign_ishandle)){ forgotCheckMins = 0; forgotBeginWorkCheckMins = 0; } kqLog.info("实际出勤计算公式" + "实际出勤=应出勤- 旷工-请假-迟到-早退 userId" + userId + "kqDate==" + kqDate+":hostIps:"+hostIps+":uuid::"+uuid); kqLog.info("实际出勤计算结果" + attendanceMins + "=" + workMins + "- " + absenteeismMins + "-" + leaveMins + "-" + (beLateMins + graveBeLateMins) + "-" + (leaveEarlyMins - graveLeaveEarlyMins)+ "-" + (repeatLeaveTime)+" 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)+"-"+(repeatLeaveTime)); } //判断当天考勤状态 // 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)); Long id = IdGenerator.generate(); params.add(workTime.getDayType()); params.add(date); params.add(date); params.add(id); params.add(JSONObject.toJSONString(flowinfo)); // if(isAmAbsent){ // params.add(1); // }else { // params.add(0); // } // if(isPmAbsent){ // params.add(1); // }else { // params.add(0); // } params.add(on_absenteeismMins); params.add(off_absenteeismMins); lsParam.add(params); resetAttendRepeatBeans(attendRepeatBeans); //这个只是记录每个时段消耗的哺乳假,用完就清掉 KQRepeatLengthContext.removeRepeatBeanLinkRange(); //把每一段的请假时长记录一下 allLeaveMins += leaveMins; } KQRepeatLengthContext.removeRepeatBean(); KQRepeatLengthContext.clear(); KQRepeatLengthContext.removeRepeatBeanLinkRange(); if(repeatLeaveMins > 0){ if(allLeaveMins == 0){ //哺乳假 有这种情况,没有迟到,也没有早退,allLeaveMins未0的情况 if(CollectionUtils.isNotEmpty(lsParam)){ List tmp = lsParam.get(0); //目前请假时长是24位,以后有新增调整列一定要记得改这里的 tmp.set(24, repeatLeaveMins); } } } } catch (Exception e) { kqLog.info("考勤格式化生成数据报错:KQFormatData:"); StringWriter errorsWriter = new StringWriter(); e.printStackTrace(new PrintWriter(errorsWriter)); kqLog.info(errorsWriter.toString()); } return lsParam; } /** * 哺乳假被当前规则用完了之后,需要把late和early的已休时长重置一下 * 为什么要在这里搞,因为前面迟到,严重迟到在判断的时候都需要用到原始数据,只有前面的判断都用完了,最后才能去更新 * @param attendRepeatBeans */ private void resetAttendRepeatBeans(List attendRepeatBeans) { if(CollectionUtils.isEmpty(attendRepeatBeans)){ return ; } KQRepeatBean attendRepeatBeanLink = KQRepeatLengthContext.getRepeatBeanLink(); if(attendRepeatBeanLink == null){ return ; } Long repeatLateLink = attendRepeatBeanLink.getRepeatLateLink(); Long repeatEarlyLink = attendRepeatBeanLink.getRepeatEarlyLink(); for (int i = 0; i < attendRepeatBeans.size(); i++) { KQRepeatBean attendRepeatBean = attendRepeatBeans.get(i); Long repeatEarly = attendRepeatBean.getRepeatEarly(); Long repeatLate = attendRepeatBean.getRepeatLate(); if(repeatLateLink != null && repeatLateLink > 0 && repeatLate != null && repeatLate > 0){ if(repeatLateLink > repeatLate){ repeatLateLink = repeatLateLink - repeatLate; attendRepeatBean.setRepeatLateLink(repeatLate); }else{ attendRepeatBean.setRepeatLateLink(repeatLateLink); repeatLateLink= 0L; } } if(repeatEarlyLink != null && repeatEarlyLink > 0 && repeatEarly != null && repeatEarly > 0){ if(repeatEarlyLink > repeatEarly){ repeatEarlyLink = repeatEarlyLink - repeatEarly; attendRepeatBean.setRepeatEarlyLink(repeatEarly); }else{ attendRepeatBean.setRepeatEarlyLink(repeatEarlyLink); repeatEarlyLink = 0L; } } } } /** * 实际出勤里也要去除哺乳假的时长 * @return */ private long getRepeatLeaveTime() { long repeatLeaveTime = 0L; KQRepeatBean attendRepeatBeanLink = KQRepeatLengthContext.getRepeatBeanLinkRange(); if(attendRepeatBeanLink == null){ return repeatLeaveTime; } Long repeatLateLink = attendRepeatBeanLink.getRepeatLateLink(); Long repeatEarlyLink = attendRepeatBeanLink.getRepeatEarlyLink(); if(repeatLateLink > 0){ repeatLeaveTime = repeatLateLink; } if(repeatEarlyLink > 0){ if(repeatLeaveTime > 0){ repeatLeaveTime += repeatEarlyLink; }else{ repeatLeaveTime = repeatEarlyLink; } } return repeatLeaveTime; } /** * 哺乳假针对异常时长部分的处理 * @param attendRepeatBeans * @param repeatLength * @param type * @return */ private long handleRepeatLength(List attendRepeatBeans, long repeatLength, String type) { if(repeatLength <= 0){ return repeatLength; } Long oriLength = repeatLength; try{ // 当天总消耗哺乳假 用于当天迟到早退 KQRepeatBean attendRepeatBeanLink = KQRepeatLengthContext.getRepeatBeanLink(); // 当前时段消耗哺乳假,用于计算缺勤 KQRepeatBean attendRepeatBeanLinkRange = KQRepeatLengthContext.getRepeatBeanLinkRange(); if(attendRepeatBeanLink == null){ attendRepeatBeanLink = new KQRepeatBean(); } if(attendRepeatBeanLinkRange == null){ attendRepeatBeanLinkRange = new KQRepeatBean(); } Long repeatLateLink = attendRepeatBeanLink.getRepeatLateLink(); if(repeatLateLink == null){ repeatLateLink = 0L; } Long repeatEarlyLink = attendRepeatBeanLink.getRepeatEarlyLink(); if(repeatEarlyLink == null){ repeatEarlyLink = 0L; } Long repeatLateLinkRange = attendRepeatBeanLinkRange.getRepeatLateLink(); if(repeatLateLinkRange == null){ repeatLateLinkRange = 0L; } Long repeatEarlyLinkRange = attendRepeatBeanLinkRange.getRepeatEarlyLink(); if(repeatEarlyLinkRange == null){ repeatEarlyLinkRange = 0L; } if(CollectionUtils.isNotEmpty(attendRepeatBeans)){ for (int i = 0; i < attendRepeatBeans.size(); i++) { KQRepeatBean attendRepeatBean = attendRepeatBeans.get(i); if(oriLength <= 0){ attendRepeatBeanLink.setRepeatLateLink(repeatLateLink); attendRepeatBeanLink.setRepeatEarlyLink(repeatEarlyLink); KQRepeatLengthContext.setRepeatBeanLink(attendRepeatBeanLink); attendRepeatBeanLinkRange.setRepeatLateLink(repeatLateLinkRange); attendRepeatBeanLinkRange.setRepeatEarlyLink(repeatEarlyLinkRange); KQRepeatLengthContext.setRepeatBeanLinkRange(attendRepeatBeanLinkRange); return oriLength; } if("late".equals(type)){ Long repeatLate = attendRepeatBean.getRepeatLate(); Long repeatLatTmp = attendRepeatBean.getRepeatLateLink(); if(repeatLate != null){ if(repeatLatTmp != null && repeatLatTmp > 0){ repeatLate = repeatLate - repeatLatTmp; repeatLate = repeatLate < 0 ? 0 : repeatLate; } oriLength = oriLength - repeatLate; oriLength = oriLength < 0 ? 0 : oriLength; if(oriLength == 0){ //如果异常已经被每天重复时长完全抵扣了,那么需要更新下AttendRepeatBeanLink repeatLateLink += repeatLength; repeatLateLinkRange += repeatLength; }else{ repeatLateLink += repeatLate; repeatLateLinkRange += repeatLate; } } } if("early".equals(type)){ Long repeatEarly = attendRepeatBean.getRepeatEarly(); Long repeatEarTmp = attendRepeatBean.getRepeatEarlyLink(); if(repeatEarly != null){ if(repeatEarTmp != null && repeatEarTmp > 0){ repeatEarly = repeatEarly - repeatEarTmp; repeatEarly = repeatEarly < 0 ? 0 : repeatEarly; } oriLength = oriLength - repeatEarly; oriLength = oriLength < 0 ? 0 : oriLength; if(oriLength == 0){ //如果异常已经被每天重复时长完全抵扣了,那么需要更新下AttendRepeatBean repeatEarlyLink += repeatLength; repeatEarlyLinkRange += repeatLength; }else{ repeatEarlyLink += repeatEarly; repeatEarlyLinkRange += repeatEarly; } } } } } attendRepeatBeanLink.setRepeatLateLink(repeatLateLink); attendRepeatBeanLink.setRepeatEarlyLink(repeatEarlyLink); KQRepeatLengthContext.setRepeatBeanLink(attendRepeatBeanLink); attendRepeatBeanLinkRange.setRepeatLateLink(repeatLateLinkRange); attendRepeatBeanLinkRange.setRepeatEarlyLink(repeatEarlyLinkRange); KQRepeatLengthContext.setRepeatBeanLinkRange(attendRepeatBeanLinkRange); }catch (Exception e){ kqLog.error("handleRepeatLength",e); } return oriLength; } public int handleRepeatWorkFlowInfo(List workFlowRepeat, String repeatKey) { int repeatLeaveMins = 0; for (int j = 0; workFlowRepeat != null && j < workFlowRepeat.size(); j++) { Map data = (Map) workFlowRepeat.get(j); String repeatType = Util.null2String(data.get("repeatType")); String repeatLate = Util.null2String(data.get("repeatLate")); String repeatEarly = Util.null2String(data.get("repeatEarly")); String newleavetype = Util.null2String(data.get("newleavetype")); String leavetypeKey = repeatKey+"_"+newleavetype; KQRepeatBean repeatBean = new KQRepeatBean(); repeatBean.setRepeatType(repeatType); if("0".equals(repeatType)){ if(repeatLate.length() > 0){ repeatBean.setRepeatLate(new Double(Double.valueOf(repeatLate)).longValue()); repeatLeaveMins += new Double(Double.valueOf(repeatLate)).longValue(); } } if("1".equals(repeatType)){ if(repeatEarly.length() > 0){ repeatBean.setRepeatEarly(new Double(Double.valueOf(repeatEarly)).longValue()); repeatLeaveMins += new Double(Double.valueOf(repeatEarly)).longValue(); } } if("2".equals(repeatType)){ if(repeatLate.length() > 0){ repeatBean.setRepeatLate(new Double(Double.valueOf(repeatLate)).longValue()); repeatLeaveMins += new Double(Double.valueOf(repeatLate)).longValue(); } if(repeatEarly.length() > 0){ repeatBean.setRepeatEarly(new Double(Double.valueOf(repeatEarly)).longValue()); repeatLeaveMins += new Double(Double.valueOf(repeatEarly)).longValue(); } } KQRepeatLengthContext.setKQRepeatBean(repeatKey,repeatBean); KQRepeatLengthContext.setKQRepeatBean(leavetypeKey,repeatBean); } return repeatLeaveMins; } 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 flowinfo = new HashMap<>();//流程信息 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")); String begintime = Util.null2String(data.get("begintime")); String endtime = Util.null2String(data.get("endtime")); beginIdx = kqTimesArrayComInfo.getArrayindexByTimes(begintime); endIdx = kqTimesArrayComInfo.getArrayindexByTimes(endtime); if (beginIdx > endIdx) { continue; } Map flowMap = Maps.newHashMap(); flowMap.put("newLeaveType", newLeaveType); flowMap.put("begintime", begintime); flowMap.put("endtime", endtime); List> flowMapList = Lists.newArrayList(); if(flowinfo.containsKey(flowType)){ List> tmpFlowMapList = (List>) flowinfo.get(flowType); tmpFlowMapList.add(flowMap); }else{ flowMapList.add(flowMap); flowinfo.put(flowType, flowMapList); } 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); nonlsParam.add(workTime.getDayType()); Timestamp date = new Timestamp(System.currentTimeMillis()); Long id = IdGenerator.generate(); nonlsParam.add(date); nonlsParam.add(date); nonlsParam.add(id); nonlsParam.add(JSONObject.toJSONString(flowinfo)); } }