package cn.com.lzt.userattendancedetail.service.impl; import cn.com.lzt.arrangeduty.entity.ArrangeDutyEntity; import cn.com.lzt.attendance.entity.TBusSpecialAttendEntity; import cn.com.lzt.calendar.entity.CalendarEntity; import cn.com.lzt.calendar.service.CalendarServiceI; import cn.com.lzt.callable.YearmonthlyDataloadCallable; import cn.com.lzt.dingattendanceinfo.entity.DingAttendanceinfoEntity; import cn.com.lzt.dingattendanceinfo.service.DingAttendanceinfoServiceI; import cn.com.lzt.holiday.entity.HolidayEntity; import cn.com.lzt.holiday.service.HolidayServiceI; import cn.com.lzt.mealsdeduct.entity.MealsDeductEntity; import cn.com.lzt.mealssubsidy.entity.MealsSubsidyEntity; import cn.com.lzt.overtimerecord.entity.OvertimeRecordEntity; import cn.com.lzt.overtimerecord.service.OvertimeRecordServiceI; import cn.com.lzt.projarrangedetail.entity.ProjarrangeDetailEntity; import cn.com.lzt.snapregularborrow.entity.SnapRegularborrowEntity; import cn.com.lzt.snapregularborrow.service.SnapRegularborrowServiceI; import cn.com.lzt.snapsingleborrow.entity.SnapSingleborrowEntity; import cn.com.lzt.snapsingleborrow.service.SnapSingleborrowServiceI; import cn.com.lzt.sysbug.entity.TSSysbugEntity; import cn.com.lzt.sysbug.service.TSSysbugUtils; import cn.com.lzt.useractiviti.data.dao.UseractivitiDataDao; import cn.com.lzt.useractiviti.sameleveltransfer.entity.TBusActivitiSamelevelTransferEntity; import cn.com.lzt.userarrangedetail.entity.UserArrangeDetailEntity; import cn.com.lzt.userattendancedetail.dao.UserAttendanceDetailDao; import cn.com.lzt.userattendancedetail.dto.AttendanceDetailJsonObj; import cn.com.lzt.userattendancedetail.dto.AttendanceDetailReqestJsonObj; import cn.com.lzt.userattendancedetail.dto.AttendanceTotalJsonObj; import cn.com.lzt.userattendancedetail.dto.UserAttendanceDetailDto; import cn.com.lzt.userattendancedetail.entity.UserAttendanceDetailAdjustedEntity; import cn.com.lzt.userattendancedetail.entity.UserAttendanceDetailEntity; import cn.com.lzt.userattendancedetail.service.UserAttendanceDetailServiceI; import cn.com.lzt.userattendancetotal.entity.UserAttendanceTotalEntity; import cn.com.lzt.userwagestrategy.entity.UserWagestrategyEntity; import cn.com.lzt.userwagestrategy.service.UserWagestrategyServiceI; import com.alibaba.fastjson.JSONObject; import org.apache.commons.httpclient.util.DateUtil; import org.jeecgframework.core.common.hibernate.qbc.CriteriaQuery; import org.jeecgframework.core.common.service.impl.CommonServiceImpl; import org.jeecgframework.core.constant.Globals; import org.jeecgframework.core.util.DataUtils; import org.jeecgframework.core.util.ListUtils; import org.jeecgframework.core.util.oConvertUtils; import org.jeecgframework.tag.vo.datatable.SortDirection; import org.jeecgframework.web.system.pojo.base.TSDepart; import org.jeecgframework.web.system.pojo.base.TSUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.*; @Service("userAttendanceDetailService") @Transactional public class UserAttendanceDetailServiceImpl extends CommonServiceImpl implements UserAttendanceDetailServiceI { @Autowired private UserAttendanceDetailDao userAttendanceDetailDao; // 员工工资策略表 @Autowired private UserWagestrategyServiceI userWagestrategyService; // 休假申请表 @Autowired private HolidayServiceI holidayService; // 加班备案表 @Autowired private OvertimeRecordServiceI overtimeRecordService; // 临时借调(单次)申请表 @Autowired private SnapSingleborrowServiceI snapSingleborrowService; // 临时固定周期申请表 @Autowired private SnapRegularborrowServiceI snapRegularborrowService; // 钉钉考勤原始信息表 @Autowired private DingAttendanceinfoServiceI dingAttendanceinfoService; @Autowired private CalendarServiceI calendarService; @Autowired private UseractivitiDataDao userAvtivitiDao; @Override public void saveOrUpdateUserAttendanceDetailEntitis( List userAttendanceTotalEntities) throws Exception { if (!ListUtils.isNullOrEmpty(userAttendanceTotalEntities)) { List obj2SaveOrUpdate = new ArrayList<>(); HashMap> hm_cache = new HashMap<>(); long s = System.currentTimeMillis(); //加载多线程 loadAllCacheTask(hm_cache, userAttendanceTotalEntities.get(0).getYearmonth()); long e = System.currentTimeMillis(); System.out.println("loadAllCacheTask costs:" + (e-s) +" ms"); for(int i=0 ; i detailEntities = null; //更新月度汇总信息 UserAttendanceTotalEntity total = null; try { detailEntities = getUpdateDetailinfoBytotalEntity(userAttendanceTotalEntity,hm_cache); total = getUpdateMonthlyInfo(userAttendanceTotalEntity,detailEntities); }catch(Exception ee) { System.out.println(ee); sentEmail(ee,userAttendanceTotalEntity.getUserId()); } if(detailEntities != null) { for(UserAttendanceDetailEntity detail2update:detailEntities) { obj2SaveOrUpdate.add(detail2update); } } if(total != null) { obj2SaveOrUpdate.add(total); } } if(obj2SaveOrUpdate.size()>0) { for(Object obj : obj2SaveOrUpdate) { saveOrUpdate(obj); } } long e1 = System.currentTimeMillis(); System.out.println("updateDetailinfoBytotalEntity 耗时:"+(e1-e)+"ms"); hm_cache.clear(); } } /** * @param ee */ private void sentEmail(Exception ee, String userid) { TSSysbugEntity tSSysbug = new TSSysbugEntity(); tSSysbug.setId(""); tSSysbug.setStatus(Globals.BUG_STATUS_NEW); tSSysbug.setProducter(Globals.BUG_CODER_PRODUCTER); tSSysbug.setBugPerson1(userid); StringBuffer exc = new StringBuffer(); exc.append(DateUtil.formatDate(new Date(), "yyyy-MM-dd hh:mm:ss SSS") + "###" +ee+":"+ee.getMessage()); StackTraceElement[] st = ee.getStackTrace(); for (StackTraceElement stackTraceElement : st){ String exclass = stackTraceElement.getClassName(); String method = stackTraceElement.getMethodName(); exc.append("【" + exclass + "."+ method + ":" + stackTraceElement.getLineNumber()+ ",异常类型:" + ee.getClass().getName()+"】"); } tSSysbug.setDescription(exc.toString()); TSUser producter = holidayService.get(TSUser.class, Globals.BUG_CODER_PRODUCTER); tSSysbug.setProducterName(producter.getRealName()); tSSysbug.setCoder(Globals.BUG_CODER_DEVELOP); TSUser coder = holidayService.get(TSUser.class, Globals.BUG_CODER_DEVELOP); tSSysbug.setCoderName(coder.getRealName()); if(tSSysbug.getBugPerson1() != null && tSSysbug.getBugPerson1().length()>0) { TSUser bugperson = holidayService.get(TSUser.class, tSSysbug.getBugPerson1()); tSSysbug.setBugPerson1Realname(bugperson.getRealName()); } TSSysbugUtils.sendBugMail(tSSysbug, tSSysbug.getProducter(),"当月考勤核算异常通知"); TSSysbugUtils.sendBugMail(tSSysbug, Globals.BUG_CODER_DESIGN,"当月考勤核算异常通知"); TSSysbugUtils.sendBugMail(tSSysbug, tSSysbug.getCoder(),"当月考勤核算异常通知"); } @Override public void saveOrUpdateUserAttendanceDetailEntitis(UserAttendanceTotalEntity userAttendanceTotalEntity) throws Exception { if (userAttendanceTotalEntity != null) { List obj2SaveOrUpdate = new ArrayList<>(); long s = System.currentTimeMillis(); List detailEntities = getUpdateDetailinfoBytotalEntity(userAttendanceTotalEntity, null); UserAttendanceTotalEntity total = getUpdateMonthlyInfo(userAttendanceTotalEntity,detailEntities); if(detailEntities != null) { for(UserAttendanceDetailEntity detail2update:detailEntities) { obj2SaveOrUpdate.add(detail2update); } } if(total != null) { obj2SaveOrUpdate.add(total); } if(obj2SaveOrUpdate.size()>0) { for(Object obj : obj2SaveOrUpdate) { saveOrUpdate(obj); } } long e = System.currentTimeMillis(); System.out.println("updateOneDetailinfoBytotalEntity 耗时:"+(e-s)+"ms"); } } /** * 通过月度考勤计算更新月度每日的考勤信息 * @author hualong.zhao * @date 2017-11-30 * @param userAttendanceTotalEntity * @param hm_cache * @throws Exception */ private List getUpdateDetailinfoBytotalEntity( UserAttendanceTotalEntity userAttendanceTotalEntity, HashMap> hm_cache) throws Exception { List uatdlist = null; if(hm_cache == null) { uatdlist = getallUsefulField(userAttendanceTotalEntity, null, null); }else { uatdlist = getallUsefulFieldWithCache(hm_cache,userAttendanceTotalEntity); } List detailEntities = new ArrayList<>(); for (UserAttendanceDetailDto dto : uatdlist) { // // if("ff808081657e96b10165848ae5d61df2".equals(dto.getUserid())) { // System.out.println("张义华日夜"); // }else { // continue; // } // 只计算今日之前的考勤 // Date ymdDate = dto.getYmdDate(); // if(ymdDate.after(new Date())) { // continue; // } UserAttendanceDetailEntity userAttendanceDetailEntity = new UserAttendanceDetailEntity(); //时间微调 默认为零 userAttendanceDetailEntity.setTimeFineTuning(BigDecimal.ZERO); //设置当前时间 userAttendanceDetailEntity.setYmdDate(dto.getYmdDate()); // 设置考勤id; ok userAttendanceDetailEntity.setAttendanceId(dto.getAttendanceId()); // 设置实际出勤时间 userAttendanceDetailEntity.setAttendanceDate(dto.getActattendanceDate()); // 设置实际退勤时间 if (oConvertUtils.isNotEmpty(dto.getActattendanceDate())&& oConvertUtils.isNotEmpty(dto.getActretreatDate())&& dto.getActattendanceDate().equals(dto.getActretreatDate())) { userAttendanceDetailEntity.setRetreatDate(null); }else { userAttendanceDetailEntity.setRetreatDate(dto.getActretreatDate()); } // 设置班次id 如果排班类型为休息 则此处不存储班次id if (Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType()))) { userAttendanceDetailEntity.setDutyId(null); }else { userAttendanceDetailEntity.setDutyId(dto.getShiftid()); } // 设置基准时间 userAttendanceDetailEntity.setDatumDate(dto.getDatumDate()); // 設置时间差值 if (null==dto.getTimeDifference()) { userAttendanceDetailEntity.setTimeDifference(BigDecimal.ZERO); }else { userAttendanceDetailEntity.setTimeDifference(dto.getTimeDifference()); } //设置超时加班时长 userAttendanceDetailEntity.setTimeoutOvertimeDuration(dto.getTimeoutOvertimeDuration()); //设置 国定加班时长 userAttendanceDetailEntity.setNationalOvertimeDuration(dto.getNationalOvertimeDuration()); //设置 特殊加班时长 userAttendanceDetailEntity.setSpecialOvertime(dto.getSpecialOvertime()); // 获取当前状态 userAttendanceDetailEntity.setStatus(dto.getCurdateStatus()); // 获取借调信息-==start userAttendanceDetailEntity.setBorrowstatus(dto.getBorrowstatus()); userAttendanceDetailEntity.setBorrowspid(dto.getBorrowspid()); userAttendanceDetailEntity.setBorrowsdepartid(dto.getBorrowsdepartid()); userAttendanceDetailEntity.setDayPay(dto.getDayPay()); // 获取借调信息-==end // 设置实际出勤时间 if (null==dto.getActualAttendanceDate()) { userAttendanceDetailEntity.setAttendanceMins(BigDecimal.ZERO); userAttendanceDetailEntity.setActualAttendanceDate(BigDecimal.ZERO); }else{ userAttendanceDetailEntity.setAttendanceMins(dto.getActualAttendanceDate()); userAttendanceDetailEntity.setActualAttendanceDate(dto.getActualAttendanceDate()); } AttendanceDetailJsonObj jsonobj = getjsonObjfromDto(dto); if(hm_cache != null) { // 单个考勤核算不覆盖调整记录 // 恢复调整记录, 主要是针对重复生成考勤的调整记录被覆盖的问题 List adjustedEntities = getAdjustedAttendEntitiesWithCache(hm_cache, dto); UserAttendanceDetailAdjustedEntity currDateAdjustEntity = getCurrDateAdjustEntity(adjustedEntities, dto); if(currDateAdjustEntity != null) { userAttendanceDetailEntity.setStatus(currDateAdjustEntity.getStatus()); userAttendanceDetailEntity.setFineTuningType(currDateAdjustEntity.getFineTuningType()); userAttendanceDetailEntity.setAdjustReason(currDateAdjustEntity.getAdjustReason()); userAttendanceDetailEntity.setTimeFineTuning(currDateAdjustEntity.getTimeFineTuning()); jsonobj.setPrimevalAttendanceDate(dto.getPrimevalAttendanceDate()); jsonobj.setPrimevalRetreatDate(dto.getPrimevalRetreatDate()); jsonobj.setAdjustRecord(1); userAttendanceTotalEntity.setAdjustRecord("1"); } }else { List adjustedEntities = getAdjustedAttendEntityByUserId(dto.getUserid(), dto); UserAttendanceDetailAdjustedEntity currDateAdjustEntity = getCurrDateAdjustEntity(adjustedEntities, dto); if(currDateAdjustEntity != null) { userAttendanceDetailEntity.setStatus(currDateAdjustEntity.getStatus()); userAttendanceDetailEntity.setFineTuningType(currDateAdjustEntity.getFineTuningType()); userAttendanceDetailEntity.setAdjustReason(currDateAdjustEntity.getAdjustReason()); userAttendanceDetailEntity.setTimeFineTuning(currDateAdjustEntity.getTimeFineTuning()); jsonobj.setPrimevalAttendanceDate(dto.getPrimevalAttendanceDate()); jsonobj.setPrimevalRetreatDate(dto.getPrimevalRetreatDate()); jsonobj.setAdjustRecord(1); userAttendanceTotalEntity.setAdjustRecord("1"); } } //设置其他参数 userAttendanceDetailEntity.setJsonObj(JSONObject.toJSONString(jsonobj)); // saveOrUpdate(userAttendanceDetailEntity); detailEntities.add(userAttendanceDetailEntity); } //设置固定固定餐费补贴 /**固定餐费补贴*/ UserWagestrategyEntity userWagestrategy = userWagestrategyService.getUserWagestrategyEntityByUserId(userAttendanceTotalEntity.getUserId()); Integer fixedValue = null; if (null!=userWagestrategy) { /**餐补类型*/ String strategyType=oConvertUtils.getString(userWagestrategy.getStrategyType()); if (strategyType.equals("0")) { // 0按固定餐补;1按班次餐补 String temp = userWagestrategy.getNofixedmealsSubsidyid(); try { fixedValue = Integer.valueOf(oConvertUtils.getString(temp)); } catch (Exception e) { } } } if (null==fixedValue) { fixedValue = 0; } userAttendanceTotalEntity.setFixedValue(fixedValue); return detailEntities; } /** * @param adjustedEntities * @param dto * @return */ private UserAttendanceDetailAdjustedEntity getCurrDateAdjustEntity( List adjustedEntities, UserAttendanceDetailDto dto) { if(adjustedEntities != null && adjustedEntities.size()>0 && dto != null) { for(UserAttendanceDetailAdjustedEntity ae : adjustedEntities) { if(dto.getYmdDate().compareTo(ae.getYmdDate()) == 0) { return ae; } } } return null; } //将dto 中的其他字段信息 转化成jsonString 用于数据库保存 private AttendanceDetailJsonObj getjsonObjfromDto(UserAttendanceDetailDto dto) { AttendanceDetailJsonObj jsonobj = new AttendanceDetailJsonObj(); jsonobj.setNoPunchCard(0); jsonobj.setAdjustRecord(0); jsonobj.setMoneyLeave(false); jsonobj.setWorktype(dto.getDtype()); BigDecimal actDatumDate = dto.getDatumDate(); if (null==actDatumDate) { actDatumDate = BigDecimal.ZERO; } //设置 早退 状态 jsonobj.setLeaveEarly(dto.isLeaveEarly()); //设置 迟到 状态 jsonobj.setBelate(dto.isBelate()); //设置 旷工 状态 jsonobj.setAbsenteeism(dto.getAbsenteeism()); //设置事假请假的分钟数 jsonobj.setThingLeaveMins(dto.getThingLeaveMins()); //设置病假请假的分钟数 jsonobj.setSickLeaveMins(dto.getSickLeaveMins()); //dgq 设置调休分钟数 jsonobj.setExchangeMins(dto.getExchagneMins()); //设置这一天加过班 jsonobj.setIhadDuty(dto.isIhadDuty()); //设置这一天未打卡 if (oConvertUtils.isNotEmpty(dto.getActattendanceDate())&& oConvertUtils.isNotEmpty(dto.getActretreatDate())&& dto.getActattendanceDate().equals(dto.getActretreatDate())) { //如果上班时间和下班时间相等 则认定为 一次漏打卡 if (Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType()))) { //休息的时候 不记录漏打卡 jsonobj.setNoPunchCard(0); }else { jsonobj.setNoPunchCard(1); } } jsonobj.setExtraOvertime(dto.getExtraOvertime()); //如果既没有开始时间 也没有结束时间 切 当前状态为正常的时候记录 漏打卡两次 if (oConvertUtils.isEmpty(dto.getActattendanceDate())&& oConvertUtils.isEmpty(dto.getActretreatDate()) ) { if (Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType()))) { //休息的时候 不记录漏打卡 jsonobj.setNoPunchCard(0); }else { //正常的需要工作的时候 // 判断当天有没有长假期 Boolean longHoliday = dto.getLongHoliday(); //没有请长假 切当天没有打卡记录 则记录两次漏打卡 if (!longHoliday) { // 如果当天请了事假或者是病假,不记录未打卡 事假和病假 也按照480计算 if ((!dto.getSickLeaveMins().equals(BigDecimal.ZERO))|| (!dto.getThingLeaveMins().equals(BigDecimal.ZERO)) ) { actDatumDate = new BigDecimal(480); jsonobj.setNoPunchCard(0); }else { //当该员工在没有情况在前提下 没有打卡记录的时候, 实际出勤时间记作480分,避免超时加班时长) actDatumDate = new BigDecimal(480); jsonobj.setMoneyLeave(true); jsonobj.setNoPunchCard(2); } } } } //如果这一天又带薪假 将工作状态记录为已请假 Boolean longHoliday = dto.getLongHoliday(); if (longHoliday) { actDatumDate = new BigDecimal(480); } jsonobj.setActDatumDate(actDatumDate ); jsonobj.setDayShiftSubsidy(dto.getDayShiftSubsidy()); jsonobj.setNightShiftSubsidy(dto.getNightShiftSubsidy()); jsonobj.setDayShift(dto.getDayShift()); jsonobj.setRegularShift(dto.getRegularShift()); jsonobj.setDayShiftId(dto.getDayShiftId()); jsonobj.setNightShiftSubsidyId(dto.getNightShiftSubsidyId()); jsonobj.setDayShiftSubsidyId(dto.getDayShiftSubsidyId()); jsonobj.setRegularShiftId(dto.getRegularShiftId()); jsonobj.setDutyShift(dto.getDutyShift()); jsonobj.setDutyShiftId(dto.getDutyShiftId()); return jsonobj; } private UserAttendanceTotalEntity getUpdateMonthlyInfo( UserAttendanceTotalEntity userAttendanceTotalEntity,List detailEntities,HashMap> hm_cache) throws Exception { UserAttendanceTotalEntity total = getUpdateMonthlyInfoBase(userAttendanceTotalEntity, detailEntities); //计算加班餐补 calOvertimeMealWithCache(total, hm_cache); return total; } private UserAttendanceTotalEntity getUpdateMonthlyInfo( UserAttendanceTotalEntity userAttendanceTotalEntity,List detailEntities) throws Exception { UserAttendanceTotalEntity total = getUpdateMonthlyInfoBase(userAttendanceTotalEntity, detailEntities); //计算加班餐补 calOvertimeMeal(total); return total; } //更新月度请假信息 private UserAttendanceTotalEntity getUpdateMonthlyInfoBase( UserAttendanceTotalEntity userAttendanceTotalEntity,List detailEntities) throws Exception { /**调整时间*/ BigDecimal adjustTime = BigDecimal.ZERO; /**总时间差*/ BigDecimal timeDifferenceTotal= BigDecimal.ZERO; /**总加班时间*/ BigDecimal overtimeTotalTime= BigDecimal.ZERO; /**超时加班时长*/ BigDecimal timeoutOvertimeDuration= BigDecimal.ZERO; /**国定加班时长*/ BigDecimal nationalOvertimeDuration= BigDecimal.ZERO; /**特殊加班费*/ BigDecimal specialOvertime= BigDecimal.ZERO; /**夜班白班津贴*/ Integer dayShiftSubsidy= 0; /**夜班夜班津贴*/ Integer nightShiftSubsidy= 0; /**日班*/ Integer dayShift= 0; /**常班*/ Integer regularShift= 0; /**值班*/ Integer dutyShift= 0; /**额外加班*/ Integer extraOvertime= 0; /**基准出勤时间*/ BigDecimal datumAttendanceDate = BigDecimal.ZERO; /**实际出勤时间*/ BigDecimal actualAttendanceDate= BigDecimal.ZERO; /** 早退次数 */ Integer earlyLeaveAmount = 0; /** 迟到次数 */ Integer lateAmount = 0; /** 旷工次数 */ BigDecimal absenteeismAmount = BigDecimal.ZERO; /** 未打卡次 */ Integer noPunchCardAmount = 0; /** 带薪假 */ BigDecimal paidLeave = BigDecimal.ZERO; /** 事假 */ BigDecimal thingLeave = BigDecimal.ZERO; /** 病假 */ BigDecimal sickLeave = BigDecimal.ZERO; /** 调休 */ BigDecimal exchange = BigDecimal.ZERO; /** 病假分钟数 */ BigDecimal sickLeavetotalmins = BigDecimal.ZERO; /** 婚假 */ BigDecimal marriageLeave = BigDecimal.ZERO; /** 丧假 */ BigDecimal funeralLeave = BigDecimal.ZERO; /** 产假 */ BigDecimal maternityLeave = BigDecimal.ZERO; /** 陪产假 */ BigDecimal accompanyMaternityLeave = BigDecimal.ZERO; /**请假总时间*/ BigDecimal leaveTotalTime= BigDecimal.ZERO; /**普通值班时长*/ BigDecimal dutyDuration = BigDecimal.ZERO; /**国定值班天数*/ BigDecimal nationalDutyDuration = BigDecimal.ZERO; /** * 月度基准时间合计 */ BigDecimal monthlyActDatumsum = BigDecimal.ZERO;; /** * 国定假日排班时长 */ BigDecimal monthlyLegalholidaysum = BigDecimal.ZERO;; /** * 月度法定工时天数 */ Integer monthlyLegalworktime = 0; /** * 是否单次临时调动过 0没有调动过;1调动过 */ String ifmoved = Globals.SHIFOU_01_0; /**夜班白班津贴主键*/ String dayShiftSubsidyId = ""; /**夜班夜班津贴主键*/ String nightShiftSubsidyId= ""; /**日班津贴主键*/ String dayShiftId= ""; /**常班津贴主键*/ String regularShiftId= ""; //缓存出勤日期和出勤实体,用于解决请病假却出勤的病假扣除问题 HashMap hm_Date2AttendanceDetail = new HashMap(); for (UserAttendanceDetailEntity entity:detailEntities) { //读取其他字段信息, 变转化成实体类 对其进行相关逻辑判断 AttendanceDetailJsonObj jsonObj = getJsonObjFromString(oConvertUtils .getString(entity.getJsonObj())); if (jsonObj.getIhadDuty()) { // 把国定值班从值班天数中分离出去 zy 20180416 if(jsonObj.getWorktype().equals(Globals.dtype_2)) { //国定值班 nationalDutyDuration = nationalDutyDuration.add(BigDecimal.ONE); }else { //非国定普通加班 //如果这一天加班了 月度加班总和+1 dutyDuration = dutyDuration.add(BigDecimal.ONE); } } hm_Date2AttendanceDetail.put(DataUtils.date2Str(entity.getYmdDate(), DataUtils.date_sdf), entity); //查看当天是否有迟到 if (jsonObj.getBelate()) { lateAmount = lateAmount +1 ; } //查看当天是否有早退 if (jsonObj.getLeaveEarly()) { earlyLeaveAmount = earlyLeaveAmount +1 ; } //查看当天是否有旷工 if (null!=jsonObj.getAbsenteeism() && !jsonObj.getWorktype().equals(Globals.dtype_2)) { absenteeismAmount = absenteeismAmount.add(jsonObj.getAbsenteeism()); } //查看月度基准时间 if (null!=jsonObj.getActDatumDate() /*&& !jsonObj.getWorktype().equals(Globals.dtype_2)*/) { monthlyActDatumsum = monthlyActDatumsum.add(jsonObj.getActDatumDate()); } //查看 月度额外加班 if (null!=jsonObj.getExtraOvertime()) { extraOvertime = extraOvertime+jsonObj.getExtraOvertime(); } String worktype = jsonObj.getWorktype(); //查看月度国定假日时长 if (null!=worktype) { if (worktype.equals(Globals.dtype_2)) { //国定休日 monthlyLegalholidaysum = monthlyLegalholidaysum.add(jsonObj.getActDatumDate()); } if (worktype.equals(Globals.dtype_0)) { //工作日 monthlyLegalworktime++; } } //查看 夜班白班津贴 if (null!=jsonObj.getDayShiftSubsidy()) { dayShiftSubsidy = dayShiftSubsidy+jsonObj.getDayShiftSubsidy(); } //查看夜班夜班津贴 if (null!=jsonObj.getNightShiftSubsidy()) { nightShiftSubsidy = nightShiftSubsidy+jsonObj.getNightShiftSubsidy(); } //查看日班 if (null!=jsonObj.getDayShift()) { dayShift = dayShift+jsonObj.getDayShift(); } //查看值班 if (null!=jsonObj.getDutyShift()) { dutyShift = dutyShift+jsonObj.getDutyShift(); } //查看 常班 if (null!=jsonObj.getRegularShift()) { regularShift = regularShift+jsonObj.getRegularShift(); } if(isPayLeave(entity)) { //年假等带薪假+8小时 datumAttendanceDate = datumAttendanceDate.add(new BigDecimal(8*60)); }else if (null!=entity.getDatumDate()) { // add by zy 20180413 // 刨除国定假 // 在计算应出勤时间是已经处理过国定时间 -zy 20180513 if(null!=worktype /*&& !worktype.equals(Globals.dtype_2)*/) { datumAttendanceDate = datumAttendanceDate.add(entity.getDatumDate()); } } //查看员工的 实际出勤时间 if(isPayLeave(entity)) { //年假等带薪假+8小时 actualAttendanceDate = actualAttendanceDate.add(new BigDecimal(8*60)); }else if (null!=entity.getActualAttendanceDate()) { // add by zy 20180413 // 刨除国定假 // 直接减掉国定加班时长 if(null!=worktype /*&& !worktype.equals(Globals.dtype_2))*/) { actualAttendanceDate = actualAttendanceDate.add(entity.getActualAttendanceDate()); if(entity.getNationalOvertimeDuration() != null && entity.getNationalOvertimeDuration().compareTo(BigDecimal.ZERO)>0) { actualAttendanceDate =actualAttendanceDate.subtract(entity.getNationalOvertimeDuration()); } } } //查看员工的 国定加班时长 if (null!=entity.getNationalOvertimeDuration()) { nationalOvertimeDuration = nationalOvertimeDuration.add(entity.getNationalOvertimeDuration()); } //查看员工的 临时借调状态 if (null!=entity.getBorrowstatus()&&"1".equals(entity.getBorrowstatus())) { ifmoved =Globals.SHIFOU_01_1; } //查看员工的 时间差值 if (null!=entity.getTimeDifference()) { timeDifferenceTotal = timeDifferenceTotal.add(entity.getTimeDifference()); } //查看员工的 特殊加班费 if (null!=entity.getSpecialOvertime()) { specialOvertime = specialOvertime.add(entity.getSpecialOvertime()); } //查看员工的 时间微调 if (null!=entity.getTimeFineTuning()) { adjustTime = adjustTime.add(entity.getTimeFineTuning()); } //查看当天是否有未打卡 if (null!=jsonObj.getNoPunchCard()) { noPunchCardAmount = noPunchCardAmount +jsonObj.getNoPunchCard() ; } /*//这一天状态是事假 事假统计分钟数 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_0)) { BigDecimal thingLeaveMins =jsonObj.getThingLeaveMins(); if (null==thingLeaveMins) { thingLeaveMins = BigDecimal.ZERO; } thingLeave = thingLeave.add(thingLeaveMins); }*/ //这一天状态是病假 月度病假数+1 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_1)) { /*BigDecimal sickLeaveMins =jsonObj.getSickLeaveMins(); if (null==sickLeaveMins) { sickLeaveMins = BigDecimal.ZERO; }*/ sickLeave = sickLeave.add( BigDecimal.ONE); //sickLeavetotalmins = sickLeavetotalmins.add(sickLeaveMins); } //这一天状态是年假? 年假就是带薪假 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_2)) { paidLeave = paidLeave.add(BigDecimal.ONE); } //这一天状态是丧假 月度丧假数+1 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_3)) { funeralLeave = funeralLeave.add(BigDecimal.ONE); } //这一天状态是婚假 月度婚假数+1 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_4)) { marriageLeave = marriageLeave.add(BigDecimal.ONE); } //这一天状态是产假 月度产假数+1 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_5)) { maternityLeave = maternityLeave.add(BigDecimal.ONE); } //这一天状态是陪产假 月度陪产假数+1 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_6)) { accompanyMaternityLeave = accompanyMaternityLeave.add(BigDecimal.ONE); } //调休 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_7)) { exchange = exchange.add( BigDecimal.ONE); } //这一天状态是法定假日 法定假日也归属于带薪假 if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_11)) { paidLeave = paidLeave.add(BigDecimal.ONE); } } // =====查询请假情况 String yearmonth=userAttendanceTotalEntity.getYearmonth(); String userid = userAttendanceTotalEntity.getUserId(); String ymdDate = yearmonth+"-01"; Calendar calendar = Calendar.getInstance(); Date endDate = DataUtils.str2Date(ymdDate, DataUtils.date_sdf); calendar.setTime(endDate); calendar.add(Calendar.DATE, -1); // 上个月的最后一天 String lastmonthlatestday = DataUtils.date2Str(endDate, DataUtils.date_sdf); calendar.add(Calendar.DATE, 1); //这个月的第一天 String monthfirstday = DataUtils.date2Str(endDate, DataUtils.date_sdf); calendar.add(Calendar.MONTH, 1); endDate = calendar.getTime(); //下个月的第一天 String nextmonthfirstday = DataUtils.date2Str(endDate, DataUtils.date_sdf); calendar.add(Calendar.DATE, -1); endDate = calendar.getTime(); //这个月的最后一天 String monthlatestday = DataUtils.date2Str(endDate, DataUtils.date_sdf); List userHolidayEntities = holidayService .getUserHolidayEntities(userid, yearmonth); List holidaysFromActiviti = userAvtivitiDao.getHolidayFromExchangeActiviti(userid, yearmonth); if (null==userHolidayEntities) { userHolidayEntities = new ArrayList(); } if(holidaysFromActiviti != null && holidaysFromActiviti.size() > 0) userHolidayEntities.addAll(holidaysFromActiviti); for (HolidayEntity holiday:userHolidayEntities) { String hilidaytype =oConvertUtils.getString( holiday.getHolidayType()); BigDecimal holidayDuration= holiday.getHolidayDuration(); Date holidayStime= holiday.getHolidayStime(); Date holidayEtime= holiday.getHolidayEtime(); //如果开始时间 和结束时间为空// 跳过 if (null==holidayStime||null==holidayEtime) { continue; } //请假类型不是事假 也不是病假 、调休 , 跳过 不做处理 if (!(Globals.REST_TYPE_1.equals(hilidaytype)|| Globals.REST_TYPE_0.equals(hilidaytype) ||Globals.REST_TYPE_7.equals(hilidaytype))) { continue; } String holidaySdate = DataUtils.date2Str(holidayStime, DataUtils.date_sdf); String holidayEdate = DataUtils.date2Str(holidayEtime, DataUtils.date_sdf); //如果结束日期晚于下月一号 跳过 if (holidayEdate.compareTo(nextmonthfirstday)>0) { continue; } /* 此处处理逻辑混乱, 注释不知所云. 暂且去掉. 20180702 xzx // 如果请假开始日期 等于本月的一号 切请假结束日期也是本月的一号 if (holidaySdate.equals(monthfirstday)&&holidayEdate.equals(monthfirstday)) { //判断上月的最后一天 是否为夜班 List yestoryday = userAttendanceDetailDao. getlistbyProjarrangeDetailid(null,userid,lastmonthlatestday); if (!ListUtils.isNullOrEmpty(yestoryday)) { UserAttendanceDetailDto ydto = yestoryday.get(0); if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) { //如果上月的最后一天是夜班, 则将该事假/病假 记录 }else { //如果上月的最后一天不是夜班, 则将该事假/病假 记录 continue; } } } // 如果请假开始日期 等于下个月的一号 切请假结束日期也是下个月的一号 if (holidaySdate.equals(nextmonthfirstday)&&holidayEdate.equals(nextmonthfirstday)) { //判断本月的最后一天 是否为夜班 List yestoryday = userAttendanceDetailDao. getlistbyProjarrangeDetailid(null,userid,monthlatestday); if (!ListUtils.isNullOrEmpty(yestoryday)) { UserAttendanceDetailDto ydto = yestoryday.get(0); if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) { //如果本月的最后一天是夜班, 则将该事假/病假 记录 }else { //如果本月的最后一天不是夜班, 则将该事假/病假 记录 continue; } } } */ //对 每天请假时长 非空处理 if (oConvertUtils.isEmpty(holidayDuration)) { holidayDuration = BigDecimal.ZERO; } //对 每天请假时长 进行单位转换: 小时--> 分钟 holidayDuration = holidayDuration.multiply(new BigDecimal(60)); Calendar dd = Calendar.getInstance(); dd.setTime(holidayStime); while(dd.getTime().compareTo(holidayEtime)<=0) { UserAttendanceDetailEntity temp_entity = hm_Date2AttendanceDetail.get(DataUtils.date2Str(dd.getTime(), DataUtils.date_sdf)); if(temp_entity != null && temp_entity.getActualAttendanceDate() != null && temp_entity.getActualAttendanceDate().compareTo(BigDecimal.ZERO)>0) { if (temp_entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_10)) { holidayDuration = holidayDuration.subtract(temp_entity.getActualAttendanceDate()); if(holidayDuration.compareTo(BigDecimal.ZERO)<0) { holidayDuration = BigDecimal.ZERO; } } } dd.add(Calendar.DATE, 1); } if (Globals.REST_TYPE_1.equals(hilidaytype) ) { sickLeavetotalmins = sickLeavetotalmins.add(holidayDuration); }else if ( Globals.REST_TYPE_0.equals(hilidaytype)) { thingLeave = thingLeave.add(holidayDuration); }else if ( Globals.REST_TYPE_7.equals(hilidaytype)) { exchange = exchange.add(holidayDuration); } } //超时加班时长计算 月度基准时间-国定假日排班时长 -带薪休假时长-法定工时 ---原算法,新算法是月基准时间-法定工时然后抵扣旷工时长 zy20180416 //月度法定工时=(当月天数-休假天数-国定休假天数)*8;datumAttendanceDate // timeoutOvertimeDuration= monthlyActDatumsum.subtract(monthlyLegalholidaysum) // .subtract(new BigDecimal(monthlyLegalworktime*8*60)); // 2018年11月15日前的算法是169应出勤时间-月度法定工时 // timeoutOvertimeDuration= datumAttendanceDate.subtract(new BigDecimal(monthlyLegalworktime*8*60));//xzx //2018年11月15日后的算法是实际出勤时间-法定工时,这里面实际出勤时间包含漏打卡时间 //xzx timeoutOvertimeDuration= actualAttendanceDate.subtract(new BigDecimal(monthlyLegalworktime*8*60)); // 记录抵扣前的原始的超时加班时长和旷工时长 if(timeoutOvertimeDuration == null) { userAttendanceTotalEntity.setTimeoutOvertimeDuration_orig(BigDecimal.ZERO); }else { userAttendanceTotalEntity.setTimeoutOvertimeDuration_orig(timeoutOvertimeDuration); } if(absenteeismAmount == null) { absenteeismAmount = BigDecimal.ZERO; userAttendanceTotalEntity.setAbsenteeismAmount_orig(BigDecimal.ZERO); }else { userAttendanceTotalEntity.setAbsenteeismAmount_orig(absenteeismAmount); } // 负数归零 // 2019/2/11 超时加班时长负数代表没有做满法定工时 // if(timeoutOvertimeDuration.compareTo(BigDecimal.ZERO) < 0) { // timeoutOvertimeDuration = BigDecimal.ZERO; // } if(absenteeismAmount.compareTo(BigDecimal.ZERO) < 0) { absenteeismAmount = BigDecimal.ZERO; } //旷工工时和超时加班工时进行相互抵扣 zy20180415 // 2019/2/11由于超时加班采用实际出勤时间来计算,故不存在抵扣 // if(timeoutOvertimeDuration.compareTo(absenteeismAmount) == 0) { // //旷工工时等于超时加班工时 // timeoutOvertimeDuration = BigDecimal.ZERO; // absenteeismAmount = BigDecimal.ZERO; // }else if(timeoutOvertimeDuration.compareTo(absenteeismAmount) > 0) { // //超时加班工时多 // timeoutOvertimeDuration = timeoutOvertimeDuration.subtract(absenteeismAmount); // absenteeismAmount = BigDecimal.ZERO; // }else { // //旷工工时多 // absenteeismAmount = absenteeismAmount.subtract(timeoutOvertimeDuration); // timeoutOvertimeDuration = BigDecimal.ZERO; // } // /** // * 超时加班时长 当小于零的时候, 按 零存储 // */ // if (timeoutOvertimeDuration.compareTo(BigDecimal.ZERO)<0) { // timeoutOvertimeDuration = BigDecimal.ZERO; // } userAttendanceTotalEntity.setPaidLeave(paidLeave); userAttendanceTotalEntity.setThingLeave(thingLeave); userAttendanceTotalEntity.setSickLeave(sickLeave); userAttendanceTotalEntity.setMarriageLeave(marriageLeave); userAttendanceTotalEntity.setFuneralLeave(funeralLeave); userAttendanceTotalEntity.setMaternityLeave(maternityLeave); userAttendanceTotalEntity.setExchangeTime(exchange); leaveTotalTime = thingLeave.add(sickLeavetotalmins) .add(exchange) .add((paidLeave .add(marriageLeave) .add(funeralLeave) .add(maternityLeave) .add(accompanyMaternityLeave)).multiply(new BigDecimal(8*60))); userAttendanceTotalEntity.setLeaveTotalTime(leaveTotalTime); userAttendanceTotalEntity.setAccompanyMaternityLeave(accompanyMaternityLeave); userAttendanceTotalEntity.setDutyDuration(dutyDuration); userAttendanceTotalEntity.setNationalDutyDuration(nationalDutyDuration); userAttendanceTotalEntity.setEarlyLeaveAmount(earlyLeaveAmount); userAttendanceTotalEntity.setLateAmount(lateAmount); userAttendanceTotalEntity.setAbsenteeismAmount(absenteeismAmount); userAttendanceTotalEntity.setNoPunchCardAmount(noPunchCardAmount); userAttendanceTotalEntity.setDatumAttendanceDate(datumAttendanceDate); userAttendanceTotalEntity.setActualAttendanceDate(actualAttendanceDate); /**调整时间*/ userAttendanceTotalEntity.setAdjustTime(adjustTime); /**超时加班时长*/ userAttendanceTotalEntity.setTimeoutOvertimeDuration(timeoutOvertimeDuration); /**国定加班时长*/ userAttendanceTotalEntity.setNationalOvertimeDuration(nationalOvertimeDuration); /**总时间差*/ userAttendanceTotalEntity.setTimeDifferenceTotal(timeDifferenceTotal); /**特殊加班费*/ userAttendanceTotalEntity.setSpecialOvertime(specialOvertime); /**总加班时间*/ overtimeTotalTime = timeoutOvertimeDuration.add(nationalOvertimeDuration).add(specialOvertime); // 当总加班时间小于零的时候 以零处理 if (overtimeTotalTime.compareTo(BigDecimal.ZERO)<0) { overtimeTotalTime = BigDecimal.ZERO; } userAttendanceTotalEntity.setOvertimeTotalTime(overtimeTotalTime); /**夜班白班津贴*/ userAttendanceTotalEntity.setDayShiftSubsidy(dayShiftSubsidy); /**夜班夜班津贴*/ userAttendanceTotalEntity.setNightShiftSubsidy(nightShiftSubsidy); /**日班*/ userAttendanceTotalEntity.setDayShift(dayShift); /**值班*/ userAttendanceTotalEntity.setDutyShift(dutyShift); /**常班*/ userAttendanceTotalEntity.setRegularShift(regularShift); /** 额外加班 */ userAttendanceTotalEntity.setExtraOvertime(extraOvertime); /** 是否单次临时调动过 */ userAttendanceTotalEntity.setIfmoved(ifmoved); AttendanceTotalJsonObj json = new AttendanceTotalJsonObj(); json.setSickLeavetotalmins(sickLeavetotalmins); userAttendanceTotalEntity.setJsonObj(JSONObject.toJSONString(json)); //saveOrUpdate(userAttendanceTotalEntity); // if(object2SaveOrUpdate != null) { // object2SaveOrUpdate.add(userAttendanceTotalEntity); // } return userAttendanceTotalEntity; } private void calOvertimeMealWithCache(UserAttendanceTotalEntity totalEntity,HashMap> hm_cache) throws Exception { List list = getOvertimeRecordEntitiesWithCache(hm_cache, totalEntity.getUserId(), ""); totalEntity.setOvertimeMeal(BigDecimal.ZERO); for (OvertimeRecordEntity overtimeRecord : list) { totalEntity.setOvertimeMeal(totalEntity.getOvertimeMeal().add(overtimeRecord.getMealsSubsidy())); } } private void calOvertimeMeal(UserAttendanceTotalEntity totalEntity) throws Exception { List list = overtimeRecordService.getOvertimeRecordEntities(totalEntity.getUserId(), totalEntity.getYearmonth()); totalEntity.setOvertimeMeal(BigDecimal.ZERO); for (OvertimeRecordEntity overtimeRecord : list) { BigDecimal ms = BigDecimal.ZERO; if(overtimeRecord.getMealsSubsidy() != null) { ms = overtimeRecord.getMealsSubsidy(); } totalEntity.setOvertimeMeal(totalEntity.getOvertimeMeal().add(ms)); } } /** * 判断是否是带薪假 * @param entity * @return */ private boolean isPayLeave(UserAttendanceDetailEntity entity) { if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_2)) { return true; } if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_3)) { return true; } if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_4)) { return true; } if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_5)) { return true; } if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_6)) { return true; } return false; } /** * 将从数据库中读取的字符串信息转化成实体类 * 需求變更: 2018年1月12日17:30:17 * 当员工两次都没打卡的时候, 默认界定为该员工旷工, 此时不提供餐补 * @author hualong.zhao * @date 2017-11-29 * * @param jsonobjString * @return */ @Override public AttendanceDetailJsonObj getJsonObjFromString(String jsonobjString) { AttendanceDetailJsonObj jsonObj = new AttendanceDetailJsonObj(); if (oConvertUtils.isNotEmpty(jsonobjString)) { try { jsonObj = (JSONObject.parseObject(jsonobjString)).toJavaObject(AttendanceDetailJsonObj.class); } catch (Exception e) { } } return jsonObj; } /*记一次迟到情况: 出勤时间>排班工作开始时间;并且10分钟<两者之差≤30分钟;*/ /*当月的迟到次数累计 迟到:10min之内不算迟到,10<min≤30 算迟到,min>30 算旷工半天; 当天请事假,也得考察迟到;*/ private void calculateBelateAndLeaveEarlyAndabsenteeism( UserAttendanceDetailDto dto) { //判断当天是否请了长假期 boolean longHoliday = dto.getLongHoliday(); //实际上班时间 Date actattendanceDate = dto.getActattendanceDate();; //实际下班时间 Date actretreatDate= dto.getActretreatDate(); String dutyType = oConvertUtils.getString(dto.getDutyType()); //前提条件: 如果排班为休息时 , 不考虑 迟到 / 早退 / 旷工 if (!Globals.DUTYTYPE_xiuxi.equals(dutyType)) { //当班次为加班 或者是值班时 不考虑 迟到 / 早退 if (oConvertUtils.isNotEmpty(dto.getNormalworkStime())&&oConvertUtils.isNotEmpty(dto.getNormalworkEtime())) { /**理应工作开始时间*/ Date workStarttime =getexactDate(dto.getYmdDate(), dto.getNormalworkStime(), 0, 0); /**理应工作结束时间*/ Integer t1flag = 0; boolean hassickorthingLeave = false; if (Globals.DUTYTYPE_yeban115.equals(dutyType)) { t1flag = 1; } Date workendtime = getexactDate(dto.getYmdDate(), dto.getNormalworkEtime(), t1flag, 0); // =====查询请假情况, 去掉事假的加班申请时长,计算理应的开始和结束工作时间 如果员工在这一天请了非事假意外的假 不认为该员工旷工 /迟到/早退 List userHolidayEntities = dto.getUserHolidayEntities(); if (!ListUtils.isNullOrEmpty(userHolidayEntities)) { for (HolidayEntity holiday:userHolidayEntities) { String hilidaytype =oConvertUtils.getString( holiday.getHolidayType()); //增加调休情况处理 dgq if (Globals.REST_TYPE_1.equals(hilidaytype)||Globals.REST_TYPE_0.equals(hilidaytype)||Globals.REST_TYPE_7.equals(hilidaytype)) { BigDecimal holidayDuration= calculateHolidayDuration(holiday,workStarttime,workendtime,dto); /**休假开始时间*/ Date holidayStime = holiday.getHolidayStime(); /**休假结束时间*/ Date holidayEtime = holiday.getHolidayEtime(); if (holidayStime.compareTo(workStarttime)<=0&&holidayEtime.compareTo(workStarttime)>=0) { workStarttime = holidayEtime; } if (holidayStime.compareTo(workendtime)<=0&&holidayEtime.compareTo(workendtime)>=0) { workendtime = holidayStime; } BigDecimal datumDate = dto.getDatumDate(); //如果休假表中填写的申请假期时长 大于当天的基准时间 是按照基准时间处理 holidayDuration = holidayDuration.compareTo(datumDate)>0?datumDate:holidayDuration; if(dto.getActualAttendanceDate() != null && dto.getActualAttendanceDate().compareTo(BigDecimal.ZERO)>0) { // 如果当天有实际出勤时间,那么从请假中扣除 holidayDuration = holidayDuration.subtract(dto.getActualAttendanceDate()); } if (Globals.REST_TYPE_1.equals(hilidaytype)) { dto.setSickLeaveMins(holidayDuration); }else if(Globals.REST_TYPE_0.equals(hilidaytype)) { // 修改为 改天请假的 小时数 这算的分钟数 dto.setThingLeaveMins(holidayDuration); }else if(Globals.REST_TYPE_7.equals(hilidaytype)) { dto.setExchagneMins(holidayDuration); } hassickorthingLeave = true; }else { dto.setLeaveEarly(false); dto.setBelate(false); dto.setAbsenteeism(BigDecimal.ZERO); longHoliday = true; break; } } } //如果请了事假之外的假期, 则认为该员工没有迟到 没有早退 没有旷工 //如果是国定假出现缺勤,不算旷工 if (!longHoliday && !Globals.dtype_2.equals(oConvertUtils.getString(dto.getDtype()))) { //如果两个打卡时间均为空, 则该员工旷工(前提条件是该员工没有请事假或者是病假) if (!hassickorthingLeave) { if (oConvertUtils.isEmpty(actattendanceDate)&&oConvertUtils.isEmpty(actretreatDate)) { // 当员工两次都没打卡的时候, 界定为该员工旷工, 此时不提供餐补 dto.setAbsenteeism(dto.getDatumDate()); } } //计算是否为迟到 或者是早旷工 if (oConvertUtils.isNotEmpty(actattendanceDate)&&actattendanceDate.after(workStarttime)) { // 实际上班时间 Calendar actattendanceCalendar = Calendar.getInstance(); actattendanceCalendar.setTime(actattendanceDate); // 理论应该工作时间 Calendar workStartCalendar = Calendar.getInstance(); workStartCalendar.setTime(workStarttime); int dateDiffint = DataUtils.dateDiff('m', actattendanceCalendar,workStartCalendar); if (actattendanceDate.equals(actretreatDate)) { // 如果開始時間等於结束时间 则定义为该员工漏打卡 , 此时 不计算欠勤时间 dateDiffint = 0; } dto.setBelatemins(dateDiffint); //出勤时间>排班工作开始时间;并且10分钟<两者之差≤30分钟; if (dateDiffint>10&&dateDiffint<=30) { dto.setBelate(true); } //迟到,min>30 切小于240分钟 算旷工4小时 if (dateDiffint>30&&dateDiffint<240) { BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(240)); dto.setAbsenteeism(absenteeism); } //迟到,min>=240&&dateDiffint<480 算旷工8小时 if(dateDiffint>=240&&dateDiffint<480) { BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(480)); dto.setAbsenteeism(absenteeism); } //迟到,min>=480 算旷工实际班次工时 if (dateDiffint>=480) { BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(dateDiffint)); dto.setAbsenteeism(absenteeism); } } if (oConvertUtils.isNotEmpty(actretreatDate) && oConvertUtils.isNotEmpty(actattendanceDate) && actretreatDate.after(actattendanceDate) && actretreatDate.before(workendtime)) { // 实际下班时间 Calendar actretreatCalendar = Calendar.getInstance(); actretreatCalendar.setTime(actretreatDate); // 理论应该下班时间 Calendar workendCalendar = Calendar.getInstance(); workendCalendar.setTime(workendtime); int dateDiffint = DataUtils.dateDiff('m',workendCalendar, actretreatCalendar); if (actattendanceDate.equals(actretreatDate)) { // 如果開始時間等於结束时间 则定义为该员工漏打卡 , 此时 不计算欠勤时间 dateDiffint = 0; } dto.setLeaveEarlymins(dateDiffint); //出勤时间>排班工作开始时间;并且10分钟<两者之差≤30分钟; if (dateDiffint>10&&dateDiffint<=30) { dto.setLeaveEarly(true); } //迟到,min>30 切小于240分钟 算旷工4小时 if (dateDiffint>30&&dateDiffint<240) { BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(240)); dto.setAbsenteeism(absenteeism); } //迟到,min>=240&&dateDiffint<480 算旷工8小时 if(dateDiffint>=240&&dateDiffint<480) { BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(480)); dto.setAbsenteeism(absenteeism); } //迟到,min>=480 算旷工实际班次工时 if (dateDiffint>=480) { BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(dateDiffint)); dto.setAbsenteeism(absenteeism); } } // BigDecimal absenteeism = dto.getAbsenteeism(); // if (absenteeism.compareTo(new BigDecimal(8))>=0) { // dto.setLeaveEarly(false); // dto.setBelate(false); // dto.setAbsenteeism(new BigDecimal(8)); // } // 如果漏打卡: 打卡开始时间等于打卡结束时间 这个时候 只计算迟到和早退 旷工按零计算 if (oConvertUtils.isNotEmpty(actattendanceDate) && oConvertUtils.isNotEmpty(actretreatDate) && actattendanceDate.equals(actretreatDate)) { dto.setAbsenteeism(BigDecimal.ZERO); } } }else { // 当加班/值班 的时候 不迟到 也不早退 也不认为该员工旷工 } } dto.setLongHoliday(longHoliday); } /**FIXME 有待校验 * 动态计算 事假/病假的分钟数 * @author hualong.zhao * @date 2018-1-10 * @param holiday * @param workStarttime * @param workendtime * @param dto * @param dto * @return */ private BigDecimal calculateHolidayDuration(HolidayEntity holiday, Date workStarttime, Date workendtime, UserAttendanceDetailDto dto) { BigDecimal holidayDuration=BigDecimal.ZERO; /**休假开始时间*/ Date holidayStime = holiday.getHolidayStime(); /**休假结束时间*/ Date holidayEtime = holiday.getHolidayEtime(); Date startmax =workStarttime; Date endmin =workendtime; if (workStarttime.compareTo(holidayStime) <= 0 && holidayStime.compareTo(workendtime) <= 0){ startmax = holidayStime; } if (workStarttime.compareTo(holidayEtime) <= 0 && holidayEtime.compareTo(workendtime) <= 0){ endmin =holidayEtime; } String durationCode = "0"; //如果请假开始时间小于等于上班开始时间 且请假结束时间早于下班时间 则认为该员工请的假期为前半夜假期 if (holidayStime.compareTo(workStarttime) <= 0 && holidayEtime.compareTo(workendtime) <0){ durationCode = "1"; } //如果请假开始时间大于上班开始时间 且请假结束时间等于或者是晚于下班时间 则认为该员工请的假期为后半夜假期 if (workStarttime.compareTo(holidayStime ) < 0 &&workendtime.compareTo(holidayEtime) <=0) { durationCode = "2"; } dto.setDurationCode(durationCode); // 时间段开始时间 Calendar startCalendar = Calendar.getInstance(); startCalendar.setTime(startmax); // 时间段结束时间 Calendar endCalendar = Calendar.getInstance(); endCalendar.setTime(endmin); int startDiffint = DataUtils.dateDiff('m', endCalendar,startCalendar); holidayDuration = new BigDecimal(Math.abs(startDiffint)); return holidayDuration; } /**设置基准时间 * 排班计划中的: 正常工作基准工时 每日的排班的基准时间 排班信息:获取员工当日的排班基准时间; * 根据“月度员工排班”中的员工排班情况,获取每日的班次; 根据“班次设定”中的“基准时间”获取每日的基准时长; * * * * 请婚假、丧假、带薪假、陪产假情况下,计算超时加班时长=月度基准时长-法定工时,其中请假当天的月度基准时长要按照8小时累计 * @param hm_cache */ private void calculateDatumDate(HashMap> hm_cache, UserAttendanceDetailDto dto) { // 基准时间 BigDecimal datumDate = BigDecimal.ZERO; if (Globals.DUTYTYPE_yeban115.equals(dto.getDutyType())) { //如果是跨日期夜班,需要判断是否有国定时间,有的话要刨除 -zy 20180513 BigDecimal yebanNationalDuration = calculateHalfNationalOvertime(hm_cache, dto,false); if(yebanNationalDuration.compareTo(BigDecimal.ZERO) < 0) { yebanNationalDuration = BigDecimal.ZERO; } datumDate = dto.getDatumWorkhours().multiply(new BigDecimal(60)).subtract(yebanNationalDuration); if(datumDate.compareTo(BigDecimal.ZERO) < 0) { datumDate = BigDecimal.ZERO; } }else if(Globals.dtype_2.equals(oConvertUtils.getString(dto.getDtype()))) { //如果是国定排班,且不跨夜 datumDate = BigDecimal.ZERO; }else { BigDecimal datumWorkhours = dto.getDatumWorkhours(); if (null != datumWorkhours) { datumDate = datumWorkhours.multiply(new BigDecimal(60)); } } dto.setDatumDate(datumDate); } /** * 获取借调信息 疑问点: 1 当某人处于周期临时借调中时, 刚好这一天又有单次临时借调, 这个怎么处置? (目前在临时借调处没有限制) 2 同一天, * 某人即被A部门临时借调, 又被B部门临时借调, 算哪一天 * * * * @author hualong.zhao * @date 2017-11-25 * @param dto */ private void calculateBorrowsInfo(UserAttendanceDetailDto dto) { // 借调状态;0未借调,1单次借调 2 周期性临时借调 String borrowstatus = "0"; // 借调项目id String borrowspid = null; // 借调部门id 对应的是临时借调表中的调入单位id String borrowsdepartid = null; // 单次借调日薪 BigDecimal dayPay = null; // 01 临时借调(单次)申请表 List snapSingleborrowEntities = dto .getSnapSingleborrowEntities(); // 02 临时借调(固定周期)申请表 List snapRegularborrowEntities = dto .getSnapRegularborrowEntities(); if (!ListUtils.isNullOrEmpty(snapRegularborrowEntities)) { borrowstatus = "2"; for (SnapRegularborrowEntity entity : snapRegularborrowEntities) { // 临时借调表中的调入单位id borrowsdepartid = entity.getInUnitid(); TSDepart tsDepart = getQyDepartByorgid(borrowsdepartid); if (oConvertUtils.isEmpty(tsDepart)||oConvertUtils.isEmpty(tsDepart.getId())) { }else { borrowspid = tsDepart.getId(); } } } if (!ListUtils.isNullOrEmpty(snapSingleborrowEntities)) { borrowstatus = "1"; for (SnapSingleborrowEntity entity : snapSingleborrowEntities) { // 临时借调表中的调入单位id borrowspid = entity.getInUnitid(); // 查询当前员工的区域组织机构 TSDepart tsDepart = getQyDepartByorgid(borrowspid); if (oConvertUtils.isEmpty(tsDepart)||oConvertUtils.isEmpty(tsDepart.getId())) { }else { borrowspid = tsDepart.getId(); } borrowsdepartid = entity.getInUnitid(); //--author:zhaohualong-----start----date: 2018年1月19日--------for: 需求确认: 当且仅当是工作日的时候 才允许给该员工单日的日付薪------ // if (oConvertUtils.getString(dto.getDtype()).equals(Globals.dtype_0)) { if(dayPay == null) { dayPay = BigDecimal.ZERO; } //按借调总额计算,放到第一天考勤中 if(!entity.isInject2AttendanceDto()) { dayPay = dayPay.add(entity.getDayPay()); entity.setInject2AttendanceDto(true); } // } } } dto.setBorrowstatus(borrowstatus); dto.setBorrowspid(borrowspid); dto.setBorrowsdepartid(borrowsdepartid); dto.setDayPay(dayPay); } /** * 根据组织机构id 获取项目 (直属项目 or 区域项目) * @author hualong.zhao * @date 2018-1-17 * @param orgid * @return */ private TSDepart getQyDepartByorgid(String orgid) { if (oConvertUtils.isEmpty(orgid)) { return null; } TSDepart tsDepart = get(TSDepart.class, orgid); if (tsDepart.getOrgType().equals(Globals.org_type_3)||tsDepart.getOrgType().equals(Globals.org_type_5)) { return tsDepart; } else { TSDepart parentdepart = tsDepart.getTSPDepart(); if (oConvertUtils.isEmpty(parentdepart)||oConvertUtils.isEmpty(parentdepart.getId())) { return null; } else { return getQyDepartByorgid(tsDepart.getTSPDepart().getId()); } } } /** * * * new* 1 如果"考勤退勤时间"晚于"排班基准时间"的"结束时间",并且"考勤出勤时间"早于"排班基准时间"的"开始时间":(未早退也未迟到) 实际出勤时间="排班基准时间";(未更改) 2如果"考勤退勤时间"早于"排班基准时间"的"结束时间",并且"考勤出勤时间"早于"排班基准时间"的"开始时间":(早退 但是没有迟到) 实际出勤时间=排班基准时间-早退的分钟数 3 如果"考勤退勤时间"晚于"排班基准时间"的"结束时间",并且"考勤出勤时间"晚于"排班基准时间"的"开始时间":(迟到 但是没有早退) 实际出勤时间=排班基准时间-迟到的分钟数 4 如果"考勤退勤时间"早于"排班基准时间"的"结束时间",并且"考勤出勤时间"晚于"排班基准时间"的"开始时间":(有迟到 也有早退) 实际出勤时间= 排班基准时间-(早退的分钟数"+迟到的分钟数); * old * 根据实际考勤记录计算的时间 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”: * 实际出勤时间=“排班基准时间”; 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”: * 实际出勤时间=“考勤退勤时间”-“排班基准时间”的开始时间; * 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”: * 实际出勤时间=“排班基准时间”的结束时间-“考勤出勤时间”; * 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”: 实际出勤时间= * “考勤退勤时间”-“考勤出勤时间”; 实际出勤时长不考虑中间的休息时长; * 考勤退勤时间、考勤出勤时间点应该是在当日打卡标准范围内的才计算,超出范围内视为漏打卡; * * * 实际出勤时间大于基准时间的按照基准时间计算; * * @author hualong.zhao * @date 2017-11-24 * @param dto */ private void calculateActualAttendanceDate(UserAttendanceDetailDto dto) { BigDecimal actualAttendanceDate = new BigDecimal(0); // 正常上班时间 String normalworkStime = dto.getNormalworkStime(); // 正常下班时间 String normalworkEtime = dto.getNormalworkEtime(); if (oConvertUtils.isEmpty(normalworkStime)||oConvertUtils.isEmpty(normalworkEtime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)) { normalworkStime = oConvertUtils.getString(dto.getTimeOutOvertimeStime(), "00:00"); normalworkEtime =oConvertUtils.getString( dto.getTimeOutOvertimeEtime(), "23:59"); //计算加班的时候的实际出勤时间 }else if ( Globals.DUTYTYPE_zhiban.equals(dutyType)) { // normalworkStime = oConvertUtils.getString(dto.getOndutyStime(), "00:00"); // normalworkEtime =oConvertUtils.getString( dto.getOndutyEtime(), "23:59"); return; //计算加班的时候的实际出勤时间 }else if (Globals.DUTYTYPE_xiuxi.equals(dutyType)) { // 当他休息的时候 //计算加班的时候的实际出勤时间 return ; } } Date normalworkStartdate = getexactDate(dto.getYmdDate(), normalworkStime, 0, 0); Integer t1flag = 0; if (oConvertUtils.getString(dto.getDutyType()).equals(Globals.DUTYTYPE_yeban115)) { t1flag = 1; } Date normalworkenddate = getexactDate(dto.getYmdDate(), normalworkEtime, t1flag, 0); // 实际打卡开始时间 Date actattendanceDate = dto.getActattendanceDate(); // 实际打卡结束时间 Date actretreatDate = dto.getActretreatDate(); if (normalworkStartdate.equals(normalworkenddate)) { // 当这天安排的工作是休息时---上班时间等于下班时间 } // 正常工作基准工时 BigDecimal datumWorkhours = dto.getDatumWorkhours(); BigDecimal datumWorkmins = BigDecimal.ZERO; if (null != datumWorkhours) { datumWorkmins = datumWorkhours.multiply(new BigDecimal(60)); } if (oConvertUtils.isEmpty(actattendanceDate) && oConvertUtils.isEmpty(actretreatDate)) { dto.setActualAttendanceDate( new BigDecimal(0)); //如果开始打卡时间 或结束打卡时间为空,则时间差值 应当等于 负的 正常工作基准工时 return; }else if(oConvertUtils.isEmpty(actattendanceDate) && !oConvertUtils.isEmpty(actretreatDate)) { // 开始没打开,下班打卡 if (actretreatDate.compareTo(normalworkenddate) >= 0) { // 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,算漏打卡 // 实际出勤时间=“排班基准时间”; actualAttendanceDate = datumWorkmins; }else { // 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,算早退 Calendar actretreatDateCalendar = Calendar.getInstance(); actretreatDateCalendar.setTime(actretreatDate); // “排班基准时间”的结束时间 Calendar normalworkendCalendar = Calendar.getInstance(); normalworkendCalendar.setTime(normalworkenddate); //早退的分钟数 int dateDiffint = DataUtils.dateDiff('m', actretreatDateCalendar,normalworkendCalendar); actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint))); } }else if(!oConvertUtils.isEmpty(actattendanceDate) && oConvertUtils.isEmpty(actretreatDate)) { // 上班打卡,结束没打卡 if (actattendanceDate.compareTo(normalworkStartdate) <= 0) { // 如果“考勤开始时间”早于“排班基准时间”的“开始时间”,算漏打卡 // 实际出勤时间=“排班基准时间”; actualAttendanceDate = datumWorkmins; }else { // 如果“考勤开始时间”晚于“排班基准时间”的“开始时间”,算迟到 // “排班基准时间”的“开始时间” Calendar normalworkStartCalendar = Calendar.getInstance(); normalworkStartCalendar.setTime(normalworkStartdate); // “考勤出勤时间” Calendar actattendanceCalendar = Calendar.getInstance(); actattendanceCalendar.setTime(actattendanceDate); //迟到的分钟数 int dateDiffint = DataUtils.dateDiff('m', normalworkStartCalendar,actattendanceCalendar); actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint))); } }else { // 上下班都有考勤打卡 // 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”: // 实际出勤时间=“排班基准时间”; if ((actretreatDate.compareTo(normalworkenddate) >= 0) && (actattendanceDate.compareTo(normalworkStartdate) <= 0)) { actualAttendanceDate = datumWorkmins; } // 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”: // 实际出勤时间=排班基准时间- 早退的分钟数 if ((actretreatDate.compareTo(normalworkenddate) < 0) && (actattendanceDate.compareTo(normalworkStartdate) <= 0)) { // 考勤退勤时间" Calendar actretreatDateCalendar = Calendar.getInstance(); actretreatDateCalendar.setTime(actretreatDate); // “排班基准时间”的结束时间 Calendar normalworkendCalendar = Calendar.getInstance(); normalworkendCalendar.setTime(normalworkenddate); //早退的分钟数 int dateDiffint = DataUtils.dateDiff('m', actretreatDateCalendar,normalworkendCalendar); actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint))); } // 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”: // 实际出勤时间=排班基准时间- 迟到的分钟数 if ((actretreatDate.compareTo(normalworkenddate) >= 0) && (actattendanceDate.compareTo(normalworkStartdate) > 0)) { // “排班基准时间”的“开始时间” Calendar normalworkStartCalendar = Calendar.getInstance(); normalworkStartCalendar.setTime(normalworkStartdate); // “考勤出勤时间” Calendar actattendanceCalendar = Calendar.getInstance(); actattendanceCalendar.setTime(actattendanceDate); //迟到的分钟数 int dateDiffint = DataUtils.dateDiff('m', normalworkStartCalendar,actattendanceCalendar); actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint))); } // 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”: // 实际出勤时间= 排班基准时间- (“考勤退勤欠勤时间”+“考勤出勤欠勤时间”); if ((actretreatDate.compareTo(normalworkenddate) < 0) && (actattendanceDate.compareTo(normalworkStartdate) > 0)) { // 考勤退勤时间" Calendar actretreatCalendar = Calendar.getInstance(); actretreatCalendar.setTime(actretreatDate); //“排班基准时间”的“结束时间” Calendar normalworkenddateCalendar = Calendar.getInstance(); normalworkenddateCalendar.setTime(normalworkenddate); // “考勤出勤时间” Calendar actattendanceCalendar = Calendar.getInstance(); actattendanceCalendar.setTime(actattendanceDate); // “排班基准时间”的“开始时间” Calendar normalworkStartdateCalendar = Calendar.getInstance(); normalworkStartdateCalendar.setTime(normalworkStartdate); //出勤欠勤分钟数 int belatedateDiffint = DataUtils.dateDiff('m', actattendanceCalendar, normalworkStartdateCalendar); //退勤欠勤分钟数 int leaveearlyDiffint = DataUtils.dateDiff('m', normalworkenddateCalendar, actretreatCalendar); //实际出勤分钟数 = min(打卡结束时间, 理论下班结束时间)-max(实际打卡时间, 理论上班时间) Date startDate =normalworkStartdate.compareTo(actattendanceDate)<= 0?actattendanceDate:normalworkStartdate; Date endDate =normalworkenddate.compareTo(actretreatDate)<= 0?normalworkenddate:actretreatDate; Calendar startCalendar = Calendar.getInstance(); startCalendar.setTime(startDate); Calendar endCalendar = Calendar.getInstance(); endCalendar.setTime(endDate); int dateDiffint = 0; if (startDate.compareTo(endDate)<=0) { dateDiffint = Math.abs(DataUtils.dateDiff('m', startCalendar, endCalendar)); } actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(belatedateDiffint))) .subtract(new BigDecimal(Math.abs(leaveearlyDiffint))); //当值班或者是加班的时候 只要有打卡记录, 代码就会走到这里来, 这个时候 将实际出勤时间 记作 加班/值班的基准时间 String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { //当为值班或者是加班的时候 获取这一天的实际出勤分钟数, 与这一天的基准出勤分钟数 取这两个值的最小值 记为实际出勤时间 BigDecimal actmins = new BigDecimal(dateDiffint); actualAttendanceDate =datumWorkmins.compareTo(actmins)<0?datumWorkmins:actmins; } } } // 实际出勤时间大于基准时间的按照基准时间计算; if (!datumWorkmins.equals(BigDecimal.ZERO)&&datumWorkmins.compareTo(actualAttendanceDate)<0) { actualAttendanceDate = datumWorkmins; } //实际出勤时间小于零的时候 写为零 if (actualAttendanceDate.compareTo(BigDecimal.ZERO)<0) { actualAttendanceDate = BigDecimal.ZERO; } //设置实际出勤时间 dto.setActualAttendanceDate(actualAttendanceDate); } private void calculateActAttendancetime(UserAttendanceDetailDto dto, List dingAttendanceinfoEntitiesOneMonth,HashMap hm_specialAttendEntities, List adjustedEntities, List uatdlist, UserAttendanceDetailEntity detailEntity) { Date curdate = dto.getYmdDate(); Calendar calendar1 = Calendar.getInstance(); calendar1.setTime(curdate); calendar1.add(Calendar.DATE, 2); Date tomdate = calendar1.getTime(); List currDingInfoEntities = new ArrayList<>(); for (DingAttendanceinfoEntity dingOneMonth : dingAttendanceinfoEntitiesOneMonth) { if (dingOneMonth.getAttendanceTime().compareTo(curdate) >= 0 && dingOneMonth.getAttendanceTime().compareTo(tomdate) <= 0) { currDingInfoEntities.add(dingOneMonth); } } // 根据钉钉打卡记录原始数据, 查询有效开始打卡时间内的最早打卡时间 和 最晚打卡时间 //获取有效开始打卡时间 Date effectiveStime = dto.getEffectiveStime(); //获取有效结束打卡时间 Date effectiveEtime = dto.getEffectiveEtime(); // 实际打卡开始时间 Date actattendanceDate = null; // 实际打卡结束时间 Date actretreatDate = null; boolean yesterdayisyb = true; // 如果是特殊考勤类型,不管钉钉记录如何,都进行统一处理,比如手工考勤——默认全勤 if (hm_specialAttendEntities.containsKey(dto.getUserid())) { // 默认全勤, 模拟钉钉考勤记录, 默认有效开始和结束打卡时间 currDingInfoEntities = new ArrayList(); DingAttendanceinfoEntity startDingdingAttend = new DingAttendanceinfoEntity(); DingAttendanceinfoEntity endDingdingAttend = new DingAttendanceinfoEntity(); // =====查询请假情况, 去掉事假的加班申请时长,计算理应的开始和结束工作时间 如果员工在这一天请了非事假意外的假 不认为该员工旷工 /迟到/早退 List userHolidayEntities = dto.getUserHolidayEntities(); String dutyType = oConvertUtils.getString(dto.getDutyType()); if (!ListUtils.isNullOrEmpty(userHolidayEntities)) { /**理应工作开始时间*/ Date workStarttime = getexactDate(dto.getYmdDate(), dto.getNormalworkStime(), 0, 0); /**理应工作结束时间*/ Integer t1flag = 0; if (Globals.DUTYTYPE_yeban115.equals(dutyType)) { t1flag = 1; } Date workendtime = getexactDate(dto.getYmdDate(), dto.getNormalworkEtime(), t1flag, 0); Date setStartTime = null; Date setEndTime = null; for (HolidayEntity holiday : userHolidayEntities) { String hilidaytype = oConvertUtils.getString(holiday.getHolidayType()); //dgq 增加调休情况处理 if (Globals.REST_TYPE_1.equals(hilidaytype) || Globals.REST_TYPE_0.equals(hilidaytype)) { /**休假开始时间*/ Date holidayStime = holiday.getHolidayStime(); /**休假结束时间*/ Date holidayEtime = holiday.getHolidayEtime(); if (holidayStime.compareTo(workStarttime) > 0 && holidayStime.compareTo(workendtime) < 0) { setStartTime = holidayStime; } if (holidayEtime.compareTo(workendtime) < 0 && holidayEtime.compareTo(workStarttime) > 0) { setEndTime = holidayEtime; } if (setStartTime != null && setEndTime == null) { setEndTime = workendtime; } if (setStartTime == null && setEndTime != null) { setStartTime = workStarttime; } } else if (Globals.REST_TYPE_7.equals(hilidaytype)) { /**休假开始时间*/ Date holidayStime = holiday.getHolidayStime(); /**休假结束时间*/ Date holidayEtime = holiday.getHolidayEtime(); if (holidayStime.compareTo(workStarttime) > 0 && holidayStime.compareTo(workendtime) < 0) { setEndTime = holidayStime; } else if (holidayEtime.compareTo(workendtime) < 0 && holidayEtime.compareTo(workStarttime) > 0) { setStartTime = holidayEtime; } if (setStartTime != null && setEndTime == null) { setEndTime = workendtime; } if (setStartTime == null && setEndTime != null) { setStartTime = workStarttime; } } else { break; } } startDingdingAttend.setAttendanceTime(setStartTime); endDingdingAttend.setAttendanceTime(setEndTime); } else { startDingdingAttend.setAttendanceTime(calculateNormalStime(dto)); endDingdingAttend.setAttendanceTime(calculateNormalEtime(dto)); } currDingInfoEntities.add(startDingdingAttend); currDingInfoEntities.add(endDingdingAttend); } // 在钉钉打卡记录不为空情况下查询下述 if (!ListUtils.isNullOrEmpty(currDingInfoEntities)) { //正向遍历打卡记录 查询在有效打开记录区间内 最早的一次打卡记录 if (oConvertUtils.isNotEmpty(effectiveStime)) { for (int i = 0; i < currDingInfoEntities.size(); i++) { DingAttendanceinfoEntity dingAttendanceinfoEntity = currDingInfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && temp.compareTo(effectiveEtime) <= 0 && (temp.compareTo(effectiveStime) >= 0)) { actattendanceDate = dingAttendanceinfoEntity .getAttendanceTime(); break; } } } else { //effectiveStime 值为空: 说明当天没有排班信息 或这天是休息查询这一天的最早打卡时间(必须是本天的最早开始时间) yesterdayisyb = checkYesterdaytype(dto, uatdlist); // 先校验上一天是否为夜班 如果是夜班 不执行下述操作 if (!yesterdayisyb) { Date todayend = getexactDate(dto.getYmdDate(), "00:00", 1, 0); for (int i = 0; i < currDingInfoEntities.size(); i++) { DingAttendanceinfoEntity dingAttendanceinfoEntity = currDingInfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && temp.before(todayend)) { actattendanceDate = dingAttendanceinfoEntity.getAttendanceTime(); break; } } } } //如果值班/加班 和正常工作时间连续了 则 先查询 有效结束打卡时间后 的最新一次打卡, // 此处应该加限制 因为现在 加班时间有16:30~18:30 往后找 就找到了t1的07:15 去了 //如果这个时间没有, 则查询值班/加班 结束时间之前的最后一次打卡 // ----------值班情况处理 ---20180308---yangxi---add---start---------- if (!Globals.DUTYTYPE_zhiban.equals(oConvertUtils.getString(dto.getDutyType()))) { if (dto.isJiabanContinuous()) { Integer epunchMinute = oConvertUtils.getInt(dto.getEpunchMinute(), 0); Calendar calendar = Calendar.getInstance(); calendar.setTime(effectiveEtime); calendar.add(Calendar.MINUTE, epunchMinute); // 默认全勤处理加班 if (hm_specialAttendEntities.containsKey(dto.getUserid())) { DingAttendanceinfoEntity endDingdingAttend = new DingAttendanceinfoEntity(); endDingdingAttend.setAttendanceTime(effectiveEtime); currDingInfoEntities.add(endDingdingAttend); } Date endmaxTime = calendar.getTime(); for (int i = 0; i < currDingInfoEntities.size(); i++) { DingAttendanceinfoEntity dingAttendanceinfoEntity = currDingInfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && (temp.compareTo(effectiveEtime) >= 0) && (temp.compareTo(endmaxTime) <= 0)) { actretreatDate = temp; break; } } } //判断是否在超时加班时出勤,判断标准是超时加班时长内打卡至少一次 //如果有出勤,则timeoutOvertimeDuration=timeOutOvertimeHours(排班中超时时长);实际出勤中加上加班时长actualAttendanceDate += timeOutOvertimeHours //zy20180413 String jiabanStarttimeStr = dto.getTimeOutOvertimeStime(); String jiabanEndtimeStr = dto.getTimeOutOvertimeEtime(); Date jiabanStarttime = getexactDate(dto.getYmdDate(), jiabanStarttimeStr, 0, 0); Date jiabanEndtime = getexactDate(dto.getYmdDate(), jiabanEndtimeStr, 0, 90);//增加90分钟有效范围 // 如果超时加班跨天设置,则加一 if (jiabanStarttime.after(jiabanEndtime)) { Calendar jiabanendCal = Calendar.getInstance(); jiabanendCal.setTime(jiabanEndtime); jiabanendCal.add(Calendar.DATE, 1); jiabanEndtime = jiabanendCal.getTime(); } // // 默认全勤处理值班 // if(hm_specialAttendEntities.containsKey(dto.getUserid())) { // DingAttendanceinfoEntity endDingdingAttend = new DingAttendanceinfoEntity(); // endDingdingAttend.setAttendanceTime(jiabanStarttime); // dingAttendanceinfoEntities.add(endDingdingAttend); // } if (oConvertUtils.isNotEmpty(jiabanStarttimeStr) && oConvertUtils.isNotEmpty(jiabanEndtimeStr)) { for (int i = 0; i < currDingInfoEntities.size(); i++) { DingAttendanceinfoEntity dingAttendanceinfoEntity = currDingInfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && temp.compareTo(jiabanEndtime) <= 0 && (temp.compareTo(jiabanStarttime) >= 0)) { //设置实际超时加班时间 dto.setTimeoutOvertimeDuration(dto.getTimeOutOvertimeHours()); //实际出勤时间加上超时加班时间 BigDecimal actattendTime = dto.getActualAttendanceDate(); if (actattendTime != null) { dto.setActualAttendanceDate(actattendTime.add(dto.getTimeoutOvertimeDuration())); } break; } } } } //反向遍历打卡记录, 寻找在有效打卡记录区间内 最后一次打卡 if (oConvertUtils.isNotEmpty(effectiveEtime) && oConvertUtils.isEmpty(actretreatDate)) { for (int i = (currDingInfoEntities.size() - 1); i >= 0; i--) { DingAttendanceinfoEntity dingAttendanceinfoEntity = currDingInfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && temp.compareTo(effectiveStime) >= 0 && temp.compareTo(effectiveEtime) <= 0) { actretreatDate = temp; break; } } } if (oConvertUtils.isEmpty(effectiveEtime)) { // effectiveEtime 值为空: 说明当天没有排班信息 或这天是休息 查询这一天的最晚打卡时间 // 先校验上一天是否为夜班 如果是夜班 不执行下述操作 if (!yesterdayisyb) { Date todayendDate = getexactDate(dto.getYmdDate(), "00:00", 1, 0); for (int i = (currDingInfoEntities.size() - 1); i >= 0; i--) { DingAttendanceinfoEntity dingAttendanceinfoEntity = currDingInfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && temp.compareTo(todayendDate) < 0) { actretreatDate = temp; break; } } } } } //如果是最后一天夜班,退勤记录需要去下个月找 gjs if (oConvertUtils.isNotEmpty(effectiveEtime)) { Date ymtDate = dto.getYmdDate(); Calendar c = Calendar.getInstance(); c.setTime(ymtDate); c.set(Calendar.DAY_OF_MONTH, 1); c.add(Calendar.MONTH, 1); Date firstDayInNewMonth = c.getTime(); c.add(Calendar.DAY_OF_MONTH, -1); Date monthLastDay = c.getTime(); if (ymtDate.compareTo(monthLastDay) == 0) { if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) { UserAttendanceDetailDto searchDto = new UserAttendanceDetailDto(); searchDto.setUserid(dto.getUserid()); searchDto.setYmdDate(firstDayInNewMonth); try { List tmpList = dingAttendanceinfoService.getDingAttendanceinfoEntities(searchDto); if(tmpList!=null && !tmpList.isEmpty()) { for (int i = (tmpList.size() - 1); i >= 0; i--) { DingAttendanceinfoEntity dingAttendanceinfoEntity = tmpList.get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) && temp.compareTo(effectiveStime) >= 0 && temp.compareTo(effectiveEtime) <= 0) { actretreatDate = temp; break; } } } } catch(Exception e){ e.printStackTrace(); } } } } UserAttendanceDetailAdjustedEntity currDateAdjustEntity = getCurrDateAdjustEntity(adjustedEntities, dto); dto.setActattendanceDate(actattendanceDate); dto.setActretreatDate(actretreatDate); //如果是通过页面编辑调用的该方法, 将实际打卡时间修改为页面填写的时间 if (oConvertUtils.isNotEmpty(detailEntity)) { dto.setActattendanceDate(detailEntity.getAttendanceDate()); //如果用户选择的结束时间为空, 在dto 中设置结束时间等于开始时间 便于dto相关计算 Date retreatDate =detailEntity.getRetreatDate(); if (null==retreatDate) { retreatDate = detailEntity.getAttendanceDate(); } dto.setActretreatDate(retreatDate); }else if(currDateAdjustEntity != null) { dto.setPrimevalAttendanceDate(actattendanceDate); dto.setPrimevalRetreatDate(actretreatDate); dto.setActattendanceDate(currDateAdjustEntity.getAttendanceDate()); dto.setActretreatDate(currDateAdjustEntity.getRetreatDate()); } // 值班天数 计算当月的班次中有值班时间的天数 累8计当前月的有值班时间的天数 值班按次计算,只要有实际出勤记录我们就计做一次值班; Date ondutyStarttime = dto.getOndutyStarttime(); Date ondutyEndtime = dto.getOndutyEndtime(); if (oConvertUtils.isNotEmpty(ondutyStarttime)&&oConvertUtils.isNotEmpty(ondutyEndtime)) { // for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) { // DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities // .get(i); // Date temp = dingAttendanceinfoEntity.getAttendanceTime(); // if (oConvertUtils.isNotEmpty(temp) // &&temp.compareTo(ondutyEndtime) <=0 // && (temp.compareTo(ondutyStarttime) >= 0)) { // dto.setIhadDuty(true); // break; // } // } // 默认全勤处理加班 if(hm_specialAttendEntities.containsKey(dto.getUserid())) { dto.setIhadDuty(true); } // 根据出勤时间和退勤时间计算值班是否有效,原因是出勤时间和退勤时间可能是手动修改后的结果 zy 20180425 if (oConvertUtils.isNotEmpty(dto.getActattendanceDate()) && dto.getActattendanceDate().compareTo(ondutyEndtime) <=0 && (dto.getActattendanceDate().compareTo(ondutyStarttime) >= 0)) { dto.setIhadDuty(true); } if (oConvertUtils.isNotEmpty(dto.getActretreatDate()) && dto.getActretreatDate().compareTo(ondutyEndtime) <=0 && (dto.getActretreatDate().compareTo(ondutyStarttime) >= 0)) { dto.setIhadDuty(true); } } // =====查询加班情况 List overtimeRecordEntities =dto.getOvertimeRecordEntities(); if (!ListUtils.isNullOrEmpty(overtimeRecordEntities)) { for (OvertimeRecordEntity entry:overtimeRecordEntities) { //额外加班 餐补次数,需要 考虑 加班备案申请里 的 是否 提供餐补。 否 的时候,不能计入次数。 //只要有加班记录 就记作额外加班一次 //del-->如果有加班备案 且这个加班备案不是法定加班 校验在这个区间内是否有打卡记录 如果有 则 额外加班记一次 "0".equals(entry.getIfnational()) if ("1".equals(oConvertUtils.getString(entry.getIfmeal()))) { dto.setExtraOvertime(1); } /*if (true) { *//**加班开始时间*//* Date overtimeStime = entry.getOvertimeStime(); *//**加班结束时间*//* Date overtimeEtime= entry.getOvertimeEtime(); for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) { DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities .get(i); Date temp = dingAttendanceinfoEntity.getAttendanceTime(); if (oConvertUtils.isNotEmpty(temp) &&temp.compareTo(overtimeEtime) <=0 && (temp.compareTo(overtimeStime) >= 0)) { //额外加班 餐补次数,需要 考虑 加班备案申请里 的 是否 提供餐补。 否 的时候,不能计入次数。 if ("1".equals(oConvertUtils.getString(entry.getIfmeal()))) { dto.setExtraOvertime(1); } break; } } //如果钉钉原始打卡记录为空, 在判断编辑页传入的开始打卡时间 和结束打卡时间 是否满足额外加班条件 if (ListUtils.isNullOrEmpty(dingAttendanceinfoEntities)) { List tempdates = new ArrayList(); tempdates.add(dto.getActattendanceDate()); tempdates.add(dto.getActretreatDate()); for (int i = 0; i < tempdates.size(); i++) { Date temp = tempdates.get(i); if (oConvertUtils.isNotEmpty(temp) &&temp.compareTo(overtimeEtime) <=0 && (temp.compareTo(overtimeStime) >= 0)) { //额外加班 餐补次数,需要 考虑 加班备案申请里 的 是否 提供餐补。 否 的时候,不能计入次数。 if ("1".equals(oConvertUtils.getString(entry.getIfmeal()))) { dto.setExtraOvertime(1); } break; } } } }*/ } } } /** * 判断上一天是否为夜班 是夜班为true 其他为false * @author hualong.zhao * @date 2017-12-5 * @param dto * @param uatdlist * @return */ private boolean checkYesterdaytype(UserAttendanceDetailDto dto, List uatdlist) { boolean result = true; for (int i = 0; i < uatdlist.size(); i++) { UserAttendanceDetailDto tdto = uatdlist.get(i); UserAttendanceDetailDto ydto = uatdlist.get(i); if (tdto.getYmdDate().equals(dto.getYmdDate())) { ydto = uatdlist.get(Math.max(0, i-1)); if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) { result = true; }else { result = false; } if (i==0) { Date yesterday = getexactDate(dto.getYmdDate(), "00:00", -1, 0); //月度首日 需要查询上一个月的最后一天 是否为夜班 List yestoryday = userAttendanceDetailDao. getlistbyProjarrangeDetailid(null,dto.getUserid(),DataUtils.date2Str(yesterday, DataUtils.date_sdf)); if (!ListUtils.isNullOrEmpty(yestoryday)) { ydto = yestoryday.get(0); if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) { result = true; }else { result = false; } } } } } return result; } /** * 获取有效结束打卡时间 * * * 如果是夜班,跨天的情况: 考勤机记录的本日后一天的认可范围内最晚刷卡时间,例如:7:30; 否则为 考勤机记录的本日最晚刷卡时间,例如:19:50 * * 要考虑是否有连续加班或值班的情况,如果排班中的“正常工作下班时间”>=“加班或值班开始时间”,退勤时间为最晚的打卡时间; * 否则为正常打卡结束时间范围内的最后时间; 要考虑夜班跨自然日的情况; * * * 如果值班/加班 和正常工作时间没有连续 则查询有效结束打卡时间 之前的最后一次打卡时间 * 如果值班/加班 和正常工作时间连续了 则 先查询 有效结束打卡时间 的最新一次打卡, 如果这个时间没有, 则查询值班/加班 结束时间之前的最后一次打卡 * * * @author hualong.zhao * @date 2017-11-23 * @param dto * @return */ private Date calculateEffectiveAttendanceEtime(UserAttendanceDetailDto dto) { Date effectiveEnddate = dto.getYmdDate(); // 获取正常上班时间 String normalworkStime = oConvertUtils.getString(dto .getNormalworkStime()); if (oConvertUtils.isEmpty(normalworkStime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { normalworkStime = "00:00"; } } // 获取正常下班时间 String normalworkEtime = oConvertUtils.getString(dto .getNormalworkEtime()); if (oConvertUtils.isEmpty(normalworkEtime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { normalworkEtime = "23:59"; }else{ // 当他休息的时候 //计算加班的时候的实际出勤时间 return null; } } Integer t1flag = 0; if (oConvertUtils.isNotEmpty(normalworkEtime) && oConvertUtils.isNotEmpty(normalworkStime)) { t1flag = normalworkEtime.compareTo(normalworkStime) < 0 ? 1 : 0; if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) { t1flag = 1; } Integer epunchMinute = oConvertUtils.getInt(dto.getEpunchMinute(), 0); effectiveEnddate = getexactDate(dto.getYmdDate(), normalworkEtime, t1flag, 0 + epunchMinute); } // 值班开始时间 String ondutyStime = oConvertUtils.getString(dto.getOndutyStime()); if (oConvertUtils.isNotEmpty(ondutyStime)) { // 获取值班 的开始时间 Date ondutyStarttime = getexactDate(dto.getYmdDate(), ondutyStime, t1flag,0); dto.setOndutyStarttime(ondutyStarttime); } //值班结束时间 String mondutyEtime = oConvertUtils.getString(dto.getOndutyEtime()); if (oConvertUtils.isNotEmpty(mondutyEtime)) { // 获取值班 的结束时间 if (mondutyEtime.compareTo(ondutyStime)<0) { Date ondutyEndtime = getexactDate(dto.getYmdDate(), mondutyEtime, t1flag+1,0); dto.setOndutyEndtime(ondutyEndtime); }else { Date ondutyEndtime = getexactDate(dto.getYmdDate(), mondutyEtime, t1flag,0); dto.setOndutyEndtime(ondutyEndtime); } } // 加班开始时间 String timeOutOvertimeStime = oConvertUtils.getString(dto .getTimeOutOvertimeStime()); Date overtimeStartdate = null; if (oConvertUtils.isNotEmpty(timeOutOvertimeStime)) { // 加班开始时间date overtimeStartdate = getexactDate(dto.getYmdDate(), timeOutOvertimeStime, t1flag,0); } // 加班结束时间 String timeOutOvertimeEtime = oConvertUtils.getString(dto .getTimeOutOvertimeEtime()); Date overtimeEnddate = null; if (oConvertUtils.isNotEmpty(timeOutOvertimeEtime)) { // 加班结束时间date if (timeOutOvertimeEtime.compareTo(timeOutOvertimeStime)<0) { overtimeEnddate = getexactDate(dto.getYmdDate(), timeOutOvertimeEtime, t1flag+1,0); }else { overtimeEnddate = getexactDate(dto.getYmdDate(), timeOutOvertimeEtime, t1flag,0); } } // 最早加班/值班开始时间 Date jiabanstartDate = null; Date jiabanendDate = null; //如果值班时间不为空 则将此值置为值班时间 if (oConvertUtils.isNotEmpty(dto.getOndutyStarttime())) { jiabanstartDate = dto.getOndutyStarttime(); jiabanendDate = dto.getOndutyEndtime(); } //如果加班时间不为空 则将此值置为加班时间 if (oConvertUtils.isNotEmpty(overtimeStartdate)) { jiabanstartDate = overtimeStartdate; jiabanendDate = overtimeEnddate; } if (oConvertUtils.isNotEmpty(dto.getOndutyStarttime())&&oConvertUtils.isNotEmpty(overtimeStartdate)) { jiabanstartDate = (dto.getOndutyStarttime().after(overtimeStartdate))?overtimeStartdate:dto.getOndutyStarttime(); jiabanendDate = (dto.getOndutyStarttime().after(overtimeStartdate))?overtimeEnddate:dto.getOndutyEndtime(); } if (oConvertUtils.isNotEmpty(jiabanstartDate) &&(oConvertUtils.isNotEmpty(jiabanendDate)) && (jiabanstartDate.compareTo(effectiveEnddate) <= 0)) { effectiveEnddate = jiabanendDate; dto.setJiabanContinuous(true); } else { dto.setJiabanContinuous(false); } // ----------值班情况处理 ---20180308---yangxi---add---start---------- if(Globals.DUTYTYPE_zhiban.equals(dto.getDutyType())) { effectiveEnddate = dto.getOndutyEndtime(); } // ----------值班情况处理 ---20180308---yangxi---add---end---------- // 有效结束打卡时间应该为59秒 Calendar calendar = Calendar.getInstance(); calendar.setTime(effectiveEnddate); calendar.add(Calendar.SECOND, 59); return calendar.getTime(); } /** * * @author hualong.zhao * @date 2017-11-23 * @param ymdDate * 由年月日获取的Date类型的时间 基准时间 * @param time * 小时:分钟 * @param t1 * 是否加一天 * @param addmins * 时间波动 * @return */ private Date getexactDate(Date ymdDate, String time, int t1, int addmins) { Calendar effectivecal = Calendar.getInstance(); effectivecal.setTime(ymdDate); if (oConvertUtils.isNotEmpty(time)) { String[] temp = time.split(":"); // 将正常上班时间 设定至 时间戳上 effectivecal.set(Calendar.HOUR_OF_DAY, Integer.valueOf(temp[0])); effectivecal.set(Calendar.MINUTE, Integer.valueOf(temp[1])); } effectivecal.add(Calendar.DATE, t1); // 开始打卡分钟数 if (oConvertUtils.isNotEmpty(addmins)) { effectivecal.add(Calendar.MINUTE, addmins); } return effectivecal.getTime(); } /** * 获取有效开始打卡时间 * * 考勤机记录的本日认可范围内最早刷卡时间,例如:7:32 * * @author hualong.zhao * @date 2017-11-23 * @param dto * @return */ private Date calculateEffectiveAttendanceStime(UserAttendanceDetailDto dto) { // 获取正常上班时间 String normalworkStime = oConvertUtils.getString(dto .getNormalworkStime()); Date normalworkStartdate = dto.getYmdDate(); if (oConvertUtils.isEmpty(normalworkStime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { normalworkStime = "00:00"; } else { return null; } } if (oConvertUtils.isNotEmpty(normalworkStime)) { int spunchMinute = oConvertUtils.getInt(dto.getSpunchMinute(), 0); normalworkStartdate = getexactDate(dto.getYmdDate(), normalworkStime, 0, 0 - spunchMinute); } // ----------值班情况处理 ---20180308---yangxi---add---start---------- if(Globals.DUTYTYPE_zhiban.equals(dto.getDutyType())) { normalworkStartdate = getexactDate(dto.getYmdDate(), dto.getOndutyStime(), 0, 0); } // ----------值班情况处理 ---20180308---yangxi---add---end---------- return normalworkStartdate; } /** * 包括: 正常、法定假日、带薪假、病假、事假、婚假、丧假、陪产假; “正常”、“法定假日”按照每年的法定节假日信息设定并校验; * 其他假期,需要根据已经确认的“休假申请”中日期及休假类型设定并校验; * * @author hualong.zhao * @date 2017-11-23 * @param dto * @return */ private void calculateCurdateStatus(UserAttendanceDetailDto dto) { String curdateStatus = Globals.ATTENDANCE_STATUS_EDIT_10; // 当这一天为法定假日时 ,切这一天该员工有排班。 则认定为该员工为正常上班。可手动调整为法定假日。 List userHolidayEntities = dto.getUserHolidayEntities(); if (!ListUtils.isNullOrEmpty(userHolidayEntities)) { curdateStatus = userHolidayEntities.get(0).getHolidayType(); } dto.setCurdateStatus(curdateStatus); } /** * 检查某人某天是否有 固定周期临时借调 * * @author hualong.zhao * @date 2017-11-23 * @param dto * @param snapRegularborrowEntities */ private void checkIshavesnapRegularborrows(UserAttendanceDetailDto dto, List snapRegularborrowEntities) { Date curdate = dto.getYmdDate(); List uSingleborrowEntities = dto .getSnapRegularborrowEntities(); // 遍历本月固定周期临时借调, for (SnapRegularborrowEntity snapRegularborrowEntity : snapRegularborrowEntities) { Date inTime = snapRegularborrowEntity.getInTime(); Date deadDate = snapRegularborrowEntity.getDeadDate(); // 如果当前时间在固定周期临时调度范围内 if (oConvertUtils.isNotEmpty(inTime) && oConvertUtils.isNotEmpty(deadDate) && (inTime.compareTo(curdate) <= 0 && curdate .compareTo(deadDate) <= 0)) { // 当天在固定周期的 调入日期 和终止日期之间 String fixedCycle = oConvertUtils .getString(snapRegularborrowEntity.getFixedCycle()); // 固定周期内有这一天 星期N = 星期N if (fixedCycle.contains(dto.getWeek())) { uSingleborrowEntities.add(snapRegularborrowEntity); } } } dto.setSnapRegularborrowEntities(uSingleborrowEntities); } /** * 检查某人某天是否有单次临时借调 * * @author hualong.zhao * @date 2017-11-23 * @param dto * @param snapSingleborrowEntities */ private void checkIshavesnapSingleborrows(UserAttendanceDetailDto dto, List snapSingleborrowEntities) { Date curdate = dto.getYmdDate(); List uSingleborrowEntities = dto .getSnapSingleborrowEntities(); // 遍历本月单次临时借调, for (SnapSingleborrowEntity snapSingleborrowEntity : snapSingleborrowEntities) { Date inTime = snapSingleborrowEntity.getInTime(); Date deadDate = snapSingleborrowEntity.getDeadDate(); if (inTime.equals(curdate) || (inTime.before(curdate) && curdate.before(deadDate)) || (deadDate.equals(curdate))) { uSingleborrowEntities.add(snapSingleborrowEntity); } } dto.setSnapSingleborrowEntities(uSingleborrowEntities); } /** * 检查某人某天是否有加班备案记录 * * @author hualong.zhao * @date 2017-11-23 * @param dto * @param overtimeRecordEntities */ private void checkIshaveovertimeRecord(UserAttendanceDetailDto dto, List overtimeRecordEntities) { Date curdate = dto.getYmdDate(); Calendar calendar = Calendar.getInstance(); calendar.setTime(curdate); calendar.add(Calendar.DATE, 1); Date tomDate = calendar.getTime(); List uOvertimeRecordEntities = dto .getOvertimeRecordEntities(); // 遍历本月的加班记录, for (OvertimeRecordEntity overtimeRecordEntity : overtimeRecordEntities) { Date stime = overtimeRecordEntity.getOvertimeStime(); // 如果加班开始时间在这一天内 if (oConvertUtils.isNotEmpty(stime) && curdate.compareTo(stime)<=0 && stime.compareTo(tomDate)<=0) { // 将这一天的加班信息 记录至该天中 uOvertimeRecordEntities.add(overtimeRecordEntity); } } dto.setOvertimeRecordEntities(uOvertimeRecordEntities); } /** * 检查这一天是否有过请假 * * @author hualong.zhao * @date 2017-11-23 * @param dto * @param userHolidayEntities */ private void checkIshaveHolidaies(UserAttendanceDetailDto dto, List userHolidayEntities) { //获取有效开始打卡时间 Date effectiveStime =dto.getEffectiveStime(); if (oConvertUtils.isEmpty(effectiveStime)) { effectiveStime = dto.getYmdDate(); } //获取有效结束打卡时间 Date effectiveEtime = dto.getEffectiveEtime(); if (oConvertUtils.isEmpty(effectiveEtime)) { effectiveEtime = getexactDate(dto.getYmdDate(), "23:59",0, 0); } List uHolidayEntities = new ArrayList(); // 遍历本月的请假记录, for (HolidayEntity holidayEntity : userHolidayEntities) { Date startdate = holidayEntity.getHolidayStime(); Date enddate = holidayEntity.getHolidayEtime(); // 如果请假开始日期是当天 或者是在当天之前 且 结束日期是当天或当天之后, 则这一天为请假日期 if (oConvertUtils.isEmpty(startdate)||oConvertUtils.isEmpty(enddate)) { //如果开始时间或者是结束时间为空 则认定为该数据为脏数据 continue; } // 当请假类型是病假和事假以外的情况 // 杨曦 20180417 if(!Globals.REST_TYPE_0.equals(holidayEntity.getHolidayType()) && !Globals.REST_TYPE_1.equals(holidayEntity.getHolidayType()) &&!Globals.REST_TYPE_7.equals(holidayEntity.getHolidayType())) { // 如果跨天,将有效打卡时间设置成前一天的23:59:59 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); if(dateFormat.format(effectiveEtime).compareTo(dateFormat.format(effectiveStime)) > 0) { Calendar cal = Calendar.getInstance(); cal.setTime(effectiveEtime); cal.add(Calendar.DATE, -1); cal.set(Calendar.HOUR_OF_DAY, 23);//时 cal.set(Calendar.MINUTE, 59);//分 cal.set(Calendar.SECOND, 59);//秒 effectiveEtime = cal.getTime(); } } if (effectiveStime.compareTo(enddate)<=0&&effectiveEtime.compareTo(startdate)>=0) { // 将这一天的请假信息 记录至该天中 uHolidayEntities.add(holidayEntity); } } dto.setUserHolidayEntities(uHolidayEntities); } private List getTBusActivitiSamelevelTransferEntityWithCache(HashMap> hm_cache,String userid, String moth) { HashMap hm = null; if(hm_cache != null) { hm = hm_cache.get("getTBusActivitiSamelevelTransferEntityWithCache"); } if(hm == null) { hm = new HashMap<>(); if(hm_cache != null) { hm_cache.put("getTBusActivitiSamelevelTransferEntityWithCache", hm); } StringBuffer str = new StringBuffer(); str.append("select * from t_bus_activiti_samelevel_transfer where (wage_yearmonth = '"+moth+"' or wage_yearmonth_last = '"+moth+"') and bpm_status = '3'"); List usList = this.getSession().createSQLQuery(str.toString()).addEntity(TBusActivitiSamelevelTransferEntity.class).list(); for(TBusActivitiSamelevelTransferEntity entity : usList) { String userInEntity = entity.getUserid(); String userAndMonth = userInEntity + entity.getWageYearmonth(); String userAndLastMonth = userInEntity + entity.getWageYearmonthLast(); if(hm.containsKey(userAndMonth)) { List entitylist = (List)hm.get(userAndMonth); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userAndMonth, newlist); } if(hm.containsKey(userAndLastMonth)) { List entitylist = (List)hm.get(userAndLastMonth); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userAndLastMonth, newlist); } } } return (List)hm.get(userid+moth); } /** * * @param hm_cache * @param userid * @param pid 管理处id * @param moth 月度 * @param workSartTime 要判断的时间,是否在调入新项目之后 * @return */ private boolean isWorkedInNewProjectAfterSameLevelTrans(HashMap> hm_cache ,String userid, String pid, String moth, Date workSartTime) { List samelevelTransferEntities = getTBusActivitiSamelevelTransferEntityWithCache(hm_cache, userid, moth); if(workSartTime != null && samelevelTransferEntities != null && samelevelTransferEntities.size()>0) { // 查询一下调入项目和月份 for(TBusActivitiSamelevelTransferEntity entity : samelevelTransferEntities) { if(pid.equals(entity.getInUnitPid()) && moth.equals(entity.getWageYearmonth()) && workSartTime.compareTo(entity.getInTime())<0) { return false; } } } return true; } private List getallUsefulFieldWithCache(HashMap> hm_cache, UserAttendanceTotalEntity userAttendanceTotalEntity) throws Exception{ List uatdlist = new ArrayList(); List updatelist = new ArrayList(); String yearmonth = userAttendanceTotalEntity.getYearmonth(); String userid = userAttendanceTotalEntity.getUserId(); List projarrangeDetailEntities = getUserProjarrangeDetailEntityWithCache(hm_cache, userid, yearmonth); ArrayList attendanceDetailEntities = new ArrayList(); if (!ListUtils.isNullOrEmpty(projarrangeDetailEntities)) { ProjarrangeDetailEntity projarrangeDetailEntity = projarrangeDetailEntities.get(0); { // 当前月无详细考勤记录数据 // 查询当前月的排班记录。 String ymddateString = null; uatdlist = getlistbyProjarrangeDetailidWithCache(hm_cache, projarrangeDetailEntity.getId(), ymddateString); // =====查询请假情况 List userHolidayEntities = getUserHolidayEntitiesWithCache(hm_cache, userid, yearmonth); // =====查询加班情况 List overtimeRecordEntities = getOvertimeRecordEntitiesWithCache(hm_cache, userid, yearmonth); // =====查询调度情况 // 01 临时借调(单次)申请表 List snapSingleborrowEntities = getSnapSingleborrowEntitiesWithCache(hm_cache, userid, yearmonth); // 02 临时借调(固定周期)申请表 List snapRegularborrowEntities = getSnapRegularborrowEntitiesWithCache(hm_cache, userid, yearmonth); //餐费补贴 List mealsSubsidyEntities = getMealsSubsidyEntitiesWithCache(hm_cache); //餐费扣除标准 List mealsDeductEntities= getMealsDeductEntitiesWithCache(hm_cache); //特殊考勤-手工考勤(默认全勤)的员工 List specialAttendEntities = getSpecialAttendEntitiesWithCache(hm_cache, userid); HashMap hm_specialAttendEntities = new HashMap(); if(specialAttendEntities != null && !specialAttendEntities.isEmpty()) { for(TBusSpecialAttendEntity spe : specialAttendEntities) { hm_specialAttendEntities.put(spe.getUserid(), spe); } } if (!ListUtils.isNullOrEmpty(uatdlist)) { for (UserAttendanceDetailDto dto : uatdlist) { UserAttendanceDetailEntity detailEntity = getUserAttendanceDetailEntityfromList(dto,attendanceDetailEntities); if ((!ListUtils.isNullOrEmpty(attendanceDetailEntities))&&null==detailEntity) { continue; } dto.setUserid(userid); dto.setAttendanceId(userAttendanceTotalEntity.getId()); if (oConvertUtils.isNotEmpty(dto.getYmdDate())) { if (!ListUtils.isNullOrEmpty(overtimeRecordEntities)) { checkIshaveovertimeRecord(dto, overtimeRecordEntities); } if (!ListUtils.isNullOrEmpty(snapSingleborrowEntities)) { checkIshavesnapSingleborrows(dto, snapSingleborrowEntities); } if (!ListUtils.isNullOrEmpty(snapRegularborrowEntities)) { checkIshavesnapRegularborrows(dto, snapRegularborrowEntities); } //将某人某天的餐费补贴 信息 添加至dto 中 if (!ListUtils.isNullOrEmpty(mealsSubsidyEntities)) { checkIshavemealsSubsidyEntities(dto, mealsSubsidyEntities); } //将某人某天的餐费补贴 的餐费扣除标准 添加至dto 中 if (!ListUtils.isNullOrEmpty(mealsDeductEntities)) { dto.setMealsDeductEntities(mealsDeductEntities); } } //获取有效开始打卡时间 Date effectiveStime = calculateEffectiveAttendanceStime(dto); dto.setEffectiveStime(effectiveStime); //获取有效结束打卡时间 Date effectiveEtime = calculateEffectiveAttendanceEtime(dto); dto.setEffectiveEtime(effectiveEtime); if (!ListUtils.isNullOrEmpty(userHolidayEntities)) { checkIshaveHolidaies(dto, userHolidayEntities); } // 获取当前状态; calculateCurdateStatus(dto); // 获取某人某天在某排班情况下的考勤记录 List dingAttendanceinfoEntities = getDingAttendanceinfoEntitiesWithCache(hm_cache,dto); Collections.sort(dingAttendanceinfoEntities); // dingAttendanceinfoService // .getDingAttendanceinfoEntities(dto); List adjustedEntities = getAdjustedAttendEntitiesWithCache(hm_cache, dto); // if("ff80808165eb2f2d01660e8b01f94905".equals(dto.getUserid())) { // System.out.println("wu"); // } // 获取借调信息 calculateBorrowsInfo(dto); boolean isWorkInvalidProject = isWorkedInNewProjectAfterSameLevelTrans(hm_cache, userid, projarrangeDetailEntity.getPid(), yearmonth, effectiveStime); if(isWorkInvalidProject && (dto.getBorrowstatus() == null ||"0".equals(dto.getBorrowstatus()) || "0".equals(dto.getBorrowstatus()))) { calculateActAttendancetime(dto, dingAttendanceinfoEntities,hm_specialAttendEntities, adjustedEntities, uatdlist,detailEntity); } //设置基准时间 calculateDatumDate(hm_cache,dto); // 获取实际出勤时间 calculateActualAttendanceDate(dto); // 获取时间差值 calculateActualtimeDifference(dto); //获取迟到/早退/旷工信息 calculateBelateAndLeaveEarlyAndabsenteeism(dto); //获取加班信息 calculateOvertime(hm_cache,dto,userAttendanceTotalEntity); //计算各种津贴 calculateSubsidy(dto); if (oConvertUtils.isNotEmpty(detailEntity)) { updatelist.add(dto); } } } else { // 当前人员本月份排班列表为空 } } } if (!ListUtils.isNullOrEmpty(attendanceDetailEntities)) { return updatelist ; }else { return uatdlist; } } /** * @param hm_cache * @param userid * @return */ private List getAdjustedAttendEntitiesWithCache( HashMap> hm_cache,UserAttendanceDetailDto dto) { HashMap hm = hm_cache.get("getAdjustedAttendEntitiesWithCache"); Date curdate = dto.getYmdDate(); String strDateFormat = "yyyy-MM"; SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getAdjustedAttendEntitiesWithCache", hm); String hql = "from UserAttendanceDetailAdjustedEntity where ymd_date like '" +sdf.format(curdate)+"%'"; List entitiesFromDB = findHql(hql); for(UserAttendanceDetailAdjustedEntity entity : entitiesFromDB) { String userInEntity = entity.getUserId(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(dto.getUserid()); } /** * @param userid * @return */ private List getAdjustedAttendEntityByUserId( String userid,UserAttendanceDetailDto dto) { Date curdate = dto.getYmdDate(); String strDateFormat = "yyyy-MM"; SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat); List list = null; String hql = "from UserAttendanceDetailAdjustedEntity where ymd_date like '" +sdf.format(curdate)+"%' and user_id='" +userid+"'"; List entitiesFromDB = findHql(hql); return entitiesFromDB; } /** * @param hm_cache * @param ymddateString * @param ymddateString2 * @return */ private List getlistbyProjarrangeDetailidWithCache( HashMap> hm_cache, String projarrangeDetailEntityId, String ymddateString) { HashMap hm = hm_cache.get("getlistbyProjarrangeDetailidWithCache"); if(hm == null || hm.isEmpty()) { hm = new HashMap<>(); hm_cache.put("getlistbyProjarrangeDetailidWithCache", hm); List entitiesFromDB = userAttendanceDetailDao.getlistbyProjarrangeDetailid(null,null,ymddateString); for(UserAttendanceDetailDto entity : entitiesFromDB) { String id = entity.getProjarrangeDetailid(); if(hm.containsKey(id)) { List entitylist = (List)hm.get(id); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(id, newlist); } } } return (List)hm.get(projarrangeDetailEntityId); } /** * 多线程查询排班 * @author xzx * * 2019年8月31日 * */ @Transactional class ProjarrangeDetailidWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public ProjarrangeDetailidWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); // TODO Auto-generated constructor stub } /** * @param hm_cache * @param ymddateString * @param ymddateString2 * @return */ private HashMap> getlistbyProjarrangeDetailidWithCache(String ymddateString) { HashMaphm = new HashMap<>(); List entitiesFromDB = userAttendanceDetailDao.getlistbyyearmonth(ymddateString); for(UserAttendanceDetailDto entity : entitiesFromDB) { String id = entity.getProjarrangeDetailid(); if(hm.containsKey(id)) { List entitylist = (List)hm.get(id); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(id, newlist); } } HashMap> result = new HashMap>(); result.put("getlistbyProjarrangeDetailidWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() { // TODO Auto-generated method stub return getlistbyProjarrangeDetailidWithCache(getYearmonth()); } } /** * @param dto * @return */ private List getDingAttendanceinfoEntitiesWithCache(HashMap> hm_cache,UserAttendanceDetailDto dto) { HashMap hm = hm_cache.get("getDingAttendanceinfoEntitiesWithCache"); Date curdate = dto.getYmdDate(); String strDateFormat = "yyyy-MM"; SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat); Calendar calendar = Calendar.getInstance(); calendar.setTime(curdate); calendar.add(Calendar.DATE, 2); Date tomdate = calendar.getTime(); if(hm == null) { hm = new HashMap<>(); hm_cache.put("getDingAttendanceinfoEntitiesWithCache", hm); CriteriaQuery cq = new CriteriaQuery(DingAttendanceinfoEntity.class); cq.like("attendanceTime", sdf.format(curdate)+"%"); cq.add(); // cq.between("attendanceTime", curdate, tomdate); // cq.add(); cq.addOrder("attendanceTime", SortDirection.asc); String hql = "from DingAttendanceinfoEntity where attendanceTime like '" +sdf.format(curdate)+"%'"; List entitiesFromDB = findHql(hql); //getListByCriteriaQuery(cq, false); for(DingAttendanceinfoEntity entity : entitiesFromDB) { String userInEntity = entity.getUserId(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } List allList = (List)hm.get(dto.getUserid()); if(allList == null) { return new ArrayList(); } List selectList = new ArrayList<>(); for(DingAttendanceinfoEntity attInAll : allList) { Date attendanceTime = attInAll.getAttendanceTime(); if(attendanceTime.after(curdate) && attendanceTime.before(tomdate)) { selectList.add(attInAll); } } return selectList; } /** * 多线程查询钉钉考勤数据 * @author xzx * * 2019年8月31日 * */ @Transactional class DingAttendanceinfoEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public DingAttendanceinfoEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } public HashMap> loadData(){ return getDingAttendanceinfoEntitiesWithCache(getYearmonth()); } private HashMap> getDingAttendanceinfoEntitiesWithCache(String ymddateString) { HashMap hm = new HashMap<>(); String hql = "from DingAttendanceinfoEntity where attendanceTime like '" +ymddateString+"%'"; List entitiesFromDB = getCommonService().findHql(hql); for(DingAttendanceinfoEntity entity : entitiesFromDB) { String userInEntity = entity.getUserId(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getDingAttendanceinfoEntitiesWithCache", hm); return result; } } /** * @param hm_cache * @return */ private List getSpecialAttendEntitiesWithCache(HashMap> hm_cache,String userid) { // TODO Auto-generated method stub HashMap hm = hm_cache.get("getSpecialAttendEntitiesWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getSpecialAttendEntitiesWithCache", hm); CriteriaQuery specialcq = new CriteriaQuery(TBusSpecialAttendEntity.class); specialcq.eq("attendtype", Globals.Special_Attend_Type_All_IN); specialcq.add(); List entitiesFromDB = getListByCriteriaQuery(specialcq, false); for(TBusSpecialAttendEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(userid); } @Transactional class SpecialAttendEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public SpecialAttendEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } private HashMap> getSpecialAttendEntitiesWithCache() { HashMap hm = new HashMap<>(); CriteriaQuery specialcq = new CriteriaQuery(TBusSpecialAttendEntity.class); specialcq.eq("attendtype", Globals.Special_Attend_Type_All_IN); specialcq.add(); List entitiesFromDB = snapSingleborrowService.getListByCriteriaQuery(specialcq, false); for(TBusSpecialAttendEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getSpecialAttendEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() throws Exception { return getSpecialAttendEntitiesWithCache(); } } @Transactional class MealsDeductEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public MealsDeductEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } /** * @param hm_cache * @return */ private HashMap> getMealsDeductEntitiesWithCache() { // TODO Auto-generated method stub HashMap hm =new HashMap<>(); hm = new HashMap<>(); CriteriaQuery mdcq = new CriteriaQuery(MealsDeductEntity.class); mdcq.eq("deleteFlag", "0"); mdcq.add(); mdcq.eq("status", "0"); mdcq.add(); List entitiesFromDB = getListByCriteriaQuery(mdcq, false); hm.put("ALL", entitiesFromDB); HashMap> result = new HashMap>(); result.put("getMealsDeductEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() { return getMealsDeductEntitiesWithCache(); } } /** * @param hm_cache * @return */ private List getMealsDeductEntitiesWithCache(HashMap> hm_cache) { // TODO Auto-generated method stub HashMap hm = hm_cache.get("getMealsDeductEntitiesWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getMealsDeductEntitiesWithCache", hm); CriteriaQuery mdcq = new CriteriaQuery(MealsDeductEntity.class); mdcq.eq("deleteFlag", "0"); mdcq.add(); mdcq.eq("status", "0"); mdcq.add(); List entitiesFromDB = getListByCriteriaQuery(mdcq, false); hm.put("ALL", entitiesFromDB); } return list = (List)hm.get("ALL"); } /** * @param hm_cache * @return */ private List getMealsSubsidyEntitiesWithCache(HashMap> hm_cache) { HashMap hm = hm_cache.get("getMealsSubsidyEntitiesWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getMealsSubsidyEntitiesWithCache", hm); CriteriaQuery mscq = new CriteriaQuery(MealsSubsidyEntity.class); mscq.eq("deleteFlag", "0"); mscq.add(); mscq.eq("status", "0"); mscq.add(); List entitiesFromDB = getListByCriteriaQuery(mscq, false); hm.put("ALL", entitiesFromDB); } return (List)hm.get("ALL"); } @Transactional class MealsSubsidyEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public MealsSubsidyEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } private HashMap> getMealsSubsidyEntitiesWithCache() { HashMap hm = new HashMap<>(); CriteriaQuery mscq = new CriteriaQuery(MealsSubsidyEntity.class); mscq.eq("deleteFlag", "0"); mscq.add(); mscq.eq("status", "0"); mscq.add(); List entitiesFromDB = getListByCriteriaQuery(mscq, false); hm.put("ALL", entitiesFromDB); HashMap> result = new HashMap>(); result.put("getMealsSubsidyEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() { // TODO Auto-generated method stub return getMealsSubsidyEntitiesWithCache(); } } /** * @param hm_cache * @param userid * @param yearmonth * @return * @throws Exception */ private List getSnapRegularborrowEntitiesWithCache( HashMap> hm_cache, String userid, String yearmonth) throws Exception { HashMap hm = hm_cache.get("getSnapRegularborrowEntitiesWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getSnapRegularborrowEntitiesWithCache", hm); CriteriaQuery cq = new CriteriaQuery( SnapRegularborrowEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List entitiesFromDB = snapRegularborrowService .getSnapRegularborrowEntities(null, yearmonth); for(SnapRegularborrowEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(userid); } @Transactional class SnapRegularborrowEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public SnapRegularborrowEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } private HashMap> getSnapSingleborrowEntitiesWithCache(String yearmonth) { HashMap hm = new HashMap<>(); hm = new HashMap<>(); CriteriaQuery cq = new CriteriaQuery( SnapSingleborrowEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List entitiesFromDB = null; try { entitiesFromDB = snapSingleborrowService .getSnapSingleborrowEntities(null, yearmonth); } catch (Exception e) { System.out.println(e.getMessage()); } for(SnapSingleborrowEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getSnapSingleborrowEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() { return getSnapSingleborrowEntitiesWithCache(getYearmonth()); } } /** * @param hm_cache * @param userid * @param yearmonth * @return * @throws Exception */ private List getSnapSingleborrowEntitiesWithCache( HashMap> hm_cache, String userid, String yearmonth) throws Exception { HashMap hm = hm_cache.get("getSnapSingleborrowEntitiesWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getSnapSingleborrowEntitiesWithCache", hm); CriteriaQuery cq = new CriteriaQuery( SnapSingleborrowEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List entitiesFromDB = snapSingleborrowService .getSnapSingleborrowEntities(null, yearmonth); for(SnapSingleborrowEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(userid); } @Transactional class SnapSingleborrowEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public SnapSingleborrowEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); // TODO Auto-generated constructor stub } private HashMap> getSnapSingleborrowEntitiesWithCache(String yearmonth) throws Exception { HashMap hm = new HashMap<>(); CriteriaQuery cq = new CriteriaQuery( SnapSingleborrowEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List entitiesFromDB = snapSingleborrowService .getSnapSingleborrowEntities(null, yearmonth); for(SnapSingleborrowEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getSnapSingleborrowEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() throws Exception { return getSnapSingleborrowEntitiesWithCache(getYearmonth()); } } /** * @param hm_cache * @param userid * @param yearmonth * @return * @throws Exception */ private List getOvertimeRecordEntitiesWithCache( HashMap> hm_cache, String userid, String yearmonth) throws Exception { HashMap hm = hm_cache.get("getOvertimeRecordEntitiesWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getOvertimeRecordEntitiesWithCache", hm); CriteriaQuery cq = new CriteriaQuery( OvertimeRecordEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List entitiesFromDB = overtimeRecordService.getOvertimeRecordEntities(null, yearmonth); for(OvertimeRecordEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(userid); } @Transactional class OvertimeRecordEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public OvertimeRecordEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } private HashMap> getOvertimeRecordEntitiesWithCache(String yearmonth) { HashMap hm = new HashMap<>(); CriteriaQuery cq = new CriteriaQuery( OvertimeRecordEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List entitiesFromDB = null; try { entitiesFromDB = overtimeRecordService.getOvertimeRecordEntities(null, yearmonth); } catch (Exception e) { System.out.println(e.getMessage()); } for(OvertimeRecordEntity entity : entitiesFromDB) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getOvertimeRecordEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() { return getOvertimeRecordEntitiesWithCache(getYearmonth()); } } /** * @param hm_cache * @param userid * @param yearmonth * @return * @throws Exception */ private List getUserHolidayEntitiesWithCache(HashMap> hm_cache, String userid, String yearmonth) throws Exception { HashMap hm = hm_cache.get("getUserHolidayEntitiesWithCache"); if(hm == null) { hm = new HashMap<>(); hm_cache.put("getUserHolidayEntitiesWithCache", hm); List userHolidayEntities = holidayService .getUserHolidayEntities(null, yearmonth); for(HolidayEntity entity : userHolidayEntities) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(userid); } @Transactional class UserHolidayEntitiesWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public UserHolidayEntitiesWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } private HashMap> getUserHolidayEntitiesWithCache(String yearmonth){ HashMap hm = new HashMap<>(); List userHolidayEntities = null; try { userHolidayEntities = holidayService .getUserHolidayEntities(null, yearmonth); List activitiHoliday = userAvtivitiDao.getHolidayFromExchangeActiviti(null, yearmonth); userHolidayEntities.addAll(activitiHoliday); } catch (Exception e) { org.jeecgframework.core.util.LogUtil.error(e.getMessage()); } for(HolidayEntity entity : userHolidayEntities) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getUserHolidayEntitiesWithCache", hm); return result; } /* (non-Javadoc) * @see cn.com.lzt.callable.YearmonthlyDataloadCallable#loadData() */ @Override public HashMap> loadData() { return getUserHolidayEntitiesWithCache(getYearmonth()); } } /** * @param hm_cache * @param userid * @param yearmonth * @return */ @SuppressWarnings("unchecked") private List getUserProjarrangeDetailEntityWithCache( HashMap> hm_cache, String userid, String yearmonth) { HashMap hm = hm_cache.get("getUserProjarrangeDetailEntityWithCache"); List list = null; if(hm == null) { hm = new HashMap<>(); hm_cache.put("getUserProjarrangeDetailEntityWithCache", hm); CriteriaQuery cq = new CriteriaQuery( ProjarrangeDetailEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List projarrangeDetailEntities = getListByCriteriaQuery( cq, false); for(ProjarrangeDetailEntity entity : projarrangeDetailEntities) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } } return (List)hm.get(userid); } @Transactional class UserProjarrangeDetailEntityWithCache extends YearmonthlyDataloadCallable { /** * @param commonService * @param yearmonth */ public UserProjarrangeDetailEntityWithCache(CommonServiceImpl commonService, String yearmonth) { super(commonService, yearmonth); } private HashMap> getUserProjarrangeDetailEntityWithCache(String yearmonth) { HashMap hm = new HashMap<>(); CriteriaQuery cq = new CriteriaQuery( ProjarrangeDetailEntity.class); cq.eq("yearmonth", yearmonth); cq.add(); List projarrangeDetailEntities = getListByCriteriaQuery( cq, false); for(ProjarrangeDetailEntity entity : projarrangeDetailEntities) { String userInEntity = entity.getUserid(); if(hm.containsKey(userInEntity)) { List entitylist = (List)hm.get(userInEntity); entitylist.add(entity); }else { List newlist = new ArrayList<>(); newlist.add(entity); hm.put(userInEntity, newlist); } } HashMap> result = new HashMap>(); result.put("getUserProjarrangeDetailEntityWithCache", hm); return result; } @Override public HashMap> loadData() { return getUserProjarrangeDetailEntityWithCache(getYearmonth()); } } private void loadAllCacheTask(HashMap> hm_cache, String yearmonth) throws InterruptedException, ExecutionException { List>>> tasks = new ArrayList<>(); // dingding task Callable>> dingdingTask = new DingAttendanceinfoEntitiesWithCache(this,yearmonth); tasks.add(dingdingTask); //mealsDeduct Callable>> mealsDeductTask = new MealsDeductEntitiesWithCache(this,yearmonth); tasks.add(mealsDeductTask); //mealsSubsidy Callable>> mealsSubsidyTask = new MealsSubsidyEntitiesWithCache(this,yearmonth); tasks.add(mealsSubsidyTask); //OvertimeRecord Callable>> OvertimeRecordTask = new OvertimeRecordEntitiesWithCache(this,yearmonth); tasks.add(OvertimeRecordTask); //ProarrangeDetail Callable>> ProarrangeDetailTask = new ProjarrangeDetailidWithCache(this,yearmonth); tasks.add(ProarrangeDetailTask); //SnapRegular Callable>> SnapRegularTask = new SnapRegularborrowEntitiesWithCache(this,yearmonth); tasks.add(SnapRegularTask); //SnapSingle Callable>> SnapSingleTask = new SnapSingleborrowEntitiesWithCache(this,yearmonth); tasks.add(SnapSingleTask); //SpecialAttend Callable>> SpecialAttendTask = new SpecialAttendEntitiesWithCache(this,yearmonth); tasks.add(SpecialAttendTask); //userHoliday Callable>> userHolidayTask = new UserHolidayEntitiesWithCache(this,yearmonth); tasks.add(userHolidayTask); //userProjarrangeDetail Callable>> userProjarrangeDetail = new UserProjarrangeDetailEntityWithCache(this,yearmonth); tasks.add(userProjarrangeDetail); //定义固定长度的线程池 防止线程过多 ExecutorService executorService = Executors.newFixedThreadPool(10); long s = System.currentTimeMillis(); //Future用于获取结果 List>>> futures=executorService.invokeAll(tasks); //处理线程返回结果 if(futures!=null&&futures.size()>0){ for (Future>> future:futures){ HashMap> result = future.get(); for(String key : result.keySet()) { hm_cache.put(key,result.get(key)); } } } long e = System.currentTimeMillis(); System.out.println("CurrThreadLoadCache costs: " + (e-s) + " ms"); executorService.shutdown();//关闭线程池 } @Override public List getallUsefulField(UserAttendanceTotalEntity userAttendanceTotalEntity,List attendanceDetailEntities ,Date ymdDate) throws Exception { List uatdlist = new ArrayList(); List updatelist = new ArrayList(); String yearmonth = userAttendanceTotalEntity.getYearmonth(); String userid = userAttendanceTotalEntity.getUserId(); long startTotal = System.currentTimeMillis(); { // 查询当前员工在当前处理月度的【项目排班详细】 CriteriaQuery cq = new CriteriaQuery( ProjarrangeDetailEntity.class); cq.eq("userid", userid); cq.add(); cq.eq("yearmonth", yearmonth); cq.add(); long start1 = System.currentTimeMillis(); // 通过上述三个条件的筛选, 原则上而言, 应该是有且只有一条记录 List projarrangeDetailEntities = getListByCriteriaQuery( cq, false); long end1 = System.currentTimeMillis(); //System.out.println("projarrangeDetailEntities : " +(end1-start1) + " ms"); if (!ListUtils.isNullOrEmpty(projarrangeDetailEntities)) { ProjarrangeDetailEntity projarrangeDetailEntity = projarrangeDetailEntities.get(0); { // 当前月无详细考勤记录数据 // 查询当前月的排班记录。 String ymddateString = null; if (oConvertUtils.isNotEmpty(ymdDate)) { ymddateString = DataUtils.date2Str(ymdDate, DataUtils.date_sdf); } long start2 = System.currentTimeMillis(); uatdlist = userAttendanceDetailDao.getlistbyProjarrangeDetailid(projarrangeDetailEntity.getId(),null,ymddateString); long end2 = System.currentTimeMillis(); //System.out.println("userAttendanceDetailDao.getlistbyProjarrangeDetailid : " +(end2-start2) + " ms"); long start3 = System.currentTimeMillis(); // =====查询请假情况 List userHolidayEntities = holidayService .getUserHolidayEntities(userid, yearmonth); List userHolidayFromActiviti = userAvtivitiDao .getHolidayFromExchangeActiviti(userid, yearmonth); if(userHolidayEntities == null ) { userHolidayEntities = new ArrayList(); } userHolidayEntities.addAll(userHolidayFromActiviti); long end3 = System.currentTimeMillis(); //System.out.println("userHolidayEntities : " +(end3-start3) + " ms"); long start4 = System.currentTimeMillis(); // =====查询加班情况 List overtimeRecordEntities = overtimeRecordService.getOvertimeRecordEntities(userid, yearmonth); long end4 = System.currentTimeMillis(); //System.out.println("userHolidayEntities : " +(end4-start4) + " ms"); long start5 = System.currentTimeMillis(); // =====查询调度情况 // 01 临时借调(单次)申请表 List snapSingleborrowEntities = snapSingleborrowService .getSnapSingleborrowEntities(userid, yearmonth); // 02 临时借调(固定周期)申请表 List snapRegularborrowEntities = snapRegularborrowService .getSnapRegularborrowEntities(userid, yearmonth); CriteriaQuery mscq = new CriteriaQuery(MealsSubsidyEntity.class); long end5 = System.currentTimeMillis(); //System.out.println("snapSingleborrowEntities+snapRegularborrowEntities : " +(end5-start5) + " ms"); mscq.eq("deleteFlag", "0"); mscq.add(); mscq.eq("status", "0"); mscq.add(); long start6 = System.currentTimeMillis(); //餐费补贴 List mealsSubsidyEntities=getListByCriteriaQuery(mscq, false); long end6 = System.currentTimeMillis(); //System.out.println("mealsSubsidyEntities : " +(end6-start6) + " ms"); long start7 = System.currentTimeMillis(); CriteriaQuery mdcq = new CriteriaQuery(MealsDeductEntity.class); mdcq.eq("deleteFlag", "0"); mdcq.add(); mdcq.eq("status", "0"); mdcq.add(); //餐费扣除标准 List mealsDeductEntities=getListByCriteriaQuery(mdcq, false); long end7 = System.currentTimeMillis(); //System.out.println("mealsDeductEntities : " +(end7-start7) + " ms"); long start8 = System.currentTimeMillis(); //特殊考勤-手工考勤(默认全勤)的员工 CriteriaQuery specialcq = new CriteriaQuery(TBusSpecialAttendEntity.class); specialcq.eq("attendtype", Globals.Special_Attend_Type_All_IN); specialcq.add(); List specialAttendEntities = getListByCriteriaQuery(specialcq, false); HashMap hm_specialAttendEntities = new HashMap(); if(specialAttendEntities != null && !specialAttendEntities.isEmpty()) { for(TBusSpecialAttendEntity spe : specialAttendEntities) { hm_specialAttendEntities.put(spe.getUserid(), spe); } } long end8 = System.currentTimeMillis(); //System.out.println("specialAttendEntities : " +(end8-start8) + " ms"); if (null==attendanceDetailEntities) { attendanceDetailEntities = new ArrayList(); } if (!ListUtils.isNullOrEmpty(uatdlist)) { // 把一个月的考勤都查询出来 long start14 = System.currentTimeMillis(); List dingAttendanceinfoEntities = dingAttendanceinfoService .getDingAttendanceinfoEntitiesInOneMonth(userid, uatdlist.get(0).getYmdDate()); long end14 = System.currentTimeMillis(); //System.out.println(uatdlist.get(0).getYmdDate()+":dingAttendanceinfoService : " +(end14-start14) + " ms"); long start13 = System.currentTimeMillis(); List adjustedEntities = getAdjustedAttendEntityByUserId(userid, uatdlist.get(0)); long end13 = System.currentTimeMillis(); //System.out.println(uatdlist.get(0).getYmdDate()+":adjustedEntities : " +(end13-start13) + " ms"); long startFor = System.currentTimeMillis(); for (UserAttendanceDetailDto dto : uatdlist) { long start9 = System.currentTimeMillis(); UserAttendanceDetailEntity detailEntity = getUserAttendanceDetailEntityfromList(dto,attendanceDetailEntities); long end9 = System.currentTimeMillis(); //System.out.println(dto.getYmdDate()+":getUserAttendanceDetailEntityfromList : " +(end9-start9) + " ms"); if ((!ListUtils.isNullOrEmpty(attendanceDetailEntities))&&null==detailEntity) { continue; } if(detailEntity!= null && !dto.getShiftid().equals(detailEntity.getDutyId())) { long start10 = System.currentTimeMillis(); //班次发生了修改,因为是嵌套事务,所以还没有及时更新库表 reloadWithNewDutyId(dto, detailEntity.getDutyId()); long end10 = System.currentTimeMillis(); //System.out.println(dto.getYmdDate()+":reloadWithNewDutyId : " +(end10-start10) + " ms"); } dto.setUserid(userid); dto.setAttendanceId(userAttendanceTotalEntity.getId()); if (oConvertUtils.isNotEmpty(dto.getYmdDate())) { long start11 = System.currentTimeMillis(); if (!ListUtils.isNullOrEmpty(overtimeRecordEntities)) { checkIshaveovertimeRecord(dto, overtimeRecordEntities); } if (!ListUtils.isNullOrEmpty(snapSingleborrowEntities)) { checkIshavesnapSingleborrows(dto, snapSingleborrowEntities); } if (!ListUtils.isNullOrEmpty(snapRegularborrowEntities)) { checkIshavesnapRegularborrows(dto, snapRegularborrowEntities); } //将某人某天的餐费补贴 信息 添加至dto 中 if (!ListUtils.isNullOrEmpty(mealsSubsidyEntities)) { checkIshavemealsSubsidyEntities(dto, mealsSubsidyEntities); } //将某人某天的餐费补贴 的餐费扣除标准 添加至dto 中 if (!ListUtils.isNullOrEmpty(mealsDeductEntities)) { dto.setMealsDeductEntities(mealsDeductEntities); } long end11 = System.currentTimeMillis(); //System.out.println(dto.getYmdDate()+":check...record : " +(end11-start11) + " ms"); } long start11 = System.currentTimeMillis(); //获取有效开始打卡时间 Date effectiveStime = calculateEffectiveAttendanceStime(dto); dto.setEffectiveStime(effectiveStime); //获取有效结束打卡时间 Date effectiveEtime = calculateEffectiveAttendanceEtime(dto); dto.setEffectiveEtime(effectiveEtime); long end11 = System.currentTimeMillis(); //System.out.println(dto.getYmdDate()+":获取有效打卡时间 : " +(end11-start11) + " ms"); long start12 = System.currentTimeMillis(); if (!ListUtils.isNullOrEmpty(userHolidayEntities)) { checkIshaveHolidaies(dto, userHolidayEntities); } long end12 = System.currentTimeMillis(); //System.out.println(dto.getYmdDate()+":checkIshaveHolidaies : " +(end12-start12) + " ms"); // 获取当前状态; calculateCurdateStatus(dto); // 获取借调信息 calculateBorrowsInfo(dto); long start15 = System.currentTimeMillis(); boolean isWorkInvalidProject = isWorkedInNewProjectAfterSameLevelTrans(null, userid, projarrangeDetailEntity.getPid(), yearmonth, effectiveStime); if(isWorkInvalidProject && (dto.getBorrowstatus() == null ||"0".equals(dto.getBorrowstatus()) || "0".equals(dto.getBorrowstatus()))) { calculateActAttendancetime(dto, dingAttendanceinfoEntities,hm_specialAttendEntities, adjustedEntities, uatdlist,detailEntity); } //设置基准时间 calculateDatumDate(null,dto); // 获取实际出勤时间 calculateActualAttendanceDate(dto); // 获取时间差值 calculateActualtimeDifference(dto); //获取迟到/早退/旷工信息 calculateBelateAndLeaveEarlyAndabsenteeism(dto); //获取加班信息 calculateOvertime(null,dto,userAttendanceTotalEntity); //计算各种津贴 calculateSubsidy(dto); if (oConvertUtils.isNotEmpty(detailEntity)) { updatelist.add(dto); } long end15 = System.currentTimeMillis(); //System.out.println(dto.getYmdDate()+":calculate.... : " +(end15-start15) + " ms"); // if (oConvertUtils.isNotEmpty(ymdDate)) { // AttendanceDetailJsonObj jsonObj = getjsonObjfromDto(dto); // dto.setJsonObj(jsonObj); // } } long endFor = System.currentTimeMillis(); //System.out.println("ForCircleCost : " +(endFor-startFor) + " ms"); } else { // 当前人员本月份排班列表为空 } } } } long endTotal = System.currentTimeMillis(); // System.out.println(userAttendanceTotalEntity.getUserId()+"_getUsefulField_total_Cost : " +(endTotal-startTotal) + " ms"); if (!ListUtils.isNullOrEmpty(attendanceDetailEntities)) { return updatelist ; }else { return uatdlist; } } /** * @param dto * @param dutyId */ private void reloadWithNewDutyId(UserAttendanceDetailDto dto, String dutyId) { if(oConvertUtils.isEmpty(dutyId)) { return; } ArrangeDutyEntity duty = get(ArrangeDutyEntity.class, dutyId); dto.setDutyName(duty.getDutyName()); dto.setPid(duty.getPid()); dto.setDutyType(duty.getDutyType()); dto.setNormalworkStime(duty.getNormalworkStime()); dto.setNormalworkEtime(duty.getNormalworkEtime()); dto.setSpunchMinute(duty.getSpunchMinute()); dto.setEpunchMinute(duty.getEpunchMinute()); dto.setDatumWorkhours(duty.getDatumWorkhours()); dto.setShiftWorkhours(duty.getShiftWorkhours()); dto.setOndutyStime(duty.getOndutyStime()); dto.setOndutyEtime(duty.getOndutyEtime()); dto.setOndutyWorkhours(duty.getOndutyWorkhours()); dto.setTimeOutOvertimeStime(duty.getTimeOutOvertimeStime()); dto.setTimeOutOvertimeEtime(duty.getTimeOutOvertimeEtime()); dto.setTimeOutOvertimeHours(duty.getTimeOutOvertimeHours()); dto.setDutyMealid(duty.getDutyMealid()); dto.setStatus(duty.getStatus()); dto.setDeleteFlag(duty.getDeleteFlag()); } /** * 通过考勤详情列表 获取考勤详情信息 * @author hualong.zhao * @date 2017-12-5 * @param dto * @param attendanceDetailEntities * @return */ private UserAttendanceDetailEntity getUserAttendanceDetailEntityfromList(UserAttendanceDetailDto dto, List attendanceDetailEntities){ UserAttendanceDetailEntity resultentry = null; if (!ListUtils.isNullOrEmpty(attendanceDetailEntities)) { for (UserAttendanceDetailEntity entry:attendanceDetailEntities) { if (dto.getYmdDate().equals(entry.getYmdDate())) { resultentry = entry; break; } } } return resultentry; } /** * 检查某人某天的餐费补贴 * @author hualong.zhao * @date 2017-12-2 * @param dto * @param mealsSubsidyEntities */ private void checkIshavemealsSubsidyEntities(UserAttendanceDetailDto dto, List mealsSubsidyEntities) { List dtomealsSubsidyEntities = dto .getMealsSubsidyEntities(); /** 班次餐补ID */ String dutyMealid = oConvertUtils.getString(dto.getDutyMealid()); if (oConvertUtils.isNotEmpty(dutyMealid)) { for (MealsSubsidyEntity entity : mealsSubsidyEntities) { if (dutyMealid.contains(entity.getId())) { if (Globals.SUBSIDY_TYPE_BCCB.equals(oConvertUtils.getString(entity.getSubsidyType()))) { dtomealsSubsidyEntities.add(entity); } } } } dto.setMealsSubsidyEntities(dtomealsSubsidyEntities); } /** * 计算津贴 * 夜班最多可提供两次餐补 , 餐补类型【夜班白班津贴】 和【夜班夜班津贴】 由班次表 动态配置 * 日班提供两次餐补, * 常班提供一次餐补, * 扣除规则: * 如果是夜班时 ,根据迟到时间, 判断是否给与第一次餐补【夜班夜班津贴】 * 如果是夜班时 ,根据早退时间, 判断是否给与第二次餐补【夜班白班津贴】 * 如果是日班时 ,根据总的欠勤数, 判断扣除几顿 * * 如果是常班时,根据总的欠勤数,判断是否给与餐补 * 2018年1月12日 需求变更: 当员工当天没有打卡记录的时候, 该员工餐补不提供 * @author hualong.zhao * @date 2017-12-2 * @param dto */ private void calculateSubsidy(UserAttendanceDetailDto dto) { /**夜班白班津贴*/ Integer dayShiftSubsidy = 0 ; /**夜班夜班津贴*/ Integer nightShiftSubsidy = 0; /**日班*/ Integer dayShift = 0; /**常班*/ Integer regularShift = 0; /**值班*/ Integer dutyShift = 0; /** 餐补补贴次数~餐补idmap */ HashMap mealsmap = new HashMap<>(); //餐费补贴 List dtomealsSubsidyEntities = dto.getMealsSubsidyEntities(); //餐费扣除标准 List mealsDeductEntities=dto.getMealsDeductEntities(); // 请假 /休息 补贴清零 旷工一天 补贴清空 迟到早退 根据欠勤分钟数 按照餐费扣除标准 进行扣除 只记录 查询 判断 班次餐补 加班情况下 只考虑按此给0 or 1 if (dto.getLongHoliday()) { if(dto.getActualAttendanceDate() == null || dto.getActualAttendanceDate().compareTo(BigDecimal.ZERO)<=0) { dto.setDayShiftSubsidy(dayShiftSubsidy); dto.setNightShiftSubsidy(nightShiftSubsidy); dto.setDayShift(dayShift); dto.setRegularShift(regularShift); dto.setDutyShift(dutyShift); return; } } if((Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType())))) { dto.setDayShiftSubsidy(dayShiftSubsidy); dto.setNightShiftSubsidy(nightShiftSubsidy); dto.setDayShift(dayShift); dto.setRegularShift(regularShift); dto.setDutyShift(dutyShift); return; } if (!ListUtils.isNullOrEmpty(dtomealsSubsidyEntities)) { for (MealsSubsidyEntity entry:dtomealsSubsidyEntities) { String shiftSubsidyType = oConvertUtils.getString(entry.getShiftSubsidyType()); if (Globals.SHIFT_SUBSIDY_TYPE_YEBANJINTIEWAN.equals(shiftSubsidyType)) { if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) { nightShiftSubsidy = 1 ; mealsmap.put("nightShiftSubsidy", entry); } } if (Globals.SHIFT_SUBSIDY_TYPE_BAIBANJINTIEZAO.equals(shiftSubsidyType)) { if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) { dayShiftSubsidy = 1 ; mealsmap.put("dayShiftSubsidy", entry); } } if (Globals.SHIFT_SUBSIDY_TYPE_RIBAN.equals(shiftSubsidyType)) { if (Globals.DUTYTYPE_riban11h.equals(oConvertUtils.getString(dto.getDutyType()))) { dayShift = 2; mealsmap.put("dayShift", entry); } } if (Globals.SHIFT_SUBSIDY_TYPE_CHANGBAN.equals(shiftSubsidyType)) { if (Globals.DUTYTYPE_CHANGBAN8H.equals(oConvertUtils.getString(dto.getDutyType()))) { regularShift = 1 ; mealsmap.put("regularShift", entry); } } if (Globals.SHIFT_SUBSIDY_TYPE_ZHIBAN.equals(shiftSubsidyType)) { if (Globals.DUTYTYPE_zhiban.equals(oConvertUtils.getString(dto.getDutyType()))) { dutyShift = 1 ; mealsmap.put("dutyShift", entry); } } } } //如果扣费规则不为空 if (!ListUtils.isNullOrEmpty(mealsDeductEntities)) { /**迟到分钟数*/ int belatemins = dto.getBelatemins(); /**早退分钟数*/ int leaveEarlymins = dto.getLeaveEarlymins(); int thinsorsickmins = dto.getSickLeaveMins().intValue()+dto.getThingLeaveMins().intValue(); int qqmins =belatemins + leaveEarlymins+thinsorsickmins ; String durationCode = dto.getDurationCode(); //根据餐费扣除标准 扣除餐补 for (MealsDeductEntity entity : mealsDeductEntities) { if (Globals.SUBSIDY_TYPE_BCCB.equals(oConvertUtils.getString(entity.getSubsidyType()))) { Integer leftHours = entity.getLeftHours(); Integer rightHours = entity.getRightHours(); /**扣除数*/ BigDecimal deductNum = entity.getDeductNum(); if (oConvertUtils.isNotEmpty(leftHours)&&oConvertUtils.isNotEmpty(rightHours)) { leftHours = leftHours*60; rightHours = rightHours*60; if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) { int iamlate = belatemins ; //迟到满足扣除标准 if ("1".equals(oConvertUtils.getString(durationCode))) { //当天请假是前半夜假期 iamlate += thinsorsickmins; } if (iamlate>=leftHours&&iamlate=leftHours&&iamleaveEarly=leftHours&&qqmins=2) { nightShiftSubsidy = 0; dayShiftSubsidy = 0; } } catch (Exception e) { } } }else { /** * 迟到满足扣除标准 * 如果是日班时 ,根据总的欠勤数, 判断扣除几顿 * 如果是常班时,根据总的欠勤数,判断是否给与餐补 * * 欠勤分钟数 应该添加 当天申请的事假 or 病假的分钟数 */ if (qqmins>=leftHours&&qqmins> hm_cache, UserAttendanceDetailDto dto, UserAttendanceTotalEntity userAttendanceTotalEntity) { /**国定加班时长*/ BigDecimal nationalOvertimeDuration = BigDecimal.ZERO; /**特殊加班费*/ BigDecimal specialOvertime = BigDecimal.ZERO; List list = dto.getOvertimeRecordEntities(); /** * 国定加班时长 包括两部分: 1. 排班中按照不同的班次及法定假日计算当月的法定假日; 2. 当月加班备案中申请的国定加班时长 * A=法定假日当天排班的基准时长累计; B=当月加班备案中国定加班时长累计; 国定加班时长 = A+B; */ if (!ListUtils.isNullOrEmpty(list)) { //检索加班 for (OvertimeRecordEntity entry:list) { BigDecimal overtimeBigDecimal = entry.getOvertimeHours(); if (null==overtimeBigDecimal) { overtimeBigDecimal = BigDecimal.ZERO; } overtimeBigDecimal = overtimeBigDecimal.multiply(new BigDecimal(60)); if ("1".equals(oConvertUtils.getString(entry.getIfnational()))) { nationalOvertimeDuration =overtimeBigDecimal; }else { specialOvertime=overtimeBigDecimal; } } } // if("000000006120dd1c01612cf52162014f".equals(dto.getUserid())) { // System.out.println(); // } //计算115夜班前半夜或者后半夜是国定假的情况 BigDecimal halfNationOvertime = calculateHalfNationalOvertime(hm_cache, dto,true); if(halfNationOvertime.compareTo(BigDecimal.ZERO)>0 && halfNationOvertime.compareTo(new BigDecimal(11.5*60))<0) { nationalOvertimeDuration = nationalOvertimeDuration.add(halfNationOvertime); //把超时加班中计算的部分去掉,设置的是负数 // BigDecimal timeoverDuration = userAttendanceTotalEntity.getTimeoutOvertimeDuration_orig(); // if(timeoverDuration == null) { // timeoverDuration = BigDecimal.ZERO; // } // timeoverDuration = timeoverDuration.subtract(halfNationOvertime); // userAttendanceTotalEntity.setTimeoutOvertimeDuration_orig(timeoverDuration); }else { //如果是全天都在国定时间内,将这一天的实际出勤时间计入国定加班时长 zy 20180416 if ((Globals.dtype_2.equals(oConvertUtils.getString(dto.getDtype())))) { // nationalOvertimeDuration = dto.getDatumDate(); nationalOvertimeDuration = dto.getActualAttendanceDate(); } } dto.setNationalOvertimeDuration(nationalOvertimeDuration); dto.setSpecialOvertime(specialOvertime); } /** * 计算前半夜或者后半夜是国定加班的情况 * @param hm_cache * @param dto */ private BigDecimal calculateHalfNationalOvertime(HashMap> hm_cache, UserAttendanceDetailDto dto, boolean isAccordingActualAttendance) { if (!Globals.DUTYTYPE_yeban115.equals(dto.getDutyType())) { return BigDecimal.ZERO; } if (!oConvertUtils.isNotEmpty(dto.getNormalworkStime())||!oConvertUtils.isNotEmpty(dto.getNormalworkEtime())) { return BigDecimal.ZERO; } /**理应工作开始时间*/ Date workStarttime =getexactDate(dto.getYmdDate(), dto.getNormalworkStime(), 0, 0); Calendar workStartCalendar = Calendar.getInstance(); workStartCalendar.setTime(workStarttime); /**理应工作结束时间*/ Date workendtime = getexactDate(dto.getYmdDate(), dto.getNormalworkEtime(), 1, 0); Calendar workEndCalendar = Calendar.getInstance(); workEndCalendar.setTime(workendtime); List calendarList = new ArrayList<>(); if(hm_cache == null) { String calendarHql = "from CalendarEntity where (year =? and month =? and day = ? ) or (year =? and month =? and day = ?5)"; calendarList = calendarService.findHql(calendarHql, workStartCalendar.get(Calendar.YEAR), workStartCalendar.get(Calendar.MONTH)+1, workStartCalendar.get(Calendar.DATE) ,workEndCalendar.get(Calendar.YEAR), workEndCalendar.get(Calendar.MONTH)+1, workEndCalendar.get(Calendar.DATE)); }else { CalendarEntity calStart = getCalendarListWithCache(hm_cache, workStartCalendar.get(Calendar.YEAR), workStartCalendar.get(Calendar.MONTH)+1, workStartCalendar.get(Calendar.DATE)); CalendarEntity calEnd = getCalendarListWithCache(hm_cache, workEndCalendar.get(Calendar.YEAR), workEndCalendar.get(Calendar.MONTH)+1, workEndCalendar.get(Calendar.DATE)); if(calStart != null) { calendarList.add(calStart); } if(calEnd != null) { calendarList.add(calEnd); } } if(calendarList.size() != 2) { return BigDecimal.ZERO; } if(Globals.dtype_2.equals(calendarList.get(0).getDtype()) && Globals.dtype_2.equals(calendarList.get(1).getDtype())) { return new BigDecimal(11.5*60); //都是国定假 }else if(!Globals.dtype_2.equals(calendarList.get(0).getDtype()) && !Globals.dtype_2.equals(calendarList.get(1).getDtype())) { return BigDecimal.ZERO; } // if("000000006120dd1c01612cf5232001d6".equals(dto.getUserid())) { // System.out.println(); // } Date nationTypeDate = null; if(Globals.dtype_2.equals(calendarList.get(0).getDtype())){ nationTypeDate = calendarList.get(0).getYmdDate(); }else { nationTypeDate = calendarList.get(1).getYmdDate(); } // 前半夜结束时间 Date standardAttendEndDate = new Date(workendtime.getYear(), workendtime.getMonth(), workendtime.getDate()); Calendar standardAttendEndCalendar = Calendar.getInstance(); standardAttendEndCalendar.setTime(standardAttendEndDate); // 后半夜开始时间,有半小时休息。00:30分开始 Calendar standardHalfTwoCalendar = Calendar.getInstance(); standardHalfTwoCalendar.setTime(standardAttendEndDate); standardHalfTwoCalendar.add(Calendar.MINUTE, 30); // 实际打卡开始时间 Date actattendanceDate = workStarttime; // 实际打卡结束时间 Date actretreatDate = workendtime; if(isAccordingActualAttendance) { actattendanceDate = dto.getActattendanceDate(); actretreatDate = dto.getActretreatDate(); if(actattendanceDate == null || actretreatDate == null || actattendanceDate.equals(actretreatDate)) { return BigDecimal.ZERO; } if(actattendanceDate.compareTo(workStarttime) < 0) { actattendanceDate = workStarttime; } if(actretreatDate.compareTo(workendtime) > 0) { actretreatDate = workendtime; } } //差值 int nationalDateDiffint = 0; if(nationTypeDate.compareTo(new Date(workStarttime.getYear(), workStarttime.getMonth(), workStarttime.getDate())) == 0) { // “考勤出勤时间” Calendar actattendanceCalendar = Calendar.getInstance(); actattendanceCalendar.setTime(actattendanceDate); //差值 nationalDateDiffint = DataUtils.dateDiff('m', standardAttendEndCalendar,actattendanceCalendar); }else { // “考勤出勤时间” Calendar actretreatCalendar = Calendar.getInstance(); actretreatCalendar.setTime(actretreatDate); //差值 nationalDateDiffint = DataUtils.dateDiff('m',actretreatCalendar, standardHalfTwoCalendar); } return new BigDecimal(Math.abs(nationalDateDiffint)); } /** * @param hm_cache * @param i * @param j * @param k * @return */ private CalendarEntity getCalendarListWithCache(HashMap> hm_cache, int year, int month, int day) { HashMap hm = hm_cache.get("getCalendarListWithCache"); if(hm == null) { hm = new HashMap<>(); hm_cache.put("getCalendarListWithCache", hm); String calendarHql = "from CalendarEntity where 1=1"; List listDB = calendarService.findHql(calendarHql); for(CalendarEntity entity : listDB) { String userInEntity = entity.getYear()+"_"+entity.getMonth()+"_"+entity.getDay(); hm.put(userInEntity, entity); } } return (CalendarEntity)hm.get(year+"_"+month+"_"+day); } // 计算时间差值 “实际出勤时间”与“基准时间”的差值; 实际出勤时间(每日)【时间小于等于 基准出勤时间】-基准时间(每日)【排班时间的N个小时】 private void calculateActualtimeDifference(UserAttendanceDetailDto dto) { BigDecimal timeDifference = BigDecimal.ZERO; // 加班值班的时候为零 String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_xiuxi.equals(dutyType)||Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { }else { // 基准时间 BigDecimal datumDate = dto.getDatumDate(); BigDecimal actualAttendanceDate =dto.getActualAttendanceDate(); if (datumDate==null) { datumDate = BigDecimal.ZERO; } if (actualAttendanceDate==null) { actualAttendanceDate = BigDecimal.ZERO; } //实际打卡开始时间 Date actattendanceDate = dto.getActattendanceDate(); //实际打卡结束时间 Date actretreatDate = dto.getActretreatDate(); if (oConvertUtils.isNotEmpty(actattendanceDate)&& oConvertUtils.isNotEmpty(actretreatDate)&& actattendanceDate.equals(actretreatDate)) { }else { timeDifference = actualAttendanceDate.subtract(datumDate); } } // 設置时间差值 dto.setTimeDifference(timeDifference); } @Override public void batchUpdate(AttendanceDetailReqestJsonObj reqstjson) throws Exception { String attendanceId = oConvertUtils.getString(reqstjson.getAttendanceId()); UserAttendanceTotalEntity userAttendanceTotalEntity = get(UserAttendanceTotalEntity.class, attendanceId); if (oConvertUtils.isEmpty(attendanceId)) { return; } List attendanceDetailEntities = findByProperty(UserAttendanceDetailEntity.class, "attendanceId", attendanceId); List adjustedEntitiesInDB = findByProperty(UserAttendanceDetailAdjustedEntity.class , "attendanceId", attendanceId); List> userAttendanceDetails = reqstjson.getUserAttendanceDetails(); // List attendanceDetailEntities = new ArrayList<>(); List object2SaveOrUpdate = new ArrayList<>(); if (!ListUtils.isNullOrEmpty(userAttendanceDetails)) { for (Map map : userAttendanceDetails) { String id = oConvertUtils.getString(map.get("id")); String status = oConvertUtils.getString(map.get("status")); String attendanceDate = oConvertUtils.getString(map.get("attendanceDate")); String retreatDate = oConvertUtils.getString(map.get("retreatDate")); String fineTuningType = oConvertUtils.getString(map.get("fineTuningType")); String adjustReason = oConvertUtils.getString(map.get("adjustReason")); String dutyId = oConvertUtils.getString(map.get("dutyId")); Date changeattendanceDate = null; if (oConvertUtils.isNotEmpty(attendanceDate)) { changeattendanceDate = DataUtils.str2Date(attendanceDate, DataUtils.time_sdf); } Date changeretreatDate = null; if (oConvertUtils.isNotEmpty(retreatDate)) { changeretreatDate = DataUtils.str2Date(retreatDate, DataUtils.time_sdf); } UserAttendanceDetailEntity entity = getUserAttendanceDetailEntityInList(attendanceDetailEntities, id); AttendanceDetailJsonObj jsonObj = getJsonObjFromString(oConvertUtils.getString(entity.getJsonObj())); SimpleDateFormat dfYMD = new SimpleDateFormat("yyyy-MM-dd"); String dateString = dfYMD.format(entity.getYmdDate()); String yearMonth = dateString.substring(0, 7); int year = Integer.valueOf(dateString.substring(0, 4)); int month = Integer.valueOf(dateString.substring(5, 7)); int day = Integer.valueOf(dateString.substring(8, 10)); String entityDutyId = entity.getDutyId() == null ? "" : entity.getDutyId(); String newDutyId = dutyId == null ? "" : dutyId; if (!entityDutyId.equals(newDutyId)) { // 排班修改保存 entity.setDutyId(dutyId); // 查询当前员工在当前处理月度的【项目排班详细】 CriteriaQuery cq = new CriteriaQuery(ProjarrangeDetailEntity.class); cq.eq("userid", reqstjson.getUserId()); cq.add(); cq.eq("yearmonth", yearMonth); cq.add(); // 通过上述三个条件的筛选, 原则上而言, 应该是有且只有一条记录 List projarrangeDetailEntities = getListByCriteriaQuery(cq, false); if (!ListUtils.isNullOrEmpty(projarrangeDetailEntities)) { ProjarrangeDetailEntity projarrangeDetailEntity = projarrangeDetailEntities.get(0); String projarrangeDetailId = projarrangeDetailEntity.getId(); // 检索日历表 String calendarHql = "from CalendarEntity where year =? and month =? and day = ? "; List calendarList = calendarService.findHql(calendarHql, year, month, day); // 日历表ID String calendarId = calendarList.get(0).getId(); // 检索员工排班详情表 String userArrangeDetailHql = "from UserArrangeDetailEntity where calendarid =? and projarrangeDetailid =? "; List userArrangeDetailEntityList = findHql(userArrangeDetailHql, calendarId, projarrangeDetailId); if (!ListUtils.isNullOrEmpty(userArrangeDetailEntityList)) { UserArrangeDetailEntity userArrangeDetail = userArrangeDetailEntityList.get(0); // notTransationUpdateUserArrangeDetail(dutyId, userArrangeDetail); userArrangeDetail.setShiftid(dutyId); object2SaveOrUpdate.add(userArrangeDetail); // saveOrUpdate(userArrangeDetail); } } } // 获取数据库中的原始打卡记录 Date dbattendanceDate = entity.getAttendanceDate(); Date dbretreatDate = entity.getRetreatDate(); // 如果没有调整记录 , 则先将打卡记录的原始信息 记录到上述两个字段中 , 用于页面显示 // 如果有调整记录, 则读取的原始打卡记录 应当为jsonObj 里的primevalAttendanceDate 和primevalRetreatDate // 字段 if (0 == oConvertUtils.getInt(jsonObj.getAdjustRecord(), 0)) { jsonObj.setPrimevalAttendanceDate(entity.getAttendanceDate()); jsonObj.setPrimevalRetreatDate(entity.getRetreatDate()); jsonObj.setAdjustRecord(1); } else { // 如果有调整记录, 则读取的原始打卡记录 应当为jsonObj 里的primevalAttendanceDate 和primevalRetreatDate // 字段 dbattendanceDate = jsonObj.getPrimevalAttendanceDate(); dbretreatDate = jsonObj.getPrimevalRetreatDate(); } // 当调整后的时间都不为空的时候 计算微调时间 if (oConvertUtils.isNotEmpty(changeretreatDate) && oConvertUtils.isNotEmpty(changeattendanceDate)) { Calendar startCalendar = Calendar.getInstance(); Calendar endCalendar = Calendar.getInstance(); if (oConvertUtils.isEmpty(dbattendanceDate) && oConvertUtils.isEmpty(dbretreatDate)) { // 原始数据两个都为空 // 直接计算 changeattendanceDate 和 changeretreatDate 的差值 startCalendar.setTime(changeattendanceDate); endCalendar.setTime(changeretreatDate); int dateDiffint = DataUtils.dateDiff('m', startCalendar, endCalendar); entity.setTimeFineTuning(new BigDecimal(Math.abs(dateDiffint))); } else if (oConvertUtils.isEmpty(dbattendanceDate) && oConvertUtils.isNotEmpty(dbretreatDate)) { // 原始数据dbattendanceDate 为空 dbretreatDate 不为空 startCalendar.setTime(changeattendanceDate); endCalendar.setTime(changeretreatDate); int dateDiffint = DataUtils.dateDiff('m', startCalendar, endCalendar); entity.setTimeFineTuning(new BigDecimal(Math.abs(dateDiffint))); } else if (oConvertUtils.isNotEmpty(dbattendanceDate) && oConvertUtils.isEmpty(dbretreatDate)) { // 原始数据dbattendanceDate 不为空 dbretreatDate 为空 startCalendar.setTime(changeattendanceDate); endCalendar.setTime(changeretreatDate); int dateDiffint = DataUtils.dateDiff('m', startCalendar, endCalendar); entity.setTimeFineTuning(new BigDecimal(Math.abs(dateDiffint))); } else { // 两个都不为空 Calendar dbattendanceCalendar = Calendar.getInstance(); dbattendanceCalendar.setTime(dbattendanceDate); Calendar changeattendanceCalendar = Calendar.getInstance(); changeattendanceCalendar.setTime(changeattendanceDate); int attendanceDiffint = DataUtils.dateDiff('m', dbattendanceCalendar, changeattendanceCalendar); dbattendanceCalendar.setTime(dbretreatDate); changeattendanceCalendar.setTime(changeretreatDate); int retreatDiffint = DataUtils.dateDiff('m', changeattendanceCalendar, dbattendanceCalendar); entity.setTimeFineTuning(new BigDecimal(attendanceDiffint + retreatDiffint)); } } else { // 当两次打卡记录都为空的时候,记录调整时间为零。 entity.setTimeFineTuning(BigDecimal.ZERO); } // 将新的两个字段赋值至 出勤时间 和退勤时间 entity.setAttendanceDate(changeattendanceDate); entity.setRetreatDate(changeretreatDate); entity.setStatus(status); entity.setFineTuningType(fineTuningType); entity.setAdjustReason(adjustReason); entity.setJsonObj(JSONObject.toJSONString(jsonObj)); // saveOrUpdate(entity); // attendanceDetailEntities.add(entity); object2SaveOrUpdate.add(entity); } List updateDetailEntities = new ArrayList(); for(Object obj : object2SaveOrUpdate) { if(obj instanceof UserAttendanceDetailEntity) { updateDetailEntities.add((UserAttendanceDetailEntity)obj); } } List detailDtolist = getallUsefulField(userAttendanceTotalEntity, updateDetailEntities, null); for (UserAttendanceDetailDto dto : detailDtolist) { UserAttendanceDetailEntity userAttendanceDetailEntity = getUserAttendanceDetailEntityfromList(dto, attendanceDetailEntities); if (oConvertUtils.isEmpty(userAttendanceDetailEntity)) { continue; } // 設置时间差值 if (null == dto.getTimeDifference()) { userAttendanceDetailEntity.setTimeDifference(BigDecimal.ZERO); } else { userAttendanceDetailEntity.setTimeDifference(dto.getTimeDifference()); } if (null == dto.getDatumDate()) { userAttendanceDetailEntity.setDatumDate(BigDecimal.ZERO); } else { userAttendanceDetailEntity.setDatumDate(dto.getDatumDate()); } // 设置 国定加班时长 userAttendanceDetailEntity.setNationalOvertimeDuration(dto.getNationalOvertimeDuration()); // 设置 特殊加班时长 userAttendanceDetailEntity.setSpecialOvertime(dto.getSpecialOvertime()); // 设置实际出勤时间 if (null == dto.getActualAttendanceDate()) { userAttendanceDetailEntity.setAttendanceMins(BigDecimal.ZERO); userAttendanceDetailEntity.setActualAttendanceDate(BigDecimal.ZERO); } else { userAttendanceDetailEntity.setAttendanceMins(dto.getActualAttendanceDate()); userAttendanceDetailEntity.setActualAttendanceDate(dto.getActualAttendanceDate()); } // 设置超时加班 zy20180413 userAttendanceDetailEntity.setTimeoutOvertimeDuration(dto.getTimeoutOvertimeDuration()); AttendanceDetailJsonObj jsonObj = getJsonObjFromString(oConvertUtils.getString(userAttendanceDetailEntity.getJsonObj())); AttendanceDetailJsonObj dtojsonobj = getjsonObjfromDto(dto); dtojsonobj.setPrimevalAttendanceDate(jsonObj.getPrimevalAttendanceDate()); dtojsonobj.setPrimevalRetreatDate(jsonObj.getPrimevalRetreatDate()); dtojsonobj.setAdjustRecord(jsonObj.getAdjustRecord()); // 微调过程中 不修改漏打卡数据 dtojsonobj.setNoPunchCard(jsonObj.getNoPunchCard()); userAttendanceDetailEntity.setJsonObj(JSONObject.toJSONString(dtojsonobj)); //saveOrUpdate(userAttendanceDetailEntity); // object2SaveOrUpdate.add(userAttendanceDetailEntity); saveOrUpdateAdjustEntity(object2SaveOrUpdate, adjustedEntitiesInDB, userAttendanceDetailEntity, userAttendanceTotalEntity); } userAttendanceTotalEntity.setAdjustRecord("1"); } // 重新更新下 考勤合计信息 UserAttendanceTotalEntity total = getUpdateMonthlyInfo(userAttendanceTotalEntity, attendanceDetailEntities); if(object2SaveOrUpdate != null) { for(Object obj : object2SaveOrUpdate) { saveOrUpdate(obj); } saveOrUpdate(total); } } /** * @param detailEntities * @param id * @return */ private UserAttendanceDetailEntity getUserAttendanceDetailEntityInList(List detailEntities, String id) { if(detailEntities != null && id != null) { for(UserAttendanceDetailEntity e : detailEntities) { if(id.equals(e.getId())) { return e; } } } return null; } // @Transactional(propagation=Propagation.NEVER) // private void notTransationUpdateUserArrangeDetail(String dutyId, UserArrangeDetailEntity userArrangeDetail) { // // 变更dutyid 班次id // userArrangeDetail.setShiftid(dutyId); // saveOrUpdate(userArrangeDetail); // } /** * 保存考勤调整记录 * @param object2SaveOrUpdate * @param entity * @param userAttendanceTotalEntity */ private void saveOrUpdateAdjustEntity(List object2SaveOrUpdate, List adjustedEntitiesInDB, UserAttendanceDetailEntity entity, UserAttendanceTotalEntity userAttendanceTotalEntity) { String detailId = entity.getId(); if(detailId == null) { return; } UserAttendanceDetailAdjustedEntity adjustedEntity = null; if(adjustedEntitiesInDB != null && adjustedEntitiesInDB.size()>0) { for(UserAttendanceDetailAdjustedEntity adjust : adjustedEntitiesInDB) { if(detailId.equals(adjust.getAttendanceDetailId())) { adjustedEntity = adjust; break; } } } if(adjustedEntity == null) { adjustedEntity = new UserAttendanceDetailAdjustedEntity(); } adjustedEntity.setAttendanceDate(entity.getAttendanceDate()); adjustedEntity.setRetreatDate(entity.getRetreatDate()); adjustedEntity.setStatus(entity.getStatus()); adjustedEntity.setFineTuningType(entity.getFineTuningType()); adjustedEntity.setTimeFineTuning(entity.getTimeFineTuning()); adjustedEntity.setAdjustReason(entity.getAdjustReason()); adjustedEntity.setJsonObj(entity.getJsonObj()); adjustedEntity.setUserId(userAttendanceTotalEntity.getUserId()); adjustedEntity.setAttendanceDetailId(detailId); adjustedEntity.setAttendanceId(userAttendanceTotalEntity.getId()); adjustedEntity.setTimeDifference(entity.getTimeDifference()); //设置 国定加班时长 adjustedEntity.setNationalOvertimeDuration(entity.getNationalOvertimeDuration()); //设置 特殊加班时长 adjustedEntity.setSpecialOvertime(entity.getSpecialOvertime()); adjustedEntity.setAttendanceMins(entity.getActualAttendanceDate()); adjustedEntity.setActualAttendanceDate(entity.getActualAttendanceDate()); adjustedEntity.setTimeoutOvertimeDuration(entity.getTimeoutOvertimeDuration()); adjustedEntity.setYmdDate(entity.getYmdDate()); // saveOrUpdate(adjustedEntity); object2SaveOrUpdate.add(adjustedEntity); } private Date calculateNormalStime(UserAttendanceDetailDto dto) { // 获取正常上班时间 String normalworkStime = oConvertUtils.getString(dto .getNormalworkStime()); Date normalworkStartdate = dto.getYmdDate(); if (oConvertUtils.isEmpty(normalworkStime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { normalworkStime = "00:00"; } else { return null; } } if (oConvertUtils.isNotEmpty(normalworkStime)) { normalworkStartdate = getexactDate(dto.getYmdDate(), normalworkStime, 0, 0 ); } // ----------值班情况处理 ---20180308---yangxi---add---start---------- if(Globals.DUTYTYPE_zhiban.equals(dto.getDutyType())) { normalworkStartdate = getexactDate(dto.getYmdDate(), dto.getOndutyStime(), 0, 0); } // ----------值班情况处理 ---20180308---yangxi---add---end---------- return normalworkStartdate; } private Date calculateNormalEtime(UserAttendanceDetailDto dto) { Date normalEnddate = dto.getYmdDate(); // 获取正常上班时间 String normalworkStime = oConvertUtils.getString(dto .getNormalworkStime()); if (oConvertUtils.isEmpty(normalworkStime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { normalworkStime = "00:00"; } } // 获取正常下班时间 String normalworkEtime = oConvertUtils.getString(dto .getNormalworkEtime()); if (oConvertUtils.isEmpty(normalworkEtime)) { String dutyType = oConvertUtils.getString(dto.getDutyType()); if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) { normalworkEtime = "23:59"; }else{ // 当他休息的时候 //计算加班的时候的实际出勤时间 return null; } } Integer t1flag = 0; if (oConvertUtils.isNotEmpty(normalworkEtime) && oConvertUtils.isNotEmpty(normalworkStime)) { t1flag = normalworkEtime.compareTo(normalworkStime) < 0 ? 1 : 0; if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) { t1flag = 1; } normalEnddate = getexactDate(dto.getYmdDate(), normalworkEtime, t1flag, 0 ); } // 值班开始时间 String ondutyStime = oConvertUtils.getString(dto.getOndutyStime()); if (oConvertUtils.isNotEmpty(ondutyStime)) { // 获取值班 的开始时间 Date ondutyStarttime = getexactDate(dto.getYmdDate(), ondutyStime, t1flag,0); dto.setOndutyStarttime(ondutyStarttime); } //值班结束时间 String mondutyEtime = oConvertUtils.getString(dto.getOndutyEtime()); if (oConvertUtils.isNotEmpty(mondutyEtime)) { // 获取值班 的结束时间 if (mondutyEtime.compareTo(ondutyStime)<0) { Date ondutyEndtime = getexactDate(dto.getYmdDate(), mondutyEtime, t1flag+1,0); dto.setOndutyEndtime(ondutyEndtime); }else { Date ondutyEndtime = getexactDate(dto.getYmdDate(), mondutyEtime, t1flag,0); dto.setOndutyEndtime(ondutyEndtime); } } // 加班开始时间 String timeOutOvertimeStime = oConvertUtils.getString(dto .getTimeOutOvertimeStime()); Date overtimeStartdate = null; if (oConvertUtils.isNotEmpty(timeOutOvertimeStime)) { // 加班开始时间date overtimeStartdate = getexactDate(dto.getYmdDate(), timeOutOvertimeStime, t1flag,0); } // 加班结束时间 String timeOutOvertimeEtime = oConvertUtils.getString(dto .getTimeOutOvertimeEtime()); Date overtimeEnddate = null; if (oConvertUtils.isNotEmpty(timeOutOvertimeEtime)) { // 加班结束时间date if (timeOutOvertimeEtime.compareTo(timeOutOvertimeStime)<0) { overtimeEnddate = getexactDate(dto.getYmdDate(), timeOutOvertimeEtime, t1flag+1,0); }else { overtimeEnddate = getexactDate(dto.getYmdDate(), timeOutOvertimeEtime, t1flag,0); } } // 最早加班/值班开始时间 Date jiabanstartDate = null; Date jiabanendDate = null; //如果值班时间不为空 则将此值置为值班时间 if (oConvertUtils.isNotEmpty(dto.getOndutyStarttime())) { jiabanstartDate = dto.getOndutyStarttime(); jiabanendDate = dto.getOndutyEndtime(); } //如果加班时间不为空 则将此值置为加班时间 if (oConvertUtils.isNotEmpty(overtimeStartdate)) { jiabanstartDate = overtimeStartdate; jiabanendDate = overtimeEnddate; } if (oConvertUtils.isNotEmpty(dto.getOndutyStarttime())&&oConvertUtils.isNotEmpty(overtimeStartdate)) { jiabanstartDate = (dto.getOndutyStarttime().after(overtimeStartdate))?overtimeStartdate:dto.getOndutyStarttime(); jiabanendDate = (dto.getOndutyStarttime().after(overtimeStartdate))?overtimeEnddate:dto.getOndutyEndtime(); } if (oConvertUtils.isNotEmpty(jiabanstartDate) &&(oConvertUtils.isNotEmpty(jiabanendDate)) && (jiabanstartDate.compareTo(normalEnddate) <= 0)) { normalEnddate = jiabanendDate; dto.setJiabanContinuous(true); } else { dto.setJiabanContinuous(false); } // ----------值班情况处理 ---20180308---yangxi---add---start---------- if(Globals.DUTYTYPE_zhiban.equals(dto.getDutyType())) { normalEnddate = dto.getOndutyEndtime(); } // ----------值班情况处理 ---20180308---yangxi---add---end---------- Calendar calendar = Calendar.getInstance(); calendar.setTime(normalEnddate); calendar.add(Calendar.SECOND, 59); return calendar.getTime(); } }