|
@@ -0,0 +1,658 @@
|
|
|
|
+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.IWorkCalendarRuleService;
|
|
|
|
+import com.persagy.calendar.service.IWorkCalendarService;
|
|
|
|
+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 cn.hutool.core.util.BooleanUtil;
|
|
|
|
+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;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 实时查询作息时间信息,包括自定义的
|
|
|
|
+ * @param queryVO
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public List<CalendarDateResult> queryWorkCalendarDateList(WorkCalendarDateQueryVO queryVO) {
|
|
|
|
+ // key-日期,value-此日对应的作息时间集合
|
|
|
|
+ Map<String, List<WorkCalendarDate>> resultMap = new HashMap<String, List<WorkCalendarDate>>();
|
|
|
|
+ // key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
|
|
|
|
+ Map<String, Boolean> existsCustom = new HashMap<String, Boolean>();
|
|
|
|
+
|
|
|
|
+ // 1.优先获取start~end的作息时间信息,包含自定义的,判断对应日期内是否包含自定义的
|
|
|
|
+ this.selectHistoryDate(resultMap, existsCustom, queryVO);
|
|
|
|
+
|
|
|
|
+ // 2.获取满足 明日/start~end日期 的规则信息集合
|
|
|
|
+ String format = DateUtil.format(new Date(), DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ DateTime currentDate = DateUtil.parse(format, DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ String dateStartStr = queryVO.getWorkDateStart();
|
|
|
|
+ String dateEndStr = queryVO.getWorkDateEnd();
|
|
|
|
+ DateTime dateStart = DateUtil.parse(dateStartStr, DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ DateTime dateEnd = DateUtil.parse(dateEndStr, DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ if (currentDate.before(dateStart)) {
|
|
|
|
+ currentDate = dateStart;
|
|
|
|
+ } else {
|
|
|
|
+ currentDate.offset(DateField.DAY_OF_YEAR, 1);
|
|
|
|
+ }
|
|
|
|
+ if (currentDate.before(dateEnd) || currentDate.equals(dateEnd)) {
|
|
|
|
+ // 因为dataEnd时分秒一定是000000,所以这里只要当前日期时间点在dateEnd之前,就说明偏移后最坏与dateEnd相同
|
|
|
|
+ String offsetStr = currentDate.toString(DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ List<WorkCalendarRule> ruleList = this.selectWorkCalendarRuleList(offsetStr, dateEndStr, queryVO);
|
|
|
|
+ if (CollectionUtil.isNotEmpty(ruleList)) {
|
|
|
|
+ // 3.实时解析规则,并判断是否存在自定义的作息时间信息,最后封装返回数据
|
|
|
|
+ long betweenDay = DateUtil.between(currentDate, dateEnd, DateUnit.DAY) + 1;
|
|
|
|
+ this.paserWorkCalendarRule(betweenDay, currentDate, ruleList, resultMap, existsCustom);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取start~end之间的天数,+1 包括首尾
|
|
|
|
+ dateStart = DateUtil.parse(dateStartStr, DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ long betweenDay = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1;
|
|
|
|
+
|
|
|
|
+ return this.setResultList(queryVO.getCalendarId(), betweenDay, dateStart, resultMap);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 响应数据,最后处理加工,根据dictCode,剔除某天多余的数据
|
|
|
|
+ * @param calendarId
|
|
|
|
+ * @param betweenDay
|
|
|
|
+ * @param dateStart
|
|
|
|
+ * @param resultMap
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private List<CalendarDateResult> setResultList(String calendarId, long betweenDay, DateTime dateStart,
|
|
|
|
+ Map<String, List<WorkCalendarDate>> resultMap) {
|
|
|
|
+ List<CalendarDateResult> resultList = new ArrayList<CalendarDateResult>();
|
|
|
|
+
|
|
|
|
+ String nextDay = null;
|
|
|
|
+ for (int i = 0; i < betweenDay; i++) {
|
|
|
|
+ nextDay = dateStart.toString(DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ CalendarDateResult result = new CalendarDateResult();
|
|
|
|
+ int dayOfWeek = DateUtil.dayOfWeek(dateStart);
|
|
|
|
+ if (dayOfWeek == 1 || dayOfWeek == 7) {
|
|
|
|
+ result.setWorkday(false);
|
|
|
|
+ }
|
|
|
|
+ result.setWorkDate(nextDay);
|
|
|
|
+ result.setCalendarId(calendarId);
|
|
|
|
+ result.setDate(DateUtil.dayOfMonth(dateStart));
|
|
|
|
+ result.setWeek(WorkCalendarConstant.DAY_OF_WEEK.get(dayOfWeek));
|
|
|
|
+ List<WorkCalendarDate> list = resultMap.get(nextDay);
|
|
|
|
+ if (CollectionUtil.isNotEmpty(list)) {
|
|
|
|
+ for (int j = list.size() - 1; j >= 0; j--) {
|
|
|
|
+ WorkCalendarDate calendarDate = list.get(j);
|
|
|
|
+ // 是工作日,剔除非工作日的数据,目前仅有OpenTime-1,工作日,OpenTime-2,休息日
|
|
|
|
+ if (result.isWorkday() && "OpenTime-2".equals(calendarDate.getDictCode())) {
|
|
|
|
+ list.remove(j);
|
|
|
|
+ } else if (!result.isWorkday() && "OpenTime-1".equals(calendarDate.getDictCode())) {
|
|
|
|
+ list.remove(j);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ result.setTimeTable(CollectionUtil.isEmpty(list) ? Lists.newArrayList() : list);
|
|
|
|
+ resultList.add(result);
|
|
|
|
+ dateStart.offset(DateField.DAY_OF_YEAR, 1); // 下一天
|
|
|
|
+ }
|
|
|
|
+ resultMap.clear(); //释放
|
|
|
|
+ return resultList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ *
|
|
|
|
+ * @param resultMap key-日期,value-此日对应的作息时间集合,包含未来自定义的
|
|
|
|
+ * @param existsCustom key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
|
|
|
|
+ */
|
|
|
|
+ public void selectHistoryDate(Map<String, List<WorkCalendarDate>> resultMap, Map<String, Boolean> existsCustom, WorkCalendarDateQueryVO queryVO) {
|
|
|
|
+ List<WorkCalendarDate> dates = this.selectWorkCalendarDateList(queryVO);
|
|
|
|
+ for (WorkCalendarDate calendarDate : dates) {
|
|
|
|
+ // 是否存在自定义,存在true就不在更新
|
|
|
|
+ String existsKey = calendarDate.getCalendarId() + calendarDate.getProjectId() + calendarDate.getWorkDate() + calendarDate.getDictType() + (StringUtil.isBlank(calendarDate.getDictCode()) ? "" : calendarDate.getDictCode());
|
|
|
|
+ boolean exists = WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES.equals(calendarDate.getCustomFlag());
|
|
|
|
+ if (!BooleanUtil.isTrue(existsCustom.get(existsKey))) {
|
|
|
|
+ existsCustom.put(existsKey, exists);
|
|
|
|
+ }
|
|
|
|
+ // 将自定义的或历史的,按照日期,分组
|
|
|
|
+ if (resultMap != null) {
|
|
|
|
+ if (resultMap.containsKey(calendarDate.getWorkDate())) {
|
|
|
|
+ List<WorkCalendarDate> list = resultMap.get(calendarDate.getWorkDate());
|
|
|
|
+ list.add(calendarDate);
|
|
|
|
+ } else {
|
|
|
|
+ List<WorkCalendarDate> list = new ArrayList<WorkCalendarDate>();
|
|
|
|
+ list.add(calendarDate);
|
|
|
|
+ resultMap.put(calendarDate.getWorkDate(), list);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取满足条件的所有已存在的作息时间信息,包括自定义的
|
|
|
|
+ * @param workCalendarDateQueryVO
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public List<WorkCalendarDate> selectWorkCalendarDateList(WorkCalendarDateQueryVO workCalendarDateQueryVO) {
|
|
|
|
+ QueryWrapper<WorkCalendarDate> queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper()
|
|
|
|
+ .projectIdEq(workCalendarDateQueryVO.getProjectId())
|
|
|
|
+ .idEq(workCalendarDateQueryVO.getId())
|
|
|
|
+ .ruleIdEq(workCalendarDateQueryVO.getRuleId())
|
|
|
|
+ .calendarIdEq(workCalendarDateQueryVO.getCalendarId())
|
|
|
|
+ .workDateGe(workCalendarDateQueryVO.getWorkDateStart())
|
|
|
|
+ .workDateLe(workCalendarDateQueryVO.getWorkDateEnd())
|
|
|
|
+ .dictTypeEq(workCalendarDateQueryVO.getDictType())
|
|
|
|
+ .dictTypeIn(workCalendarDateQueryVO.getDictTypes())
|
|
|
|
+ .dictCodeIn(workCalendarDateQueryVO.getDictCode())
|
|
|
|
+ .calendarNameLike(workCalendarDateQueryVO.getCalendarName())
|
|
|
|
+ .builderQueryWrapper();
|
|
|
|
+ queryWrapper.select("ID, RULE_ID, CALENDAR_ID, PROJECT_ID, CALENDAR_NAME, CALENDAR_DESC, DICT_TYPE, "
|
|
|
|
+ + "DICT_CODE, WORK_DATE, WORK_TIME, CUSTOM_FLAG");
|
|
|
|
+ List<WorkCalendarDate> list = workCalendarDateService.list(queryWrapper);
|
|
|
|
+ return list == null ? new ArrayList<WorkCalendarDate>() : list;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 解析此段时间的规则
|
|
|
|
+ * @param betweenDay 时间范围
|
|
|
|
+ * @param workDateEnd
|
|
|
|
+ * @param workDateStart
|
|
|
|
+ * @param ruleList 规则信息
|
|
|
|
+ * @param resultMap 已有的作息时间信息
|
|
|
|
+ * @param existsCusetom key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
|
|
|
|
+ */
|
|
|
|
+ public void paserWorkCalendarRule(long betweenDay, DateTime currentDate, List<WorkCalendarRule> ruleList,
|
|
|
|
+ Map<String, List<WorkCalendarDate>> resultMap, Map<String, Boolean> existsCustom) {
|
|
|
|
+ Map<String, WorkCalendar> calendarMap = new HashMap<String, WorkCalendar>();
|
|
|
|
+ for(int i = 0; i < betweenDay; i++) {
|
|
|
|
+ // 判断此天有没有对应的规则信息,每次都要循环全部,生成多条信息
|
|
|
|
+ for (WorkCalendarRule rule : ruleList) {
|
|
|
|
+ // 判断当前规则是否
|
|
|
|
+ this.parseWorkCalendarRule(rule, currentDate, calendarMap, resultMap, existsCustom);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ currentDate.offset(DateField.DAY_OF_YEAR, 1);
|
|
|
|
+ }
|
|
|
|
+ calendarMap.clear();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 解析规则信息,生成对应作息时间记录
|
|
|
|
+ *
|
|
|
|
+ * @param rule
|
|
|
|
+ * @param currentDate 日期
|
|
|
|
+ * @param calendarMap 工作历类型集合
|
|
|
|
+ * @param resultMap 等于null时,插库,否则添加进此map
|
|
|
|
+ * @param existsCusetom key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private void parseWorkCalendarRule(WorkCalendarRule rule, DateTime currentDate, Map<String, WorkCalendar> calendarMap,
|
|
|
|
+ Map<String, List<WorkCalendarDate>> resultMap, Map<String, Boolean> existsCustom) {
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
|
|
+ String existsKey = rule.getCalendarId() + rule.getProjectId() + workDate + rule.getDictType() + (StringUtil.isBlank(dictCode) ? "" : dictCode);
|
|
|
|
+ // 优先判断当日是否存在同类型 同编码的自定义作息时间
|
|
|
|
+ if (existsCustom != null && BooleanUtil.isTrue(existsCustom.get(existsKey))) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 当不存在自定义的作息时间时
|
|
|
|
+ // 解析规则,生成数据
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 组合数据
|
|
|
|
+ WorkCalendarDate calendarDate = this.comWorkCalendarOrRule(rule, workDate, dictCode, calendarMap);
|
|
|
|
+ if (calendarDate == null) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 数据添加
|
|
|
|
+ this.addCalendarDateResult(workDate, calendarDate, resultMap);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 解析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<String> 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<String> 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 响应数据添加
|
|
|
|
+ * @param resultMap 为null时插库
|
|
|
|
+ */
|
|
|
|
+ public void addCalendarDateResult(String workDate, WorkCalendarDate calendarDate, Map<String, List<WorkCalendarDate>> resultMap) {
|
|
|
|
+ if (resultMap == null) {
|
|
|
|
+ boolean result = this.workCalendarDateService.save(calendarDate);
|
|
|
|
+ //boolean result = this.workCalendarDateService.replaceIntoCalendarDate(calendarDate);
|
|
|
|
+ if (!result) {
|
|
|
|
+ throw new BusinessException("新增作息时间信息失败,规则ID: " + calendarDate.getRuleId());
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!resultMap.containsKey(workDate)) {
|
|
|
|
+ List<WorkCalendarDate> list = new ArrayList<WorkCalendarDate>();
|
|
|
|
+ list.add(calendarDate);
|
|
|
|
+ resultMap.put(workDate, list);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<WorkCalendarDate> list = resultMap.get(workDate);
|
|
|
|
+ list.add(calendarDate);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 组合出作息时间对象
|
|
|
|
+ * @param workCalendar
|
|
|
|
+ * @param rule
|
|
|
|
+ * @param calendarIds
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public WorkCalendarDate comWorkCalendarOrRule(WorkCalendarRule rule, String workDate, String dictCode,
|
|
|
|
+ Map<String, WorkCalendar> calendarMap) {
|
|
|
|
+ // 首先判断工作历是否还存在
|
|
|
|
+ WorkCalendar workCalendar = null;
|
|
|
|
+ if (calendarMap.containsKey(rule.getCalendarId())) {
|
|
|
|
+ workCalendar = calendarMap.get(rule.getCalendarId());
|
|
|
|
+ } else {
|
|
|
|
+ workCalendar = this.workCalendarService.getById(rule.getCalendarId(), rule.getProjectId());
|
|
|
|
+ calendarMap.put(rule.getCalendarId(), workCalendar);
|
|
|
|
+ }
|
|
|
|
+ if (workCalendar == null) {
|
|
|
|
+ log.warn("规则ID为[{}]的规则,所对应的工作历信息不存在", rule.getId());
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ WorkCalendarDate workCalendarDate = new WorkCalendarDate();
|
|
|
|
+ workCalendarDate.setGroupCode(rule.getGroupCode());
|
|
|
|
+ workCalendarDate.setCalendarId(workCalendar.getId());
|
|
|
|
+ workCalendarDate.setRuleId(rule.getId());
|
|
|
|
+ workCalendarDate.setCalendarName(workCalendar.getCalendarName());
|
|
|
|
+ workCalendarDate.setCalendarDesc(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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取满足条件的所有新版规则信息
|
|
|
|
+ * @param workDatestart
|
|
|
|
+ * @param workDateEnd
|
|
|
|
+ * @param workCalendarDateQueryVO
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public List<WorkCalendarRule> selectWorkCalendarRuleList(String workDatestart, String workDateEnd, WorkCalendarDateQueryVO queryVO) {
|
|
|
|
+ QueryWrapper<WorkCalendarRule> queryWrapper = new WorkCalendarRule.Builder().createQueryWrapper()
|
|
|
|
+ .projectIdEq(queryVO.getProjectId()).idEq(queryVO.getRuleId())
|
|
|
|
+ .calendarIdEq(queryVO.getCalendarId()).ruleDateBetween(workDatestart, workDateEnd)
|
|
|
|
+ .dictTypeEq(queryVO.getDictType()).dictCodeIn(queryVO.getDictCode())
|
|
|
|
+ .dictTypeIn(queryVO.getDictTypes())
|
|
|
|
+ .delFlagEq(WorkCalendarConstant.WORK_CALENDAR_DEL_FLAG_NOR)
|
|
|
|
+ .ruleFlagEq(WorkCalendarConstant.WORK_CALENDAR_RULE_FLAG_NEW).builderQueryWrapper();
|
|
|
|
+ return this.workCalendarRuleService.list(queryWrapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 解析规则信息,并插库
|
|
|
|
+ * @param queryVO
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ @Transactional
|
|
|
|
+ public boolean handleParseCalendarRule(WorkCalendarDateQueryVO queryVO) {
|
|
|
|
+ // 1.防止重复执行,优先删除从今日开始的非自定义的作息时间信息
|
|
|
|
+ QueryWrapper<WorkCalendarDate> queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper()
|
|
|
|
+ .projectIdEq(queryVO.getProjectId()).calendarIdEq(queryVO.getCalendarId())
|
|
|
|
+ .calendarNameEq(queryVO.getCalendarName()).dictTypeEq(queryVO.getDictType())
|
|
|
|
+ .dictCodeIn(queryVO.getDictCode()).workDateGe(queryVO.getWorkDateStart())
|
|
|
|
+ .workDateLe(queryVO.getWorkDateEnd()).customFlagEq(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_NO)
|
|
|
|
+ .builderQueryWrapper();
|
|
|
|
+ this.workCalendarDateService.remove(queryWrapper);
|
|
|
|
+
|
|
|
|
+ // 1.查询出满足条件的所有的规则信息
|
|
|
|
+ List<WorkCalendarRule> ruleList = this.selectWorkCalendarRuleList(queryVO.getWorkDateStart(), queryVO.getWorkDateEnd(), queryVO);
|
|
|
|
+ if (CollectionUtil.isNotEmpty(ruleList)) {
|
|
|
|
+ // 2.获取此日期内,已存在的自定义的作息时间
|
|
|
|
+ // key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
|
|
|
|
+ Map<String, Boolean> existsCustom = new HashMap<String, Boolean>();
|
|
|
|
+ // 1.优先获取start~end的作息时间信息,包含自定义的,判断对应日期内是否包含自定义的
|
|
|
|
+ this.selectHistoryDate(null, existsCustom, queryVO);
|
|
|
|
+
|
|
|
|
+ // 3.解析规则信息
|
|
|
|
+ DateTime dateStart = DateUtil.parse(queryVO.getWorkDateStart(), DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ DateTime dateEnd = DateUtil.parse(queryVO.getWorkDateEnd(), DateUtil.FORMAT_DATE_YYYYMMDD);
|
|
|
|
+ long between = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1;
|
|
|
|
+ this.paserWorkCalendarRule(between, dateStart, ruleList, null, existsCustom);
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 批量自定义作息时间信息
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public void batchCreateCalendarDate(CustomCalendarVO<WorkCalendarDateCreateVO> createVO) {
|
|
|
|
+ boolean result = false;
|
|
|
|
+ List<WorkCalendarDateCreateVO> batchInfos = createVO.getBatchInfo();
|
|
|
|
+ for (WorkCalendarDateCreateVO batchInfo : batchInfos) {
|
|
|
|
+ // 判断日期是否合法
|
|
|
|
+ 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 workDate = Integer.valueOf(batchInfo.getWorkDate());
|
|
|
|
+ if (workDate < current) {
|
|
|
|
+ throw new BusinessException("作息日期不合法,必须大于今日");
|
|
|
|
+ }
|
|
|
|
+ // 判断工作历类型是否存在
|
|
|
|
+ WorkCalendar calendar = this.workCalendarService.getById(batchInfo.getCalendarId(), createVO.getProjectId());
|
|
|
|
+ if (calendar == null) {
|
|
|
|
+ throw new BusinessException("工作历类型不存在");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ WorkCalendarDate calendarDate = new WorkCalendarDate();
|
|
|
|
+ BeanUtils.copyProperties(batchInfo, calendarDate);
|
|
|
|
+ // 验证数据有效性
|
|
|
|
+ result = this.workCalendarDateService.checkWorkDateValid(calendarDate);
|
|
|
|
+ if (!result) {
|
|
|
|
+ throw new BusinessException("当天已存在相同类型额定义,不可重复添加");
|
|
|
|
+ }
|
|
|
|
+ calendarDate.setGroupCode(createVO.getGroupCode());
|
|
|
|
+ calendarDate.setProjectId(createVO.getProjectId());
|
|
|
|
+ calendarDate.setUpdateUser(createVO.getUserId());
|
|
|
|
+ calendarDate.setCalendarName(calendar.getCalendarName());
|
|
|
|
+ calendarDate.setCalendarDesc(calendar.getCalendarDesc());
|
|
|
|
+ calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES);
|
|
|
|
+ result = this.workCalendarDateService.save(calendarDate);
|
|
|
|
+ if (!result) {
|
|
|
|
+ throw new BusinessException("自定义工作历作息时间添加失败");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 批量自定义作息时间信息
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public <T> void batchUpdateCalendarDate(CustomCalendarVO<WorkCalendarDateUpdateVO> updateVO) {
|
|
|
|
+ boolean result = false;
|
|
|
|
+ List<WorkCalendarDateUpdateVO> batchInfos = updateVO.getBatchInfo();
|
|
|
|
+ for (WorkCalendarDateUpdateVO batchInfo : batchInfos) {
|
|
|
|
+ // 判断日期是否合法
|
|
|
|
+ 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 workDate = Integer.valueOf(batchInfo.getWorkDate());
|
|
|
|
+ if (workDate < current) {
|
|
|
|
+ throw new BusinessException("作息日期不合法,必须大于今日");
|
|
|
|
+ }
|
|
|
|
+ // 判断工作历类型是否存在
|
|
|
|
+ WorkCalendar calendar = this.workCalendarService.getById(batchInfo.getCalendarId(), updateVO.getProjectId());
|
|
|
|
+ if (calendar == null) {
|
|
|
|
+ throw new BusinessException("工作历类型不存在");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ WorkCalendarDate calendarDate = new WorkCalendarDate();
|
|
|
|
+ BeanUtils.copyProperties(batchInfo, calendarDate);
|
|
|
|
+ // 验证数据有效性
|
|
|
|
+ result = this.workCalendarDateService.checkWorkDateValid(calendarDate);
|
|
|
|
+ if (!result) {
|
|
|
|
+ throw new BusinessException("当天已存在相同类型的定义,不可重复添加");
|
|
|
|
+ }
|
|
|
|
+ calendarDate.setGroupCode(updateVO.getGroupCode());
|
|
|
|
+ calendarDate.setProjectId(updateVO.getProjectId());
|
|
|
|
+ calendarDate.setUpdateUser(updateVO.getUserId());
|
|
|
|
+ calendarDate.setCalendarName(calendar.getCalendarName());
|
|
|
|
+ calendarDate.setCalendarDesc(calendar.getCalendarDesc());
|
|
|
|
+ calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES);
|
|
|
|
+ result = this.workCalendarDateService.updateById(calendarDate);
|
|
|
|
+ if (!result) {
|
|
|
|
+ throw new BusinessException("自定义工作历作息时间添加失败");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 多时间段添加工作历作息时间信息,先删除此dictType下数据,再添加
|
|
|
|
+ * @param createVO
|
|
|
|
+ * @param calendar
|
|
|
|
+ */
|
|
|
|
+ @Transactional
|
|
|
|
+ public void batchCreateCalendarMoreDate(WorkCalendarMoreDateCreateVO createVO, WorkCalendar calendar) {
|
|
|
|
+ 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<String> timetables = createVO.getTimetable();
|
|
|
|
+ List<WorkCalendarDate> datas = new ArrayList<WorkCalendarDate>();
|
|
|
|
+ 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<WorkCalendarDate> queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper()
|
|
|
|
+ .calendarIdEq(calendarId).projectIdEq(projectId).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.getCalendarName());
|
|
|
|
+ calendarDate.setCalendarDesc(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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|