package com.engine.kq.job; import com.alibaba.fastjson.JSON; import com.engine.kq.biz.KQShiftOnOffWorkSectionComInfo; import com.engine.kq.biz.KQShiftRestTimeSectionComInfo; import com.engine.kq.biz.KQWorkTime; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import weaver.common.DateUtil; import weaver.conn.RecordSet; import weaver.general.TimeUtil; import weaver.general.Util; import weaver.interfaces.schedule.BaseCronJob; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; /** * @Title * @Author wangchaofa * @CreateDate 2024/1/7 * @Version 1.0 * @Description */ public class SynClockInTimeJob extends BaseCronJob { /** * 日期时间格式化 */ private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); @Override public void execute() { RecordSet rs = new RecordSet(); rs.writeLog("----------- start to syn overtime work card time ------------"); String currentdate = TimeUtil.getCurrentDateString(); String currenttime = TimeUtil.getOnlyCurrentTimeString(); String currentdatetime = currentdate+" "+currenttime; String lastdate = addDateDay(currentdate,-50); String lastdatetime = lastdate+" "+currenttime; try{ RecordSet rs1 = new RecordSet(); rs.executeQuery("select * from uf_jbtz where ksrq>=? and jsrq<=?",lastdate,currentdate); while(rs.next()){ String mainid = Util.null2String(rs.getString("id")); String userid = Util.null2String(rs.getString("jbr")); String ksrq = Util.null2String(rs.getString("ksrq")); String kssj = Util.null2String(rs.getString("kssj")); String jsrq = Util.null2String(rs.getString("jsrq")); String jssj = Util.null2String(rs.getString("jssj")); String starttime = ksrq+" "+kssj+":00"; String endtime = jsrq+" "+jssj+":00"; String beforetwohours_starttime = addDateHour(starttime,-2); String aftertwohours_endtime = addDateHour(endtime,2); String earlystarttime = getEarlyStartTime(beforetwohours_starttime,starttime,ksrq,userid); String afterendtime = getAfterEndTime(endtime,aftertwohours_endtime,jsrq,userid); boolean bool = rs1.executeUpdate("update uf_jbtz set zzdksj=?,zwdkrq=? where id=?",earlystarttime,afterendtime,mainid); if(bool){ rs.writeLog(userid+ " ------------ "+ kssj +" ------------ "+ jsrq +" ---------- "+ bool); // 计算有效时长 rs.writeLog("计算有效时长开始"); String gzrq = Util.null2String(rs.getString("gzrq")); updateEffectiveDuration(mainid, userid, gzrq, earlystarttime, afterendtime); rs.writeLog("计算有效时长结束"); } } }catch(Exception e){ e.printStackTrace(); rs.writeLog("---------- syn overtime work card time error ---------- "+ e); } rs.writeLog("---------- end to syn overtime work card time ----------"); } /** * 更新加班台账表,有效时长字段 *

*

导入的加班数据增加根据班次的最早最晚打卡时间取交集,按照系统的加班单和打卡数据取交集处理

* * @param mainId 当前数据ID * @param userId 加班人ID * @param gzrq 归属日志 * @param earlyStartTime 最早打卡时间 * @param afterEndTime 最晚打卡时间 */ private void updateEffectiveDuration(String mainId, String userId, String gzrq, String earlyStartTime, String afterEndTime) { RecordSet recordSet = new RecordSet(); try { KQWorkTime kqWorkTime = new KQWorkTime(); Map serialInfo = kqWorkTime.getSerialInfo(userId, gzrq, false, true); recordSet.writeLog("userId==" + userId + ",serialInfo===" + JSON.toJSONString(serialInfo)); String serialId = Util.null2String(serialInfo.get(gzrq)); List workSectionTimes = new KQShiftOnOffWorkSectionComInfo().getWorkSectionTimes(serialId); recordSet.writeLog("userId==" + userId + ",workSectionTimes===" + JSON.toJSONString(workSectionTimes)); // 转换所有的工作时间 List> workTimeList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(workSectionTimes)) { convertDateTime(gzrq, workSectionTimes, workTimeList); recordSet.writeLog("userId==" + userId + ",workTimeList===" + JSON.toJSONString(workTimeList)); } // 转换所有的休息时间 List restSectionTimes = new KQShiftRestTimeSectionComInfo().getRestSectionTimes(serialId); recordSet.writeLog("userId==" + userId + ",restSectionTimes===" + JSON.toJSONString(restSectionTimes)); List> restTimeList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(restSectionTimes)) { convertDateTime(gzrq, restSectionTimes, restTimeList); recordSet.writeLog("userId==" + userId + ",restTimeList===" + JSON.toJSONString(restTimeList)); } // 所有的有效时间区间 List effectiveTime = getEffectiveTime(earlyStartTime, afterEndTime, workTimeList, restTimeList); recordSet.writeLog("userId==" + userId + ",effectiveTime===" + JSON.toJSONString(effectiveTime)); // 有效区间总计分钟数 long totalMinutes = effectiveTime.stream() .mapToInt(interval -> { String[] parts = interval.split(","); LocalDateTime start = LocalDateTime.parse(parts[0], DATE_TIME_FORMATTER); LocalDateTime end = LocalDateTime.parse(parts[1], DATE_TIME_FORMATTER); return (int) (start.until(end, ChronoUnit.MINUTES)); }) .sum(); double totalHours = (double) totalMinutes / 60; // 将小时数按照0.5小时的单位向下取整 double roundedHours = (int) Math.floor(totalHours / 0.5) * 0.5; recordSet.writeLog("userId==" + userId + ",totalMinutes===" + totalMinutes + ",totalHours==" + totalHours + ",roundedHours==" + roundedHours); // 更新当前数据的有效时长 recordSet.executeUpdate("update uf_jbtz set yxsc=? where id=? ", roundedHours, mainId); } catch (Exception e) { recordSet.writeLog(e); } } /** * 获取有效时长时间区间 * * @param earlyStartTime 最早打卡时间 * @param afterEndTime 最晚打卡时间 * @param workTimeList 工作时间集合 * @param restTimeList 休息时间集合 * @return */ private List getEffectiveTime(String earlyStartTime, String afterEndTime, List> workTimeList, List> restTimeList) { // 打卡时间区间,去除所有的休息时间 List effectiveTimeList = new ArrayList<>(); LocalDateTime startSignTime = LocalDateTime.parse(earlyStartTime, DATE_TIME_FORMATTER); LocalDateTime endSignTime = LocalDateTime.parse(afterEndTime, DATE_TIME_FORMATTER); for (Map workTimeMap : workTimeList) { LocalDateTime startWorkTime = LocalDateTime.parse(workTimeMap.get("startTimes"), DATE_TIME_FORMATTER); LocalDateTime endWorkTime = LocalDateTime.parse(workTimeMap.get("endTimes"), DATE_TIME_FORMATTER); // 计算交集 LocalDateTime intersectionStart = startSignTime.isAfter(startWorkTime) ? startSignTime : startWorkTime; LocalDateTime intersectionEnd = endSignTime.isBefore(endWorkTime) ? endSignTime : endWorkTime; if (intersectionStart.isBefore(intersectionEnd)) { // 去除休息时间 for (Map restTimeMap : restTimeList) { LocalDateTime startRestTime = LocalDateTime.parse(restTimeMap.get("startTimes"), DATE_TIME_FORMATTER); LocalDateTime endRestTime = LocalDateTime.parse(restTimeMap.get("endTimes"), DATE_TIME_FORMATTER); if (!intersectionEnd.isBefore(startRestTime) && !intersectionStart.isAfter(endRestTime)) { if (intersectionStart.isBefore(startRestTime)) { // 交集在休息时间之前 intersectionEnd = intersectionEnd.isBefore(startRestTime) ? intersectionEnd : startRestTime; } else if (intersectionEnd.isAfter(endRestTime)) { // 交集在休息时间之后 intersectionStart = intersectionStart.isAfter(endRestTime) ? intersectionStart : endRestTime; } else { // 休息时间在交集中间 intersectionStart = startRestTime; intersectionEnd = endRestTime; } } } effectiveTimeList.add(intersectionStart.format(DATE_TIME_FORMATTER) + "," + intersectionEnd.format(DATE_TIME_FORMATTER)); } } return effectiveTimeList; } /** * 转换日期时间 * * @param gzrq 归属日期 * @param sectionTimes 转换前时间 * @param timeList 转换后日期时间 */ private void convertDateTime(String gzrq, List sectionTimes, List> timeList) { String currentDate = gzrq; String preTime = ""; for (Object sectionTime : sectionTimes) { List> sectionTime1 = (List) sectionTime; if (sectionTime1.size() != 2) { break; } // 获取当前的打卡时间 Map startMap = sectionTime1.get(0); String startTimes = startMap.get("times"); Map map = new HashMap<>(); currentDate = getDateStr(currentDate, preTime, startTimes); map.put("startTimes", currentDate + " " + startTimes); Map endMap = sectionTime1.get(1); String endTimes = endMap.get("times"); currentDate = getDateStr(currentDate, startTimes, endTimes); map.put("endTimes", currentDate + " " + endTimes); preTime = endTimes; timeList.add(map); } } /** * 组合日期、时间 * * @param currentDate 当前日期 * @param preTime 之前处理的时间 * @param currentTime 当前需要处理的时间 * @return */ private String getDateStr(String currentDate, String preTime, String currentTime) { // 前一个时间为空,返回当前日期+当前时间 if (StringUtils.isBlank(preTime)) { return currentDate; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); LocalTime localPreTime = LocalTime.parse(preTime, formatter); LocalTime localCurrentTime = LocalTime.parse(currentTime, formatter); if (localPreTime.isAfter(localCurrentTime)) { return DateUtil.addDate(currentDate, 1); } else { return currentDate; } } /** * 获取 最早开始日期时间 * @param beforetwohours_starttime * @param starttime * @param ksrq * @param userid * @return */ public static String getEarlyStartTime(String beforetwohours_starttime,String starttime,String ksrq,String userid){ String result = ""; RecordSet rs = new RecordSet(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); List list = new ArrayList<>(); try { rs.executeQuery("select a.*,b.subcompanyId1,b.departmentId,b.jobtitle,b.workcode " + " from HrmScheduleSign a,HrmResource b " + " where a.userId=b.id and (signfrom is null or signfrom='' or signfrom not like 'card%') " + " and (signDate is not null and signDate>='"+ ksrq +"') " + " and (signDate is not null and signDate<='"+ ksrq +"') " + " and (loginId is not null and loginId<>'') " + " and signType=1 "+ " and (b.status = 0 or b.status = 1 or b.status = 2 or b.status = 3)" + " and userId in ("+ userid +")" + " order by signDate,signTime"); while (rs.next()) { String signDate = Util.null2String(rs.getString("signDate")); String signTime = Util.null2String(rs.getString("signTime")); String signdatetime = signDate + " " + signTime; boolean bool = belongCalendar(signdatetime, beforetwohours_starttime, starttime); if (bool) { list.add(format.parse(signdatetime)); } } if(list.size()>0){ if(list.size()>1){ result = format.format(Collections.min(list)); }else{ result = format.format(list.get(0)); } } }catch (Exception e){ e.printStackTrace(); } return result; } /** * 获取 最晚结束日期时间 * @param endtime * @param aftertwohours_endtime * @param jsrq * @param userid * @return */ public static String getAfterEndTime(String endtime,String aftertwohours_endtime,String jsrq,String userid){ String result = ""; RecordSet rs = new RecordSet(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); List list = new ArrayList<>(); try { rs.executeQuery("select a.*,b.subcompanyId1,b.departmentId,b.jobtitle,b.workcode " + " from HrmScheduleSign a,HrmResource b " + " where a.userId=b.id and (signfrom is null or signfrom='' or signfrom not like 'card%') " + " and (signDate is not null and signDate>='"+ jsrq +"') " + " and (signDate is not null and signDate<='"+ jsrq +"') " + " and (loginId is not null and loginId<>'') " + " and signType=1 "+ " and (b.status = 0 or b.status = 1 or b.status = 2 or b.status = 3)" + " and userId in ("+ userid +")" + " order by signDate,signTime"); while (rs.next()) { String signDate = Util.null2String(rs.getString("signDate")); String signTime = Util.null2String(rs.getString("signTime")); String signdatetime = signDate + " " + signTime; boolean bool = belongCalendar(signdatetime, endtime, aftertwohours_endtime); if (bool) { list.add(format.parse(signdatetime)); } } if(list.size()>0){ if(list.size()>1){ result = format.format(Collections.max(list)); }else{ result = format.format(list.get(0)); } } }catch (Exception e){ e.printStackTrace(); } return result; } /** * 判断一个时间是否在一个时间段内 * * @param nowString 当前时间 * @param beginString 开始时间 * @param endString 结束时间 */ public static boolean belongCalendar(String nowString, String beginString, String endString) { boolean b = false; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date nowTime = format.parse(nowString); Calendar date = Calendar.getInstance(); date.setTime(nowTime); Date beginTime = format.parse(beginString); Calendar begin = Calendar.getInstance(); begin.setTime(beginTime); Date endTime = format.parse(endString); Calendar end = Calendar.getInstance(); end.setTime(endTime); if (date.after(begin) && date.before(end)) {//在时间段内 b = true; } }catch (Exception e){ e.printStackTrace(); } return b; } /** * 对时间的天数进行加减 * @param daytime 时间的格式:yyyy-MM-dd * @param day 天数 -1则代表减一天 * @return */ public static String addDateDay(String daytime, int day){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = format.parse(daytime); if (date == null){ return ""; } Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.add(Calendar.DAY_OF_MONTH, day);// 加一天 date = cal.getTime(); cal = null; return format.format(date); } catch (Exception ex) { ex.printStackTrace(); } return ""; } /** * 给时间加上几个小时 * @param day 时间的格式:yyyy-MM-dd HH:mm:ss * @param hour 需要加的小时数 -1 则代表减1小时 * @return */ public static String addDateHour(String day, int hour){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = null; try { date = format.parse(day); if (date == null){ return ""; } Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.add(Calendar.HOUR, hour);// 24小时制 date = cal.getTime(); cal = null; return format.format(date); } catch (Exception ex) { ex.printStackTrace(); } return ""; } }