WorkCalendarLabelHandler.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. package com.persagy.calendar.handle;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.Date;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Set;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.apache.commons.lang3.StringUtils;
  11. import org.springframework.beans.BeanUtils;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.stereotype.Component;
  14. import org.springframework.transaction.annotation.Transactional;
  15. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  16. import com.google.common.collect.Lists;
  17. import com.persagy.calendar.constant.WorkCalendarConstant;
  18. import com.persagy.calendar.pojo.dto.WorkCalendar;
  19. import com.persagy.calendar.pojo.dto.WorkCalendarDict;
  20. import com.persagy.calendar.pojo.dto.WorkCalendarLabel;
  21. import com.persagy.calendar.pojo.dto.WorkCalendarLabel.Builder;
  22. import com.persagy.calendar.pojo.dto.WorkCalendarObject;
  23. import com.persagy.calendar.pojo.vo.WorkCalendarLabelQueryVO;
  24. import com.persagy.calendar.pojo.vo.WorkCalendarLabelUpdateVO;
  25. import com.persagy.calendar.pojo.vo.WorkCalendarMoreDateCreateVO;
  26. import com.persagy.calendar.pojo.vo.WorkLabelBatchUpdateVO;
  27. import com.persagy.calendar.service.IWorkCalendarDictService;
  28. import com.persagy.calendar.service.IWorkCalendarLabelService;
  29. import com.persagy.calendar.service.IWorkCalendarObjectService;
  30. import com.persagy.calendar.service.IWorkCalendarService;
  31. import com.persagy.common.enums.ResponseCode;
  32. import com.persagy.common.exception.BusinessException;
  33. import com.persagy.common.utils.DateUtil;
  34. import com.persagy.common.utils.IdGenerator;
  35. import com.persagy.common.utils.ResponseResult;
  36. import com.persagy.common.utils.ResponseUtil;
  37. import com.persagy.common.utils.StringUtil;
  38. import cn.hutool.core.collection.CollectionUtil;
  39. import cn.hutool.core.date.DateField;
  40. import cn.hutool.core.date.DateTime;
  41. import cn.hutool.core.date.DateUnit;
  42. import cn.hutool.core.util.BooleanUtil;
  43. /**
  44. * @version
  45. * @description
  46. * @company persagy
  47. * @author zhangqiankun
  48. * @since 2021年3月3日: 下午6:14:49
  49. */
  50. @Component
  51. @Slf4j
  52. public class WorkCalendarLabelHandler {
  53. public static final String LABEL_COLUMN = "GROUP_CODE, PROJECT_ID, CALENDAR_ID, DICT_TYPE, DICT_CODE, DIY_LABEL, DIY_VALUE, LABEL_DATE, CONVERT(SUBSTR(LABEL_DATE, 5, 2), SIGNED) AS labelMonth, CREATE_TIME, UPDATE_TIME, UPDATE_USER";
  54. @Autowired
  55. private IWorkCalendarService workCalendarService;
  56. @Autowired
  57. private IWorkCalendarLabelService workCalendarLabelService;
  58. @Autowired
  59. private IWorkCalendarDictService workCalendarDictService;
  60. @Autowired
  61. private WorkCalendarDateHandler workCalendarDateHandler;
  62. @Autowired
  63. private IWorkCalendarObjectService workCalendarObjectService;
  64. /**
  65. * 日期标签属性列表查询
  66. *
  67. * @param queryVO
  68. * @return
  69. */
  70. public List<WorkCalendarLabel> queryCalendarLabelList(WorkCalendarLabelQueryVO queryVO) {
  71. // 获取字典类型的级别
  72. int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(queryVO.getGroupCode(), queryVO.getDictType());
  73. // 获取字典类型的级别 Bd Pj37030300011 f5546f29cd64d75b57514cbb621da48
  74. if (StringUtils.isBlank(queryVO.getProjectId()) && StringUtils.isNotBlank(queryVO.getObjId())) {
  75. String objId = queryVO.getObjId();
  76. queryVO.setProjectId(getProjectId(objId));
  77. }
  78. // 如果条件为对象ID,且属于工作历级别的类型,反查出工作历ID,再进行查询
  79. if (StringUtil.isNotBlank(queryVO.getObjId()) && dictTypeLevel == 2) {
  80. //查询出此对象对应的工作历ID和项目ID
  81. QueryWrapper<WorkCalendarObject> objectWrapper = new WorkCalendarObject.Builder().createQueryWrapper()
  82. .groupCodeEq(queryVO.getGroupCode()).objectIdEq(queryVO.getObjId())
  83. .projectIdEq(queryVO.getProjectId()).builderQueryWrapper();
  84. WorkCalendarObject calendarObject = this.workCalendarObjectService.getOne(objectWrapper);
  85. if (calendarObject == null) {
  86. return null;
  87. }
  88. queryVO.setCalendarId(calendarObject.getCalendarId());
  89. }
  90. QueryWrapper<WorkCalendarLabel> queryWrapper = new WorkCalendarLabel.Builder().createQueryWrapper().groupCodeEq(queryVO.getGroupCode())
  91. .projectIdEq(queryVO.getProjectId(), dictTypeLevel).calendarIdEq(queryVO.getCalendarId(), dictTypeLevel)
  92. .dictTypeEq(queryVO.getDictType()).dictCodeEq(queryVO.getDictCode()).diyLabelEq(queryVO.getDiyLabel())
  93. .labelDateGe(queryVO.getLabelDateStart()).labelDateLe(queryVO.getLabelDateEnd()).builderQueryWrapper();
  94. return this.workCalendarLabelService.list(queryWrapper.select(LABEL_COLUMN).orderByAsc(Lists.newArrayList("LABEL_DATE", "ID")));
  95. }
  96. private String getProjectId(String objId) {
  97. try {
  98. return "Pj" + objId.substring(2, 12);
  99. } catch (Exception ex) {
  100. log.warn("WorkCalendarLabelHandler getProjectId error:", ex);
  101. }
  102. return "";
  103. }
  104. /**
  105. * 查询标签的有效期,仅允许查询某一项目、某一标签对应的有效期
  106. *
  107. * @param queryVO
  108. * @return
  109. */
  110. public List<WorkCalendarLabel> queryCalendarLabelValid(WorkCalendarLabelQueryVO queryVO) {
  111. // 获取字典类型的级别
  112. int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(queryVO.getGroupCode(), queryVO.getDictType());
  113. if (StringUtil.isNotBlank(queryVO.getObjId()) && dictTypeLevel == 2) {
  114. //查询出此对象对应的工作历ID和项目ID
  115. QueryWrapper<WorkCalendarObject> objectWrapper = new WorkCalendarObject.Builder().createQueryWrapper()
  116. .groupCodeEq(queryVO.getGroupCode()).objectIdEq(queryVO.getObjId())
  117. .projectIdEq(queryVO.getProjectId()).builderQueryWrapper();
  118. WorkCalendarObject calendarObject = this.workCalendarObjectService.getOne(objectWrapper);
  119. if (calendarObject == null) {
  120. return null;
  121. }
  122. queryVO.setCalendarId(calendarObject.getCalendarId());
  123. }
  124. // 获取字典类型的级别 Bd Pj37030300011 f5546f29cd64d75b57514cbb621da48
  125. if (StringUtils.isBlank(queryVO.getProjectId()) && StringUtils.isNotBlank(queryVO.getObjId())) {
  126. String objId = queryVO.getObjId();
  127. queryVO.setProjectId(getProjectId(objId));
  128. }
  129. QueryWrapper<WorkCalendarLabel> queryWrapper = new WorkCalendarLabel.Builder().createQueryWrapper().groupCodeEq(queryVO.getGroupCode())
  130. .projectIdEq(queryVO.getProjectId(), dictTypeLevel).calendarIdEq(queryVO.getCalendarId(), dictTypeLevel)
  131. .dictTypeEq(queryVO.getDictType()).dictCodeEq(queryVO.getDictCode()).diyLabelEq(queryVO.getDiyLabel())
  132. .labelDateGe(queryVO.getLabelDateStart()).labelDateLe(queryVO.getLabelDateEnd()).builderQueryWrapper();
  133. queryWrapper.select("GROUP_CODE, PROJECT_ID, CALENDAR_ID, DICT_TYPE, DICT_CODE, LABEL_DATE, DIY_LABEL").orderByAsc("DICT_CODE");
  134. List<WorkCalendarLabel> labels = this.workCalendarLabelService.list(queryWrapper);
  135. return this.convert2Response(labels);
  136. }
  137. /**
  138. * 结果封装
  139. *
  140. * @param labels 此集合内容,必须是同一项目、同一标签类型下的数据
  141. * @return
  142. */
  143. private List<WorkCalendarLabel> convert2Response(List<WorkCalendarLabel> labels) {
  144. if (CollectionUtil.isEmpty(labels)) {
  145. return null;
  146. }
  147. // 生成响应的数据结构
  148. Map<String, WorkCalendarLabel> dictCode2Label = new HashMap<String, WorkCalendarLabel>();
  149. Map<String, List<String>> dictCode2Date = new HashMap<String, List<String>>();
  150. for (WorkCalendarLabel workCalendarLabel : labels) {
  151. String dictCode = workCalendarLabel.getDictCode();
  152. if (!dictCode2Label.containsKey(dictCode)) {
  153. dictCode2Label.put(dictCode, workCalendarLabel);
  154. }
  155. if (dictCode2Date.containsKey(dictCode)) {
  156. dictCode2Date.get(dictCode).add(workCalendarLabel.getLabelDate());
  157. } else {
  158. dictCode2Date.put(dictCode, Lists.newArrayList(workCalendarLabel.getLabelDate()));
  159. }
  160. }
  161. List<WorkCalendarLabel> resultList = new ArrayList<WorkCalendarLabel>();
  162. // 解析出对应code每个时间段内的最小日期和最大日期
  163. Set<String> dictCodes = dictCode2Date.keySet();
  164. for (String dictCode : dictCodes) {
  165. List<String> labelDates = dictCode2Date.get(dictCode);
  166. WorkCalendarLabel calendarLabel = dictCode2Label.get(dictCode);
  167. if (labelDates.size() == 1) {
  168. resultList.add(this.convert2Response(calendarLabel, null, null));
  169. continue;
  170. }
  171. // 先排序
  172. Collections.sort(labelDates);
  173. int size = labelDates.size();
  174. String preDate = labelDates.get(0);
  175. String minDate = labelDates.get(0);
  176. DateTime currentDate = null;
  177. DateTime preDateTime = DateUtil.parse(labelDates.get(0), DateUtil.FORMAT_DATE_YYYYMMDD);
  178. for (int i = 1; i < size; i++) {
  179. // 获取当前时间和日期
  180. String labelDate = labelDates.get(i);
  181. currentDate = DateUtil.parse(labelDate, DateUtil.FORMAT_DATE_YYYYMMDD);
  182. // 当前时间往前偏移一天,判断是否相等
  183. currentDate.offset(DateField.DAY_OF_YEAR, -1);
  184. if (preDateTime.equals(currentDate)) {
  185. } else {
  186. // 两个日期不相等的情况下,证明当前日期不连续,封装响应结果
  187. resultList.add(this.convert2Response(calendarLabel, minDate, preDate));
  188. minDate = labelDate;
  189. }
  190. // 无论哪种情况下,都需要为上一日期赋最新值
  191. preDate = labelDate;
  192. preDateTime = DateUtil.parse(labelDate, DateUtil.FORMAT_DATE_YYYYMMDD);
  193. // 最后一天无论与之前的相不相等,都应该封装响应结果
  194. if (i == (size - 1)) {
  195. resultList.add(this.convert2Response(calendarLabel, minDate, labelDate));
  196. }
  197. }
  198. }
  199. return resultList;
  200. }
  201. /**
  202. * 创建或更新日期标签属性
  203. *
  204. * @param createVO
  205. */
  206. @Transactional
  207. public void updateLabelInfo(WorkCalendarLabelUpdateVO updateVO) {
  208. // 获取字典类型的级别
  209. int dictTypeLevel = this.workCalendarDictService.getDictTypeLevel(updateVO.getGroupCode(), updateVO.getDictType());
  210. boolean result = false;
  211. if (BooleanUtil.isTrue(updateVO.getIsDelete())) {
  212. Builder builder = new WorkCalendarLabel.Builder().createQueryWrapper();
  213. QueryWrapper<WorkCalendarLabel> queryWrapper = builder.groupCodeEq(updateVO.getGroupCode())
  214. .projectIdEq(updateVO.getProjectId(), dictTypeLevel).calendarIdEq(updateVO.getCalendarId(), dictTypeLevel)
  215. .labelDateGe(updateVO.getLabelDateStart()).labelDateLe(updateVO.getLabelDateEnd())
  216. .dictTypeEq(updateVO.getDictType()).diyLabelEq(updateVO.getDiyLabel()).builderQueryWrapper();
  217. this.workCalendarLabelService.remove(queryWrapper);
  218. return;
  219. } else if (BooleanUtil.isTrue(updateVO.getIsUpdate())) {
  220. Builder builder = new WorkCalendarLabel.Builder().createQueryWrapper();
  221. QueryWrapper<WorkCalendarLabel> queryWrapper = builder.groupCodeEq(updateVO.getGroupCode())
  222. .projectIdEq(updateVO.getProjectId(), dictTypeLevel).calendarIdEq(updateVO.getCalendarId(), dictTypeLevel)
  223. .labelDateGe(updateVO.getLabelDateStart()).labelDateLe(updateVO.getLabelDateEnd())
  224. .dictTypeEq(updateVO.getDictType()).diyLabelEq(updateVO.getDiyLabel()).builderQueryWrapper();
  225. this.workCalendarLabelService.remove(queryWrapper);
  226. }
  227. WorkCalendarLabel calendarLabel = new WorkCalendarLabel();
  228. BeanUtils.copyProperties(updateVO, calendarLabel);
  229. String now = DateUtil.format(new Date(), DateUtil.FORMAT_DATE_YYYYMMDDHHMMSS);
  230. calendarLabel.setCreateTime(now);
  231. calendarLabel.setUpdateTime(now);
  232. calendarLabel.setUpdateUser(updateVO.getUserId());
  233. calendarLabel.setGroupCode(updateVO.getGroupCode());
  234. if (dictTypeLevel == 0) {
  235. // 集团级
  236. calendarLabel.setCalendarId("0");
  237. calendarLabel.setProjectId("0");
  238. } else if (dictTypeLevel == 1) {
  239. // 项目级
  240. calendarLabel.setCalendarId("0");
  241. }
  242. DateTime dateStart = DateUtil.parse(updateVO.getLabelDateStart(), DateUtil.FORMAT_DATE_YYYYMMDD);
  243. DateTime dateEnd = DateUtil.parse(updateVO.getLabelDateEnd(), DateUtil.FORMAT_DATE_YYYYMMDD);
  244. long betweenDay = DateUtil.between(dateStart, dateEnd, DateUnit.DAY) + 1;
  245. for (int i = 0; i < betweenDay; i++) {
  246. calendarLabel.setId(null);
  247. calendarLabel.setLabelDate(DateUtil.format(dateStart, DateUtil.FORMAT_DATE_YYYYMMDD));
  248. if (WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES.equals(updateVO.getDiyLabel())) {
  249. calendarLabel.setDictType(WorkCalendarConstant.CUSTOM_CALENDAR_DICT_TYPE);
  250. }
  251. result = this.workCalendarLabelService.save(calendarLabel);
  252. if (!result) {
  253. throw new BusinessException("日期标签属性设置失败");
  254. }
  255. dateStart.offset(DateField.DAY_OF_YEAR, 1);
  256. }
  257. // 设置成功后,将自定义的标签插入到字典表中
  258. if (WorkCalendarConstant.CUSTOM_CALENDAR_DATE_YES.equals(updateVO.getDiyLabel())) {
  259. // 当自定义标签时,存入字典表
  260. List<WorkCalendarDict> calendarDicts = new ArrayList<WorkCalendarDict>();
  261. Set<String> diyValues = updateVO.getDiyValue();
  262. for (String diyValue : diyValues) {
  263. WorkCalendarDict calendarDict = new WorkCalendarDict();
  264. calendarDict.setId(IdGenerator.getUUID());
  265. calendarDict.setCalendarId(updateVO.getCalendarId());
  266. calendarDict.setProjectId(updateVO.getProjectId());
  267. calendarDict.setGroupCode(updateVO.getGroupCode());
  268. calendarDict.setDictType(WorkCalendarConstant.CUSTOM_CALENDAR_DICT_TYPE);
  269. calendarDict.setDictDesc(diyValue);
  270. calendarDicts.add(calendarDict);
  271. }
  272. this.workCalendarDictService.batchCreateDictTypeByDelete(calendarDicts);
  273. }
  274. }
  275. /**
  276. * 重新定义日期段内每天的属性标签
  277. *
  278. * @param updateVO
  279. */
  280. @Transactional
  281. public void updateCalendarDateAttribute(WorkLabelBatchUpdateVO updateVO) {
  282. List<WorkCalendarMoreDateCreateVO> times = updateVO.getTimes();
  283. if (CollectionUtil.isNotEmpty(times)) {
  284. // 自定义时间时,一定是属于某个工作历下的,不用判断标签所属
  285. for (WorkCalendarMoreDateCreateVO moreDateCreateVO : times) {
  286. // 判断工作历类型是否存在
  287. WorkCalendar calendar = this.workCalendarService.getById(moreDateCreateVO.getCalendarId(), moreDateCreateVO.getGroupCode(), moreDateCreateVO.getProjectId());
  288. if (calendar == null) {
  289. throw new BusinessException("工作历类型不存在");
  290. }
  291. moreDateCreateVO.setGroupCode(updateVO.getGroupCode());
  292. this.workCalendarDateHandler.batchCreateCalendarMoreDate(moreDateCreateVO, calendar);
  293. }
  294. }
  295. List<WorkCalendarLabelUpdateVO> labels = updateVO.getLabels();
  296. if (CollectionUtil.isNotEmpty(labels)) {
  297. for (WorkCalendarLabelUpdateVO labelUpdateVO : labels) {
  298. labelUpdateVO.setGroupCode(updateVO.getGroupCode());
  299. this.updateLabelInfo(labelUpdateVO);
  300. }
  301. }
  302. }
  303. /**
  304. * 检查数据的有效性
  305. * @param updateVO
  306. * @return null - 有效
  307. */
  308. public static ResponseResult checkDataValidity(WorkCalendarLabelUpdateVO updateVO) {
  309. if (WorkCalendarConstant.CUSTOM_CALENDAR_DATE_NO.equals(updateVO.getDiyLabel())) {
  310. if (StringUtil.isBlank(updateVO.getDictType())) {
  311. return ResponseUtil.errorResult(ResponseCode.A0400.getCode(), "字典类型不可为空");
  312. }
  313. if (BooleanUtil.isFalse(updateVO.getIsDelete())) {
  314. if (StringUtil.isBlank(updateVO.getDictCode())) {
  315. return ResponseUtil.errorResult(ResponseCode.A0400.getCode(), "字典编码不可为空");
  316. }
  317. if (CollectionUtil.isNotEmpty(updateVO.getDiyValue())) {
  318. return ResponseUtil.errorResult(ResponseCode.A0400.getCode(), "非自定义情况下,diyValue必须为空");
  319. }
  320. }
  321. } else {
  322. if (BooleanUtil.isFalse(updateVO.getIsDelete())) {
  323. if (CollectionUtil.isEmpty(updateVO.getDiyValue())) {
  324. return ResponseUtil.errorResult(ResponseCode.A0400.getCode(), "自定义标签值不可为空");
  325. }
  326. if (StringUtil.isNotBlank(updateVO.getDictType()) || StringUtil.isNotBlank(updateVO.getDictCode())) {
  327. return ResponseUtil.errorResult(ResponseCode.A0400.getCode(), "自定义情况下,字典类型和字典编码必须为空");
  328. }
  329. }
  330. }
  331. return null;
  332. }
  333. /**
  334. * 转为响应数据
  335. *
  336. * @param temp
  337. * @param labelDateStart
  338. * @param labelDateEnd
  339. * @return
  340. */
  341. private WorkCalendarLabel convert2Response(WorkCalendarLabel temp, String labelDateStart, String labelDateEnd) {
  342. WorkCalendarLabel result = new WorkCalendarLabel();
  343. BeanUtils.copyProperties(temp, result);
  344. result.setLabelDate(null);
  345. result.setLabelDateStart(labelDateStart == null ? temp.getLabelDate() : labelDateStart);
  346. result.setLabelDateEnd(labelDateEnd == null ? temp.getLabelDate() : labelDateEnd);
  347. return result;
  348. }
  349. }