package com.persagy.calendar.handle; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Lists; import com.persagy.calendar.constant.WorkCalendarConstant; import com.persagy.calendar.pojo.dto.WorkCalendar; import com.persagy.calendar.pojo.dto.WorkCalendarDate; import com.persagy.calendar.pojo.dto.WorkCalendarRule; import com.persagy.calendar.pojo.vo.CalendarDateResult; import com.persagy.calendar.pojo.vo.CustomCalendarVO; import com.persagy.calendar.pojo.vo.WorkCalendarDateCreateVO; import com.persagy.calendar.pojo.vo.WorkCalendarDateQueryVO; import com.persagy.calendar.pojo.vo.WorkCalendarDateUpdateVO; import com.persagy.calendar.pojo.vo.WorkCalendarMoreDateCreateVO; import com.persagy.calendar.service.IWorkCalendarDateService; import com.persagy.calendar.service.IWorkCalendarDictService; import com.persagy.calendar.service.IWorkCalendarRuleService; import com.persagy.calendar.service.IWorkCalendarService; import com.persagy.common.enums.ResponseCode; import com.persagy.common.exception.BusinessException; import com.persagy.common.utils.DateUtil; import com.persagy.common.utils.IdGenerator; import com.persagy.common.utils.StringUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUnit; import lombok.extern.slf4j.Slf4j; /** * @version * @description * @company persagy * @author zhangqiankun * @since 2020年10月3日: 下午1:03:19 */ @Slf4j @Component public class WorkCalendarDateHandler { @Autowired private IWorkCalendarService workCalendarService; @Autowired private IWorkCalendarRuleService workCalendarRuleService; @Autowired private IWorkCalendarDateService workCalendarDateService; @Autowired private IWorkCalendarDictService workCalendarDictService; /** * 创建工作历作息时间信息,先删除在创建 * * @param workCalendarDates * @param workDateStart 不能为空 * @param workDateEnd 不能为空 * @return */ @Transactional public boolean createCalendarDateByDelete(List workCalendarDates, String workDateStart, String workDateEnd) { // 1.防止重复执行,优先删除从今日开始的非自定义的作息时间信息 QueryWrapper queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper() .customFlagEq(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_NO) .workDateGe(workDateStart).workDateLe(workDateEnd).builderQueryWrapper(); this.workCalendarDateService.remove(queryWrapper); // 2.信息插入 boolean result = this.workCalendarDateService.batchCreateCalendarDate(workCalendarDates); return result; } /** * 实时查询作息时间信息,包括自定义的,当日的作息时间,走规则解析 * * @param queryVO * @return */ public List queryWorkCalendarDateList(WorkCalendarDateQueryVO queryVO) { // 优先进行时间调整解析,所有的时间都必须是 YYYYMMDD 格式 String dateStartStr = queryVO.getWorkDateStart(); String dateEndStr = queryVO.getWorkDateEnd(); // 中间时间 String now = DateUtil.format(new Date(), DateUtil.FORMAT_DATE_YYYYMMDD); DateTime dateStart = DateUtil.parse(dateStartStr, DateUtil.FORMAT_DATE_YYYYMMDD); DateTime dateEnd = DateUtil.parse(dateEndStr, DateUtil.FORMAT_DATE_YYYYMMDD); Map parseWorkDate = this.parseWorkDate(dateStart, dateEnd, now); DateTime historyStart = parseWorkDate.get("historyStart"); DateTime historyEnd = parseWorkDate.get("historyEnd"); DateTime parseRuleStart = parseWorkDate.get("parseRuleStart"); DateTime parseRuleEnd = parseWorkDate.get("parseRuleEnd"); // 判断字典类型,TODO 这里该不该判断??后续再做修改 int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(null, queryVO.getDictType()); // 1.取历史作息时间记录 Map> calendarDateMap = new HashMap>(); if (historyStart != null && historyEnd != null) { queryVO.setWorkDateStart(DateUtil.format(historyStart, DateUtil.FORMAT_DATE_YYYYMMDD)); queryVO.setWorkDateEnd(DateUtil.format(historyEnd, DateUtil.FORMAT_DATE_YYYYMMDD)); List historyDateList = this.selectWorkCalendarDateList(queryVO, null, dictTypeLevel); if (CollectionUtil.isNotEmpty(historyDateList)) { for (WorkCalendarDate historyDate : historyDateList) { if (calendarDateMap.containsKey(historyDate.getWorkDate())) { calendarDateMap.get(historyDate.getWorkDate()).add(historyDate); } else { calendarDateMap.put(historyDate.getWorkDate(), Lists.newArrayList(historyDate)); } } } } // 2.取当日往后的自定义作息时间 List customDateList = null; if (parseRuleStart != null && parseRuleEnd != null) { queryVO.setWorkDateStart(DateUtil.format(parseRuleStart, DateUtil.FORMAT_DATE_YYYYMMDD)); queryVO.setWorkDateEnd(DateUtil.format(parseRuleEnd, DateUtil.FORMAT_DATE_YYYYMMDD)); customDateList = this.selectWorkCalendarDateList(queryVO, WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES, dictTypeLevel); } // 3.获取当日往后的规则信息中的作息时间 if (parseRuleStart != null && parseRuleEnd != null) { List ruleList = this.selectWorkCalendarRuleList(queryVO, dictTypeLevel); long betweenDay = DateUtil.between(parseRuleStart, parseRuleEnd, DateUnit.DAY) + 1; this.paserWorkCalendarRule(calendarDateMap, ruleList, parseRuleStart, betweenDay); } // 获取start~end之间的天数,+1 包括首尾 dateStart = DateUtil.parse(dateStartStr, DateUtil.FORMAT_DATE_YYYYMMDD); long betweenDay = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1; // 4.结果加工处理返回 return this.setResultList(calendarDateMap, customDateList, dateStart, betweenDay); } /** * 响应数据,最后处理加工,自定义的将会覆盖掉非自定义的 * * @param calendarDateMap 包含历史与实时规则中的作息时间集合 * @param customDateList * @param dateStart * @param betweenDay * @return */ private List setResultList(Map> calendarDateMap, List customDateList, DateTime dateStart, long betweenDay) { // 结果集 List resultList = new ArrayList(); // 自定义作息时间 当日~end时间内的 Map> customDateMap = new HashMap>(); if (CollectionUtil.isNotEmpty(customDateList)) { for (WorkCalendarDate customDate : customDateList) { if (customDateMap.containsKey(customDate.getWorkDate())) { customDateMap.get(customDate.getWorkDate()).add(customDate); } else { customDateMap.put(customDate.getWorkDate(), Lists.newArrayList(customDate)); } } } String workDate = null; for (int i = 0; i < betweenDay; i++) { workDate = dateStart.toString(DateUtil.FORMAT_DATE_YYYYMMDD); List historyOrRuleDates = calendarDateMap.get(workDate); List customDates = customDateMap.get(workDate); CalendarDateResult result = new CalendarDateResult(); int dayOfWeek = DateUtil.dayOfWeek(dateStart); if (dayOfWeek == 1 || dayOfWeek == 7) { result.setWorkday(false); } result.setWorkDate(workDate); // 判断是否需要覆盖掉非自定义的作息时间信息 if (CollectionUtil.isNotEmpty(customDates)) { historyOrRuleDates = this.coverCalendarDate(historyOrRuleDates, customDates, true); } result.setDate(DateUtil.dayOfMonth(dateStart)); result.setWeek(WorkCalendarConstant.DAY_OF_WEEK.get(dayOfWeek)); if (CollectionUtil.isNotEmpty(historyOrRuleDates)) { for (int j = historyOrRuleDates.size() - 1; j >= 0; j--) { WorkCalendarDate calendarDate = historyOrRuleDates.get(j); // 是工作日,剔除非工作日的数据,目前仅有OpenTime-1,工作日,OpenTime-2,休息日 if (result.isWorkday() && "OpenTime-2".equals(calendarDate.getDictCode())) { historyOrRuleDates.remove(j); } else if (!result.isWorkday() && "OpenTime-1".equals(calendarDate.getDictCode())) { historyOrRuleDates.remove(j); } } } result.setTimeTable(CollectionUtil.isEmpty(historyOrRuleDates) ? Lists.newArrayList() : historyOrRuleDates); resultList.add(result); dateStart.offset(DateField.DAY_OF_YEAR, 1); // 下一天 } customDateMap.clear(); //释放 calendarDateMap.clear(); return resultList; } /** * 自定义与规则的进行判断,存在的自定义的将不再进行插入 * * @param queryVO * @param customDateList * @param calendarDateMap * @return */ public List handleParseCalendarRule(WorkCalendarDateQueryVO queryVO, List customDateList, Map> calendarDateMap) { List resultList = new ArrayList(); Set keySet = calendarDateMap.keySet(); if (CollectionUtil.isEmpty(customDateList)) { for (String key : keySet) { resultList.addAll(calendarDateMap.get(key)); } } else { for (String key : keySet) { List ruleDates = calendarDateMap.get(key); ruleDates = this.coverCalendarDate(ruleDates, customDateList, false); resultList.addAll(ruleDates); } } resultList.forEach(calendarDate -> calendarDate.setId(IdGenerator.getSnowIdStr(WorkCalendarConstant.WORK_CALENDAR_DATE_ID_PREFIX))); return resultList; } /** * 是否需要覆盖掉非自定义的作息时间,自定义覆盖掉规则的 * * @param ruleDates 允许为空 * @param customDates 不能为空 * @param isCover true-自定义的覆盖非自定义的,false-当天存在自定义的信息时,非自定义的丢弃 * @return 不会返回null */ private List coverCalendarDate(List ruleDates, List customDates, boolean isCover) { if (CollectionUtil.isEmpty(ruleDates)) { return customDates; } // 开始验证 List result = new ArrayList(); Map dictTypeLevelMap = new HashMap(); for (int i = ruleDates.size() - 1; i >= 0; i--) { WorkCalendarDate ruleDate = ruleDates.get(i); // 判断当前字典类型级别 Integer dictTypeLevel = dictTypeLevelMap.get(ruleDate.getDictType()); if (dictTypeLevel == null) { dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(ruleDate.getGroupCode(), ruleDate.getDictType()); dictTypeLevelMap.put(ruleDate.getDictType(), dictTypeLevel); } // 项目ID和工作历ID转换 if (dictTypeLevel == 0) { ruleDate.setProjectId("0"); ruleDate.setCalendarId("0"); } else if (dictTypeLevel == 1) { ruleDate.setCalendarId("0"); } boolean isCustom = false; for (WorkCalendarDate customDate : customDates) { // 项目ID和工作历ID转换 if (dictTypeLevel == 0) { customDate.setProjectId("0"); customDate.setCalendarId("0"); } else if (dictTypeLevel == 1) { customDate.setCalendarId("0"); } // 相等,证明非自定义的需要被覆盖 if (customDate.equals(ruleDate)) { isCustom = true; if (isCover) { // 是否需要将自定义的加入到结果集中 result.add(customDate); } else { // 移除这一作息时间 ruleDates.remove(i); } break; } } // 如果没有找到自定义的,加入到结果集 if (!isCustom) { result.add(ruleDate); } } return result; } /** * 解析此段时间的规则 * * @param ruleList 规则信息 * @param dateStart 开始时间 * @param betweenDay 时间范围 * @return 这里返回的结果,一定要在后续判断当日是否存在自定义的作息时间,才能继续使用,此处不会返回null */ public void paserWorkCalendarRule(Map> calendarDateMap, List ruleList, DateTime dateStart, long betweenDay) { Map calendarMap = new HashMap(); for(int i = 0; i < betweenDay; i++) { // 判断此天有没有对应的规则信息,每次都要循环全部,生成多条信息 for (WorkCalendarRule rule : ruleList) { // 验证对应的工作历类型是否存,假若为工作历级别的规则配置 WorkCalendar calendar = null; if (!"0".equals(rule.getCalendarId())) { calendar = this.workCalendarService.getById(rule.getCalendarId(), rule.getGroupCode(), rule.getProjectId()); if (calendar == null) { log.warn("规则ID为[{}]的规则,所对应的工作历信息不存在", rule.getId()); continue; } } // 判断当前规则是否生效 WorkCalendarDate calendarDate = this.parseWorkCalendarRule(rule, calendar, dateStart); if (calendarDate == null) { continue; } // 数据添加 String workDate = dateStart.toString(DateUtil.FORMAT_DATE_YYYYMMDD); if (calendarDateMap.containsKey(workDate)) { calendarDateMap.get(workDate).add(calendarDate); } else { calendarDateMap.put(workDate, Lists.newArrayList(calendarDate)); } } dateStart.offset(DateField.DAY_OF_YEAR, 1); } calendarMap.clear(); } /** * 解析规则信息,生成对应作息时间记录 * * @param rule * @param workCalendar 为null, 代表非工作历级别的规则配置 * @param dateStart */ private WorkCalendarDate parseWorkCalendarRule(WorkCalendarRule rule, WorkCalendar workCalendar, DateTime currentDate) { String workDate = currentDate.toString(DateUtil.FORMAT_DATE_YYYYMMDD); String dictCode = StringUtil.isBlank(rule.getDictCode()) ? "" : rule.getDictCode(); int indexOf = dictCode.indexOf(WorkCalendarConstant.WORK_CALENDAR_D_OF_W); if (indexOf <= 0) { indexOf = dictCode.indexOf(WorkCalendarConstant.WORK_CALENDAR_D_OF_M); if (indexOf <= 0) { indexOf = dictCode.indexOf(WorkCalendarConstant.WORK_CALENDAR_M_AND_D); } } if (indexOf > 0) { dictCode = dictCode.substring(0, indexOf - 1); } // 解析规则,生成数据 int work = Integer.valueOf(workDate); String ruleStart = rule.getRuleDateStart(); String ruleEnd = rule.getRuleDateEnd(); if (StringUtil.isNotBlank(ruleStart) && StringUtil.isNotBlank(ruleEnd)) { int start = Integer.valueOf(ruleStart); int end = Integer.valueOf(ruleEnd); if (work >= start && work <= end) { // 当日期生效 if (indexOf > 0) { // 验证value是否存在,存在按周 月 解析,判断是否生效 boolean result = this.parseRuleValue(rule, currentDate, workDate); if (!result) { return null; } } // 组合数据 WorkCalendarDate calendarDate = this.comWorkCalendarOrRule(rule, workDate, dictCode, workCalendar); return calendarDate; } } return null; } /** * 获取满足条件的所有新版规则信息 * TODO 这里工作历和项目ID不传参,则无影响,若传参了,目前仅支持工作历级别的规则解析 * * @param workCalendarDateQueryVO * @param dictTypeLevel 0-集团级别,1-项目级别,2-工作历级别,null-默认工作历级别 * @return */ public List selectWorkCalendarRuleList(WorkCalendarDateQueryVO queryVO, Integer dictTypeLevel) { QueryWrapper queryWrapper = new WorkCalendarRule.Builder().createQueryWrapper().projectIdEq(queryVO.getProjectId(), dictTypeLevel) .calendarIdEq(queryVO.getCalendarId(), dictTypeLevel).ruleDateBetween(queryVO.getWorkDateStart(), queryVO.getWorkDateEnd()) .dictTypeEq(queryVO.getDictType()).dictCodeIn(queryVO.getDictCode()).dictTypeIn(queryVO.getDictTypes()) .idEq(queryVO.getRuleId()).delFlagEq(WorkCalendarConstant.WORK_CALENDAR_DEL_FLAG_NOR) .ruleFlagEq(WorkCalendarConstant.WORK_CALENDAR_RULE_FLAG_NEW).builderQueryWrapper(); return this.workCalendarRuleService.list(queryWrapper); } /** * 获取满足条件的所有已存在的作息时间信息,包括自定义的 * @param workCalendarDateQueryVO * @return */ public List selectWorkCalendarDateList(WorkCalendarDateQueryVO workCalendarDateQueryVO, String customFlag, Integer dictTypeLevel) { QueryWrapper queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper() .projectIdEq(workCalendarDateQueryVO.getProjectId(), dictTypeLevel).idEq(workCalendarDateQueryVO.getId()) .ruleIdEq(workCalendarDateQueryVO.getRuleId()).calendarIdEq(workCalendarDateQueryVO.getCalendarId(), dictTypeLevel) .workDateGe(workCalendarDateQueryVO.getWorkDateStart()).workDateLe(workCalendarDateQueryVO.getWorkDateEnd()) .dictTypeEq(workCalendarDateQueryVO.getDictType()).dictTypeIn(workCalendarDateQueryVO.getDictTypes()) .dictCodeIn(workCalendarDateQueryVO.getDictCode()).calendarNameLike(workCalendarDateQueryVO.getCalendarName()) .customFlagEq(customFlag).builderQueryWrapper(); queryWrapper.select("ID, GROUP_CODE, RULE_ID, CALENDAR_ID, PROJECT_ID, CALENDAR_NAME, CALENDAR_DESC, DICT_TYPE, " + "DICT_CODE, WORK_DATE, WORK_TIME, CUSTOM_FLAG, UPDATE_USER"); List list = workCalendarDateService.list(queryWrapper); return list == null ? new ArrayList() : list; } /** * 组合出作息时间对象 * * @param rule * @param workDate * @param dictCode * @param workCalendar * @return */ public WorkCalendarDate comWorkCalendarOrRule(WorkCalendarRule rule, String workDate, String dictCode, WorkCalendar workCalendar) { // 首先判断工作历是否还存在 WorkCalendarDate workCalendarDate = new WorkCalendarDate(); workCalendarDate.setGroupCode(rule.getGroupCode()); workCalendarDate.setCalendarId(workCalendar == null ? "0" : workCalendar.getId()); workCalendarDate.setRuleId(rule.getId()); workCalendarDate.setCalendarName(workCalendar == null ? "" : workCalendar.getCalendarName()); workCalendarDate.setCalendarDesc(workCalendar == null ? "" : workCalendar.getCalendarDesc()); workCalendarDate.setProjectId(rule.getProjectId()); workCalendarDate.setDictType(rule.getDictType()); workCalendarDate.setDictCode(dictCode); workCalendarDate.setWorkDateStart(rule.getRuleDateStart()); workCalendarDate.setWorkDateEnd(rule.getRuleDateEnd()); workCalendarDate.setWorkDate(workDate); workCalendarDate.setWorkTime(StringUtil.isBlank(rule.getRuleTime()) ? (CollectionUtil.isEmpty(rule.getValue()) ? null : rule.getValue().stream().collect(Collectors.joining(","))) : rule.getRuleTime()); // 自定义的一定是查出来的,封装的一定是非自定义添加的 workCalendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_NO); workCalendarDate.setUpdateUser(rule.getUpdateUser()); return workCalendarDate; } /** * 批量自定义作息时间信息 * @return */ public void batchCreateCalendarDate(CustomCalendarVO createVO) { boolean result = false; List batchInfos = createVO.getBatchInfo(); // 判断日期是否合法 DateTime now = DateUtil.date(); //now = now.offset(DateField.DAY_OF_YEAR, 1); //明天 String format = DateUtil.format(now, DateUtil.FORMAT_DATE_YYYYMMDD); Integer current = Integer.valueOf(format); for (WorkCalendarDateCreateVO batchInfo : batchInfos) { int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(createVO.getGroupCode(), batchInfo.getDictType()); Integer workDate = Integer.valueOf(batchInfo.getWorkDate()); if (workDate < current) { throw new BusinessException("作息日期不合法,必须大于等于当日"); } // 判断工作历类型是否存在 WorkCalendar calendar = null; if (dictTypeLevel == 2) { calendar = this.workCalendarService.getById(batchInfo.getCalendarId(), createVO.getGroupCode(), createVO.getProjectId()); if (calendar == null) { throw new BusinessException("工作历类型不存在"); } } WorkCalendarDate calendarDate = new WorkCalendarDate(); BeanUtils.copyProperties(batchInfo, calendarDate); // 验证数据有效性 result = this.workCalendarDateService.checkWorkDateValid(calendarDate, dictTypeLevel); if (!result) { throw new BusinessException("当天已存在相同类型额定义,不可重复添加"); } calendarDate.setGroupCode(createVO.getGroupCode()); calendarDate.setCalendarName(calendar == null ? null : calendar.getCalendarName()); calendarDate.setCalendarDesc(calendar == null ? null : calendar.getCalendarDesc()); calendarDate.setProjectId(dictTypeLevel == 0 ? "0" : createVO.getProjectId()); if (dictTypeLevel != 2) { calendarDate.setCalendarId("0"); } calendarDate.setUpdateUser(createVO.getUserId()); calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES); result = this.workCalendarDateService.save(calendarDate); if (!result) { throw new BusinessException("自定义工作历作息时间添加失败"); } } } /** * 解析rule 的 value属性,判断其是否生效 * @param rule * @param workDate * @return value为空,默认返回true */ private boolean parseRuleValue(WorkCalendarRule rule, DateTime currentDate, String workDate) { if (CollectionUtil.isEmpty(rule.getValue())) { return true; } // 获取月日 String mmddStr = workDate.substring(4, 8); Integer mmdd = Integer.valueOf(mmddStr); Set values = rule.getValue(); String dictCode = rule.getDictCode(); String[] split = dictCode.split("-"); dictCode = split[0]; // 真实的code编码 String type = split[1]; // 类型 switch (type) { case WorkCalendarConstant.WORK_CALENDAR_D_OF_W: //周 // 1表示周日,2表示周一 int dayOfWeek = DateUtil.dayOfWeek(currentDate); dayOfWeek = dayOfWeek - 1; if (dayOfWeek == 0) { dayOfWeek = 7; } String num = String.valueOf(dayOfWeek); if (values.contains(num)) { return true; } break; case WorkCalendarConstant.WORK_CALENDAR_D_OF_M: //月 // 当前日期为此月的第几天 int ofMonth = DateUtil.dayOfMonth(currentDate); Iterator iterator = values.iterator(); while(iterator.hasNext()) { String next = iterator.next(); if (next.contains("-")) { String[] split2 = next.split("-"); int start = Integer.parseInt(split2[0]); int end = Integer.parseInt(split2[1]); if (ofMonth >= start && ofMonth <= end) { return true; } } else if (next.equals(String.valueOf(ofMonth))) { return true; } } break; case WorkCalendarConstant.WORK_CALENDAR_M_AND_D: //年 iterator = values.iterator(); while(iterator.hasNext()) { String next = iterator.next(); if (next.contains("-")) { String[] split2 = next.split("-"); Integer startInt = Integer.valueOf(split2[0]); Integer endInt = Integer.valueOf(split2[1]); if (mmdd >= startInt && mmdd <= endInt) { return true; } } else if (mmddStr.equals(next)) { return true; } } break; default: break; } return false; } /** * 批量自定义作息时间信息 * @return */ public void batchUpdateCalendarDate(CustomCalendarVO updateVO) { boolean result = false; List batchInfos = updateVO.getBatchInfo(); // 判断日期是否合法 DateTime now = DateUtil.date(); //now = now.offset(DateField.DAY_OF_YEAR, 1); //明天 String format = DateUtil.format(now, DateUtil.FORMAT_DATE_YYYYMMDD); Integer current = Integer.valueOf(format); for (WorkCalendarDateUpdateVO batchInfo : batchInfos) { Integer workDate = Integer.valueOf(batchInfo.getWorkDate()); if (workDate < current) { throw new BusinessException("作息日期不合法,必须大于等于当日"); } // 验证是否存在 WorkCalendarDate temp = this.workCalendarDateService.getById(batchInfo.getId()); if (temp == null || !WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES.equals(temp.getCustomFlag())) { throw new BusinessException("当天不存在自定义的作息时间信息"); } int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(updateVO.getGroupCode(), batchInfo.getDictType()); // 判断工作历类型是否存在 WorkCalendar calendar = null; if (dictTypeLevel == 2) { calendar = this.workCalendarService.getById(batchInfo.getCalendarId(), updateVO.getGroupCode(), updateVO.getProjectId()); if (calendar == null) { throw new BusinessException("工作历类型不存在"); } } WorkCalendarDate calendarDate = new WorkCalendarDate(); BeanUtils.copyProperties(batchInfo, calendarDate); calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES); calendarDate.setGroupCode(updateVO.getGroupCode()); calendarDate.setCalendarName(calendar == null ? null : calendar.getCalendarName()); calendarDate.setCalendarDesc(calendar == null ? null : calendar.getCalendarDesc()); calendarDate.setProjectId(dictTypeLevel == 0 ? "0" : updateVO.getProjectId()); if (dictTypeLevel != 2) { calendarDate.setCalendarId("0"); } calendarDate.setUpdateUser(updateVO.getUserId()); result = this.workCalendarDateService.updateById(calendarDate); if (!result) { throw new BusinessException("自定义工作历作息时间添加失败"); } } } /** * 多时间段添加工作历作息时间信息,先删除此dictType下数据,再添加 * * @param createVO * @param calendar */ @Transactional public void batchCreateCalendarMoreDate(WorkCalendarMoreDateCreateVO createVO, WorkCalendar calendar) { int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(createVO.getGroupCode(), createVO.getDictType()); String calendarId = createVO.getCalendarId(); String projectId = createVO.getProjectId(); String now = DateUtil.format(new Date(), DateUtil.FORMAT_DATE_YYYYMMDDHHMMSS); DateTime dateStart = DateUtil.parse(createVO.getWorkDateStart(), DateUtil.FORMAT_DATE_YYYYMMDD); DateTime dateEnd = DateUtil.parse(createVO.getWorkDateEnd(), DateUtil.FORMAT_DATE_YYYYMMDD); long betweenDay = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1; Set timetables = createVO.getTimetable(); List datas = new ArrayList(); for (int i = 0; i < betweenDay; i++) { String currentDay = DateUtil.format(dateStart, DateUtil.FORMAT_DATE_YYYYMMDD); if (CollectionUtil.isEmpty(timetables)) { WorkCalendarDate calendarDate = this.setCalendarDate(createVO, calendar, currentDay, null, now); datas.add(calendarDate); } else { for (String timetable : timetables) { // 数据库数据组装 WorkCalendarDate calendarDate = this.setCalendarDate(createVO, calendar, currentDay, timetable, now); datas.add(calendarDate); } } // 偏移天数 dateStart.offset(DateField.DAY_OF_YEAR, 1); } // 先删除 QueryWrapper queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper() .calendarIdEq(calendarId, dictTypeLevel).projectIdEq(projectId, dictTypeLevel).dictTypeEq(createVO.getDictType()) .workDateGe(createVO.getWorkDateStart()).workDateLe(createVO.getWorkDateEnd()) .customFlagEq(createVO.getCustomFlag()).builderQueryWrapper(); this.workCalendarDateService.remove(queryWrapper); // 批量添加数据 this.workCalendarDateService.batchCreateCalendarDate(datas); } /** * 参数赋值 * @param createVO * @param calendar * @param currentDay * @param timetable * @param now * @return */ private WorkCalendarDate setCalendarDate(WorkCalendarMoreDateCreateVO createVO, WorkCalendar calendar, String currentDay, String timetable, String now) { WorkCalendarDate calendarDate = new WorkCalendarDate(); calendarDate.setId(IdGenerator.getSnowIdStr(WorkCalendarConstant.WORK_CALENDAR_DATE_ID_PREFIX)); calendarDate.setGroupCode(createVO.getGroupCode()); calendarDate.setProjectId(createVO.getProjectId()); calendarDate.setCalendarId(createVO.getCalendarId()); calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES); calendarDate.setCalendarName(calendar == null ? "" : calendar.getCalendarName()); calendarDate.setCalendarDesc(calendar == null ? "" : calendar.getCalendarDesc()); calendarDate.setDictType(createVO.getDictType()); calendarDate.setDictCode(createVO.getDictCode()); calendarDate.setWorkDate(currentDay); calendarDate.setWorkTime(timetable); calendarDate.setCreateTime(now); calendarDate.setUpdateTime(now); calendarDate.setUpdateUser(createVO.getUserId()); return calendarDate; } /** * 检查参数日期是否大于当前日期 * @param workDate 工作日期 yyyyMMdd * @return */ public static boolean isMoreThanToday(String workDate) { DateTime now = DateUtil.date(); //now = now.offset(DateField.DAY_OF_YEAR, 1); //明天 String format = DateUtil.format(now, DateUtil.FORMAT_DATE_YYYYMMDD); Integer current = Integer.valueOf(format); Integer dateInt = Integer.valueOf(workDate); if (dateInt < current) { return false; } return true; } /** * 解析起止时间,判读当前时间位于哪里 * @param dateStart yyyyMMdd * @param dateEnd yyyyMMdd * @param now yyyyMMdd * @return */ private Map parseWorkDate(DateTime dateStart, DateTime dateEnd, String now) { if (dateEnd.before(dateStart)) { throw new BusinessException(ResponseCode.A0400.getCode(), "结束日期不能早于开始日期"); } DateTime historyStart = null; DateTime historyEnd = null; DateTime parseRuleStart = null; DateTime parseRuleEnd = null; Map result = new HashMap(); DateTime currentDate = DateUtil.parse(now, DateUtil.FORMAT_DATE_YYYYMMDD); // 第一种情况,当日在start之前 if (!dateStart.before(currentDate)) { // 开始日期,不早于当日,全部走解析 parseRuleStart = dateStart; parseRuleEnd = dateEnd; } else if (dateStart.before(currentDate) && !dateEnd.before(currentDate)) { // 第二种情况,当日在start~end之间,包含等于dateEnd 的情况 historyStart = dateStart; historyEnd = currentDate.offset(DateField.DAY_OF_YEAR, -1); parseRuleStart = DateUtil.parse(now, DateUtil.FORMAT_DATE_YYYYMMDD); parseRuleEnd = dateEnd; } else { // 第三种情况,当日在dataEnd之后,全部查历史即可 historyStart = dateStart; historyEnd = dateEnd; } result.put("historyStart", historyStart); result.put("historyEnd", historyEnd); result.put("parseRuleStart", parseRuleStart); result.put("parseRuleEnd", parseRuleEnd); return result; } /** * 判断是否存在自动作息时间的依据key * * @param calendarId 工作历类型ID * @param workDate 当日 * @param dictType 字典类型,不可为空 * @param dictCode 字典类型下的编码,允许为空 * @return */ public String getCustomCalendarDateTempKey(String calendarId, String workDate, String dictType, String dictCode) { return workDate + dictType + (StringUtil.isBlank(dictCode) ? "" : dictCode); } /** * 判断是否存在自动作息时间的依据key * * @param rule * @param workDate * @param dictCode * @return */ public String getCustomKey(WorkCalendarRule rule, String workDate, String dictCode) { String customKey = rule.getCalendarId() + rule.getProjectId() + workDate + rule.getDictType() + (StringUtil.isBlank(dictCode) ? "" : dictCode); return customKey; } }