WorkCalendarDateHandler.java 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. package com.persagy.calendar.handle;
  2. import java.util.ArrayList;
  3. import java.util.Date;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Set;
  9. import java.util.stream.Collectors;
  10. import org.springframework.beans.BeanUtils;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.stereotype.Component;
  13. import org.springframework.transaction.annotation.Transactional;
  14. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  15. import com.google.common.collect.Lists;
  16. import com.persagy.calendar.constant.WorkCalendarConstant;
  17. import com.persagy.calendar.pojo.dto.WorkCalendar;
  18. import com.persagy.calendar.pojo.dto.WorkCalendarDate;
  19. import com.persagy.calendar.pojo.dto.WorkCalendarRule;
  20. import com.persagy.calendar.pojo.vo.CalendarDateResult;
  21. import com.persagy.calendar.pojo.vo.CustomCalendarVO;
  22. import com.persagy.calendar.pojo.vo.WorkCalendarDateCreateVO;
  23. import com.persagy.calendar.pojo.vo.WorkCalendarDateQueryVO;
  24. import com.persagy.calendar.pojo.vo.WorkCalendarDateUpdateVO;
  25. import com.persagy.calendar.pojo.vo.WorkCalendarMoreDateCreateVO;
  26. import com.persagy.calendar.service.IWorkCalendarDateService;
  27. import com.persagy.calendar.service.IWorkCalendarRuleService;
  28. import com.persagy.calendar.service.IWorkCalendarService;
  29. import com.persagy.common.exception.BusinessException;
  30. import com.persagy.common.utils.DateUtil;
  31. import com.persagy.common.utils.IdGenerator;
  32. import com.persagy.common.utils.StringUtil;
  33. import cn.hutool.core.collection.CollectionUtil;
  34. import cn.hutool.core.date.DateField;
  35. import cn.hutool.core.date.DateTime;
  36. import cn.hutool.core.date.DateUnit;
  37. import cn.hutool.core.util.BooleanUtil;
  38. import lombok.extern.slf4j.Slf4j;
  39. /**
  40. * @version
  41. * @description
  42. * @company persagy
  43. * @author zhangqiankun
  44. * @since 2020年10月3日: 下午1:03:19
  45. */
  46. @Slf4j
  47. @Component
  48. public class WorkCalendarDateHandler {
  49. @Autowired
  50. private IWorkCalendarService workCalendarService;
  51. @Autowired
  52. private IWorkCalendarRuleService workCalendarRuleService;
  53. @Autowired
  54. private IWorkCalendarDateService workCalendarDateService;
  55. /**
  56. * 实时查询作息时间信息,包括自定义的
  57. * @param queryVO
  58. * @return
  59. */
  60. public List<CalendarDateResult> queryWorkCalendarDateList(WorkCalendarDateQueryVO queryVO) {
  61. // key-日期,value-此日对应的作息时间集合
  62. Map<String, List<WorkCalendarDate>> resultMap = new HashMap<String, List<WorkCalendarDate>>();
  63. // key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
  64. Map<String, Boolean> existsCustom = new HashMap<String, Boolean>();
  65. // 1.优先获取start~end的作息时间信息,包含自定义的,判断对应日期内是否包含自定义的
  66. this.selectHistoryDate(resultMap, existsCustom, queryVO);
  67. // 2.获取满足 明日/start~end日期 的规则信息集合
  68. String format = DateUtil.format(new Date(), DateUtil.FORMAT_DATE_YYYYMMDD);
  69. DateTime currentDate = DateUtil.parse(format, DateUtil.FORMAT_DATE_YYYYMMDD);
  70. String dateStartStr = queryVO.getWorkDateStart();
  71. String dateEndStr = queryVO.getWorkDateEnd();
  72. DateTime dateStart = DateUtil.parse(dateStartStr, DateUtil.FORMAT_DATE_YYYYMMDD);
  73. DateTime dateEnd = DateUtil.parse(dateEndStr, DateUtil.FORMAT_DATE_YYYYMMDD);
  74. if (currentDate.before(dateStart)) {
  75. currentDate = dateStart;
  76. } else {
  77. // 验证此日是否已存在数据,已存在,这里往后偏移一日
  78. if (resultMap.containsKey(currentDate.toString(DateUtil.FORMAT_DATE_YYYYMMDD))) {
  79. currentDate.offset(DateField.DAY_OF_YEAR, 1);
  80. }
  81. }
  82. // 因为dataEnd时分秒一定是000000,所以这里只要当前日期时间点在dateEnd之前,就说明偏移后最坏与dateEnd相同
  83. if (currentDate.before(dateEnd) || currentDate.equals(dateEnd)) {
  84. String offsetStr = currentDate.toString(DateUtil.FORMAT_DATE_YYYYMMDD);
  85. List<WorkCalendarRule> ruleList = this.selectWorkCalendarRuleList(offsetStr, dateEndStr, queryVO);
  86. if (CollectionUtil.isNotEmpty(ruleList)) {
  87. // 3.实时解析规则,并判断是否存在自定义的作息时间信息,最后封装返回数据
  88. long betweenDay = DateUtil.between(currentDate, dateEnd, DateUnit.DAY) + 1;
  89. this.paserWorkCalendarRule(betweenDay, currentDate, ruleList, resultMap, existsCustom);
  90. }
  91. }
  92. // 获取start~end之间的天数,+1 包括首尾
  93. dateStart = DateUtil.parse(dateStartStr, DateUtil.FORMAT_DATE_YYYYMMDD);
  94. long betweenDay = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1;
  95. return this.setResultList(queryVO.getCalendarId(), betweenDay, dateStart, resultMap);
  96. }
  97. /**
  98. * 响应数据,最后处理加工,根据dictCode,剔除某天多余的数据
  99. * @param calendarId
  100. * @param betweenDay
  101. * @param dateStart
  102. * @param resultMap
  103. * @return
  104. */
  105. private List<CalendarDateResult> setResultList(String calendarId, long betweenDay, DateTime dateStart,
  106. Map<String, List<WorkCalendarDate>> resultMap) {
  107. List<CalendarDateResult> resultList = new ArrayList<CalendarDateResult>();
  108. String nextDay = null;
  109. for (int i = 0; i < betweenDay; i++) {
  110. nextDay = dateStart.toString(DateUtil.FORMAT_DATE_YYYYMMDD);
  111. CalendarDateResult result = new CalendarDateResult();
  112. int dayOfWeek = DateUtil.dayOfWeek(dateStart);
  113. if (dayOfWeek == 1 || dayOfWeek == 7) {
  114. result.setWorkday(false);
  115. }
  116. result.setWorkDate(nextDay);
  117. result.setCalendarId(calendarId);
  118. result.setDate(DateUtil.dayOfMonth(dateStart));
  119. result.setWeek(WorkCalendarConstant.DAY_OF_WEEK.get(dayOfWeek));
  120. List<WorkCalendarDate> list = resultMap.get(nextDay);
  121. if (CollectionUtil.isNotEmpty(list)) {
  122. for (int j = list.size() - 1; j >= 0; j--) {
  123. WorkCalendarDate calendarDate = list.get(j);
  124. // 是工作日,剔除非工作日的数据,目前仅有OpenTime-1,工作日,OpenTime-2,休息日
  125. if (result.isWorkday() && "OpenTime-2".equals(calendarDate.getDictCode())) {
  126. list.remove(j);
  127. } else if (!result.isWorkday() && "OpenTime-1".equals(calendarDate.getDictCode())) {
  128. list.remove(j);
  129. }
  130. }
  131. }
  132. result.setTimeTable(CollectionUtil.isEmpty(list) ? Lists.newArrayList() : list);
  133. resultList.add(result);
  134. dateStart.offset(DateField.DAY_OF_YEAR, 1); // 下一天
  135. }
  136. resultMap.clear(); //释放
  137. return resultList;
  138. }
  139. /**
  140. * 获取此段日期内,所有的历史数据,包含自定义的
  141. *
  142. * @param resultMap key-日期,value-此日对应的作息时间集合,包含未来自定义的
  143. * @param existsCustom key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
  144. */
  145. public void selectHistoryDate(Map<String, List<WorkCalendarDate>> resultMap, Map<String, Boolean> existsCustom, WorkCalendarDateQueryVO queryVO) {
  146. List<WorkCalendarDate> dates = this.selectWorkCalendarDateList(queryVO);
  147. for (WorkCalendarDate calendarDate : dates) {
  148. // 是否存在自定义,存在true就不在更新
  149. String existsKey = calendarDate.getCalendarId() + calendarDate.getProjectId() + calendarDate.getWorkDate() + calendarDate.getDictType() + (StringUtil.isBlank(calendarDate.getDictCode()) ? "" : calendarDate.getDictCode());
  150. boolean exists = WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES.equals(calendarDate.getCustomFlag());
  151. if (!BooleanUtil.isTrue(existsCustom.get(existsKey))) {
  152. existsCustom.put(existsKey, exists);
  153. }
  154. // 将自定义的或历史的,按照日期,分组
  155. if (resultMap != null) {
  156. if (resultMap.containsKey(calendarDate.getWorkDate())) {
  157. List<WorkCalendarDate> list = resultMap.get(calendarDate.getWorkDate());
  158. list.add(calendarDate);
  159. } else {
  160. List<WorkCalendarDate> list = new ArrayList<WorkCalendarDate>();
  161. list.add(calendarDate);
  162. resultMap.put(calendarDate.getWorkDate(), list);
  163. }
  164. }
  165. }
  166. }
  167. /**
  168. * 获取满足条件的所有已存在的作息时间信息,包括自定义的
  169. * @param workCalendarDateQueryVO
  170. * @return
  171. */
  172. public List<WorkCalendarDate> selectWorkCalendarDateList(WorkCalendarDateQueryVO workCalendarDateQueryVO) {
  173. QueryWrapper<WorkCalendarDate> queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper()
  174. .projectIdEq(workCalendarDateQueryVO.getProjectId())
  175. .idEq(workCalendarDateQueryVO.getId())
  176. .ruleIdEq(workCalendarDateQueryVO.getRuleId())
  177. .calendarIdEq(workCalendarDateQueryVO.getCalendarId())
  178. .workDateGe(workCalendarDateQueryVO.getWorkDateStart())
  179. .workDateLe(workCalendarDateQueryVO.getWorkDateEnd())
  180. .dictTypeEq(workCalendarDateQueryVO.getDictType())
  181. .dictTypeIn(workCalendarDateQueryVO.getDictTypes())
  182. .dictCodeIn(workCalendarDateQueryVO.getDictCode())
  183. .calendarNameLike(workCalendarDateQueryVO.getCalendarName())
  184. .builderQueryWrapper();
  185. queryWrapper.select("ID, RULE_ID, CALENDAR_ID, PROJECT_ID, CALENDAR_NAME, CALENDAR_DESC, DICT_TYPE, "
  186. + "DICT_CODE, WORK_DATE, WORK_TIME, CUSTOM_FLAG");
  187. List<WorkCalendarDate> list = workCalendarDateService.list(queryWrapper);
  188. return list == null ? new ArrayList<WorkCalendarDate>() : list;
  189. }
  190. /**
  191. * 解析此段时间的规则
  192. * @param betweenDay 时间范围
  193. * @param workDateEnd
  194. * @param workDateStart
  195. * @param ruleList 规则信息
  196. * @param resultMap 已有的作息时间信息
  197. * @param existsCusetom key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
  198. */
  199. public void paserWorkCalendarRule(long betweenDay, DateTime currentDate, List<WorkCalendarRule> ruleList,
  200. Map<String, List<WorkCalendarDate>> resultMap, Map<String, Boolean> existsCustom) {
  201. Map<String, WorkCalendar> calendarMap = new HashMap<String, WorkCalendar>();
  202. for(int i = 0; i < betweenDay; i++) {
  203. // 判断此天有没有对应的规则信息,每次都要循环全部,生成多条信息
  204. for (WorkCalendarRule rule : ruleList) {
  205. // 判断当前规则是否
  206. this.parseWorkCalendarRule(rule, currentDate, calendarMap, resultMap, existsCustom);
  207. }
  208. currentDate.offset(DateField.DAY_OF_YEAR, 1);
  209. }
  210. calendarMap.clear();
  211. }
  212. /**
  213. * 解析规则信息,生成对应作息时间记录
  214. *
  215. * @param rule
  216. * @param currentDate 日期
  217. * @param calendarMap 工作历类型集合
  218. * @param resultMap 等于null时,插库,否则添加进此map
  219. * @param existsCusetom key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
  220. * @return
  221. */
  222. private void parseWorkCalendarRule(WorkCalendarRule rule, DateTime currentDate, Map<String, WorkCalendar> calendarMap,
  223. Map<String, List<WorkCalendarDate>> resultMap, Map<String, Boolean> existsCustom) {
  224. String workDate = currentDate.toString(DateUtil.FORMAT_DATE_YYYYMMDD);
  225. String dictCode = StringUtil.isBlank(rule.getDictCode()) ? "" : rule.getDictCode();
  226. int indexOf = dictCode.indexOf(WorkCalendarConstant.WORK_CALENDAR_D_OF_W);
  227. if (indexOf <= 0) {
  228. indexOf = dictCode.indexOf(WorkCalendarConstant.WORK_CALENDAR_D_OF_M);
  229. if (indexOf <= 0) {
  230. indexOf = dictCode.indexOf(WorkCalendarConstant.WORK_CALENDAR_M_AND_D);
  231. }
  232. }
  233. if (indexOf > 0) {
  234. dictCode = dictCode.substring(0, indexOf - 1);
  235. }
  236. String existsKey = rule.getCalendarId() + rule.getProjectId() + workDate + rule.getDictType() + (StringUtil.isBlank(dictCode) ? "" : dictCode);
  237. // 优先判断当日是否存在同类型 同编码的自定义作息时间
  238. if (existsCustom != null && BooleanUtil.isTrue(existsCustom.get(existsKey))) {
  239. return;
  240. }
  241. // 当不存在自定义的作息时间时
  242. // 解析规则,生成数据
  243. int work = Integer.valueOf(workDate);
  244. String ruleStart = rule.getRuleDateStart();
  245. String ruleEnd = rule.getRuleDateEnd();
  246. if (StringUtil.isNotBlank(ruleStart) && StringUtil.isNotBlank(ruleEnd)) {
  247. int start = Integer.valueOf(ruleStart);
  248. int end = Integer.valueOf(ruleEnd);
  249. if (work >= start && work <= end) {
  250. // 当日期生效
  251. if (indexOf > 0) {
  252. // 验证value是否存在,存在按周 月 解析,判断是否生效
  253. boolean result = this.parseRuleValue(rule, currentDate, workDate);
  254. if (!result) {
  255. return;
  256. }
  257. }
  258. // 组合数据
  259. WorkCalendarDate calendarDate = this.comWorkCalendarOrRule(rule, workDate, dictCode, calendarMap);
  260. if (calendarDate == null) {
  261. return;
  262. }
  263. // 数据添加
  264. this.addCalendarDateResult(workDate, calendarDate, resultMap);
  265. }
  266. }
  267. }
  268. /**
  269. * 解析rule 的 value属性,判断其是否生效
  270. * @param rule
  271. * @param workDate
  272. * @return value为空,默认返回true
  273. */
  274. private boolean parseRuleValue(WorkCalendarRule rule, DateTime currentDate, String workDate) {
  275. if (CollectionUtil.isEmpty(rule.getValue())) {
  276. return true;
  277. }
  278. // 获取月日
  279. String mmddStr = workDate.substring(4, 8);
  280. Integer mmdd = Integer.valueOf(mmddStr);
  281. Set<String> values = rule.getValue();
  282. String dictCode = rule.getDictCode();
  283. String[] split = dictCode.split("-");
  284. dictCode = split[0]; // 真实的code编码
  285. String type = split[1]; // 类型
  286. switch (type) {
  287. case WorkCalendarConstant.WORK_CALENDAR_D_OF_W: //周
  288. // 1表示周日,2表示周一
  289. int dayOfWeek = DateUtil.dayOfWeek(currentDate);
  290. dayOfWeek = dayOfWeek - 1;
  291. if (dayOfWeek == 0) {
  292. dayOfWeek = 7;
  293. }
  294. String num = String.valueOf(dayOfWeek);
  295. if (values.contains(num)) {
  296. return true;
  297. }
  298. break;
  299. case WorkCalendarConstant.WORK_CALENDAR_D_OF_M: //月
  300. // 当前日期为此月的第几天
  301. int ofMonth = DateUtil.dayOfMonth(currentDate);
  302. Iterator<String> iterator = values.iterator();
  303. while(iterator.hasNext()) {
  304. String next = iterator.next();
  305. if (next.contains("-")) {
  306. String[] split2 = next.split("-");
  307. int start = Integer.parseInt(split2[0]);
  308. int end = Integer.parseInt(split2[1]);
  309. if (ofMonth >= start && ofMonth <= end) {
  310. return true;
  311. }
  312. } else if (next.equals(String.valueOf(ofMonth))) {
  313. return true;
  314. }
  315. }
  316. break;
  317. case WorkCalendarConstant.WORK_CALENDAR_M_AND_D: //年
  318. iterator = values.iterator();
  319. while(iterator.hasNext()) {
  320. String next = iterator.next();
  321. if (next.contains("-")) {
  322. String[] split2 = next.split("-");
  323. Integer startInt = Integer.valueOf(split2[0]);
  324. Integer endInt = Integer.valueOf(split2[1]);
  325. if (mmdd >= startInt && mmdd <= endInt) {
  326. return true;
  327. }
  328. } else if (mmddStr.equals(next)) {
  329. return true;
  330. }
  331. }
  332. break;
  333. default:
  334. break;
  335. }
  336. return false;
  337. }
  338. /**
  339. * 响应数据添加
  340. * @param resultMap 为null时插库
  341. */
  342. public void addCalendarDateResult(String workDate, WorkCalendarDate calendarDate, Map<String, List<WorkCalendarDate>> resultMap) {
  343. if (resultMap == null) {
  344. boolean result = this.workCalendarDateService.save(calendarDate);
  345. //boolean result = this.workCalendarDateService.replaceIntoCalendarDate(calendarDate);
  346. if (!result) {
  347. throw new BusinessException("新增作息时间信息失败,规则ID: " + calendarDate.getRuleId());
  348. }
  349. return;
  350. }
  351. if (!resultMap.containsKey(workDate)) {
  352. List<WorkCalendarDate> list = new ArrayList<WorkCalendarDate>();
  353. list.add(calendarDate);
  354. resultMap.put(workDate, list);
  355. return;
  356. }
  357. List<WorkCalendarDate> list = resultMap.get(workDate);
  358. list.add(calendarDate);
  359. }
  360. /**
  361. * 组合出作息时间对象
  362. * @param workCalendar
  363. * @param rule
  364. * @param calendarIds
  365. * @return
  366. */
  367. public WorkCalendarDate comWorkCalendarOrRule(WorkCalendarRule rule, String workDate, String dictCode,
  368. Map<String, WorkCalendar> calendarMap) {
  369. // 首先判断工作历是否还存在
  370. WorkCalendar workCalendar = null;
  371. if (calendarMap.containsKey(rule.getCalendarId())) {
  372. workCalendar = calendarMap.get(rule.getCalendarId());
  373. } else {
  374. workCalendar = this.workCalendarService.getById(rule.getCalendarId(), rule.getProjectId());
  375. calendarMap.put(rule.getCalendarId(), workCalendar);
  376. }
  377. if (workCalendar == null) {
  378. log.warn("规则ID为[{}]的规则,所对应的工作历信息不存在", rule.getId());
  379. return null;
  380. }
  381. WorkCalendarDate workCalendarDate = new WorkCalendarDate();
  382. workCalendarDate.setGroupCode(rule.getGroupCode());
  383. workCalendarDate.setCalendarId(workCalendar.getId());
  384. workCalendarDate.setRuleId(rule.getId());
  385. workCalendarDate.setCalendarName(workCalendar.getCalendarName());
  386. workCalendarDate.setCalendarDesc(workCalendar.getCalendarDesc());
  387. workCalendarDate.setProjectId(rule.getProjectId());
  388. workCalendarDate.setDictType(rule.getDictType());
  389. workCalendarDate.setDictCode(dictCode);
  390. workCalendarDate.setWorkDateStart(rule.getRuleDateStart());
  391. workCalendarDate.setWorkDateEnd(rule.getRuleDateEnd());
  392. workCalendarDate.setWorkDate(workDate);
  393. workCalendarDate.setWorkTime(StringUtil.isBlank(rule.getRuleTime()) ?
  394. (CollectionUtil.isEmpty(rule.getValue()) ? null : rule.getValue().stream().collect(Collectors.joining(",")))
  395. : rule.getRuleTime());
  396. // 自定义的一定是查出来的,封装的一定是非自定义添加的
  397. workCalendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_NO);
  398. workCalendarDate.setUpdateUser(rule.getUpdateUser());
  399. return workCalendarDate;
  400. }
  401. /**
  402. * 获取满足条件的所有新版规则信息
  403. * @param workDatestart
  404. * @param workDateEnd
  405. * @param workCalendarDateQueryVO
  406. * @return
  407. */
  408. public List<WorkCalendarRule> selectWorkCalendarRuleList(String workDatestart, String workDateEnd, WorkCalendarDateQueryVO queryVO) {
  409. QueryWrapper<WorkCalendarRule> queryWrapper = new WorkCalendarRule.Builder().createQueryWrapper()
  410. .projectIdEq(queryVO.getProjectId()).idEq(queryVO.getRuleId())
  411. .calendarIdEq(queryVO.getCalendarId()).ruleDateBetween(workDatestart, workDateEnd)
  412. .dictTypeEq(queryVO.getDictType()).dictCodeIn(queryVO.getDictCode())
  413. .dictTypeIn(queryVO.getDictTypes())
  414. .delFlagEq(WorkCalendarConstant.WORK_CALENDAR_DEL_FLAG_NOR)
  415. .ruleFlagEq(WorkCalendarConstant.WORK_CALENDAR_RULE_FLAG_NEW).builderQueryWrapper();
  416. return this.workCalendarRuleService.list(queryWrapper);
  417. }
  418. /**
  419. * 解析规则信息,并插库
  420. * @param queryVO
  421. * @return
  422. */
  423. @Transactional
  424. public boolean handleParseCalendarRule(WorkCalendarDateQueryVO queryVO) {
  425. // 1.防止重复执行,优先删除从今日开始的非自定义的作息时间信息
  426. QueryWrapper<WorkCalendarDate> queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper()
  427. .projectIdEq(queryVO.getProjectId()).calendarIdEq(queryVO.getCalendarId())
  428. .calendarNameEq(queryVO.getCalendarName()).dictTypeEq(queryVO.getDictType())
  429. .dictCodeIn(queryVO.getDictCode()).workDateGe(queryVO.getWorkDateStart())
  430. .workDateLe(queryVO.getWorkDateEnd()).customFlagEq(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_NO)
  431. .builderQueryWrapper();
  432. this.workCalendarDateService.remove(queryWrapper);
  433. // 1.查询出满足条件的所有的规则信息
  434. List<WorkCalendarRule> ruleList = this.selectWorkCalendarRuleList(queryVO.getWorkDateStart(), queryVO.getWorkDateEnd(), queryVO);
  435. if (CollectionUtil.isNotEmpty(ruleList)) {
  436. // 2.获取此日期内,已存在的自定义的作息时间
  437. // key-项目+日期+type+code,value-true存在自定义信息,false 不存在自定义信息
  438. Map<String, Boolean> existsCustom = new HashMap<String, Boolean>();
  439. // 1.优先获取start~end的作息时间信息,包含自定义的,判断对应日期内是否包含自定义的
  440. this.selectHistoryDate(null, existsCustom, queryVO);
  441. // 3.解析规则信息
  442. DateTime dateStart = DateUtil.parse(queryVO.getWorkDateStart(), DateUtil.FORMAT_DATE_YYYYMMDD);
  443. DateTime dateEnd = DateUtil.parse(queryVO.getWorkDateEnd(), DateUtil.FORMAT_DATE_YYYYMMDD);
  444. long between = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1;
  445. this.paserWorkCalendarRule(between, dateStart, ruleList, null, existsCustom);
  446. }
  447. return true;
  448. }
  449. /**
  450. * 批量自定义作息时间信息
  451. * @return
  452. */
  453. public void batchCreateCalendarDate(CustomCalendarVO<WorkCalendarDateCreateVO> createVO) {
  454. boolean result = false;
  455. List<WorkCalendarDateCreateVO> batchInfos = createVO.getBatchInfo();
  456. // 判断日期是否合法
  457. DateTime now = DateUtil.date();
  458. //now = now.offset(DateField.DAY_OF_YEAR, 1); //明天
  459. String format = DateUtil.format(now, DateUtil.FORMAT_DATE_YYYYMMDD);
  460. Integer current = Integer.valueOf(format);
  461. for (WorkCalendarDateCreateVO batchInfo : batchInfos) {
  462. Integer workDate = Integer.valueOf(batchInfo.getWorkDate());
  463. if (workDate < current) {
  464. throw new BusinessException("作息日期不合法,必须大于等于当日");
  465. }
  466. // 判断工作历类型是否存在
  467. WorkCalendar calendar = this.workCalendarService.getById(batchInfo.getCalendarId(), createVO.getProjectId());
  468. if (calendar == null) {
  469. throw new BusinessException("工作历类型不存在");
  470. }
  471. WorkCalendarDate calendarDate = new WorkCalendarDate();
  472. BeanUtils.copyProperties(batchInfo, calendarDate);
  473. // 验证数据有效性
  474. result = this.workCalendarDateService.checkWorkDateValid(calendarDate);
  475. if (!result) {
  476. throw new BusinessException("当天已存在相同类型额定义,不可重复添加");
  477. }
  478. calendarDate.setGroupCode(createVO.getGroupCode());
  479. calendarDate.setProjectId(createVO.getProjectId());
  480. calendarDate.setUpdateUser(createVO.getUserId());
  481. calendarDate.setCalendarName(calendar.getCalendarName());
  482. calendarDate.setCalendarDesc(calendar.getCalendarDesc());
  483. calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES);
  484. result = this.workCalendarDateService.save(calendarDate);
  485. if (!result) {
  486. throw new BusinessException("自定义工作历作息时间添加失败");
  487. }
  488. }
  489. }
  490. /**
  491. * 批量自定义作息时间信息
  492. * @return
  493. */
  494. public <T> void batchUpdateCalendarDate(CustomCalendarVO<WorkCalendarDateUpdateVO> updateVO) {
  495. boolean result = false;
  496. List<WorkCalendarDateUpdateVO> batchInfos = updateVO.getBatchInfo();
  497. // 判断日期是否合法
  498. DateTime now = DateUtil.date();
  499. //now = now.offset(DateField.DAY_OF_YEAR, 1); //明天
  500. String format = DateUtil.format(now, DateUtil.FORMAT_DATE_YYYYMMDD);
  501. Integer current = Integer.valueOf(format);
  502. for (WorkCalendarDateUpdateVO batchInfo : batchInfos) {
  503. Integer workDate = Integer.valueOf(batchInfo.getWorkDate());
  504. if (workDate < current) {
  505. throw new BusinessException("作息日期不合法,必须大于等于当日");
  506. }
  507. // 判断工作历类型是否存在
  508. WorkCalendar calendar = this.workCalendarService.getById(batchInfo.getCalendarId(), updateVO.getProjectId());
  509. if (calendar == null) {
  510. throw new BusinessException("工作历类型不存在");
  511. }
  512. WorkCalendarDate calendarDate = new WorkCalendarDate();
  513. BeanUtils.copyProperties(batchInfo, calendarDate);
  514. // 验证数据有效性
  515. result = this.workCalendarDateService.checkWorkDateValid(calendarDate);
  516. if (!result) {
  517. throw new BusinessException("当天已存在相同类型的定义,不可重复添加");
  518. }
  519. calendarDate.setGroupCode(updateVO.getGroupCode());
  520. calendarDate.setProjectId(updateVO.getProjectId());
  521. calendarDate.setUpdateUser(updateVO.getUserId());
  522. calendarDate.setCalendarName(calendar.getCalendarName());
  523. calendarDate.setCalendarDesc(calendar.getCalendarDesc());
  524. calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES);
  525. result = this.workCalendarDateService.updateById(calendarDate);
  526. if (!result) {
  527. throw new BusinessException("自定义工作历作息时间添加失败");
  528. }
  529. }
  530. }
  531. /**
  532. * 多时间段添加工作历作息时间信息,先删除此dictType下数据,再添加
  533. * @param createVO
  534. * @param calendar
  535. */
  536. @Transactional
  537. public void batchCreateCalendarMoreDate(WorkCalendarMoreDateCreateVO createVO, WorkCalendar calendar) {
  538. String calendarId = createVO.getCalendarId();
  539. String projectId = createVO.getProjectId();
  540. String now = DateUtil.format(new Date(), DateUtil.FORMAT_DATE_YYYYMMDDHHMMSS);
  541. DateTime dateStart = DateUtil.parse(createVO.getWorkDateStart(), DateUtil.FORMAT_DATE_YYYYMMDD);
  542. DateTime dateEnd = DateUtil.parse(createVO.getWorkDateEnd(), DateUtil.FORMAT_DATE_YYYYMMDD);
  543. long betweenDay = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1;
  544. Set<String> timetables = createVO.getTimetable();
  545. List<WorkCalendarDate> datas = new ArrayList<WorkCalendarDate>();
  546. for (int i = 0; i < betweenDay; i++) {
  547. String currentDay = DateUtil.format(dateStart, DateUtil.FORMAT_DATE_YYYYMMDD);
  548. if (CollectionUtil.isEmpty(timetables)) {
  549. WorkCalendarDate calendarDate = this.setCalendarDate(createVO, calendar, currentDay, null, now);
  550. datas.add(calendarDate);
  551. } else {
  552. for (String timetable : timetables) {
  553. // 数据库数据组装
  554. WorkCalendarDate calendarDate = this.setCalendarDate(createVO, calendar, currentDay, timetable, now);
  555. datas.add(calendarDate);
  556. }
  557. }
  558. // 偏移天数
  559. dateStart.offset(DateField.DAY_OF_YEAR, 1);
  560. }
  561. // 先删除
  562. QueryWrapper<WorkCalendarDate> queryWrapper = new WorkCalendarDate.Builder().createQueryWrapper()
  563. .calendarIdEq(calendarId).projectIdEq(projectId).dictTypeEq(createVO.getDictType())
  564. .workDateGe(createVO.getWorkDateStart()).workDateLe(createVO.getWorkDateEnd())
  565. .customFlagEq(createVO.getCustomFlag()).builderQueryWrapper();
  566. this.workCalendarDateService.remove(queryWrapper);
  567. // 批量添加数据
  568. this.workCalendarDateService.batchCreateCalendarDate(datas);
  569. }
  570. /**
  571. * 参数赋值
  572. * @param createVO
  573. * @param calendar
  574. * @param currentDay
  575. * @param timetable
  576. * @param now
  577. * @return
  578. */
  579. private WorkCalendarDate setCalendarDate(WorkCalendarMoreDateCreateVO createVO, WorkCalendar calendar,
  580. String currentDay, String timetable, String now) {
  581. WorkCalendarDate calendarDate = new WorkCalendarDate();
  582. calendarDate.setId(IdGenerator.getSnowIdStr(WorkCalendarConstant.WORK_CALENDAR_DATE_ID_PREFIX));
  583. calendarDate.setGroupCode(createVO.getGroupCode());
  584. calendarDate.setProjectId(createVO.getProjectId());
  585. calendarDate.setCalendarId(createVO.getCalendarId());
  586. calendarDate.setCustomFlag(WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES);
  587. calendarDate.setCalendarName(calendar.getCalendarName());
  588. calendarDate.setCalendarDesc(calendar.getCalendarDesc());
  589. calendarDate.setDictType(createVO.getDictType());
  590. calendarDate.setDictCode(createVO.getDictCode());
  591. calendarDate.setWorkDate(currentDay);
  592. calendarDate.setWorkTime(timetable);
  593. calendarDate.setCreateTime(now);
  594. calendarDate.setUpdateTime(now);
  595. calendarDate.setUpdateUser(createVO.getUserId());
  596. return calendarDate;
  597. }
  598. /**
  599. * 检查参数日期是否大于当前日期
  600. * @param workDate 工作日期 yyyyMMdd
  601. * @return
  602. */
  603. public static boolean isMoreThanToday(String workDate) {
  604. DateTime now = DateUtil.date();
  605. //now = now.offset(DateField.DAY_OF_YEAR, 1); //明天
  606. String format = DateUtil.format(now, DateUtil.FORMAT_DATE_YYYYMMDD);
  607. Integer current = Integer.valueOf(format);
  608. Integer dateInt = Integer.valueOf(workDate);
  609. if (dateInt < current) {
  610. return false;
  611. }
  612. return true;
  613. }
  614. }