weaver-hrm-recruit/src/com/engine/kq/biz/KQFormatData.java

1740 lines
85 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<String,Object> logInfo = new LinkedHashMap<>();
private static final String LOCK_DEGREE = Util.null2String(Prop.getPropValue("kqLockAttenda", "LOCK_DEGREE"));
public Map<String, Object> formatKqDateByLock(String userId, String kqDate, int formatType) {
Map<String, Object> 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<String, Object> formatKqDate(String userId, String kqDate) {
//考勤报表增加锁定功能:弱控
//1、考勤流程控制请假、出差、公出、补卡、加班、销假、考勤变更新建的流程不能提交在途的流程可以正常提交归档报表能统计管理员干预归档的流程报表能统计。
//2、关账不影响考勤导入打卡数据正常的打卡数据进入报表。
//3、强控就是前2点锁定日期后也不能进入报表了
List<List<Object>> lsParam = new ArrayList<>();
boolean isKqReportHalfOpen = "1".equals(new KQSettingsComInfo().getMain_val("kq_report_half"));
//非工作日处理
List<Object> nonlsParam = null;
Map<String, Object> 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<String, Object> 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<String,Object> 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<Object> 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<List<Object>> format(String userId, String kqDate, WorkTimeEntity workTime,
Map<String, Object> workFlowInfo, String uuid) {
List<List<Object>> lsParam = new ArrayList<>();
List<Object> params = null;
HashMap<String, Integer> 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<String> hostIps = InitServer.getRealIp();
boolean oneSign = false;
List<TimeScopeEntity> lsSignTime = new ArrayList<>();
List<TimeScopeEntity> lsWorkTime = new ArrayList<>();
List<TimeScopeEntity> lsRestTime = new ArrayList<>();
List<Object> 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<Object> workFlowRepeat = (List<Object>) 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<int[]> 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<String,Object> leaveInfo = new HashMap<>();//请假信息
Map<String,Object> otherinfo = new HashMap<>();//存一些用得到的信息
Map<String,Object> 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<String, String> 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<String> 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<Object> 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<String, Object> checkInfo = (Map<String, Object>) 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<signInTimeIndx4Sign){
signMins = 1440 + signInTimeOutdx4Sign - signInTimeIndx4Sign;
}else{
signMins = 1440 + signInTimeOutdx4Sign - signInTimeIndx4Sign;
}
}
}else{
signMins=0;
}
if(signMins<0){
signMins=0;
}
}
if (checkIn == 0 && checkOut == 0) {//旷工(无签到无签退)
if (workEndIdx > 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);//下班漏签时段标识 6666呼应前面的漏签的6
}else{
//这种数据理论上不会存在,也记下吧
forgotBeginWorkCheckMins++;
}
}
}
if (workFlowInfo.get(dateKey) != null) {
workFlow = (List<Object>) workFlowInfo.get(dateKey);
}
boolean isHandle1 = false;
boolean isHandle2 = false;
List<Object> flowList = Lists.newArrayList();
for (int j = 0; workFlow != null && j < workFlow.size(); j++) {
Map<String, Object> data = (Map<String, Object>) 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<KQRepeatBean> 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<String,String> flowMap = Maps.newHashMap();
flowMap.put("newLeaveType", newLeaveType);
flowMap.put("begintime", begintime);
flowMap.put("endtime", endtime);
List<Map<String,String>> flowMapList = Lists.newArrayList();
if(flowinfo.containsKey(flowType)){
List<Map<String,String>> tmpFlowMapList = (List<Map<String, String>>) 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(beginIdx<workBeginIdx)tmpBeginIdx=workBeginIdx;
if(endIdx>workEndIdx)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<split_time_index) {
on_absenteeismMins++;
} else {
off_absenteeismMins++;
}
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;
}
List<KQRepeatBean> 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<String, String> 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<String,Object> definedFieldInfo = new KQFormatBiz().getDefinedField();
String[] definedFields = Util.splitString(Util.null2String(definedFieldInfo.get("definedField")),",");
KQReportFieldComInfo kqReportFieldComInfo = new KQReportFieldComInfo();
for (int tmpIdx = 0; tmpIdx<definedFields.length; tmpIdx++) {
String fieldname = definedFields[tmpIdx];
// System.out.println("fieldname=="+fieldname);
String fieldid = KQReportFieldComInfo.field2Id.get(fieldname);
String formula = kqReportFieldComInfo.getFormula(fieldid);
if(formula.length()==0)continue;
String expression = formula;
Pattern pattern = Pattern.compile("\\$\\{[^}]+\\}");
Matcher matcher = pattern.matcher(expression);
Map<String, Object> 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<Object> 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<KQRepeatBean> 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<KQRepeatBean> 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<Object> workFlowRepeat, String repeatKey) {
int repeatLeaveMins = 0;
for (int j = 0; workFlowRepeat != null && j < workFlowRepeat.size(); j++) {
Map<String, Object> data = (Map<String, Object>) 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<String,Object> 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<Object> nonlsParam, WorkTimeEntity workTime, Map<String, Object> workFlowInfo) {
String signInId = "";
String signInDate = "";
String signInTime = "";
String signOutId = "";
String signOutDate = "";
String signOutTime = "";
int beginIdx = 0;
int endIdx = 0;
int leaveMins = 0;//请假时长
Map<String,Object> flowinfo = new HashMap<>();//流程信息
Map<String,Object> leaveInfo = new HashMap<>();//请假信息
int evectionMins = 0;//出差时长
int outMins = 0;//公出时长
int otherMins = 0;//异常流程时长
int[] dayMins = new int[2880];//一天所有分钟数
List<Object> 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<TimeScopeEntity> 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<TimeScopeEntity> next_lsSignTime = new ArrayList<>();
if (next_workTime != null) {
next_lsSignTime = next_workTime.getSignTime();//允许打卡时间
next_lsSignTime = next_lsSignTime != null ? next_lsSignTime : new ArrayList<>();
}
List<Object> lsCheckInfo = new KQFormatSignData().getNonWorkSignInfo(userId,preDate,kqDate,pre_lsSignTime,next_lsSignTime);
for (int j = 0; lsCheckInfo != null && j < lsCheckInfo.size(); j++) {
Map<String, Object> checkInfo = (Map<String, Object>) 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<Object>) workFlowInfo.get(dateKey);
}
for (int j = 0; workFlow != null && j < workFlow.size(); j++) {
Map<String, Object> data = (Map<String, Object>) 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<String,String> flowMap = Maps.newHashMap();
flowMap.put("newLeaveType", newLeaveType);
flowMap.put("begintime", begintime);
flowMap.put("endtime", endtime);
List<Map<String,String>> flowMapList = Lists.newArrayList();
if(flowinfo.containsKey(flowType)){
List<Map<String,String>> tmpFlowMapList = (List<Map<String, String>>) 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));
}
}