package com.xjrsoft.module.job; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.db.Entity; import cn.hutool.extra.spring.SpringUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.core.type.TypeReference; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.google.gson.JsonArray; import com.xjrsoft.common.enums.CourseAdjustTypeEnum; import com.xjrsoft.common.enums.EnabledMark; import com.xjrsoft.common.enums.WorkflowApproveType; import com.xjrsoft.common.enums.WorkflowMultiInstanceType; import com.xjrsoft.common.mybatis.SqlRunnerAdapter; import com.xjrsoft.common.utils.RedisUtil; import com.xjrsoft.common.utils.VoToColumnUtil; import com.xjrsoft.config.CommonPropertiesConfig; import com.xjrsoft.module.base.entity.BaseClass; import com.xjrsoft.module.base.service.IBaseClassService; import com.xjrsoft.module.courseTable.dto.ClassTeacherDto; import com.xjrsoft.module.courseTable.entity.CourseTable; import com.xjrsoft.module.courseTable.service.ICourseTableService; import com.xjrsoft.module.organization.dto.WeChatSendMessageDto; import com.xjrsoft.module.organization.entity.User; import com.xjrsoft.module.organization.service.IUserService; import com.xjrsoft.module.organization.service.IWeChatService; import com.xjrsoft.module.schedule.entity.CourseTableBak; import com.xjrsoft.module.schedule.entity.WfCourseAdjust; import com.xjrsoft.module.schedule.service.ICourseTableBakService; import com.xjrsoft.module.schedule.service.IWfCourseAdjustService; import com.xjrsoft.module.schedule.util.DataUtil; import com.xjrsoft.module.teacher.entity.BaseTeacher; import com.xjrsoft.module.workflow.constant.WorkflowConstant; import com.xjrsoft.module.workflow.entity.WorkflowExtra; import com.xjrsoft.module.workflow.entity.WorkflowFormRelation; import com.xjrsoft.module.workflow.entity.WorkflowRecord; import com.xjrsoft.module.workflow.entity.XjrWorkflowOperateRecord; import com.xjrsoft.module.workflow.mapper.XjrWorkflowOperateRecordMapper; import com.xjrsoft.module.workflow.service.IWorkflowExecuteService; import com.xjrsoft.module.workflow.service.IWorkflowExtraService; import com.xjrsoft.module.workflow.service.IWorkflowFormRelationService; import com.xjrsoft.module.workflow.service.IWorkflowRecordService; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.log.Log; import org.camunda.bpm.engine.RuntimeService; import org.camunda.bpm.engine.TaskService; import org.camunda.bpm.engine.history.HistoricProcessInstance; import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity; import org.camunda.bpm.engine.runtime.ActivityInstance; import org.camunda.bpm.engine.runtime.ProcessInstance; import org.camunda.bpm.engine.task.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; /** * @author dzx * @date 2024/1/25 */ @Component @Slf4j public class JianyuekbScheduleTask { private final static String taskKey = "jianyuekbScheduleTask"; private final static String wechatTemplate = "OO5Ryu9_6Hh5LQW0aKG7qu3g5uV8VxvBusq1i5UFesk"; private final static String noticeTeacherTemplate = "sHsmz7LRj7HLd7GSTS3r2jCLvK-4Wp19iGzEvYK8n_I"; @Autowired private IBaseClassService classService; @Autowired private RedisUtil redisUtil; @Autowired private IWfCourseAdjustService adjustService; @Autowired private ICourseTableService courseTableService; @Autowired private ICourseTableBakService courseTableBakService; @Autowired private RuntimeService runtimeService; @Autowired private IWorkflowFormRelationService formRelationService; @Autowired private TaskService taskService; @Autowired private IWorkflowExecuteService workflowExecuteService; @Autowired private IWorkflowRecordService workflowRecordService; @Autowired private XjrWorkflowOperateRecordMapper xjrWorkflowOperateRecordMapper; @Autowired private IWeChatService weChatService; @Autowired private CommonPropertiesConfig commonPropertiesConfig; @Autowired private IUserService userService; @Autowired private IWorkflowExtraService workflowExtraService; @Async @Scheduled(cron = "0 */10 * * * ?") public void execute() { doExecute(); } public void doExecute() { String active = SpringUtil.getActiveProfile(); if (!"prod".equals(active)) { log.info("非正式环境,无法执行获取课表数据"); return; } String sql = "SELECT * FROM course_receive_msg WHERE delete_mark = 0 AND is_callback IS NULL"; List> receiveMsgs = SqlRunnerAdapter.db().selectList(sql); if (receiveMsgs.isEmpty()) { return; } syncCourseTable(receiveMsgs); } public void syncCourseTable(List> receiveMsgs) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); //查询出传入排课系统的年级和班级 List eduYearSerialNo1 = receiveMsgs.stream().map(x -> "'" + x.get("edu_year_serial_no").toString() + "'").collect(Collectors.toList()); //查询出传入排课系统的年级和班级 String sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''" + " and table_name = 'base_grade'" + " and jianyue_id in (" + eduYearSerialNo1.toString().replace("[", "").replace("]", "") + ")"; List> jianyueData = SqlRunnerAdapter.db().selectList(sql); Map> gradeClassMaps = new HashMap<>();//存入对应年级的所有班级id for (Map el : jianyueData) { String clasSql = "select source_id from jianyue_data where extend_data = '" + el.get("jianyue_id").toString() + "'"; List> list = SqlRunnerAdapter.db().selectList(clasSql); List classList = new ArrayList<>(); for (Map objectMap : list) { classList.add(Long.parseLong(objectMap.get("source_id").toString())); } gradeClassMaps.put(el.get("jianyue_id").toString(), classList); } LocalDate today = LocalDate.now(); DataUtil dataUtil = new DataUtil(); Set ongoing = redisUtil.get(taskKey, new TypeReference<>() { });//正在进行中的 if (ongoing == null) { ongoing = new HashSet<>(); } Map> dataMap = initDataMap(); for (Map receiveMsg : receiveMsgs) { String eduYearSerialNo = receiveMsg.get("edu_year_serial_no").toString(); if (ongoing.contains(eduYearSerialNo)) { continue; } ongoing.add(eduYearSerialNo); redisUtil.set(taskKey, ongoing); try { String updSql = "update course_receive_msg set is_callback = 0 where id = " + receiveMsg.get("id").toString(); SqlRunnerAdapter.db().update(updSql); JsonArray allScheduleInfo = new JsonArray(); String startDateStr = receiveMsg.get("start_date").toString(); LocalDate startDateObj = LocalDate.parse(startDateStr); String endDateStr = receiveMsg.get("end_date").toString(); LocalDate endDateObj = LocalDate.parse(endDateStr); if (today.isAfter(startDateObj)) { startDateStr = today.format(formatter); } //删除课表信息; List classIdList = gradeClassMaps.get(eduYearSerialNo); String classIds = classIdList.toString().replace("[", "").replace("]", ""); String delSql = "delete from course_table where schedule_date between '" + startDateStr + "'" + " and '" + endDateStr + "' and class_id in (" + classIds + ")"; SqlRunnerAdapter.db().delete(delSql); startDateStr = receiveMsg.get("start_date").toString(); List processIds = suspendedCourseAdjust(classIdList, startDateStr, endDateStr); long between = ChronoUnit.DAYS.between(startDateObj, endDateObj); int times = Integer.parseInt(((between / 7) + 1) + ""); for (int index = 0; index < times; index++) { LocalDate statrTime = startDateObj.plusDays(index * 7L); String startDate = statrTime.format(formatter); LocalDate endTime = statrTime.plusDays(6L); if (endTime.isAfter(endDateObj)) { endTime = endDateObj; } String endDate = endTime.format(formatter); //获取课表并存到数据库 JsonArray scheduleInfo = dataUtil.getScheduleInfoByGrade(eduYearSerialNo, startDate, endDate); allScheduleInfo.addAll(scheduleInfo); } updSql = "update course_receive_msg set is_callback = 1 where id = " + receiveMsg.get("id").toString(); SqlRunnerAdapter.db().update(updSql); ongoing.remove(eduYearSerialNo); redisUtil.set(taskKey, ongoing); insertCourse(allScheduleInfo, dataMap, dataUtil, receiveMsg, startDateStr, endDateStr); //恢复挂起的流程 restoreCourseAdjust(processIds); //处理该日期内已经审批通过的调课和顶课申请 handleCourseAdjust(classIdList, startDateStr, endDateStr); } catch (Exception e) { Log.error(e.getMessage(), e); } finally { ongoing.remove(eduYearSerialNo); redisUtil.set(taskKey, ongoing); } } } void insertCourse(JsonArray scheduleInfo, Map> dataMap, DataUtil dataUtil, Map receiveMsg, String startDate, String endDate) { //获取年级 String tableName = "base_grade"; // Map gradeMap = dataMap.get(tableName); //获取学期 tableName = "base_semester"; Map semesterMap = dataMap.get(tableName); //获取课程 tableName = "base_course_subject"; Map courseMap = dataMap.get(tableName); //获取教职工 tableName = "base_teacher"; Map teacherMap = dataMap.get(tableName); //获取行政班 tableName = "base_class"; Map classMap = dataMap.get(tableName); tableName = "base_classroom"; Map classroomMap = dataMap.get(tableName); Set techerIds = dataUtil.insertCourseTableEntiy(scheduleInfo, classroomMap, courseMap, semesterMap, teacherMap, classMap, receiveMsg.get("id").toString(), startDate, endDate); CompletableFuture.runAsync(() -> { sendMsg(techerIds, receiveMsg); }); // dataUtil.insertClassTime(scheduleInfo); } void sendMsg(Set techerIds, Map receiveMsg) { String tableName = "jianyue_data"; Entity where = Entity.create(tableName); where.set("jianyue_id", receiveMsg.get("edu_year_serial_no").toString()); Map jianyueData = SqlRunnerAdapter.db().dynamicSelectOne(tableName, where); String[] sourceId = jianyueData.get("source_id").toString().split("_"); tableName = "xjr_department"; where = Entity.create(tableName); where.set("id", sourceId[0]); Map department = SqlRunnerAdapter.db().dynamicSelectOne(tableName, where); tableName = "base_grade"; where = Entity.create(tableName); where.set("id", sourceId[1]); Map grade = SqlRunnerAdapter.db().dynamicSelectOne(tableName, where); //通知对应教师 String sql = "SELECT * FROM xjr_user WHERE id IN (" + techerIds.toString().replace("[", "").replace("]", "") + ")"; List> userList = SqlRunnerAdapter.db().selectList(sql); sql = "SELECT t1.* FROM xjr_user t1" + " INNER JOIN xjr_user_role_relation t2 ON t1.id = t2.user_id" + " INNER JOIN xjr_role t3 ON t2.role_id = t3.id" + " WHERE t1.delete_mark = 0 AND t3.delete_mark = 0 AND t3.code = 'KEBIAOGX'"; List> userList1 = SqlRunnerAdapter.db().selectList(sql); userList.addAll(userList1); LocalDateTime createDate = (LocalDateTime) receiveMsg.get("create_date"); String createDateStr = createDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); for (Map user : userList) { try { WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(noticeTeacherTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing8 = new JSONObject(); thing8.put("value", "课表更新"); paramJson.put("thing8", thing8); JSONObject thing2 = new JSONObject(); thing2.put("value", department.get("name").toString() + grade.get("name").toString()); paramJson.put("thing2", thing2); JSONObject thing6 = new JSONObject(); thing6.put("value", "教务处"); paramJson.put("thing6", thing6); JSONObject time3 = new JSONObject(); time3.put("value", createDateStr); paramJson.put("time3", time3); weChatSendMessageDto.setContent(paramJson); weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); String openId = user.get("open_id").toString(); if (openId != null && !"".equals(openId)) { weChatSendMessageDto.setUserId(openId); weChatService.sendTemplateMessage(weChatSendMessageDto); } } catch (Exception e) { Log.error(e.getMessage(), e); } } } Map> initDataMap() { Map> dataMap = new HashMap<>(); String sql = "SELECT distinct table_name FROM jianyue_data WHERE 1 = 1"; List> query = SqlRunnerAdapter.db().selectList(sql); Set tables = new HashSet<>(); for (Map jianyueData : query) { tables.add(jianyueData.get("table_name").toString()); } sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''"; List> list = SqlRunnerAdapter.db().selectList(sql); for (String table : tables) { Map tableData = new HashMap<>(); for (Map jianyueData : list) { if (!table.equals(jianyueData.get("table_name").toString())) { continue; } tableData.put(jianyueData.get("jianyue_id").toString(), jianyueData.get("source_id").toString()); } dataMap.put(table, tableData); } return dataMap; } /** * 课程数据同步完之后,处理调课和顶课申请 * 1、课程数据入库后,将新课表日期之后的的调课顶课数据再次更新到课表中 * 2、筛选出课表变化了的调课和顶课申请,通知发起人 * 3、顶课数据,如果顶课日期那天那个老师没有课,但是新发布的课表又有课了,需要把原来的顶课数据作废 */ public void handleCourseAdjust(List classIds, String startDate, String endDate) { Map classMap = classService.listByIds(classIds).stream().collect(Collectors.toMap(BaseClass::getId, BaseClass::getName)); List bakList = courseTableBakService.list( new QueryWrapper().lambda() .in(CourseTableBak::getClassId, classIds) .between(CourseTableBak::getScheduleDate, startDate, endDate) ); Set courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet()); List courseAdjustIds = new ArrayList<>(courseAdjustIdSet); List list = adjustService.list( new MPJLambdaWrapper() .select(WfCourseAdjust::getId) .select(WfCourseAdjust.class, x -> VoToColumnUtil.fieldsToColumns(WfCourseAdjust.class).contains(x.getProperty())) .innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getFormKeyValue, WfCourseAdjust::getId) .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds) .and(wq -> wq.between(WfCourseAdjust::getAdjustDate, startDate, endDate).or().between(WfCourseAdjust::getExchangeDate, startDate, endDate)) .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED) .eq(WfCourseAdjust::getEnabledMark, EnabledMark.ENABLED.getCode()) ); List cancelList = new ArrayList<>();//需要作废的申请 List userIds = list.stream().map(WfCourseAdjust::getUserId).collect(Collectors.toList()); List userList = userService.list( new MPJLambdaWrapper() .select(User::getId) .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty())) .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId) .in(!userIds.isEmpty(), User::getId, userIds) ); Map userOpenIdMap = new HashMap<>(); for (User user : userList) { userOpenIdMap.put(user.getId(), user.getOpenId()); } for (WfCourseAdjust courseAdjust : list) { try { List courseList = courseTableService.list( new MPJLambdaWrapper() .select(CourseTable::getId) .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty())) .innerJoin(CourseTableBak.class, CourseTableBak::getKeyInfo, CourseTable::getKeyInfo) .eq(CourseTableBak::getWfCourseAdjustId, courseAdjust.getId()) ); String[] courseIds = courseAdjust.getCourseId().split(","); String[] exchangeCourseIds = null; int courseCount = courseIds.length; if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) { exchangeCourseIds = courseAdjust.getExchangeCourseId().split(","); courseCount += exchangeCourseIds.length; } //查询顶课老师在本条申请的课程中的节次是否包含课 Integer substituteTeacherCourseCount = 0; if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) { substituteTeacherCourseCount = courseTableService.getSubstituteTeacherCourseCountByParams(new ClassTeacherDto() {{ setWfCourseAdjustId(courseAdjust.getId()); setTeacherId(Long.parseLong(courseAdjust.getExchangeTeacherId())); }}); } if (courseList.size() != courseCount || substituteTeacherCourseCount > 0) { //表明课程变化了,需要重新申请,需要将原来的申请作废并进行微信消息通 知 courseAdjust.setEnabledMark(EnabledMark.DISABLED.getCode()); courseAdjust.setModifyDate(new Date()); courseAdjust.setCancelReason("由于课表更新,当前调/顶课课程发生变化,该调顶课已失效,请重新发起调顶课"); cancelList.add(courseAdjust); List thing16Str = new ArrayList<>(); List thing2Str = new ArrayList<>(); for (CourseTableBak tableBak : bakList) { if (!tableBak.getWfCourseAdjustId().equals(courseAdjust.getId())) { continue; } thing16Str.add(classMap.get(tableBak.getId())); thing2Str.add(tableBak.getClassName()); } WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(wechatTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing16 = new JSONObject(); thing16.put("value", thing16Str.toString().replace(" ", "").replace("[", "").replace("]", "")); paramJson.put("thing16", thing16); JSONObject thing2 = new JSONObject(); thing2.put("value", thing2Str.toString().replace(" ", "").replace("[", "").replace("]", "")); paramJson.put("thing2", thing2); String const12Str = ""; if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) { const12Str = "调课失败"; } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) { const12Str = "顶课失败"; } JSONObject const12 = new JSONObject(); const12.put("value", const12Str); paramJson.put("const23", const12); //迟到人数或者缺勤人数 JSONObject thing5 = new JSONObject(); thing5.put("value", "由于课表更新,该调顶课已失效"); paramJson.put("thing5", thing5); String url = StrUtil.format( "{}/xjrsoft/pages/workflow/look?processId={}&type=my", commonPropertiesConfig.getDomainApp(), "relation.getProcessId()" ); weChatSendMessageDto.setContent(paramJson); weChatSendMessageDto.setUrl(url); weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); String openId = userOpenIdMap.get(courseAdjust.getUserId()); if (openId != null && !"".equals(openId)) { weChatSendMessageDto.setUserId(openId); weChatService.sendTemplateMessage(weChatSendMessageDto); } continue; } courseTableService.adjustCourse(courseAdjust); } catch (Exception e) { log.error(e.getMessage()); } } if (!cancelList.isEmpty()) { adjustService.updateBatchById(cancelList); } List activeList = formRelationService.list( new MPJLambdaWrapper() .select(WorkflowFormRelation::getId) .select(WorkflowFormRelation.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowFormRelation.class).contains(x.getProperty())) .innerJoin(WfCourseAdjust.class, WfCourseAdjust::getId, WorkflowFormRelation::getFormKeyValue) .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds) .and(wq -> wq.between(WfCourseAdjust::getAdjustDate, startDate, endDate).or().between(WfCourseAdjust::getExchangeDate, startDate, endDate)) .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE) ); for (WorkflowFormRelation relation : activeList) { try { List courseList = courseTableService.list( new MPJLambdaWrapper() .select(CourseTable::getId) .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty())) .innerJoin(CourseTableBak.class, CourseTableBak::getKeyInfo, CourseTable::getKeyInfo) .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue()) ); List thisbakList = courseTableBakService.list( new QueryWrapper().lambda() .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue()) ); if (courseList.size() == thisbakList.size()) { continue; } WfCourseAdjust courseAdjust = adjustService.getById(relation.getFormKeyValue()); //表明课程变化了,进行内部终止 List thing16Str = new ArrayList<>(); List thing2Str = new ArrayList<>(); for (CourseTableBak tableBak : bakList) { if (!tableBak.getWfCourseAdjustId().equals(courseAdjust.getId())) { continue; } thing16Str.add(classMap.get(tableBak.getId())); thing2Str.add(tableBak.getClassName()); } WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(wechatTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing16 = new JSONObject(); thing16.put("value", thing16Str.toString().replace(" ", "").replace("[", "").replace("]", "")); paramJson.put("thing16", classMap); JSONObject thing2 = new JSONObject(); thing2.put("value", thing2Str.toString().replace(" ", "").replace("[", "").replace("]", "")); paramJson.put("thing2", thing2); String const12Str = ""; if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) { const12Str = "调课失败"; } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) { const12Str = "顶课失败"; } JSONObject const12 = new JSONObject(); const12.put("value", const12Str); paramJson.put("const23", const12); //迟到人数或者缺勤人数 JSONObject thing5 = new JSONObject(); thing5.put("value", "由于课表更新,该调顶课已失效"); paramJson.put("thing5", thing5); weChatSendMessageDto.setContent(paramJson); List extraList = workflowExtraService.list( new QueryWrapper().lambda() .eq(WorkflowExtra::getProcessId, relation.getProcessId()) .orderByDesc(WorkflowExtra::getStartTime) ); if (!extraList.isEmpty()) { String url = StrUtil.format( "{}/xjrsoft/pages/workflow/approval?taskId={}&processId={}&type=todo", commonPropertiesConfig.getDomainApp(), extraList.get(0).getTaskId(), relation.getProcessId() ); weChatSendMessageDto.setUrl(url); weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); String openId = userOpenIdMap.get(courseAdjust.getExchangeTeacherId()); if (openId != null && !"".equals(openId)) { weChatSendMessageDto.setUserId(openId); weChatService.sendTemplateMessage(weChatSendMessageDto); } } String url = StrUtil.format( "{}/xjrsoft/pages/workflow/look?processId={}&type=my", commonPropertiesConfig.getDomainApp(), relation.getProcessId() ); weChatSendMessageDto.setUrl(url); weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); String openId = userOpenIdMap.get(courseAdjust.getUserId()); if (openId != null && !"".equals(openId)) { weChatSendMessageDto.setUserId(openId); weChatService.sendTemplateMessage(weChatSendMessageDto); } String processId = relation.getProcessId(); List taskList = taskService.createTaskQuery().processInstanceId(processId).list(); Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity()); Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY)); //获取到当前活动的实例 ActivityInstance activityInstance = runtimeService.getActivityInstance(task.getProcessInstanceId()); String message = " 因课表更新之后当前课程已发生变更,该流程已内部终止,如还需调/顶课,请重新发起调/顶课流程"; //先停止当前活动示例 然后 关闭流程 runtimeService.createProcessInstanceModification(task.getProcessInstanceId()) .cancelActivityInstance(activityInstance.getId()) .cancelAllForActivity(activityInstance.getId()) .setAnnotation("因课表更新之后当前课程已发生变更,该流程已内部终止") .execute(); //新增流程发起流程记录 WorkflowRecord record = new WorkflowRecord(); record.setNodeId(task.getId()); record.setNodeName(task.getName()); record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME); record.setProcessId(task.getProcessInstanceId()); record.setSchemaId(schemaId); record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode()); record.setRecordTime(LocalDateTime.now()); record.setWorkflowApproveType(WorkflowApproveType.FINISH.getCode()); record.setMessage(message); workflowRecordService.save(record); //新增流程发起流程记录 XjrWorkflowOperateRecord xjrWorkflowOperateRecord = new XjrWorkflowOperateRecord(); xjrWorkflowOperateRecord.setNodeId(task.getId()); xjrWorkflowOperateRecord.setNodeName(task.getName()); xjrWorkflowOperateRecord.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME); xjrWorkflowOperateRecord.setProcessId(task.getProcessInstanceId()); xjrWorkflowOperateRecord.setSchemaId(schemaId); xjrWorkflowOperateRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode()); xjrWorkflowOperateRecord.setRecordTime(LocalDateTime.now()); xjrWorkflowOperateRecord.setUsageScenario(1); xjrWorkflowOperateRecord.setOperateInfo(message); xjrWorkflowOperateRecordMapper.insert(xjrWorkflowOperateRecord); Optional historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId); historicProcessInstance.ifPresent(item -> { formRelationService.updateCurrentState(new WorkflowFormRelation() {{ setProcessId(processId); setCurrentState(item.getState()); setStartTime(item.getStartTime()); setEndTime(item.getEndTime()); }}); }); } catch (Exception e) { log.error(e.getMessage()); } } } /** * 挂起未通过的流程 */ List suspendedCourseAdjust(List classIds, String startDate, String endDate) { List bakList = courseTableBakService.list( new QueryWrapper().lambda() .in(CourseTableBak::getClassId, classIds) .between(CourseTableBak::getScheduleDate, startDate, endDate) ); Set courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet()); List courseAdjustIds = new ArrayList<>(courseAdjustIdSet); List list = formRelationService.list( new MPJLambdaWrapper() .select(WorkflowFormRelation::getId) .select(WorkflowFormRelation.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowFormRelation.class).contains(x.getProperty())) .innerJoin(WfCourseAdjust.class, WfCourseAdjust::getId, WorkflowFormRelation::getFormKeyValue) .between(WfCourseAdjust::getAdjustDate, startDate, endDate) .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds) .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE) ); List processIds = new ArrayList<>(); for (WorkflowFormRelation relation : list) { String processId = relation.getProcessId(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); List taskList = taskService.createTaskQuery().processInstanceId(processId).list(); Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity()); Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY)); //新增流程发起流程记录 WorkflowRecord record = new WorkflowRecord(); record.setNodeId(task.getId()); record.setNodeName(task.getName()); record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME); record.setProcessId(task.getProcessInstanceId()); record.setSchemaId(schemaId); record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode()); record.setRecordTime(LocalDateTime.now()); if (processInstance.isSuspended()) { runtimeService.activateProcessInstanceById(relation.getProcessId()); //[操作人名称] 将流程恢复 record.setMessage("课表同步成功,流程恢复"); } else { runtimeService.suspendProcessInstanceById(relation.getProcessId()); //[操作人名称] 将流程挂起 record.setMessage("课表更新中,暂停流程审核,请等待课表更新完成之后进行审核"); } workflowRecordService.save(record); Optional historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId); historicProcessInstance.ifPresent(item -> { formRelationService.updateCurrentState(new WorkflowFormRelation() {{ setProcessId(processId); setCurrentState(item.getState()); setStartTime(item.getStartTime()); setEndTime(item.getEndTime()); }}); }); processIds.add(relation.getProcessId()); } return processIds; } /** * 将挂起的流程恢复 */ void restoreCourseAdjust(List processIds) { for (String processId : processIds) { List taskList = taskService.createTaskQuery().processInstanceId(processId).list(); Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity()); Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY)); //新增流程发起流程记录 WorkflowRecord record = new WorkflowRecord(); record.setNodeId(task.getId()); record.setNodeName(task.getName()); record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME); record.setProcessId(task.getProcessInstanceId()); record.setSchemaId(schemaId); record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode()); record.setRecordTime(LocalDateTime.now()); record.setMessage("课表同步成功,流程恢复"); workflowRecordService.save(record); runtimeService.activateProcessInstanceById(processId); Optional historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId); historicProcessInstance.ifPresent(item -> { formRelationService.updateCurrentState(new WorkflowFormRelation() {{ setProcessId(processId); setCurrentState(item.getState()); setStartTime(item.getStartTime()); setEndTime(item.getEndTime()); }}); }); } } }