package com.engine.attendance.attendanceanalysis.cmd.workovertime; import com.engine.attendance.enums.*; import com.engine.common.biz.AbstractCommonCommand; import com.engine.common.entity.BizLogContext; import com.engine.common.util.DateUtil; import com.engine.common.util.Utils; import com.engine.core.interceptor.CommandContext; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import weaver.general.Util; import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 根据加班时间计算获得加班时长 */ @Slf4j public class GetOvertimeDurationCmd extends AbstractCommonCommand> { public GetOvertimeDurationCmd(Map params) { this.params = params; } @Override public BizLogContext getLogContext() { return null; } @Override public Map execute(CommandContext commandContext) { Map resultMap = Maps.newHashMap(); //考勤项目 List> attendanceItems = (List>)params.get("attendanceItems"); //排班 List> scheduleResult = (List>)params.get("scheduleResult"); //分析日期 String analysisDate = Util.null2String(params.get("analysisDate")); //请假记录 List> askForLeaveList = (List>)params.get("askForLeaveList"); //请假项目 Map> askForLeaveItems = (Map>)params.get("askForLeaveItems"); //外出记录 List> evectionList = (List>)params.get("evectionList"); //外出项目 Map> evectionItems = (Map>)params.get("evectionItems"); //请假后消除的异常 List> offsetAskForLeaveAnomaly = (List>)params.get("offsetAskForLeaveAnomaly"); //出差外出后消除的异常 List> offsetEvectionAnomaly = (List>)params.get("offsetEvectionAnomaly"); //经过请假外出处理过的异常项目 List> abnormalClockInList = (List>)params.get("abnormalClockInList"); //不需要记录的异常项目 List> notRecordAbnormalClockInList = (List>)params.get("notRecordAbnormalClockInList"); //加班项目 List> workTimeBeLateItems = (List>)params.get("workTimeBeLateItems"); //打卡匹配 Map> clcokInTimeMap = (Map>)params.get("clcokInTimeMap"); //班次 Map scheduleMap = (Map)params.get("scheduleMap"); abnormalClockInList.addAll(notRecordAbnormalClockInList); //总抵消异常 List> anomalyList = Lists.newArrayList(); anomalyList.addAll(offsetEvectionAnomaly); anomalyList.addAll(offsetAskForLeaveAnomaly); String bdlx = Util.null2String(scheduleMap.get("bdlx")); Map getWorkOverTimeParam = Maps.newHashMap(); //加班开始时间 String kssj = Utils.getkssjTime(scheduleMap, analysisDate); //加班结束时间 String jssj = Utils.getjssjTime(scheduleMap, analysisDate); //加班实际开始时间 String realityStartTime = ""; //加班实际结束时间 String realityEndime = ""; getWorkOverTimeParam.put("attendanceItems", attendanceItems); getWorkOverTimeParam.put("rqlx", scheduleMap.get("rqlx")); //开始必须打卡,当为加班计划类型的加班时已考勤项目设置为准 String ksjbbxydk = scheduleMap.get("ksdk").toString(); //结束必须打卡,当为加班计划类型的加班时已考勤项目设置为准 String jsjbbxydk = scheduleMap.get("jsdk").toString(); double jbsc = Double.valueOf(Util.null2String(scheduleMap.get("edxss"))); //提前打卡开始的时长计入加班 String tqdkjrjb = Util.null2String(workTimeBeLateItems.get(0).get("tqdkjrjb")); //推后打卡结束的时长计入加班 String thdkjrjb = Util.null2String(workTimeBeLateItems.get(0).get("thdkjrjb")); //结算加班时长不得超过申请的时长 String jbscbdccsqsc = Util.null2String(workTimeBeLateItems.get(0).get("jbscbdccsqsc")); //是否扣除时间区间内的就餐休息时长 String zdkcjcxxsc = Util.null2String(workTimeBeLateItems.get(0).get("zdkcjcxxsc")); //晚于开始时间忽略分钟数 String jbwdhlfzs = Util.null2String(workTimeBeLateItems.get(0).get("jbwdhlfzs")).equals("") ? "0" : Util.null2String(workTimeBeLateItems.get(0).get("jbwdhlfzs")); //早于结束时间忽略分钟数 String jbzzhlfzs = Util.null2String(workTimeBeLateItems.get(0).get("jbzzhlfzs")).equals("") ? "0" : Util.null2String(workTimeBeLateItems.get(0).get("jbzzhlfzs")); /** * 获得实际加班时间 */ if (CheckBoxEnum.CHECKED.getKey().equals(ksjbbxydk)) { Map clcokInTimeData = clcokInTimeMap.get(kssj); if (clcokInTimeData == null) { log.info("加班开始时间漏卡: {},clcokInTimeData:{}", kssj, clcokInTimeMap); resultMap.put("jbsc","0"); return resultMap; } String hourTime = clcokInTimeData.get("signtime").toString(); if (hourTime.length() > 5) { hourTime = hourTime.substring(0, 5); } String signTime = clcokInTimeData.get("signdate") + " " + hourTime; realityStartTime = signTime; } else { realityStartTime = kssj; } if (CheckBoxEnum.CHECKED.getKey().equals(jsjbbxydk)) { Map clcokInTimeData = clcokInTimeMap.get(jssj); if (clcokInTimeData == null) { log.info("加班结束时间漏卡: {},clcokInTimeData:{}", jssj, clcokInTimeData); resultMap.put("jbsc","0"); return resultMap; } String hourTime = clcokInTimeData.get("signtime").toString(); if (hourTime.length() > 5) { hourTime = hourTime.substring(0, 5); } String signTime = clcokInTimeData.get("signdate") + " " + hourTime; realityEndime = signTime; } else { realityEndime = jssj; } jbsc = jbsc * 60; if (CheckBoxEnum.CHECKED.getKey().equals(tqdkjrjb)) { //提前打卡开始的时长计入加班 if (DateUtil.getTime(realityStartTime).compareTo(DateUtil.getTime(kssj)) < 0) { jbsc += DateUtil.getBetWeenMinutes(realityStartTime, kssj); } } if (CheckBoxEnum.CHECKED.getKey().equals(thdkjrjb)) { // 推后打卡结束的时长计入加班 if (DateUtil.getTime(realityEndime).compareTo(DateUtil.getTime(jssj)) > 0) { jbsc += DateUtil.getBetWeenMinutes(jssj, realityEndime); } } /** * 当存在迟到项目时扣除异常时长,不存在时扣除实际迟到时间 */ List> beLateAbnormal = abnormalClockInList.stream().filter(e -> e.get("pointTime").equals(kssj)).collect(Collectors.toList()); double beLateTime = 0; if (beLateAbnormal.size() > 0) { String hsdw = Util.null2String(beLateAbnormal.get(0).get("hsdw")); String itemduration = Util.null2String(beLateAbnormal.get(0).get("itemduration")); AttendanceItemTypeEnum itemType = (AttendanceItemTypeEnum) beLateAbnormal.get(0).get("itemType"); if (itemType == AttendanceItemTypeEnum.MISSE_CARD) { //早上漏卡 beLateTime = jbsc; } else { if (AccountingUnitEnum.DAY.getKey().equals(hsdw)) { beLateTime = Integer.valueOf(scheduleMap.get("edsc").toString()) * Double.valueOf(itemduration); } else if (AccountingUnitEnum.HOUR.getKey().equals(hsdw)) { beLateTime = Double.valueOf(itemduration) * 60; } else if (AccountingUnitEnum.MINUTES.getKey().equals(hsdw)) { beLateTime = Double.valueOf(itemduration); } else if (AccountingUnitEnum.ONCE.getKey().equals(hsdw)) { beLateTime = jbsc; } } } else { if (DateUtil.getTime(realityStartTime).compareTo(DateUtil.getTime(kssj)) > 0) { beLateTime = DateUtil.getBetWeenMinutes(kssj, realityStartTime); List> collect1 = anomalyList.stream().filter(e -> e.get("pointTime").equals(kssj)).collect(Collectors.toList()); if (!"".equals(jbwdhlfzs) && beLateTime < Integer.valueOf(jbwdhlfzs)) { beLateTime = 0; } //当存在迟到异常被抵消的情况 if (collect1.size() > 0) { beLateTime = 0; } } } /** * 当存在早退项目时扣除异常时长,不存在时扣除实际早退时间 */ List> leaveEarlyAbnormal = abnormalClockInList.stream().filter(e -> e.get("pointTime").equals(jssj)).collect(Collectors.toList()); double leaveElaryTime = 0; if (leaveEarlyAbnormal.size() > 0) { String hsdw = Util.null2String(leaveEarlyAbnormal.get(0).get("hsdw")); String itemduration = Util.null2String(leaveEarlyAbnormal.get(0).get("itemduration")); AttendanceItemTypeEnum itemType = (AttendanceItemTypeEnum) leaveEarlyAbnormal.get(0).get("itemType"); if (itemType == AttendanceItemTypeEnum.MISSE_CARD) { //下午漏卡 leaveElaryTime = jbsc; } else { if (AccountingUnitEnum.DAY.getKey().equals(hsdw)) { leaveElaryTime = Integer.valueOf(scheduleMap.get("edsc").toString()) * Double.valueOf(itemduration); } else if (AccountingUnitEnum.HOUR.getKey().equals(hsdw)) { leaveElaryTime = Double.valueOf(itemduration) * 60; } else if (AccountingUnitEnum.MINUTES.getKey().equals(hsdw)) { leaveElaryTime = Double.valueOf(itemduration); } else if (AccountingUnitEnum.ONCE.getKey().equals(hsdw)) { leaveElaryTime = jbsc; } } } else { if (DateUtil.getTime(realityEndime).compareTo(DateUtil.getTime(jssj)) < 0) { leaveElaryTime = DateUtil.getBetWeenMinutes(realityEndime, jssj); List> collect2 = anomalyList.stream().filter(e -> e.get("pointTime").equals(jssj)).collect(Collectors.toList()); if (!"".equals(jbzzhlfzs) && leaveElaryTime < Integer.valueOf(jbzzhlfzs)) { leaveElaryTime = 0; } //当存在早退异常被抵消的情况 if (collect2.size() > 0) { leaveElaryTime = 0; } } } /** * 当存在请假时,考虑扣除请假时长 */ int askForLeaveTime = removeAskForLeave(realityStartTime, realityEndime, Util.null2String(getWorkOverTimeParam.get("workfor")) , bdlx, askForLeaveList, askForLeaveItems, offsetAskForLeaveAnomaly); /** * 当存在外出时,考虑扣除外出时长 */ int evectionTime = removeEvection(realityStartTime, realityEndime, Util.null2String(getWorkOverTimeParam.get("workfor")) , bdlx, evectionList, evectionItems, offsetEvectionAnomaly); /** * 加班时段所包含的就餐时段 */ int dinnerTime = Utils.dinnerTime(realityStartTime, realityEndime, scheduleResult, analysisDate); log.info("未扣减过的加班时长: {}", jbsc); log.info("beLateTime :[{}],leaveElaryTime :[{}],askForLeaveTime:[{}],evectionTime:[{}],dinnerTime:[{}]", beLateTime, leaveElaryTime, askForLeaveTime, evectionTime, dinnerTime); BigDecimal jbscbig = new BigDecimal(jbsc); if (CheckBoxEnum.CHECKED.getKey().equals(zdkcjcxxsc)){ //扣除就餐时长 jbsc = jbscbig.subtract(new BigDecimal(beLateTime)).subtract(new BigDecimal(leaveElaryTime)).subtract(new BigDecimal(askForLeaveTime)).subtract(new BigDecimal(evectionTime)).subtract(new BigDecimal(dinnerTime)).intValue(); }else { jbsc = jbscbig.subtract(new BigDecimal(beLateTime)).subtract(new BigDecimal(leaveElaryTime)).subtract(new BigDecimal(askForLeaveTime)).subtract(new BigDecimal(evectionTime)).intValue(); } if (CheckBoxEnum.CHECKED.getKey().equals(jbscbdccsqsc)) { if (jbsc > Double.valueOf(Util.null2String(scheduleMap.get("edxss"))) * 60) { jbsc = Double.valueOf(Util.null2String(scheduleMap.get("edxss"))) * 60; } } log.info("扣减过的加班时长 :[{}]", jbsc); resultMap.put("jbsc",jbsc); resultMap.put("realityStartTime",realityStartTime); resultMap.put("realityEndime",realityEndime); return resultMap; } /** * 请假影响加班时长 * @param kssj 加班开始时间 * @param jssj 加班结束时间 * @param workFor 作用时段 * @param askForLeaveList 请假集合 * @param askForLeaveItems 请假项目 * @return 请假在加班中所占时间 */ public int removeAskForLeave(String kssj,String jssj,String workFor,String bdlx,List> askForLeaveList, Map> askForLeaveItems,List> offsetAskForLeaveAnomaly ){ int employTime = 0; for (int i=0;i askForLeaveItem = askForLeaveItems.get(askForLeaveList.get(i).get("jqlx")); //作用时段 String zysd = Util.null2String(askForLeaveItem.get("zysd")); // if (!zysd.contains(workFor) && !zysd.contains(WorkForTimeEnum.ALL_TIME.getKey())){ // continue; // } if ("".equals(Util.null2String(askForLeaveList.get(i).get("kssj"))) || "".equals(Util.null2String(askForLeaveList.get(i).get("jssj")))){ if (!"".equals(qjsc)){ //时长请假 if (offsetAskForLeaveAnomaly.size() > 0){ List> list = offsetAskForLeaveAnomaly.stream().filter(e->bdlx.equals(e.get("bdlx"))).collect(Collectors.toList()); employTime += Math.round(list.size()/Double.valueOf(offsetAskForLeaveAnomaly.size()) *Double.valueOf(qjsc)*60); } } }else { //按照开始时间,结束时间请假 employTime +=Utils.getStartAndEndTime(kssj,jssj,askForLeaveList.get(i)); } } return employTime; } /** * 外出影响加班时长 * @param kssj 加班开始时间 * @param jssj 加班结束时间 * @param evectionList 外出、请假集合 * @return */ public int removeEvection(String kssj,String jssj,String workFor,String bdlx,List> evectionList,Map> evectionItems,List> offsetEvectionAnomaly){ int askForLeaveTime=0; for (int i=0;i evectionItem = evectionItems.get(evectionList.get(i).get("cclx")); //作用时段 String zysd = Util.null2String(evectionItem.get("zysd")); // if (!zysd.contains(workFor) && !WorkForTimeEnum.ALL_TIME.getKey().equals(zysd)){ // continue; // } if ("".equals(Util.null2String(evectionList.get(i).get("kssj"))) || "".equals(Util.null2String(evectionList.get(i).get("jssj")))){ if (!"".equals(qjsc)){ if (offsetEvectionAnomaly.size() > 0){ List> list = offsetEvectionAnomaly.stream().filter(e->bdlx.equals(e.get("bdlx"))).collect(Collectors.toList()); askForLeaveTime += Math.round(list.size()/Double.valueOf(offsetEvectionAnomaly.size()) *Double.valueOf(qjsc)*60); } } }else { //按照开始时间,结束时间请假 askForLeaveTime +=Utils.getStartAndEndTime(kssj,jssj,evectionList.get(i)); } } return askForLeaveTime; } }