JianyuekbScheduleTask.java 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. package com.xjrsoft.module.job;
  2. import cn.hutool.core.convert.Convert;
  3. import cn.hutool.core.util.IdUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import cn.hutool.db.Entity;
  6. import cn.hutool.extra.spring.SpringUtil;
  7. import com.alibaba.fastjson.JSONObject;
  8. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  9. import com.fasterxml.jackson.core.type.TypeReference;
  10. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  11. import com.google.gson.JsonArray;
  12. import com.xjrsoft.common.enums.CourseAdjustTypeEnum;
  13. import com.xjrsoft.common.enums.EnabledMark;
  14. import com.xjrsoft.common.enums.WorkflowApproveType;
  15. import com.xjrsoft.common.enums.WorkflowMultiInstanceType;
  16. import com.xjrsoft.common.mybatis.SqlRunnerAdapter;
  17. import com.xjrsoft.common.utils.RedisUtil;
  18. import com.xjrsoft.common.utils.VoToColumnUtil;
  19. import com.xjrsoft.config.CommonPropertiesConfig;
  20. import com.xjrsoft.module.base.entity.BaseClass;
  21. import com.xjrsoft.module.base.service.IBaseClassService;
  22. import com.xjrsoft.module.courseTable.dto.ClassTeacherDto;
  23. import com.xjrsoft.module.courseTable.entity.CourseTable;
  24. import com.xjrsoft.module.courseTable.service.ICourseTableService;
  25. import com.xjrsoft.module.organization.dto.WeChatSendMessageDto;
  26. import com.xjrsoft.module.organization.entity.User;
  27. import com.xjrsoft.module.organization.service.IUserService;
  28. import com.xjrsoft.module.organization.service.IWeChatService;
  29. import com.xjrsoft.module.schedule.entity.CourseTableBak;
  30. import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
  31. import com.xjrsoft.module.schedule.service.ICourseTableBakService;
  32. import com.xjrsoft.module.schedule.service.IWfCourseAdjustService;
  33. import com.xjrsoft.module.schedule.util.DataUtil;
  34. import com.xjrsoft.module.teacher.entity.BaseTeacher;
  35. import com.xjrsoft.module.workflow.constant.WorkflowConstant;
  36. import com.xjrsoft.module.workflow.entity.WorkflowExtra;
  37. import com.xjrsoft.module.workflow.entity.WorkflowFormRelation;
  38. import com.xjrsoft.module.workflow.entity.WorkflowRecord;
  39. import com.xjrsoft.module.workflow.entity.XjrWorkflowOperateRecord;
  40. import com.xjrsoft.module.workflow.mapper.XjrWorkflowOperateRecordMapper;
  41. import com.xjrsoft.module.workflow.service.IWorkflowExecuteService;
  42. import com.xjrsoft.module.workflow.service.IWorkflowExtraService;
  43. import com.xjrsoft.module.workflow.service.IWorkflowFormRelationService;
  44. import com.xjrsoft.module.workflow.service.IWorkflowRecordService;
  45. import lombok.extern.slf4j.Slf4j;
  46. import me.zhyd.oauth.log.Log;
  47. import org.camunda.bpm.engine.RuntimeService;
  48. import org.camunda.bpm.engine.TaskService;
  49. import org.camunda.bpm.engine.history.HistoricProcessInstance;
  50. import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
  51. import org.camunda.bpm.engine.runtime.ActivityInstance;
  52. import org.camunda.bpm.engine.runtime.ProcessInstance;
  53. import org.camunda.bpm.engine.task.Task;
  54. import org.springframework.beans.factory.annotation.Autowired;
  55. import org.springframework.scheduling.annotation.Async;
  56. import org.springframework.scheduling.annotation.Scheduled;
  57. import org.springframework.stereotype.Component;
  58. import java.text.SimpleDateFormat;
  59. import java.time.LocalDate;
  60. import java.time.LocalDateTime;
  61. import java.time.format.DateTimeFormatter;
  62. import java.time.temporal.ChronoUnit;
  63. import java.util.ArrayList;
  64. import java.util.Date;
  65. import java.util.HashMap;
  66. import java.util.HashSet;
  67. import java.util.List;
  68. import java.util.Map;
  69. import java.util.Optional;
  70. import java.util.Set;
  71. import java.util.concurrent.CompletableFuture;
  72. import java.util.stream.Collectors;
  73. /**
  74. * @author dzx
  75. * @date 2024/1/25
  76. */
  77. @Component
  78. @Slf4j
  79. public class JianyuekbScheduleTask {
  80. private final static String taskKey = "jianyuekbScheduleTask";
  81. private final static String wechatTemplate = "OO5Ryu9_6Hh5LQW0aKG7qu3g5uV8VxvBusq1i5UFesk";
  82. private final static String noticeTeacherTemplate = "sHsmz7LRj7HLd7GSTS3r2jCLvK-4Wp19iGzEvYK8n_I";
  83. @Autowired
  84. private IBaseClassService classService;
  85. @Autowired
  86. private RedisUtil redisUtil;
  87. @Autowired
  88. private IWfCourseAdjustService adjustService;
  89. @Autowired
  90. private ICourseTableService courseTableService;
  91. @Autowired
  92. private ICourseTableBakService courseTableBakService;
  93. @Autowired
  94. private RuntimeService runtimeService;
  95. @Autowired
  96. private IWorkflowFormRelationService formRelationService;
  97. @Autowired
  98. private TaskService taskService;
  99. @Autowired
  100. private IWorkflowExecuteService workflowExecuteService;
  101. @Autowired
  102. private IWorkflowRecordService workflowRecordService;
  103. @Autowired
  104. private XjrWorkflowOperateRecordMapper xjrWorkflowOperateRecordMapper;
  105. @Autowired
  106. private IWeChatService weChatService;
  107. @Autowired
  108. private CommonPropertiesConfig commonPropertiesConfig;
  109. @Autowired
  110. private IUserService userService;
  111. @Autowired
  112. private IWorkflowExtraService workflowExtraService;
  113. @Async
  114. @Scheduled(cron = "0 */10 * * * ?")
  115. public void execute() {
  116. doExecute();
  117. }
  118. public void doExecute() {
  119. String active = SpringUtil.getActiveProfile();
  120. if (!"prod".equals(active)) {
  121. log.info("非正式环境,无法执行获取课表数据");
  122. return;
  123. }
  124. String sql = "SELECT * FROM course_receive_msg WHERE delete_mark = 0 AND is_callback IS NULL";
  125. List<Map<String, Object>> receiveMsgs = SqlRunnerAdapter.db().selectList(sql);
  126. if (receiveMsgs.isEmpty()) {
  127. return;
  128. }
  129. syncCourseTable(receiveMsgs);
  130. }
  131. public void syncCourseTable(List<Map<String, Object>> receiveMsgs) {
  132. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  133. //查询出传入排课系统的年级和班级
  134. List<String> eduYearSerialNo1 = receiveMsgs.stream().map(x -> "'" + x.get("edu_year_serial_no").toString() + "'").collect(Collectors.toList());
  135. //查询出传入排课系统的年级和班级
  136. String sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''" +
  137. " and table_name = 'base_grade'" +
  138. " and jianyue_id in (" + eduYearSerialNo1.toString().replace("[", "").replace("]", "") + ")";
  139. List<Map<String, Object>> jianyueData = SqlRunnerAdapter.db().selectList(sql);
  140. Map<String, List<Long>> gradeClassMaps = new HashMap<>();//存入对应年级的所有班级id
  141. for (Map<String, Object> el : jianyueData) {
  142. String clasSql = "select source_id from jianyue_data where extend_data = '" + el.get("jianyue_id").toString() + "'";
  143. List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(clasSql);
  144. List<Long> classList = new ArrayList<>();
  145. for (Map<String, Object> objectMap : list) {
  146. classList.add(Long.parseLong(objectMap.get("source_id").toString()));
  147. }
  148. gradeClassMaps.put(el.get("jianyue_id").toString(), classList);
  149. }
  150. LocalDate today = LocalDate.now();
  151. DataUtil dataUtil = new DataUtil();
  152. Set<String> ongoing = redisUtil.get(taskKey, new TypeReference<>() {
  153. });//正在进行中的
  154. if (ongoing == null) {
  155. ongoing = new HashSet<>();
  156. }
  157. Map<String, Map<String, String>> dataMap = initDataMap();
  158. for (Map<String, Object> receiveMsg : receiveMsgs) {
  159. String eduYearSerialNo = receiveMsg.get("edu_year_serial_no").toString();
  160. if (ongoing.contains(eduYearSerialNo)) {
  161. continue;
  162. }
  163. ongoing.add(eduYearSerialNo);
  164. redisUtil.set(taskKey, ongoing);
  165. try {
  166. String updSql = "update course_receive_msg set is_callback = 0 where id = " + receiveMsg.get("id").toString();
  167. SqlRunnerAdapter.db().update(updSql);
  168. JsonArray allScheduleInfo = new JsonArray();
  169. String startDateStr = receiveMsg.get("start_date").toString();
  170. LocalDate startDateObj = LocalDate.parse(startDateStr);
  171. String endDateStr = receiveMsg.get("end_date").toString();
  172. LocalDate endDateObj = LocalDate.parse(endDateStr);
  173. if (today.isAfter(startDateObj)) {
  174. startDateStr = today.format(formatter);
  175. }
  176. //删除课表信息;
  177. List<Long> classIdList = gradeClassMaps.get(eduYearSerialNo);
  178. String classIds = classIdList.toString().replace("[", "").replace("]", "");
  179. String delSql = "delete from course_table where schedule_date between '" + startDateStr + "'" +
  180. " and '" + endDateStr +
  181. "' and class_id in (" + classIds + ")";
  182. SqlRunnerAdapter.db().delete(delSql);
  183. startDateStr = receiveMsg.get("start_date").toString();
  184. List<String> processIds = suspendedCourseAdjust(classIdList, startDateStr, endDateStr);
  185. long between = ChronoUnit.DAYS.between(startDateObj, endDateObj);
  186. int times = Integer.parseInt(((between / 7) + 1) + "");
  187. for (int index = 0; index < times; index++) {
  188. LocalDate statrTime = startDateObj.plusDays(index * 7L);
  189. String startDate = statrTime.format(formatter);
  190. LocalDate endTime = statrTime.plusDays(6L);
  191. if (endTime.isAfter(endDateObj)) {
  192. endTime = endDateObj;
  193. }
  194. String endDate = endTime.format(formatter);
  195. //获取课表并存到数据库
  196. JsonArray scheduleInfo = dataUtil.getScheduleInfoByGrade(eduYearSerialNo, startDate, endDate);
  197. allScheduleInfo.addAll(scheduleInfo);
  198. }
  199. updSql = "update course_receive_msg set is_callback = 1 where id = " + receiveMsg.get("id").toString();
  200. SqlRunnerAdapter.db().update(updSql);
  201. ongoing.remove(eduYearSerialNo);
  202. redisUtil.set(taskKey, ongoing);
  203. insertCourse(allScheduleInfo, dataMap, dataUtil, receiveMsg, startDateStr, endDateStr);
  204. //恢复挂起的流程
  205. restoreCourseAdjust(processIds);
  206. //处理该日期内已经审批通过的调课和顶课申请
  207. handleCourseAdjust(classIdList, startDateStr, endDateStr);
  208. } catch (Exception e) {
  209. Log.error(e.getMessage(), e);
  210. } finally {
  211. ongoing.remove(eduYearSerialNo);
  212. redisUtil.set(taskKey, ongoing);
  213. }
  214. }
  215. }
  216. void insertCourse(JsonArray scheduleInfo, Map<String, Map<String, String>> dataMap, DataUtil dataUtil, Map<String, Object> receiveMsg, String startDate, String endDate) {
  217. //获取年级
  218. String tableName = "base_grade";
  219. // Map<String, Long> gradeMap = dataMap.get(tableName);
  220. //获取学期
  221. tableName = "base_semester";
  222. Map<String, String> semesterMap = dataMap.get(tableName);
  223. //获取课程
  224. tableName = "base_course_subject";
  225. Map<String, String> courseMap = dataMap.get(tableName);
  226. //获取教职工
  227. tableName = "base_teacher";
  228. Map<String, String> teacherMap = dataMap.get(tableName);
  229. //获取行政班
  230. tableName = "base_class";
  231. Map<String, String> classMap = dataMap.get(tableName);
  232. tableName = "base_classroom";
  233. Map<String, String> classroomMap = dataMap.get(tableName);
  234. Set<String> techerIds = dataUtil.insertCourseTableEntiy(scheduleInfo, classroomMap, courseMap, semesterMap,
  235. teacherMap, classMap, receiveMsg.get("id").toString(), startDate, endDate);
  236. CompletableFuture.runAsync(() -> {
  237. sendMsg(techerIds, receiveMsg);
  238. });
  239. // dataUtil.insertClassTime(scheduleInfo);
  240. }
  241. void sendMsg(Set<String> techerIds, Map<String, Object> receiveMsg) {
  242. String tableName = "jianyue_data";
  243. Entity where = Entity.create(tableName);
  244. where.set("jianyue_id", receiveMsg.get("edu_year_serial_no").toString());
  245. Map<String, Object> jianyueData = SqlRunnerAdapter.db().dynamicSelectOne(tableName, where);
  246. String[] sourceId = jianyueData.get("source_id").toString().split("_");
  247. tableName = "xjr_department";
  248. where = Entity.create(tableName);
  249. where.set("id", sourceId[0]);
  250. Map<String, Object> department = SqlRunnerAdapter.db().dynamicSelectOne(tableName, where);
  251. tableName = "base_grade";
  252. where = Entity.create(tableName);
  253. where.set("id", sourceId[1]);
  254. Map<String, Object> grade = SqlRunnerAdapter.db().dynamicSelectOne(tableName, where);
  255. //通知对应教师
  256. String sql = "SELECT * FROM xjr_user WHERE id IN (" + techerIds.toString().replace("[", "").replace("]", "") + ")";
  257. List<Map<String, Object>> userList = SqlRunnerAdapter.db().selectList(sql);
  258. sql = "SELECT t1.* FROM xjr_user t1" +
  259. " INNER JOIN xjr_user_role_relation t2 ON t1.id = t2.user_id" +
  260. " INNER JOIN xjr_role t3 ON t2.role_id = t3.id" +
  261. " WHERE t1.delete_mark = 0 AND t3.delete_mark = 0 AND t3.code = 'KEBIAOGX'";
  262. List<Map<String, Object>> userList1 = SqlRunnerAdapter.db().selectList(sql);
  263. userList.addAll(userList1);
  264. LocalDateTime createDate = (LocalDateTime) receiveMsg.get("create_date");
  265. String createDateStr = createDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  266. for (Map<String, Object> user : userList) {
  267. try {
  268. WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
  269. weChatSendMessageDto.setTemplateId(noticeTeacherTemplate);
  270. JSONObject paramJson = new JSONObject();
  271. JSONObject thing8 = new JSONObject();
  272. thing8.put("value", "课表更新");
  273. paramJson.put("thing8", thing8);
  274. JSONObject thing2 = new JSONObject();
  275. thing2.put("value", department.get("name").toString() + grade.get("name").toString());
  276. paramJson.put("thing2", thing2);
  277. JSONObject thing6 = new JSONObject();
  278. thing6.put("value", "教务处");
  279. paramJson.put("thing6", thing6);
  280. JSONObject time3 = new JSONObject();
  281. time3.put("value", createDateStr);
  282. paramJson.put("time3", time3);
  283. weChatSendMessageDto.setContent(paramJson);
  284. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  285. String openId = user.get("open_id").toString();
  286. if (openId != null && !"".equals(openId)) {
  287. weChatSendMessageDto.setUserId(openId);
  288. weChatService.sendTemplateMessage(weChatSendMessageDto);
  289. }
  290. } catch (Exception e) {
  291. Log.error(e.getMessage(), e);
  292. }
  293. }
  294. }
  295. Map<String, Map<String, String>> initDataMap() {
  296. Map<String, Map<String, String>> dataMap = new HashMap<>();
  297. String sql = "SELECT distinct table_name FROM jianyue_data WHERE 1 = 1";
  298. List<Map<String, Object>> query = SqlRunnerAdapter.db().selectList(sql);
  299. Set<String> tables = new HashSet<>();
  300. for (Map<String, Object> jianyueData : query) {
  301. tables.add(jianyueData.get("table_name").toString());
  302. }
  303. sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''";
  304. List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
  305. for (String table : tables) {
  306. Map<String, String> tableData = new HashMap<>();
  307. for (Map<String, Object> jianyueData : list) {
  308. if (!table.equals(jianyueData.get("table_name").toString())) {
  309. continue;
  310. }
  311. tableData.put(jianyueData.get("jianyue_id").toString(), jianyueData.get("source_id").toString());
  312. }
  313. dataMap.put(table, tableData);
  314. }
  315. return dataMap;
  316. }
  317. /**
  318. * 课程数据同步完之后,处理调课和顶课申请
  319. * 1、课程数据入库后,将新课表日期之后的的调课顶课数据再次更新到课表中
  320. * 2、筛选出课表变化了的调课和顶课申请,通知发起人
  321. * 3、顶课数据,如果顶课日期那天那个老师没有课,但是新发布的课表又有课了,需要把原来的顶课数据作废
  322. */
  323. public void handleCourseAdjust(List<Long> classIds, String startDate, String endDate) {
  324. Map<Long, String> classMap = classService.listByIds(classIds).stream().collect(Collectors.toMap(BaseClass::getId, BaseClass::getName));
  325. List<CourseTableBak> bakList = courseTableBakService.list(
  326. new QueryWrapper<CourseTableBak>().lambda()
  327. .in(CourseTableBak::getClassId, classIds)
  328. .between(CourseTableBak::getScheduleDate, startDate, endDate)
  329. );
  330. Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
  331. List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
  332. List<WfCourseAdjust> list = adjustService.list(
  333. new MPJLambdaWrapper<WfCourseAdjust>()
  334. .select(WfCourseAdjust::getId)
  335. .select(WfCourseAdjust.class, x -> VoToColumnUtil.fieldsToColumns(WfCourseAdjust.class).contains(x.getProperty()))
  336. .innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getFormKeyValue, WfCourseAdjust::getId)
  337. .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds)
  338. .and(wq -> wq.between(WfCourseAdjust::getAdjustDate, startDate, endDate).or().between(WfCourseAdjust::getExchangeDate, startDate, endDate))
  339. .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED)
  340. .eq(WfCourseAdjust::getEnabledMark, EnabledMark.ENABLED.getCode())
  341. );
  342. List<WfCourseAdjust> cancelList = new ArrayList<>();//需要作废的申请
  343. List<Long> userIds = list.stream().map(WfCourseAdjust::getUserId).collect(Collectors.toList());
  344. List<User> userList = userService.list(
  345. new MPJLambdaWrapper<User>()
  346. .select(User::getId)
  347. .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
  348. .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
  349. .in(!userIds.isEmpty(), User::getId, userIds)
  350. );
  351. Map<Long, String> userOpenIdMap = new HashMap<>();
  352. for (User user : userList) {
  353. userOpenIdMap.put(user.getId(), user.getOpenId());
  354. }
  355. for (WfCourseAdjust courseAdjust : list) {
  356. try {
  357. List<CourseTable> courseList = courseTableService.list(
  358. new MPJLambdaWrapper<CourseTable>()
  359. .select(CourseTable::getId)
  360. .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty()))
  361. .innerJoin(CourseTableBak.class, CourseTableBak::getKeyInfo, CourseTable::getKeyInfo)
  362. .eq(CourseTableBak::getWfCourseAdjustId, courseAdjust.getId())
  363. );
  364. String[] courseIds = courseAdjust.getCourseId().split(",");
  365. String[] exchangeCourseIds = null;
  366. int courseCount = courseIds.length;
  367. if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
  368. exchangeCourseIds = courseAdjust.getExchangeCourseId().split(",");
  369. courseCount += exchangeCourseIds.length;
  370. }
  371. //查询顶课老师在本条申请的课程中的节次是否包含课
  372. Integer substituteTeacherCourseCount = 0;
  373. if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
  374. substituteTeacherCourseCount = courseTableService.getSubstituteTeacherCourseCountByParams(new ClassTeacherDto() {{
  375. setWfCourseAdjustId(courseAdjust.getId());
  376. setTeacherId(Long.parseLong(courseAdjust.getExchangeTeacherId()));
  377. }});
  378. }
  379. if (courseList.size() != courseCount || substituteTeacherCourseCount > 0) {
  380. //表明课程变化了,需要重新申请,需要将原来的申请作废并进行微信消息通 知
  381. courseAdjust.setEnabledMark(EnabledMark.DISABLED.getCode());
  382. courseAdjust.setModifyDate(new Date());
  383. courseAdjust.setCancelReason("由于课表更新,当前调/顶课课程发生变化,该调顶课已失效,请重新发起调顶课");
  384. cancelList.add(courseAdjust);
  385. List<String> thing16Str = new ArrayList<>();
  386. List<String> thing2Str = new ArrayList<>();
  387. for (CourseTableBak tableBak : bakList) {
  388. if (!tableBak.getWfCourseAdjustId().equals(courseAdjust.getId())) {
  389. continue;
  390. }
  391. thing16Str.add(classMap.get(tableBak.getId()));
  392. thing2Str.add(tableBak.getClassName());
  393. }
  394. WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
  395. weChatSendMessageDto.setTemplateId(wechatTemplate);
  396. JSONObject paramJson = new JSONObject();
  397. JSONObject thing16 = new JSONObject();
  398. thing16.put("value", thing16Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
  399. paramJson.put("thing16", thing16);
  400. JSONObject thing2 = new JSONObject();
  401. thing2.put("value", thing2Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
  402. paramJson.put("thing2", thing2);
  403. String const12Str = "";
  404. if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
  405. const12Str = "调课失败";
  406. } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
  407. const12Str = "顶课失败";
  408. }
  409. JSONObject const12 = new JSONObject();
  410. const12.put("value", const12Str);
  411. paramJson.put("const23", const12);
  412. //迟到人数或者缺勤人数
  413. JSONObject thing5 = new JSONObject();
  414. thing5.put("value", "由于课表更新,该调顶课已失效");
  415. paramJson.put("thing5", thing5);
  416. String url = StrUtil.format(
  417. "{}/xjrsoft/pages/workflow/look?processId={}&type=my",
  418. commonPropertiesConfig.getDomainApp(),
  419. "relation.getProcessId()"
  420. );
  421. weChatSendMessageDto.setContent(paramJson);
  422. weChatSendMessageDto.setUrl(url);
  423. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  424. String openId = userOpenIdMap.get(courseAdjust.getUserId());
  425. if (openId != null && !"".equals(openId)) {
  426. weChatSendMessageDto.setUserId(openId);
  427. weChatService.sendTemplateMessage(weChatSendMessageDto);
  428. }
  429. continue;
  430. }
  431. courseTableService.adjustCourse(courseAdjust);
  432. } catch (Exception e) {
  433. log.error(e.getMessage());
  434. }
  435. }
  436. if (!cancelList.isEmpty()) {
  437. adjustService.updateBatchById(cancelList);
  438. }
  439. List<WorkflowFormRelation> activeList = formRelationService.list(
  440. new MPJLambdaWrapper<WorkflowFormRelation>()
  441. .select(WorkflowFormRelation::getId)
  442. .select(WorkflowFormRelation.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowFormRelation.class).contains(x.getProperty()))
  443. .innerJoin(WfCourseAdjust.class, WfCourseAdjust::getId, WorkflowFormRelation::getFormKeyValue)
  444. .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds)
  445. .and(wq -> wq.between(WfCourseAdjust::getAdjustDate, startDate, endDate).or().between(WfCourseAdjust::getExchangeDate, startDate, endDate))
  446. .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
  447. );
  448. for (WorkflowFormRelation relation : activeList) {
  449. try {
  450. List<CourseTable> courseList = courseTableService.list(
  451. new MPJLambdaWrapper<CourseTable>()
  452. .select(CourseTable::getId)
  453. .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty()))
  454. .innerJoin(CourseTableBak.class, CourseTableBak::getKeyInfo, CourseTable::getKeyInfo)
  455. .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue())
  456. );
  457. List<CourseTableBak> thisbakList = courseTableBakService.list(
  458. new QueryWrapper<CourseTableBak>().lambda()
  459. .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue())
  460. );
  461. if (courseList.size() == thisbakList.size()) {
  462. continue;
  463. }
  464. WfCourseAdjust courseAdjust = adjustService.getById(relation.getFormKeyValue());
  465. //表明课程变化了,进行内部终止
  466. List<String> thing16Str = new ArrayList<>();
  467. List<String> thing2Str = new ArrayList<>();
  468. for (CourseTableBak tableBak : bakList) {
  469. if (!tableBak.getWfCourseAdjustId().equals(courseAdjust.getId())) {
  470. continue;
  471. }
  472. thing16Str.add(classMap.get(tableBak.getId()));
  473. thing2Str.add(tableBak.getClassName());
  474. }
  475. WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
  476. weChatSendMessageDto.setTemplateId(wechatTemplate);
  477. JSONObject paramJson = new JSONObject();
  478. JSONObject thing16 = new JSONObject();
  479. thing16.put("value", thing16Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
  480. paramJson.put("thing16", classMap);
  481. JSONObject thing2 = new JSONObject();
  482. thing2.put("value", thing2Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
  483. paramJson.put("thing2", thing2);
  484. String const12Str = "";
  485. if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
  486. const12Str = "调课失败";
  487. } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
  488. const12Str = "顶课失败";
  489. }
  490. JSONObject const12 = new JSONObject();
  491. const12.put("value", const12Str);
  492. paramJson.put("const23", const12);
  493. //迟到人数或者缺勤人数
  494. JSONObject thing5 = new JSONObject();
  495. thing5.put("value", "由于课表更新,该调顶课已失效");
  496. paramJson.put("thing5", thing5);
  497. weChatSendMessageDto.setContent(paramJson);
  498. List<WorkflowExtra> extraList = workflowExtraService.list(
  499. new QueryWrapper<WorkflowExtra>().lambda()
  500. .eq(WorkflowExtra::getProcessId, relation.getProcessId())
  501. .orderByDesc(WorkflowExtra::getStartTime)
  502. );
  503. if (!extraList.isEmpty()) {
  504. String url = StrUtil.format(
  505. "{}/xjrsoft/pages/workflow/approval?taskId={}&processId={}&type=todo",
  506. commonPropertiesConfig.getDomainApp(),
  507. extraList.get(0).getTaskId(),
  508. relation.getProcessId()
  509. );
  510. weChatSendMessageDto.setUrl(url);
  511. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  512. String openId = userOpenIdMap.get(courseAdjust.getExchangeTeacherId());
  513. if (openId != null && !"".equals(openId)) {
  514. weChatSendMessageDto.setUserId(openId);
  515. weChatService.sendTemplateMessage(weChatSendMessageDto);
  516. }
  517. }
  518. String url = StrUtil.format(
  519. "{}/xjrsoft/pages/workflow/look?processId={}&type=my",
  520. commonPropertiesConfig.getDomainApp(),
  521. relation.getProcessId()
  522. );
  523. weChatSendMessageDto.setUrl(url);
  524. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  525. String openId = userOpenIdMap.get(courseAdjust.getUserId());
  526. if (openId != null && !"".equals(openId)) {
  527. weChatSendMessageDto.setUserId(openId);
  528. weChatService.sendTemplateMessage(weChatSendMessageDto);
  529. }
  530. String processId = relation.getProcessId();
  531. List<Task> taskList = taskService.createTaskQuery().processInstanceId(processId).list();
  532. Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity());
  533. Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
  534. //获取到当前活动的实例
  535. ActivityInstance activityInstance = runtimeService.getActivityInstance(task.getProcessInstanceId());
  536. String message = " 因课表更新之后当前课程已发生变更,该流程已内部终止,如还需调/顶课,请重新发起调/顶课流程";
  537. //先停止当前活动示例 然后 关闭流程
  538. runtimeService.createProcessInstanceModification(task.getProcessInstanceId())
  539. .cancelActivityInstance(activityInstance.getId())
  540. .cancelAllForActivity(activityInstance.getId())
  541. .setAnnotation("因课表更新之后当前课程已发生变更,该流程已内部终止")
  542. .execute();
  543. //新增流程发起流程记录
  544. WorkflowRecord record = new WorkflowRecord();
  545. record.setNodeId(task.getId());
  546. record.setNodeName(task.getName());
  547. record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
  548. record.setProcessId(task.getProcessInstanceId());
  549. record.setSchemaId(schemaId);
  550. record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
  551. record.setRecordTime(LocalDateTime.now());
  552. record.setWorkflowApproveType(WorkflowApproveType.FINISH.getCode());
  553. record.setMessage(message);
  554. workflowRecordService.save(record);
  555. //新增流程发起流程记录
  556. XjrWorkflowOperateRecord xjrWorkflowOperateRecord = new XjrWorkflowOperateRecord();
  557. xjrWorkflowOperateRecord.setNodeId(task.getId());
  558. xjrWorkflowOperateRecord.setNodeName(task.getName());
  559. xjrWorkflowOperateRecord.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
  560. xjrWorkflowOperateRecord.setProcessId(task.getProcessInstanceId());
  561. xjrWorkflowOperateRecord.setSchemaId(schemaId);
  562. xjrWorkflowOperateRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
  563. xjrWorkflowOperateRecord.setRecordTime(LocalDateTime.now());
  564. xjrWorkflowOperateRecord.setUsageScenario(1);
  565. xjrWorkflowOperateRecord.setOperateInfo(message);
  566. xjrWorkflowOperateRecordMapper.insert(xjrWorkflowOperateRecord);
  567. Optional<HistoricProcessInstance> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
  568. historicProcessInstance.ifPresent(item -> {
  569. formRelationService.updateCurrentState(new WorkflowFormRelation() {{
  570. setProcessId(processId);
  571. setCurrentState(item.getState());
  572. setStartTime(item.getStartTime());
  573. setEndTime(item.getEndTime());
  574. }});
  575. });
  576. } catch (Exception e) {
  577. log.error(e.getMessage());
  578. }
  579. }
  580. }
  581. /**
  582. * 挂起未通过的流程
  583. */
  584. List<String> suspendedCourseAdjust(List<Long> classIds, String startDate, String endDate) {
  585. List<CourseTableBak> bakList = courseTableBakService.list(
  586. new QueryWrapper<CourseTableBak>().lambda()
  587. .in(CourseTableBak::getClassId, classIds)
  588. .between(CourseTableBak::getScheduleDate, startDate, endDate)
  589. );
  590. Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
  591. List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
  592. List<WorkflowFormRelation> list = formRelationService.list(
  593. new MPJLambdaWrapper<WorkflowFormRelation>()
  594. .select(WorkflowFormRelation::getId)
  595. .select(WorkflowFormRelation.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowFormRelation.class).contains(x.getProperty()))
  596. .innerJoin(WfCourseAdjust.class, WfCourseAdjust::getId, WorkflowFormRelation::getFormKeyValue)
  597. .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
  598. .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds)
  599. .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
  600. );
  601. List<String> processIds = new ArrayList<>();
  602. for (WorkflowFormRelation relation : list) {
  603. String processId = relation.getProcessId();
  604. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
  605. List<Task> taskList = taskService.createTaskQuery().processInstanceId(processId).list();
  606. Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity());
  607. Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
  608. //新增流程发起流程记录
  609. WorkflowRecord record = new WorkflowRecord();
  610. record.setNodeId(task.getId());
  611. record.setNodeName(task.getName());
  612. record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
  613. record.setProcessId(task.getProcessInstanceId());
  614. record.setSchemaId(schemaId);
  615. record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
  616. record.setRecordTime(LocalDateTime.now());
  617. if (processInstance.isSuspended()) {
  618. runtimeService.activateProcessInstanceById(relation.getProcessId());
  619. //[操作人名称] 将流程恢复
  620. record.setMessage("课表同步成功,流程恢复");
  621. } else {
  622. runtimeService.suspendProcessInstanceById(relation.getProcessId());
  623. //[操作人名称] 将流程挂起
  624. record.setMessage("课表更新中,暂停流程审核,请等待课表更新完成之后进行审核");
  625. }
  626. workflowRecordService.save(record);
  627. Optional<HistoricProcessInstance> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
  628. historicProcessInstance.ifPresent(item -> {
  629. formRelationService.updateCurrentState(new WorkflowFormRelation() {{
  630. setProcessId(processId);
  631. setCurrentState(item.getState());
  632. setStartTime(item.getStartTime());
  633. setEndTime(item.getEndTime());
  634. }});
  635. });
  636. processIds.add(relation.getProcessId());
  637. }
  638. return processIds;
  639. }
  640. /**
  641. * 将挂起的流程恢复
  642. */
  643. void restoreCourseAdjust(List<String> processIds) {
  644. for (String processId : processIds) {
  645. List<Task> taskList = taskService.createTaskQuery().processInstanceId(processId).list();
  646. Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity());
  647. Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
  648. //新增流程发起流程记录
  649. WorkflowRecord record = new WorkflowRecord();
  650. record.setNodeId(task.getId());
  651. record.setNodeName(task.getName());
  652. record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
  653. record.setProcessId(task.getProcessInstanceId());
  654. record.setSchemaId(schemaId);
  655. record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
  656. record.setRecordTime(LocalDateTime.now());
  657. record.setMessage("课表同步成功,流程恢复");
  658. workflowRecordService.save(record);
  659. runtimeService.activateProcessInstanceById(processId);
  660. Optional<HistoricProcessInstance> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
  661. historicProcessInstance.ifPresent(item -> {
  662. formRelationService.updateCurrentState(new WorkflowFormRelation() {{
  663. setProcessId(processId);
  664. setCurrentState(item.getState());
  665. setStartTime(item.getStartTime());
  666. setEndTime(item.getEndTime());
  667. }});
  668. });
  669. }
  670. }
  671. }