JianyuekbScheduleTask.java 38 KB

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