Procházet zdrojové kódy

Merge branch 'pre'

dzx před 1 rokem
rodič
revize
b8d9504abb
49 změnil soubory, kde provedl 2020 přidání a 196 odebrání
  1. 1 1
      src/main/java/com/xjrsoft/module/classtime/controller/ClassTimeCalendarController.java
  2. 13 0
      src/main/java/com/xjrsoft/module/classtime/dto/AddClassTimeCalendarDto.java
  3. 7 0
      src/main/java/com/xjrsoft/module/classtime/dto/AddClassTimeDeleteDto.java
  4. 13 0
      src/main/java/com/xjrsoft/module/classtime/entity/ClassTimeCalendar.java
  5. 7 0
      src/main/java/com/xjrsoft/module/classtime/entity/ClassTimeDelete.java
  6. 16 4
      src/main/java/com/xjrsoft/module/classtime/service/impl/ClassTimeCalendarServiceImpl.java
  7. 17 16
      src/main/java/com/xjrsoft/module/classtime/service/impl/ClassTimeStatisticsServiceImpl.java
  8. 12 0
      src/main/java/com/xjrsoft/module/classtime/vo/ClassTimeCalendarPageVo.java
  9. 6 0
      src/main/java/com/xjrsoft/module/classtime/vo/ClassTimeDeletePageVo.java
  10. 3 0
      src/main/java/com/xjrsoft/module/classtime/vo/CourseListVo.java
  11. 3 0
      src/main/java/com/xjrsoft/module/courseTable/entity/CourseTable.java
  12. 4 0
      src/main/java/com/xjrsoft/module/courseTable/mapper/CourseTableMapper.java
  13. 3 1
      src/main/java/com/xjrsoft/module/courseTable/service/ICourseTableService.java
  14. 176 54
      src/main/java/com/xjrsoft/module/courseTable/service/impl/CourseTableServiceImpl.java
  15. 6 0
      src/main/java/com/xjrsoft/module/generator/entity/TableConfig.java
  16. 1 1
      src/main/java/com/xjrsoft/module/hikvision/util/OutInRecordUtil.java
  17. 2 2
      src/main/java/com/xjrsoft/module/job/AttendanceMessageTask.java
  18. 1 1
      src/main/java/com/xjrsoft/module/job/JianyuekbBaseDataTask.java
  19. 566 66
      src/main/java/com/xjrsoft/module/job/JianyuekbScheduleTask.java
  20. 7 1
      src/main/java/com/xjrsoft/module/liteflow/node/StudentChangeClassNode.java
  21. 29 0
      src/main/java/com/xjrsoft/module/liteflow/node/WfCourseBackupsNode.java
  22. 4 4
      src/main/java/com/xjrsoft/module/material/controller/MaterialTaskController.java
  23. 3 3
      src/main/java/com/xjrsoft/module/material/service/impl/MaterialTaskServiceImpl.java
  24. 2 2
      src/main/java/com/xjrsoft/module/organization/controller/UserController.java
  25. 4 3
      src/main/java/com/xjrsoft/module/personnel/service/impl/CarMessageApplyServiceImpl.java
  26. 35 22
      src/main/java/com/xjrsoft/module/schedule/controller/ScheduleController.java
  27. 4 0
      src/main/java/com/xjrsoft/module/schedule/dto/CourseTableAdjustDto.java
  28. 3 0
      src/main/java/com/xjrsoft/module/schedule/entity/CourseTableBak.java
  29. 5 0
      src/main/java/com/xjrsoft/module/schedule/entity/WfCourseAdjust.java
  30. 5 3
      src/main/java/com/xjrsoft/module/schedule/service/IWfCourseAdjustService.java
  31. 46 0
      src/main/java/com/xjrsoft/module/schedule/service/impl/WfCourseAdjustServiceImpl.java
  32. 21 4
      src/main/java/com/xjrsoft/module/schedule/util/DataUtil.java
  33. 3 0
      src/main/java/com/xjrsoft/module/student/mapper/BaseStudentSchoolRollMapper.java
  34. 1 0
      src/main/java/com/xjrsoft/module/student/service/IBaseStudentSchoolRollService.java
  35. 5 0
      src/main/java/com/xjrsoft/module/student/service/impl/BaseStudentSchoolRollServiceImpl.java
  36. 9 0
      src/main/java/com/xjrsoft/module/teacher/controller/TeacherbaseManagerController.java
  37. 3 0
      src/main/java/com/xjrsoft/module/teacher/dto/AddXjrUserDto.java
  38. 3 0
      src/main/java/com/xjrsoft/module/teacher/dto/UpdateXjrUserDto.java
  39. 36 0
      src/main/java/com/xjrsoft/module/teacher/service/impl/TeacherbaseManagerServiceImpl.java
  40. 3 0
      src/main/java/com/xjrsoft/module/teacher/vo/XjrUserVo.java
  41. 35 2
      src/main/java/com/xjrsoft/module/workflow/service/impl/WorkflowExecuteServiceImpl.java
  42. 3 0
      src/main/java/com/xjrsoft/module/workflow/vo/MyProcessPageVo.java
  43. 2 1
      src/main/resources/mapper/classtime/ClassTimeDeleteMapper.xml
  44. 3 3
      src/main/resources/mapper/classtime/ClassTimeStatisticsMapper.xml
  45. 15 0
      src/main/resources/mapper/courseTable/CourseTable.xml
  46. 0 2
      src/main/resources/mapper/personnel/BasePersonnelLabourCapitalMapper.xml
  47. 69 0
      src/main/resources/sqlScript/20240911_sql.sql
  48. 139 0
      src/main/resources/sqlScript/20240926_sql.sql
  49. 666 0
      src/test/java/com/xjrsoft/module/job/JianyuekbScheduleTaskTest2.java

+ 1 - 1
src/main/java/com/xjrsoft/module/classtime/controller/ClassTimeCalendarController.java

@@ -53,7 +53,7 @@ public class ClassTimeCalendarController {
 
         LambdaQueryWrapper<ClassTimeCalendar> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper
-                    .orderByDesc(ClassTimeCalendar::getId)
+                    .orderByDesc(ClassTimeCalendar::getCreateDate)
                 .select(ClassTimeCalendar.class,x -> VoToColumnUtil.fieldsToColumns(ClassTimeCalendarPageVo.class).contains(x.getProperty()));
         IPage<ClassTimeCalendar> page = classTimeCalendarService.page(ConventPage.getPage(dto), queryWrapper);
         PageOutput<ClassTimeCalendarPageVo> pageOutput = ConventPage.getPageOutput(page, ClassTimeCalendarPageVo.class);

+ 13 - 0
src/main/java/com/xjrsoft/module/classtime/dto/AddClassTimeCalendarDto.java

@@ -33,4 +33,17 @@ public class AddClassTimeCalendarDto implements Serializable {
     @ApiModelProperty("补课日期")
     private LocalDate replaceDate;
 
+    /**
+     * 补课课程 0:上1 1:上2 2:上3 3:上4 4:下1 5:下2 6:下3 7:下4 8:晚1 9:晚2 10:晚3
+     * 多个用逗号隔开
+     */
+    @ApiModelProperty("补课课程")
+    private  String timePeriod;
+
+    /**
+     * 覆盖方式 1:选中覆盖 0:全天覆盖
+     */
+    @ApiModelProperty("覆盖方式 1:选中覆盖 0:全天覆盖")
+    private  Integer coverType;
+
 }

+ 7 - 0
src/main/java/com/xjrsoft/module/classtime/dto/AddClassTimeDeleteDto.java

@@ -48,4 +48,11 @@ public class AddClassTimeDeleteDto implements Serializable {
     @ApiModelProperty("结束日期")
     private LocalDate endDate;
 
+    /**
+     * 删除课程 0:上1 1:上2 2:上3 3:上4 4:下1 5:下2 6:下3 7:下4 8:晚1 9:晚2 10:晚3
+     * 多个用逗号隔开
+     */
+    @ApiModelProperty("删除课程")
+    private  String timePeriod;
+
 }

+ 13 - 0
src/main/java/com/xjrsoft/module/classtime/entity/ClassTimeCalendar.java

@@ -83,4 +83,17 @@ public class ClassTimeCalendar implements Serializable {
 
     @ApiModelProperty("状态(0:生效 1:锁定 2:作废)")
     private Integer status;
+
+    /**
+     * 补课课程 0:上1 1:上2 2:上3 3:上4 4:下1 5:下2 6:下3 7:下4 8:晚1 9:晚2 10:晚3
+     * 多个用逗号隔开
+     */
+    @ApiModelProperty("补课课程")
+    private  String timePeriod;
+
+    /**
+     * 覆盖方式 1:选中覆盖 0:全天覆盖
+     */
+    @ApiModelProperty("覆盖方式 1:选中覆盖 0:全天覆盖")
+    private  Integer coverType;
 }

+ 7 - 0
src/main/java/com/xjrsoft/module/classtime/entity/ClassTimeDelete.java

@@ -99,5 +99,12 @@ public class ClassTimeDelete implements Serializable {
     @ApiModelProperty("状态(0:生效 1:锁定 2:作废)")
     private Integer status;
 
+    /**
+     * 删除课程 0:上1 1:上2 2:上3 3:上4 4:下1 5:下2 6:下3 7:下4 8:晚1 9:晚2 10:晚3
+     * 多个用逗号隔开
+     */
+    @ApiModelProperty("删除课程")
+    private  String timePeriod;
+
 
 }

+ 16 - 4
src/main/java/com/xjrsoft/module/classtime/service/impl/ClassTimeCalendarServiceImpl.java

@@ -18,6 +18,7 @@ import org.springframework.stereotype.Service;
 
 import java.time.DayOfWeek;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -38,10 +39,12 @@ public class ClassTimeCalendarServiceImpl extends MPJBaseServiceImpl<ClassTimeCa
     public Boolean add(AddClassTimeCalendarDto dto) {
         try {
             ClassTimeCalendar classTimeCalendar = BeanUtil.toBean(dto, ClassTimeCalendar.class);
+
             //1、查询补课日期的数据,将日期设置为补班日期然后新增
             List<CourseTable> list = courseTableService.list(
                     new QueryWrapper<CourseTable>().lambda()
                             .eq(CourseTable::getScheduleDate, dto.getReplaceDate())
+                            .in(CourseTable::getTimeNumber, Arrays.asList(dto.getTimePeriod().split(",")))
             );
             if(list.isEmpty()){
                 throw new MyException("未能查询到补课日期那天的课表信息,请联系管理员");
@@ -51,6 +54,7 @@ public class ClassTimeCalendarServiceImpl extends MPJBaseServiceImpl<ClassTimeCa
             List<CourseTable> deleteList = courseTableService.list(
                     new QueryWrapper<CourseTable>().lambda()
                             .eq(CourseTable::getScheduleDate, dto.getSupplementDate())
+                            .in(dto.getCoverType() == 1, CourseTable::getTimeNumber, Arrays.asList(dto.getTimePeriod().split(",")))
             );
             List<CourseTableBak> bakList = new ArrayList<>();
             for (CourseTable courseTable : deleteList) {
@@ -79,8 +83,12 @@ public class ClassTimeCalendarServiceImpl extends MPJBaseServiceImpl<ClassTimeCa
             boolean isSuccess = this.save(classTimeCalendar);
             return isSuccess;
         }catch (Exception e){
-            log.error(e.getMessage());
-            throw new MyException("添加出错,请联系管理员");
+            log.error(e.getMessage(), e);
+            if(e.getClass().equals(MyException.class)){
+                throw new MyException(e.getMessage());
+            }else{
+                throw new MyException("添加出错,请联系管理员");
+            }
         }
     }
 
@@ -152,8 +160,12 @@ public class ClassTimeCalendarServiceImpl extends MPJBaseServiceImpl<ClassTimeCa
             calendar.setModifyDate(new Date());
             return this.updateById(calendar);
         }catch (Exception e){
-            log.error(e.getMessage());
-            throw new MyException("作废出错,请联系管理员");
+            log.error(e.getMessage(), e);
+            if(e.getClass().equals(MyException.class)){
+                throw new MyException(e.getMessage());
+            }else{
+                throw new MyException("添加出错,请联系管理员");
+            }
         }
     }
 }

+ 17 - 16
src/main/java/com/xjrsoft/module/classtime/service/impl/ClassTimeStatisticsServiceImpl.java

@@ -188,18 +188,18 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                             .ne(ClassTimeDelete::getStatus, 2)
             );
             Map<Long, List<ClassTimeDelete>> deleteDataMap = deleteList.stream().collect(Collectors.groupingBy(ClassTimeDelete::getClassId));
-            Map<Long, Set<LocalDate>> deleteMap = new HashMap<>();//将每个班级计算出来所有被删除的日期存入map
+            Map<Long, Map<LocalDate, String>> deleteMap = new HashMap<>();//将每个班级计算出来所有被删除的日期存入map
             for (Long classId : deleteDataMap.keySet()) {
-                List<LocalDate> dateList = new ArrayList<>();
+                Map<LocalDate, String> dateMap = new HashMap<>();
                 for (ClassTimeDelete classTimeDelete : deleteDataMap.get(classId)) {
                     LocalDate currentDate = classTimeDelete.getStartDate();
                     while (!currentDate.isAfter(classTimeDelete.getEndDate())) {
-                        dateList.add(currentDate);
+                        dateMap.put(currentDate, classTimeDelete.getTimePeriod());
                         currentDate = currentDate.plusDays(1); // 增加一天
                     }
                 }
                 //去重并存到map中
-                deleteMap.put(classId, new HashSet<>(dateList));
+                deleteMap.put(classId, dateMap);
             }
             DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
 
@@ -316,9 +316,10 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                 //循环,统计出各项数据
                 for (CourseListVo courseListVo : courseList) {
                     //如果这个课程数据包含在被删除的课时中,跳过不计算
-                    Set<LocalDate> deleteDates = deleteMap.get(courseListVo.getClassId());
+                    Map<LocalDate, String> deleteDates = deleteMap.get(courseListVo.getClassId());
                     JsonObject courseJson = new JsonObject();
-                    if(deleteDates != null && deleteDates.contains(courseListVo.getScheduleDate())){
+                    if(deleteDates != null && deleteDates.containsKey(courseListVo.getScheduleDate())
+                            && deleteDates.get(courseListVo.getScheduleDate()).contains(courseListVo.getTimeNumber()) ){
                         courseJson.addProperty("type", courseListVo.getShortName());
                         courseJson.addProperty("scheduleDate", courseListVo.getScheduleDate().format(formatter));
                         courseJson.addProperty("content", "");
@@ -366,8 +367,8 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                     for (CourseListVo courseListVo : courseList) {
                         LocalDate scheduleDate = courseListVo.getScheduleDate();
                         //如果这个课程数据包含在被删除的课时中,跳过不计算
-                        Set<LocalDate> deleteDates = deleteMap.get(courseListVo.getClassId());
-                        if(deleteDates != null && deleteDates.contains(scheduleDate)){
+                        Map<LocalDate, String> deleteDates = deleteMap.get(courseListVo.getClassId());
+                        if(deleteDates != null && deleteDates.containsKey(scheduleDate) && deleteDates.get(courseListVo.getScheduleDate()).contains(courseListVo.getTimeNumber())){
                             continue;
                         }
 
@@ -395,8 +396,8 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                             .collect(Collectors.toList());
                     Double reduceTime = 0d;//顶课课时
                     for (CourseListVo courseListVo : substituteList) {
-                        Set<LocalDate> deleteDates = deleteMap.get(courseListVo.getClassId());
-                        if(deleteDates !=null && deleteDates.contains(courseListVo.getScheduleDate())){
+                        Map<LocalDate, String> deleteDates = deleteMap.get(courseListVo.getClassId());
+                        if(deleteDates != null && deleteDates.containsKey(courseListVo.getScheduleDate()) && deleteDates.get(courseListVo.getScheduleDate()).contains(courseListVo.getTimeNumber())){
                             continue;
                         }
                         if(!( (courseListVo.getScheduleDate().equals(timeRangeVo.getMondayDate()) || courseListVo.getScheduleDate().isAfter(timeRangeVo.getMondayDate()))
@@ -409,8 +410,8 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                     substituteList = allSubstituteList.stream().filter(x -> x.getTeacherId().equals(teacher.getId().toString()))
                             .collect(Collectors.toList());
                     for (CourseListVo courseListVo : substituteList) {
-                        Set<LocalDate> deleteDates = deleteMap.get(courseListVo.getClassId());
-                        if(deleteDates !=null && deleteDates.contains(courseListVo.getScheduleDate())){
+                        Map<LocalDate, String> deleteDates = deleteMap.get(courseListVo.getClassId());
+                        if(deleteDates != null && deleteDates.containsKey(courseListVo.getScheduleDate()) && deleteDates.get(courseListVo.getScheduleDate()).contains(courseListVo.getTimeNumber())){
                             continue;
                         }
                         if(!( (courseListVo.getScheduleDate().equals(timeRangeVo.getMondayDate()) || courseListVo.getScheduleDate().isAfter(timeRangeVo.getMondayDate()))
@@ -486,8 +487,8 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                     Double reduceTime = 0d;//顶课课时
                     Double dkClassTime = 0d;//去顶课的数量,所有顶课数量
                     for (CourseListVo courseListVo : substituteList) {
-                        Set<LocalDate> deleteDates = deleteMap.get(courseListVo.getClassId());
-                        if(deleteDates !=null && deleteDates.contains(courseListVo.getScheduleDate())){
+                        Map<LocalDate, String> deleteDates = deleteMap.get(courseListVo.getClassId());
+                        if(deleteDates != null && deleteDates.containsKey(courseListVo.getScheduleDate()) && deleteDates.get(courseListVo.getScheduleDate()).contains(courseListVo.getTimeNumber())){
                             continue;
                         }
                         reduceTime += weightSetMap.get(courseListVo.getShortName());
@@ -499,8 +500,8 @@ public class ClassTimeStatisticsServiceImpl extends MPJBaseServiceImpl<ClassTime
                     substituteList = allSubstituteList.stream().filter(x -> x.getTeacherId().equals(teacher.getId().toString()))
                             .collect(Collectors.toList());
                     for (CourseListVo courseListVo : substituteList) {
-                        Set<LocalDate> deleteDates = deleteMap.get(courseListVo.getClassId());
-                        if(deleteDates !=null && deleteDates.contains(courseListVo.getScheduleDate())){
+                        Map<LocalDate, String> deleteDates = deleteMap.get(courseListVo.getClassId());
+                        if(deleteDates != null && deleteDates.containsKey(courseListVo.getScheduleDate()) && deleteDates.get(courseListVo.getScheduleDate()).contains(courseListVo.getTimeNumber())){
                             continue;
                         }
                         reduceTime = reduceTime - weightSetMap.get(courseListVo.getShortName());

+ 12 - 0
src/main/java/com/xjrsoft/module/classtime/vo/ClassTimeCalendarPageVo.java

@@ -63,5 +63,17 @@ public class ClassTimeCalendarPageVo {
 
     @ApiModelProperty("状态(0:生效 1:锁定 2:作废)")
     private Integer status;
+    /**
+     * 补课课程 0:上1 1:上2 2:上3 3:上4 4:下1 5:下2 6:下3 7:下4 8:晚1 9:晚2 10:晚3
+     * 多个用逗号隔开
+     */
+    @ApiModelProperty("补课课程")
+    private  String timePeriod;
+
+    /**
+     * 覆盖方式 1:选中覆盖 0:全天覆盖
+     */
+    @ApiModelProperty("覆盖方式 1:选中覆盖 0:全天覆盖")
+    private  Integer coverType;
 
 }

+ 6 - 0
src/main/java/com/xjrsoft/module/classtime/vo/ClassTimeDeletePageVo.java

@@ -58,5 +58,11 @@ public class ClassTimeDeletePageVo {
 
     @ApiModelProperty("状态(0:生效 1:锁定 2:作废)")
     private Integer status;
+    /**
+     * 删除课程 0:上1 1:上2 2:上3 3:上4 4:下1 5:下2 6:下3 7:下4 8:晚1 9:晚2 10:晚3
+     * 多个用逗号隔开
+     */
+    @ApiModelProperty("删除课程")
+    private  String timePeriod;
 
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/classtime/vo/CourseListVo.java

@@ -42,5 +42,8 @@ public class CourseListVo {
     @ApiModelProperty("课程名称")
     private String courseName;
 
+    @ApiModelProperty("节次")
+    private String timeNumber;
+
 
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/courseTable/entity/CourseTable.java

@@ -95,4 +95,7 @@ public class CourseTable implements Serializable {
     @ApiModelProperty("调课顶课(顶课:course_substitute 调课:course_exchange)")
     private String adjustType;
 
+    @ApiModelProperty("关键信息(存课程的教师id、班级id、日期、节次、课程id、场地以“_”拼接)")
+    private String keyInfo;
+
 }

+ 4 - 0
src/main/java/com/xjrsoft/module/courseTable/mapper/CourseTableMapper.java

@@ -3,6 +3,7 @@ package com.xjrsoft.module.courseTable.mapper;
 import com.github.yulichang.base.MPJBaseMapper;
 import com.xjrsoft.module.schedule.dto.ClassOptionDto;
 import com.xjrsoft.module.courseTable.entity.CourseTable;
+import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
 import com.xjrsoft.module.schedule.vo.ClassOptionVo;
 import com.xjrsoft.module.schedule.dto.CourseTableAdjustDto;
 import com.xjrsoft.module.schedule.dto.CourseTableDto;
@@ -28,4 +29,7 @@ public interface CourseTableMapper extends MPJBaseMapper<CourseTable> {
     List<CourseListVo> getAdjustList(@Param("dto") CourseTableAdjustDto dto);
 
     List<ClassOptionVo> getClassListByTeacherId(@Param("dto") ClassOptionDto dto);
+
+    //查询流程正在进行中或者已经完成的调课或者顶课申请
+    List<WfCourseAdjust> getExceptCourseList(@Param("userId") Long userId);
 }

+ 3 - 1
src/main/java/com/xjrsoft/module/courseTable/service/ICourseTableService.java

@@ -42,9 +42,11 @@ public interface ICourseTableService extends IService<CourseTable> {
      * @param courseAdjust
      * @return
      */
-    Boolean adjustCourse(WfCourseAdjust courseAdjust) throws Exception;
+    Boolean adjustCourse(WfCourseAdjust courseAdjust);
 
     ByteArrayOutputStream listScheduleWeekExportQuery(ScheduleWeekExportQueryDto dto);
 
     List<ClassOptionVo> getClassListByTeacherId(ClassOptionDto dto);
+
+
 }

+ 176 - 54
src/main/java/com/xjrsoft/module/courseTable/service/impl/CourseTableServiceImpl.java

@@ -26,6 +26,7 @@ import com.xjrsoft.common.enums.TimeNumberEnum;
 import com.xjrsoft.common.enums.TimePeriodEnum;
 import com.xjrsoft.common.enums.WeekEnum;
 import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.common.utils.excel.ExcelFillCellMergePrevColUtil;
 import com.xjrsoft.common.utils.excel.ExcelMergeUtil;
 import com.xjrsoft.config.TimetableConfig;
@@ -42,6 +43,8 @@ import com.xjrsoft.module.courseTable.mapper.ClassTimeMapper;
 import com.xjrsoft.module.courseTable.mapper.CourseTableMapper;
 import com.xjrsoft.module.courseTable.service.ICourseTableService;
 import com.xjrsoft.module.courseTable.vo.ClassListVo;
+import com.xjrsoft.module.organization.entity.User;
+import com.xjrsoft.module.organization.service.IUserService;
 import com.xjrsoft.module.schedule.dto.ClassOptionDto;
 import com.xjrsoft.module.schedule.dto.CourseTableAdjustDto;
 import com.xjrsoft.module.schedule.dto.CourseTableDto;
@@ -116,6 +119,7 @@ public class CourseTableServiceImpl extends ServiceImpl<CourseTableMapper, Cours
     private final BaseSemesterMapper baseSemesterMapper;
     private final IBaseStudentSchoolRollService baseStudentSchoolRollService;
     private final CourseTableBakMapper courseTableBakMapper;
+    private final IUserService userService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -299,7 +303,19 @@ public class CourseTableServiceImpl extends ServiceImpl<CourseTableMapper, Cours
             dto.setTeacherId(Long.parseLong(teacherId));
         }
         dto.setAdjustType(adjustType);
-
+        //查询正在进行中或者已经完成
+        List<WfCourseAdjust> exceptCourseList = courseTableMapper.getExceptCourseList(dto.getTeacherId());
+        List<Long> courseIds = new ArrayList<>();
+        for (WfCourseAdjust courseAdjust : exceptCourseList) {
+            String[] split = courseAdjust.getCourseId().split(",");
+            for (String s : split) {
+                if(StrUtil.isEmpty(s)){
+                    continue;
+                }
+                courseIds.add(Long.parseLong(s));
+            }
+        }
+        dto.setExceptCourseList(courseIds);
         List<CourseListVo> list = courseTableMapper.getAdjustList(dto);
         for (CourseListVo courseListVo : list) {
             if (courseListVo.getTimePeriod() == 1) {
@@ -310,7 +326,6 @@ public class CourseTableServiceImpl extends ServiceImpl<CourseTableMapper, Cours
                 courseListVo.setTimePeriodCn("晚上");
             }
         }
-
         return list;
     }
 
@@ -348,65 +363,172 @@ public class CourseTableServiceImpl extends ServiceImpl<CourseTableMapper, Cours
 
     @Override
     public Boolean adjustCourse(WfCourseAdjust courseAdjust){
+        //先查询课表数据,看是否能够查询到,如果能查到
+        List<CourseTable> list = this.list(
+                new MPJLambdaWrapper<CourseTable>()
+                        .select(CourseTable::getId)
+                        .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty()))
+                        .innerJoin(CourseTableBak.class, CourseTableBak::getId, CourseTable::getId)
+                        .eq(CourseTableBak::getWfCourseAdjustId, courseAdjust.getId())
+        );
+        String[] courseIds = courseAdjust.getCourseId().split(",");
+        String[] exchangeCourseIds = null;
+        int courseCount = courseIds.length;
         if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
-            String[] courseIds = courseAdjust.getCourseId().split(",");
-            String[] exchangeCourseIds = courseAdjust.getExchangeCourseId().split(",");
-            for (int i = 0; i < courseIds.length; i ++){
-                String courseId = courseIds[i];
-                String exchangeCourseId = exchangeCourseIds[i];
+            exchangeCourseIds = courseAdjust.getExchangeCourseId().split(",");
+            courseCount += exchangeCourseIds.length;
+        }
 
-                //调课,将双方课程的日期(schedule_date)、时段(time_period)、节次(time_number)、周(week)、星期几(1-7)(weeks)、星期中文(weeks_cn)对调
-                CourseTable courseTable = courseTableMapper.selectById(courseId);
-                CourseTableBak courseBak = BeanUtil.toBean(courseTable, CourseTableBak.class);
-                courseBak.setWfCourseAdjustId(courseAdjust.getId());
-                courseTableBakMapper.insert(courseBak);
-
-                CourseTable swapCourseTable = courseTableMapper.selectById(exchangeCourseId);
-                CourseTableBak swapCourseBak = BeanUtil.toBean(swapCourseTable, CourseTableBak.class);
-                swapCourseBak.setWfCourseAdjustId(courseAdjust.getId());
-                courseTableBakMapper.insert(swapCourseBak);
-
-                CourseTable courseTableBak = BeanUtil.toBean(courseTable, CourseTable.class);
-                CourseTable swapCourseTableBak = BeanUtil.toBean(swapCourseTable, CourseTable.class);
-
-                courseTable.setScheduleDate(swapCourseTableBak.getScheduleDate());
-                courseTable.setTimePeriod(swapCourseTableBak.getTimePeriod());
-                courseTable.setTimeNumber(swapCourseTableBak.getTimeNumber());
-                courseTable.setWeek(swapCourseTableBak.getWeek());
-                courseTable.setWeeks(swapCourseTableBak.getWeeks());
-                courseTable.setWeeksCn(swapCourseTableBak.getWeeksCn());
-                courseTable.setAdjustType(courseAdjust.getAdjustType());
-                courseTableMapper.updateById(courseTable);
-
-                swapCourseTable.setScheduleDate(courseTableBak.getScheduleDate());
-                swapCourseTable.setTimePeriod(courseTableBak.getTimePeriod());
-                swapCourseTable.setTimeNumber(courseTableBak.getTimeNumber());
-                swapCourseTable.setWeek(courseTableBak.getWeek());
-                swapCourseTable.setWeeks(courseTableBak.getWeeks());
-                swapCourseTable.setWeeksCn(courseTableBak.getWeeksCn());
-                swapCourseTable.setAdjustType(courseAdjust.getAdjustType());
-                courseTableMapper.updateById(swapCourseTable);
+        if(list.isEmpty() || list.size() != courseCount){
+            list = this.list(
+                    new MPJLambdaWrapper<CourseTable>()
+                            .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())
+            );
+            Map<String, CourseTable> courseMap = list.stream().collect(Collectors.toMap(CourseTable::getKeyInfo, x -> x));
+            List<CourseTableBak> bakList = courseTableBakMapper.selectList(
+                    new QueryWrapper<CourseTableBak>().lambda()
+                            .eq(CourseTableBak::getWfCourseAdjustId, courseAdjust.getId())
+            );
+            Map<Long, String> bakKeyInfoMap = bakList.stream().collect(Collectors.toMap(CourseTableBak::getId, CourseTableBak::getKeyInfo));
+            Map<Long, CourseTableBak> bakCourseMap = bakList.stream().collect(Collectors.toMap(CourseTableBak::getId, x -> x));
+
+            if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
+                for (int i = 0; i < courseIds.length; i ++){
+                    String courseId = courseIds[i];
+                    String exchangeCourseId = exchangeCourseIds[i];
+
+                    //调课,将双方课程的日期(schedule_date)、时段(time_period)、节次(time_number)、周(week)、星期几(1-7)(weeks)、星期中文(weeks_cn)对调
+                    CourseTable courseTable = courseMap.get(bakKeyInfoMap.get(Long.parseLong(courseId)));
+
+                    CourseTable swapCourseTable = courseMap.get(bakKeyInfoMap.get(Long.parseLong(exchangeCourseId)));
+
+                    CourseTableBak courseTableBak = bakCourseMap.get(Long.parseLong(courseId));
+                    CourseTableBak swapCourseTableBak = bakCourseMap.get(Long.parseLong(exchangeCourseId));
+
+                    courseTable.setAdjustType(courseAdjust.getAdjustType());
+                    courseTable.setCourseName(swapCourseTableBak.getCourseName());
+                    courseTable.setCourseId(swapCourseTableBak.getCourseId());
+                    courseTable.setTeacherId(swapCourseTableBak.getTeacherId());
+                    courseTable.setSiteId(swapCourseTableBak.getSiteId());
+                    courseTable.setTeacherName(swapCourseTableBak.getTeacherName());
+                    courseTable.setKeyInfo(courseTable.getTeacherId() + "_"
+                            + courseTable.getClassId() + "_"
+                            + courseTable.getScheduleDate() + "_"
+                            + courseTable.getCourseId() + "_"
+                            + courseTable.getSiteId() + "_"
+                            + courseTable.getTimeNumber()
+                    );
+                    courseTableMapper.updateById(courseTable);
+
+                    swapCourseTable.setAdjustType(courseAdjust.getAdjustType());
+                    swapCourseTable.setKeyInfo(swapCourseTable.getTeacherId() + "_"
+                            + swapCourseTable.getClassId() + "_"
+                            + swapCourseTable.getScheduleDate() + "_"
+                            + swapCourseTable.getCourseId() + "_"
+                            + swapCourseTable.getSiteId() + "_"
+                            + swapCourseTable.getTimeNumber()
+                    );
+                    swapCourseTable.setCourseId(courseTableBak.getCourseId());
+                    swapCourseTable.setCourseName(courseTableBak.getCourseName());
+                    swapCourseTable.setTeacherId(courseTableBak.getTeacherId());
+                    swapCourseTable.setSiteId(courseTableBak.getSiteId());
+                    swapCourseTable.setTeacherName(courseTableBak.getTeacherName());
+                    courseTableMapper.updateById(swapCourseTable);
+                }
+                //提交调课接口
+                //sendExchange(courseTableBak, swapCourseTableBak, courseAdjust);
+            } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
+                for (String courseId : courseIds) {
+                    CourseTable courseTable = courseMap.get(bakKeyInfoMap.get(Long.parseLong(courseId)));
+
+                    User applyUser = userService.getById(courseAdjust.getUserId());//申请人
+                    User exchangeUser = userService.getById(courseAdjust.getExchangeTeacherId());//顶课人
+
+                    String teacherId = courseTable.getTeacherId().replace(courseAdjust.getUserId().toString(), courseAdjust.getExchangeTeacherId().toString());
+                    String teacherName = courseTable.getTeacherName().replace(applyUser.getName(), exchangeUser.getName());
+                    courseTable.setAdjustType(courseAdjust.getAdjustType());
+                    courseTable.setTeacherId(teacherId);
+                    courseTable.setTeacherName(teacherName);
+
+                    courseTable.setKeyInfo(teacherId + "_" + courseTable.getClassId() + "_" + courseTable.getScheduleDate() + "_" + courseTable.getCourseId() + "_" + courseTable.getSiteId() + "_" + courseTable.getTimeNumber());
+                    courseTableMapper.updateById(courseTable);
+                }
+
+                //提交顶课接口
+                //sendSubstitute(courseTable, courseAdjust);
             }
-            //提交调课接口
-            //sendExchange(courseTableBak, swapCourseTableBak, courseAdjust);
-        } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
-            String[] courseIds = courseAdjust.getCourseId().split(",");
-            for (String courseId : courseIds) {
-                CourseTable courseTable = courseTableMapper.selectById(courseId);
+        }else{
+            if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
+                for (int i = 0; i < courseIds.length; i ++){
+                    String courseId = courseIds[i];
+                    String exchangeCourseId = exchangeCourseIds[i];
+
+                    //调课,将双方课程的日期(schedule_date)、时段(time_period)、节次(time_number)、周(week)、星期几(1-7)(weeks)、星期中文(weeks_cn)对调
+                    CourseTable courseTable = courseTableMapper.selectById(courseId);
+                    CourseTable swapCourseTable = courseTableMapper.selectById(exchangeCourseId);
+                    if(courseTable == null || swapCourseTable == null){
+                        continue;
+                    }
 
-                CourseTableBak courseBak = BeanUtil.toBean(courseTable, CourseTableBak.class);
-                courseBak.setWfCourseAdjustId(courseAdjust.getId());
-                courseTableBakMapper.insert(courseBak);
+                    CourseTable courseTableBak = BeanUtil.toBean(courseTable, CourseTable.class);
+                    CourseTable swapCourseTableBak = BeanUtil.toBean(swapCourseTable, CourseTable.class);
+
+                    courseTable.setAdjustType(courseAdjust.getAdjustType());
+                    courseTable.setCourseName(swapCourseTableBak.getCourseName());
+                    courseTable.setCourseId(swapCourseTableBak.getCourseId());
+                    courseTable.setTeacherId(swapCourseTableBak.getTeacherId());
+                    courseTable.setSiteId(swapCourseTableBak.getSiteId());
+                    courseTable.setTeacherName(swapCourseTableBak.getTeacherName());
+                    courseTable.setKeyInfo(courseTable.getTeacherId() + "_"
+                            + courseTable.getClassId() + "_"
+                            + courseTable.getScheduleDate() + "_"
+                            + courseTable.getCourseId() + "_"
+                            + courseTable.getSiteId() + "_"
+                            + courseTable.getTimeNumber()
+                    );
+                    courseTableMapper.updateById(courseTable);
+
+                    swapCourseTable.setAdjustType(courseAdjust.getAdjustType());
+                    swapCourseTable.setKeyInfo(swapCourseTable.getTeacherId() + "_"
+                            + swapCourseTable.getClassId() + "_"
+                            + swapCourseTable.getScheduleDate() + "_"
+                            + swapCourseTable.getCourseId() + "_"
+                            + swapCourseTable.getSiteId() + "_"
+                            + swapCourseTable.getTimeNumber()
+                    );
+                    swapCourseTable.setCourseId(courseTableBak.getCourseId());
+                    swapCourseTable.setCourseName(courseTableBak.getCourseName());
+                    swapCourseTable.setTeacherId(courseTableBak.getTeacherId());
+                    swapCourseTable.setSiteId(courseTableBak.getSiteId());
+                    swapCourseTable.setTeacherName(courseTableBak.getTeacherName());
+                    courseTableMapper.updateById(swapCourseTable);
+                }
+                //提交调课接口
+                //sendExchange(courseTableBak, swapCourseTableBak, courseAdjust);
+            } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
+                for (String courseId : courseIds) {
+                    CourseTable courseTable = courseTableMapper.selectById(courseId);
+
+                    User applyUser = userService.getById(courseAdjust.getUserId());//申请人
+                    User exchangeUser = userService.getById(courseAdjust.getExchangeTeacherId());//顶课人
+
+                    String teacherId = courseTable.getTeacherId().replace(courseAdjust.getUserId().toString(), courseAdjust.getExchangeTeacherId().toString());
+                    String teacherName = courseTable.getTeacherName().replace(applyUser.getName(), exchangeUser.getName());
+                    courseTable.setAdjustType(courseAdjust.getAdjustType());
+                    courseTable.setTeacherId(teacherId);
+                    courseTable.setTeacherName(teacherName);
+                    courseTable.setKeyInfo(teacherId + "_" + courseTable.getClassId() + "_" + courseTable.getScheduleDate() + "_" + courseTable.getCourseId() + "_" + courseTable.getSiteId() + "_" + courseTable.getTimeNumber());
+                    courseTableMapper.updateById(courseTable);
+                }
 
-                String teacherId = courseTable.getTeacherId().replace(courseAdjust.getUserId().toString(), courseAdjust.getExchangeTeacherId().toString());
-                courseTable.setAdjustType(courseAdjust.getAdjustType());
-                courseTable.setTeacherId(teacherId);
-                courseTableMapper.updateById(courseTable);
+                //提交顶课接口
+                //sendSubstitute(courseTable, courseAdjust);
             }
-
-            //提交顶课接口
-            //sendSubstitute(courseTable, courseAdjust);
         }
+
         return Boolean.TRUE;
     }
 

+ 6 - 0
src/main/java/com/xjrsoft/module/generator/entity/TableConfig.java

@@ -52,4 +52,10 @@ public class TableConfig {
      */
     @Length(max = 30, message = "关联表对应字段长度不能超过30!")
     private String relationTableField;
+
+    /**
+     * 是否允许为空
+     */
+    @NotNull(message = "是否允许为空!")
+    private boolean isNullable;
 }

+ 1 - 1
src/main/java/com/xjrsoft/module/hikvision/util/OutInRecordUtil.java

@@ -218,7 +218,7 @@ public class OutInRecordUtil {
                 LocalDateTime recordTimeDate = LocalDateTime.parse(recordTimeStr, formatter);
                 String attendanceStatus = discernStudentStatus(recordTimeDate, status, personId);
                 studentInsertRecord(personId, faceImportMapper.GetTeacherIdByPersonId(personId),
-                        faceImportMapper.GetClassIdByPersonId(personId), ApiUtil.GetRedirectURL(uri), recordTimeStr, status, eventId, attendanceStatus);
+                    faceImportMapper.GetClassIdByPersonId(personId), ApiUtil.GetRedirectURL(uri), recordTimeStr, status, eventId, attendanceStatus);
             }
         }
     }

+ 2 - 2
src/main/java/com/xjrsoft/module/job/AttendanceMessageTask.java

@@ -252,7 +252,7 @@ public class AttendanceMessageTask {
                 for (XjrUser xjrUser : userList) {
                     weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
                     weChatSendMessageDto.setUserId(xjrUser.getOpenId());
-                    //weChatService.sendTemplateMessage(weChatSendMessageDto);
+                    weChatService.sendTemplateMessage(weChatSendMessageDto);
                 }
             }else if(messageSet.getRoleType() != null && messageSet.getRoleType() == 2){
                 //教师总人数
@@ -297,7 +297,7 @@ public class AttendanceMessageTask {
                 for (XjrUser xjrUser : userList) {
                     weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
                     weChatSendMessageDto.setUserId(xjrUser.getOpenId());
-                    //weChatService.sendTemplateMessage(weChatSendMessageDto);
+                    weChatService.sendTemplateMessage(weChatSendMessageDto);
                 }
                 isInsert = true;
             }

+ 1 - 1
src/main/java/com/xjrsoft/module/job/JianyuekbBaseDataTask.java

@@ -90,7 +90,7 @@ public class JianyuekbBaseDataTask {
             }
             //推送学生
             tableName = "base_student";
-            dataUtil.insertStudent(tableName, grade, dataMap.get(tableName));
+//            dataUtil.insertStudent(tableName, grade, dataMap.get(tableName));
             //推送教室
             tableName = "base_classroom";
             Map<String, String> classroomMap = dataUtil.insertClassRoom(tableName, schoolDistrictData.get(0).getAsString(), dataMap.get(tableName));

+ 566 - 66
src/main/java/com/xjrsoft/module/job/JianyuekbScheduleTask.java

@@ -1,24 +1,69 @@
 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.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.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.Scheduled;
 import org.springframework.stereotype.Component;
 
 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.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -32,12 +77,58 @@ import java.util.stream.Collectors;
 public class JianyuekbScheduleTask {
     @Autowired
     private IBaseClassService classService;
+    
+    private final static String taskKey = "jianyuekbScheduleTask";
+
+    @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;
+
+    private final static String wechatTemplate = "OO5Ryu9_6Hh5LQW0aKG7qu3g5uV8VxvBusq1i5UFesk";
+
+    @Autowired
+    private IWeChatService weChatService;
+
+    @Autowired
+    private CommonPropertiesConfig commonPropertiesConfig;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IWorkflowExtraService workflowExtraService;
 
     @Scheduled(cron = "0 */10 * * * ?")
-    public void execute() throws Exception {
-        RefreshConnectionPool();
+    public void execute(){
+        doExecute();
     }
-    public void RefreshConnectionPool() throws Exception {
+    public void doExecute() {
         String active = SpringUtil.getActiveProfile();
         if(!"prod".equals(active)){
             log.info("非正式环境,无法执行获取课表数据");
@@ -48,9 +139,8 @@ public class JianyuekbScheduleTask {
         if(receiveMsgs.isEmpty()){
             return;
         }
-        JsonArray allScheduleInfo = new JsonArray();
+
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        DataUtil dataUtil = new DataUtil();
         //查询出传入排课系统的年级和班级
         List<String> eduYearSerialNo1 = receiveMsgs.stream().map(x -> "'" + x.get("edu_year_serial_no").toString() + "'").collect(Collectors.toList());
 
@@ -59,7 +149,7 @@ public class JianyuekbScheduleTask {
             " and table_name = 'base_grade'" +
             " and jianyue_id in (" + eduYearSerialNo1.toString().replace("[","").replace("]","") + ")";
         List<Map<String, Object>> jianyueData = SqlRunnerAdapter.db().selectList(sql);
-        Map<String, List<Long>> gradeClassMaps = new HashMap<>();//存入对应年级的所有班级id
+        Map<String, List<BaseClass>> gradeClassMaps = new HashMap<>();//存入对应年级的所有班级id
         for (Map<String, Object> el : jianyueData) {
             String gradeId = el.get("source_id").toString();
             String orgId = null;
@@ -73,78 +163,86 @@ public class JianyuekbScheduleTask {
                             .eq(BaseClass::getGradeId, gradeId)
                             .eq(BaseClass::getOrgId, orgId)
             );
-            List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
-
-            gradeClassMaps.put(el.get("jianyue_id").toString(), classIds);
+            gradeClassMaps.put(el.get("jianyue_id").toString(), classList);
         }
         LocalDate today = LocalDate.now();
-        for (Map<String, Object> receiveMsg : receiveMsgs) {
-            String updSql = "update course_receive_msg set is_callback = 0 where id = " + receiveMsg.get("id").toString();
-            SqlRunnerAdapter.db().update(updSql);
 
+        DataUtil dataUtil = new DataUtil();
+        Set<String> ongoing = redisUtil.get(taskKey, new TypeReference<Set<String>>() {});//正在进行中的
+        if(ongoing == null){
+            ongoing = new HashSet<>();
+        }
+
+        Map<String, Map<String, String>> dataMap = initDataMap();
+        for (Map<String, Object> receiveMsg : receiveMsgs) {
             String eduYearSerialNo = receiveMsg.get("edu_year_serial_no").toString();
-            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);
+            if(ongoing.contains(eduYearSerialNo)){
+                continue;
             }
-            //删除课表信息;
-            String classIds = gradeClassMaps.get(eduYearSerialNo).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);
-
-            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;
+            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);
                 }
 
-                String endDate = endTime.format(formatter);
-                //获取课表并存到数据库
-                JsonArray scheduleInfo = dataUtil.getScheduleInfoByGrade(eduYearSerialNo, startDate, endDate);
-                allScheduleInfo.addAll(scheduleInfo);
-            }
+                //删除课表信息;
+                List<BaseClass> classList = gradeClassMaps.get(eduYearSerialNo);
+                List<Long> classIdList = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+                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);
 
-            updSql = "update course_receive_msg set is_callback = 1 where id = " + receiveMsg.get("id").toString();
-            SqlRunnerAdapter.db().update(updSql);
-            //作废调课和顶课
-            updSql = "UPDATE wf_course_adjust SET enabled_mark = 0 WHERE adjust_type BETWEEN '" + startDateStr + "'" +
-                    " and '" + endDateStr + "' and class_id in (" + classIds + ")";
-            SqlRunnerAdapter.db().update(updSql);
-        }
-        doExecute(allScheduleInfo);
-    }
+                startDateStr = receiveMsg.get("start_date").toString();
+                List<String> processIds = suspendedCourseAdjust(classList, startDateStr, endDateStr);
 
-    void doExecute(JsonArray scheduleInfo){
-        String sql = "SELECT distinct table_name FROM jianyue_data WHERE 1 = 1";
-        List<Map<String, Object>> query = SqlRunnerAdapter.db().selectList(sql);
-        Set<String> tables = new HashSet<>();
-        for (Map<String, Object> jianyueData : query) {
-            tables.add(jianyueData.get("table_name").toString());
-        }
-        sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''";
-        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
-        Map<String, Map<String, String>> dataMap = new HashMap<>();
-        for (String table : tables) {
-            Map<String, String> tableData = new HashMap<>();
-            for (Map<String, Object> jianyueData : list) {
-                if(!table.equals(jianyueData.get("table_name").toString())){
-                    continue;
+                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);
                 }
-                tableData.put(jianyueData.get("jianyue_id").toString(), jianyueData.get("source_id").toString());
+
+                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);
+                //恢复挂起的流程
+                restoreCourseAdjust(processIds);
+                //处理该日期内已经审批通过的调课和顶课申请
+                handleCourseAdjust(classList, startDateStr, endDateStr);
+            }catch (Exception e){
+                Log.error(e.getMessage(), e);
+                ongoing.remove(eduYearSerialNo);
+                redisUtil.set(taskKey, ongoing);
             }
-            dataMap.put(table, tableData);
         }
-        DataUtil dataUtil = new DataUtil();
+    }
+
+    void insertCourse(JsonArray scheduleInfo, Map<String, Map<String, String>> dataMap, DataUtil dataUtil){
         //获取年级
         String tableName = "base_grade";
 //            Map<String, Long> gradeMap = dataMap.get(tableName);
@@ -168,4 +266,406 @@ public class JianyuekbScheduleTask {
         dataUtil.insertClassTime(scheduleInfo);
     }
 
+    Map<String, Map<String, String>> initDataMap(){
+        Map<String, Map<String, String>> dataMap = new HashMap<>();
+        String sql = "SELECT distinct table_name FROM jianyue_data WHERE 1 = 1";
+        List<Map<String, Object>> query = SqlRunnerAdapter.db().selectList(sql);
+        Set<String> tables = new HashSet<>();
+        for (Map<String, Object> jianyueData : query) {
+            tables.add(jianyueData.get("table_name").toString());
+        }
+        sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''";
+        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
+
+        for (String table : tables) {
+            Map<String, String> tableData = new HashMap<>();
+            for (Map<String, Object> 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、筛选出课表变化了的调课和顶课申请,通知发起人
+     */
+    public void handleCourseAdjust(List<BaseClass> classList, String startDate, String endDate){
+        List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+        Map<Long, String> classMap = classList.stream().collect(Collectors.toMap(BaseClass::getId, BaseClass::getName));
+        List<CourseTableBak> bakList = courseTableBakService.list(
+                new QueryWrapper<CourseTableBak>().lambda()
+                        .in(CourseTableBak::getClassId, classIds)
+                        .between(CourseTableBak::getScheduleDate, startDate, endDate)
+        );
+        Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
+        List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
+        List<WfCourseAdjust> list = adjustService.list(
+                new MPJLambdaWrapper<WfCourseAdjust>()
+                        .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)
+                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
+                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED)
+        );
+        List<WfCourseAdjust> cancelList = new ArrayList<>();//需要作废的申请
+
+        List<Long> userIds = list.stream().map(WfCourseAdjust::getUserId).collect(Collectors.toList());
+        List<User> userList = userService.list(
+                new MPJLambdaWrapper<User>()
+                        .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<Long, String> userOpenIdMap = new HashMap<>();
+        for (User user : userList) {
+            userOpenIdMap.put(user.getId(), user.getOpenId());
+        }
+
+        for (WfCourseAdjust courseAdjust : list) {
+            List<CourseTable> courseList = courseTableService.list(
+                    new MPJLambdaWrapper<CourseTable>()
+                            .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;
+            }
+            if(courseList.size() != courseCount){
+                //表明课程变化了,需要重新申请,需要将原来的申请作废并进行微信消息通知
+                courseAdjust.setEnabledMark(EnabledMark.DISABLED.getCode());
+                courseAdjust.setCancelReason("由于课表更新,当前调/顶课课程发生变化,该调顶课已失效,请重新发起调顶课");
+                cancelList.add(courseAdjust);
+                List<String> thing16Str = new ArrayList<>();
+                List<String> 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);
+        }
+        if(!cancelList.isEmpty()){
+            adjustService.updateBatchById(cancelList);
+        }
+
+        List<WorkflowFormRelation> activeList = formRelationService.list(
+                new MPJLambdaWrapper<WorkflowFormRelation>()
+                        .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)
+                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
+                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
+        );
+        for (WorkflowFormRelation relation : activeList) {
+            List<CourseTable> courseList = courseTableService.list(
+                    new MPJLambdaWrapper<CourseTable>()
+                            .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<CourseTableBak> thisbakList = courseTableBakService.list(
+                    new QueryWrapper<CourseTableBak>().lambda()
+                            .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue())
+            );
+            if(courseList.size() == thisbakList.size()){
+                continue;
+            }
+            WfCourseAdjust courseAdjust = adjustService.getById(relation.getFormKeyValue());
+            //表明课程变化了,进行内部终止
+            List<String> thing16Str = new ArrayList<>();
+            List<String> 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<WorkflowExtra> extraList = workflowExtraService.list(
+                    new QueryWrapper<WorkflowExtra>().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<Task> 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> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
+            historicProcessInstance.ifPresent(item -> {
+                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
+                    setProcessId(processId);
+                    setCurrentState(item.getState());
+                    setStartTime(item.getStartTime());
+                    setEndTime(item.getEndTime());
+                }});
+            });
+        }
+    }
+
+
+    /**
+     * 挂起未通过的流程
+     */
+    List<String> suspendedCourseAdjust(List<BaseClass> classList, String startDate, String endDate) {
+        List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+        List<CourseTableBak> bakList = courseTableBakService.list(
+                new QueryWrapper<CourseTableBak>().lambda()
+                        .in(CourseTableBak::getClassId, classIds)
+                        .between(CourseTableBak::getScheduleDate, startDate, endDate)
+        );
+        Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
+
+        List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
+        List<WorkflowFormRelation> list = formRelationService.list(
+                new MPJLambdaWrapper<WorkflowFormRelation>()
+                        .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<String> processIds = new ArrayList<>();
+        for (WorkflowFormRelation relation : list) {
+            String processId = relation.getProcessId();
+            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
+            List<Task> 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> 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<String> processIds){
+        for (String processId : processIds) {
+            List<Task> 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> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
+            historicProcessInstance.ifPresent(item -> {
+                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
+                    setProcessId(processId);
+                    setCurrentState(item.getState());
+                    setStartTime(item.getStartTime());
+                    setEndTime(item.getEndTime());
+                }});
+            });
+        }
+    }
+
 }

+ 7 - 1
src/main/java/com/xjrsoft/module/liteflow/node/StudentChangeClassNode.java

@@ -1,6 +1,8 @@
 package com.xjrsoft.module.liteflow.node;
 
 import cn.hutool.core.convert.Convert;
+import com.xjrsoft.module.base.entity.BaseClass;
+import com.xjrsoft.module.base.service.IBaseClassService;
 import com.xjrsoft.module.student.entity.StudentChangeClass;
 import com.xjrsoft.module.student.mapper.StudentChangeClassMapper;
 import com.xjrsoft.module.student.service.IBaseStudentSchoolRollService;
@@ -19,6 +21,8 @@ public class StudentChangeClassNode extends NodeComponent {
     private StudentChangeClassMapper studentChangeClassMapper;
     @Autowired
     private IBaseStudentSchoolRollService studentSchoolRollService;
+    @Autowired
+    private IBaseClassService baseClassService;
     @Override
     public void process() throws Exception {
         // 获取表单中数据编号
@@ -28,8 +32,10 @@ public class StudentChangeClassNode extends NodeComponent {
         if (formId != null) {
             //查询出数据
             StudentChangeClass changeClass = studentChangeClassMapper.selectById(formId);
+
+            BaseClass baseClass =baseClassService.getById(changeClass.getAfterClassId());
             //修改学生班级
-            studentSchoolRollService.updateStudentClass(changeClass.getAfterClassId(), changeClass.getStudentUserId());
+            studentSchoolRollService.updateStudentClass(changeClass.getAfterClassId(),baseClass.getMajorSetId(), changeClass.getStudentUserId());
         }
     }
 }

+ 29 - 0
src/main/java/com/xjrsoft/module/liteflow/node/WfCourseBackupsNode.java

@@ -0,0 +1,29 @@
+package com.xjrsoft.module.liteflow.node;
+
+import cn.hutool.core.convert.Convert;
+import com.xjrsoft.module.schedule.service.IWfCourseAdjustService;
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 调课顶课发起申请时备份数据
+ */
+@Component("wf_course_backups_node")
+public class WfCourseBackupsNode extends NodeComponent {
+    @Autowired
+    private IWfCourseAdjustService wfCourseAdjustService;
+
+    @Override
+    public void process() throws Exception {
+        Map<String, Object> params = this.getFirstContextBean();
+        Object value = util.getFormDatKey(params,"id");
+        Long formId = Convert.toLong(value);
+        if (formId != null) {
+            // 数据处理
+            wfCourseAdjustService.backupsData(formId);
+        }
+    }
+}

+ 4 - 4
src/main/java/com/xjrsoft/module/material/controller/MaterialTaskController.java

@@ -215,13 +215,13 @@ public class MaterialTaskController {
             excelVo.setDeptName(listVo.getDeptName());
             //状态 1=未提交 2=待审核 3=通过 4=重做
             String state = "";
-            if(listVo.getStatus() != null && listVo.getUserType() == 1){
+            if(listVo.getStatus() != null && listVo.getStatus() == 1){
                 state = "未提交";
-            }else if(listVo.getStatus() != null && listVo.getUserType() == 2){
+            }else if(listVo.getStatus() != null && listVo.getStatus() == 2){
                 state = "待审核";
-            }else if(listVo.getStatus() != null && listVo.getUserType() == 3){
+            }else if(listVo.getStatus() != null && listVo.getStatus() == 3){
                 state = "通过";
-            }else if(listVo.getStatus() != null && listVo.getUserType() == 4){
+            }else if(listVo.getStatus() != null && listVo.getStatus() == 4){
                 state = "重做";
             }
             excelVo.setStatus(state);

+ 3 - 3
src/main/java/com/xjrsoft/module/material/service/impl/MaterialTaskServiceImpl.java

@@ -451,7 +451,7 @@ public class MaterialTaskServiceImpl extends MPJBaseServiceImpl<MaterialTaskMapp
                 .select(MaterialTaskAssign::getId)
                 .selectAs(MaterialTaskAppendix::getFileId, MaterialTaskAssignListVo::getFileId)
 //                .selectAs(File::getFolderId, MaterialTaskAssignListVo::getFolderId)
-                .select("CASE t4.material_category WHEN 'MT0001' THEN t6.folder_id ELSE t5.file_id END folderId")
+                .select("CASE t2.material_category WHEN 'MT0001' THEN t4.folder_id ELSE t3.file_id END folderId")
                 .select("(select GROUP_CONCAT(DISTINCT b.name) from xjr_user_dept_relation a left join xjr_department b on a.dept_id=b.id where a.user_id=t.user_id) as deptName")
 //                .selectAs(MaterialTaskAppendix::getFileId, MaterialTaskAssignListVo::getFormDataId)
                 .selectAs(MaterialTask::getMaterialCategory, MaterialTaskAssignListVo::getMaterialCategory)
@@ -461,7 +461,7 @@ public class MaterialTaskServiceImpl extends MPJBaseServiceImpl<MaterialTaskMapp
 //                .leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, MaterialTypeAssign::getUserId)
 //                .leftJoin(Department.class, Department::getId, UserDeptRelation::getDeptId, ext -> ext.selectAs(Department::getName, MaterialTaskAssignListVo::getDeptName))
                 .leftJoin(MaterialTask.class, MaterialTask::getId, MaterialTaskAssign::getMaterialTaskId)
-                .leftJoin(MaterialTaskAppendix.class, MaterialTaskAppendix::getMaterialTaskId, MaterialTaskAssign::getId)
+                .leftJoin(MaterialTaskAppendix.class,on-> on.eq(MaterialTaskAppendix::getMaterialTaskId, MaterialTaskAssign::getId).eq(MaterialTaskAppendix::getDeleteMark,DeleteMark.NODELETE.getCode()) )
                 .leftJoin(File.class, File::getId, MaterialTaskAppendix::getFileId)
                 .like(dto.getName() != null && !"".equals(dto.getName()), XjrUser::getName, dto.getName())
                 .eq(MaterialTaskAssign::getMaterialTaskId, dto.getMaterialTaskId())
@@ -470,7 +470,7 @@ public class MaterialTaskServiceImpl extends MPJBaseServiceImpl<MaterialTaskMapp
 //                .eq(Department::getDeleteMark, DeleteMark.NODELETE.getCode())
                 .eq(MaterialTask::getDeleteMark, DeleteMark.NODELETE.getCode())
                 .eq(MaterialTaskAssign::getDeleteMark, DeleteMark.NODELETE.getCode())
-                .eq(MaterialTaskAppendix::getDeleteMark, DeleteMark.NODELETE.getCode())
+//                .eq(MaterialTaskAppendix::getDeleteMark, DeleteMark.NODELETE.getCode())
 //                .select("(\n" +
 //                        "SELECT id FROM xjr_file WHERE id IN (\n" +
 //                        "SELECT file_id FROM material_task_appendix WHERE material_task_id = t.id\n" +

+ 2 - 2
src/main/java/com/xjrsoft/module/organization/controller/UserController.java

@@ -749,7 +749,7 @@ public class UserController {
         User user = userService.getOne(Wrappers.<User>query().lambda()
                 .eq(User::getName, dto.getName())
                 .eq(User::getCredentialNumber, dto.getIdCard())
-                .eq(User::getMobile, dto.getMobile())
+                .eq(StrUtil.isNotBlank(dto.getMobile()), User::getMobile, dto.getMobile())
         );
 
         UserStudentAddDto userStudentAddDto = new UserStudentAddDto();
@@ -777,7 +777,7 @@ public class UserController {
         if (userStudentInfoVo == null) {
             return RT.error("学生不存在!");
         }
-        if(!dto.getMobile().equals(userStudentInfoVo.getMobile())){
+        if(StrUtil.isNotBlank(dto.getMobile())&& !dto.getMobile().equals(userStudentInfoVo.getMobile())) {
             return RT.error("该学生的手机号和当前输入的手机号不一致!");
         }
 

+ 4 - 3
src/main/java/com/xjrsoft/module/personnel/service/impl/CarMessageApplyServiceImpl.java

@@ -61,10 +61,11 @@ public class CarMessageApplyServiceImpl extends MPJBaseServiceImpl<CarMessageApp
                 idsMap.remove(object.get("vehicleId").getAsString());
             }
             Collection<String> values = idsMap.values();
-            this.removeBatchByIds(values);
-        }else{
-            this.removeBatchByIds(ids);
+//            this.removeBatchByIds(values); 远程没有数据
         }
+//        else{
+            this.removeBatchByIds(ids);
+//        }
         return true;
     }
 }

+ 35 - 22
src/main/java/com/xjrsoft/module/schedule/controller/ScheduleController.java

@@ -16,7 +16,9 @@ import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.base.entity.BaseSemester;
 import com.xjrsoft.module.base.service.IBaseSemesterService;
+import com.xjrsoft.module.courseTable.entity.ClassTime;
 import com.xjrsoft.module.courseTable.entity.CourseTable;
+import com.xjrsoft.module.courseTable.service.IClassTimeService;
 import com.xjrsoft.module.courseTable.service.ICourseTableService;
 import com.xjrsoft.module.schedule.dto.ClassOptionDto;
 import com.xjrsoft.module.schedule.dto.CourseTableAdjustDto;
@@ -26,7 +28,6 @@ import com.xjrsoft.module.schedule.dto.ScheduleWeekDto;
 import com.xjrsoft.module.schedule.dto.ScheduleWeekExportQueryDto;
 import com.xjrsoft.module.schedule.dto.WfCourseAdjustDto;
 import com.xjrsoft.module.schedule.entity.CourseReceiveMsg;
-import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
 import com.xjrsoft.module.schedule.service.ICourseReceiveMsgService;
 import com.xjrsoft.module.schedule.service.IWfCourseAdjustService;
 import com.xjrsoft.module.schedule.util.ScheduleUtil;
@@ -84,10 +85,11 @@ public class ScheduleController {
     private final ITeacherbaseManagerService teacherService;
     private final IBaseSemesterService semesterService;
     private final IWfCourseAdjustService courseAdjustService;
+    private final IClassTimeService classTimeService;
 
     @GetMapping(value = "/receive-msg")
     @ApiOperation(value="接收消息")
-    @SaCheckPermission("room:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<CourseReceiveMsg> receiveMsg(@RequestParam String schoolId, @RequestParam String eduYearSerialNo, @RequestParam String startDate, @RequestParam String endDate) throws Exception {
         CourseReceiveMsg courseReceiveMsg = new CourseReceiveMsg();
         courseReceiveMsg.setCreateDate(new Date());
@@ -104,7 +106,7 @@ public class ScheduleController {
 
     @GetMapping(value = "/course-table")
     @ApiOperation(value="课表接口(PC端)")
-    @SaCheckPermission("room:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<CourseTableVo> courseInfo(CourseTableDto dto){
         if(dto.getSemesterId() == null){
             LambdaQueryWrapper<BaseSemester> queryWrapper = new LambdaQueryWrapper<>();
@@ -122,7 +124,7 @@ public class ScheduleController {
 
     @GetMapping(value = "/course-table-day")
     @ApiOperation(value="今日课表接口(手机端)")
-    @SaCheckPermission("room:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<CourseTableVo> courseInfoDay(CourseTableDto dto){
         LocalDateTime now = LocalDateTime.now();
         DayOfWeek dayOfWeek = now.getDayOfWeek();
@@ -159,7 +161,7 @@ public class ScheduleController {
 
     @GetMapping(value = "/current-week")
     @ApiOperation(value="获取当前周次")
-    @SaCheckPermission("room:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<Integer> currentWeek(CourseTableDto dto){
         List<BaseSemester> semesterList = semesterService.list(new QueryWrapper<BaseSemester>().lambda().orderByDesc(BaseSemester::getStartDate));
         BaseSemester baseSemester = semesterList.get(0);
@@ -175,7 +177,7 @@ public class ScheduleController {
                 LocalDateTime startDate = startDateTime.plusDays(i * 6).withHour(0).withMinute(0).withSecond(0).withNano(0);
                 LocalDateTime endDate = startDateTime.plusDays((i + 1) * 6).withHour(23).withMinute(59).withSecond(59).withNano(9999);
                 if (now.isAfter(startDate) && now.isBefore(endDate)) {
-                    return RT.ok(i + 1);
+                    return RT.ok(i);
                 }
             }
         }
@@ -186,21 +188,21 @@ public class ScheduleController {
 
     @GetMapping(value = "/adjust-list")
     @ApiOperation(value = "可以调课的课程")
-    @SaCheckPermission("evaluateobject:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<List<CourseListVo>> adjustList(CourseTableAdjustDto dto){
-//        if(dto.getAdjustDate() == null || dto.getTeacherId() == null){
-//            return RT.error("请传入调整日期和教师id");
-//        }
-//        List<CourseListVo> list = courseTableService.getAdjustList(dto);
-//        if(list.isEmpty()){
-//            return RT.error("暂无可调课程");
-//        }
+        if(dto.getAdjustDate() == null || dto.getTeacherId() == null){
+            return RT.error("请传入调整日期和教师id");
+        }
+        List<CourseListVo> list = courseTableService.getAdjustList(dto.getTeacherId().toString(), dto.getAdjustDate(), dto.getClassId(), dto.getAdjustType());
+        if(list.isEmpty()){
+            return RT.error("暂无可调课程");
+        }
         return RT.ok();
     }
 
     @GetMapping(value = "/pre-check")
     @ApiOperation(value = "预检查")
-    @SaCheckPermission("evaluateobject:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<String> preCheck(CourseTablePreCheckDto dto) throws Exception {
         if(dto.getPreCheckType() != null){
             if(dto.getPreCheckType() == 1){
@@ -232,20 +234,31 @@ public class ScheduleController {
 
     @GetMapping(value = "/getCourseNames")
     @ApiOperation(value = "查询课程接口")
-    @SaCheckPermission("evaluateobject:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<String> getCourseNames(String id){
         String[] split = id.split(",");
         List<CourseTable> list = courseTableService.list(
                 new QueryWrapper<CourseTable>().lambda()
                         .in(CourseTable::getId, Arrays.asList(split))
         );
+
+        List<ClassTime> classTimeList =classTimeService.list();
         String result = "";
         for (int i = 0; i< list.size(); i ++){
             if(i > 0){
                 result += ",";
             }
             CourseTable courseTable = list.get(i);
-            result += courseTable.getCourseName();
+
+            String courseName = courseTable.getCourseName();
+
+            ClassTime classTime = classTimeList.stream().filter(u->u.getNumber().equals(courseTable.getTimeNumber())).findAny().orElse(null);
+
+            if(classTime!=null){
+                courseName +="("+classTime.getShortName()+")";
+            }
+
+            result += courseName;
         }
 
         return RT.ok(result);
@@ -324,7 +337,7 @@ public class ScheduleController {
 
     @GetMapping(value = "/login-url")
     @ApiOperation(value = "获取单点登录地址")
-    @SaCheckPermission("evaluateobject:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<String> getAccessToken() throws Exception {
         XjrUser xjrUser = teacherService.getById(StpUtil.getLoginIdAsLong());
         long timeMillis = System.currentTimeMillis();
@@ -351,7 +364,7 @@ public class ScheduleController {
 
     @GetMapping(value = "/week-list")
     @ApiOperation(value="获取周次列表")
-    @SaCheckPermission("room:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<List<ScheduleWeekVo>> weekList(@Valid ScheduleWeekDto dto){
         List<BaseSemester> semesterList = semesterService.list(new QueryWrapper<BaseSemester>().lambda().orderByDesc(BaseSemester::getStartDate));
         BaseSemester baseSemester = semesterList.get(0);
@@ -383,7 +396,7 @@ public class ScheduleController {
 
     @GetMapping(value = "/class-list")
     @ApiOperation(value="根据课表获取教师所教班级")
-    @SaCheckPermission("room:detail")
+    @SaCheckPermission("schedule:detail")
     public RT<List<ClassOptionVo>> classList(@Valid ClassOptionDto dto){
         if(dto.getUserId() == null){
             dto.setUserId(StpUtil.getLoginIdAsLong());
@@ -394,8 +407,8 @@ public class ScheduleController {
 
     @PostMapping(value = "/cancel")
     @ApiOperation(value="调课顶课的作废")
-    @SaCheckPermission("room:detail")
-    public RT<Boolean> cancel(@Valid WfCourseAdjustDto dto){
+    @SaCheckPermission("schedule:detail")
+    public RT<Boolean> cancel(@Valid @RequestBody WfCourseAdjustDto dto){
 
         return RT.ok(courseAdjustService.cancel(dto));
     }

+ 4 - 0
src/main/java/com/xjrsoft/module/schedule/dto/CourseTableAdjustDto.java

@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 
 /**
@@ -30,4 +31,7 @@ public class CourseTableAdjustDto implements Serializable {
     @ApiModelProperty("调课类型")
     private String adjustType;
 
+    @ApiModelProperty("除外的id")
+    private List<Long> exceptCourseList;
+
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/schedule/entity/CourseTableBak.java

@@ -100,4 +100,7 @@ public class CourseTableBak implements Serializable {
 
     @ApiModelProperty("调顶课申请的id")
     private Long wfCourseAdjustId;
+
+    @ApiModelProperty("关键信息(存课程的教师id、班级id、日期、节次、课程id、场地以“_”拼接)")
+    private String keyInfo;
 }

+ 5 - 0
src/main/java/com/xjrsoft/module/schedule/entity/WfCourseAdjust.java

@@ -81,4 +81,9 @@ public class WfCourseAdjust implements Serializable {
     private Integer status;
 
 
+    @ApiModelProperty("班级id")
+    private Long classId;
+
+    @ApiModelProperty("作废原因")
+    private String cancelReason;
 }

+ 5 - 3
src/main/java/com/xjrsoft/module/schedule/service/IWfCourseAdjustService.java

@@ -5,9 +5,9 @@ import com.xjrsoft.module.schedule.dto.WfCourseAdjustDto;
 import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
 
 /**
-* @title: 班级荣誉
-* @Author szs
-* @Date: 2023-12-06
+* @title: 调课顶课
+* @Author dzx
+* @Date: 2024年10月17日
 * @Version 1.0
 */
 
@@ -15,4 +15,6 @@ public interface IWfCourseAdjustService extends MPJBaseService<WfCourseAdjust> {
 
     Boolean cancel(WfCourseAdjustDto dto);
 
+    void backupsData(Long id);
+
 }

+ 46 - 0
src/main/java/com/xjrsoft/module/schedule/service/impl/WfCourseAdjustServiceImpl.java

@@ -1,11 +1,15 @@
 package com.xjrsoft.module.schedule.service.impl;
 
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.yulichang.base.MPJBaseServiceImpl;
 import com.xjrsoft.common.enums.CourseAdjustTypeEnum;
 import com.xjrsoft.common.enums.EnabledMark;
 import com.xjrsoft.module.courseTable.entity.CourseTable;
 import com.xjrsoft.module.courseTable.service.ICourseTableService;
+import com.xjrsoft.module.organization.entity.User;
+import com.xjrsoft.module.organization.service.IUserService;
 import com.xjrsoft.module.schedule.dto.WfCourseAdjustDto;
 import com.xjrsoft.module.schedule.entity.CourseTableBak;
 import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
@@ -16,6 +20,8 @@ import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -33,6 +39,7 @@ public class WfCourseAdjustServiceImpl extends MPJBaseServiceImpl<WfCourseAdjust
     
     private final ICourseTableBakService courseTableBakService;
     private final ICourseTableService courseTableService;
+    private final IUserService userService;
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean cancel(WfCourseAdjustDto dto) {
@@ -78,7 +85,46 @@ public class WfCourseAdjustServiceImpl extends MPJBaseServiceImpl<WfCourseAdjust
         }
         courseAdjust.setEnabledMark(EnabledMark.DISABLED.getCode());
         courseAdjust.setModifyDate(new Date());
+        User user = userService.getById(StpUtil.getLoginIdAsLong());
+        courseAdjust.setCancelReason("被" + user.getName() + "作废");
         this.updateById(courseAdjust);
         return true;
     }
+
+    @Override
+    public void backupsData(Long id) {
+        try {
+            WfCourseAdjust courseAdjust = this.getById(id);
+            List<CourseTableBak> insertList = new ArrayList<>();
+            if(CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())){//顶课
+                String[] courseIds = courseAdjust.getCourseId().split(",");
+                List<CourseTable> list = courseTableService.listByIds(Arrays.asList(courseIds));
+                for (CourseTable courseTable : list) {
+                    CourseTableBak tableBak = BeanUtil.toBean(courseTable, CourseTableBak.class);
+                    tableBak.setWfCourseAdjustId(id);
+                    insertList.add(tableBak);
+                }
+            }else if(CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())){
+                List<String> ids = new ArrayList<>();
+                String[] courseIds = courseAdjust.getCourseId().split(",");
+                ids.addAll(Arrays.asList(courseIds));
+
+                String[] exchangeCourseIds = courseAdjust.getExchangeCourseId().split(",");
+                ids.addAll(Arrays.asList(exchangeCourseIds));
+
+                List<CourseTable> list = courseTableService.listByIds(ids);
+                for (CourseTable courseTable : list) {
+                    CourseTableBak tableBak = BeanUtil.toBean(courseTable, CourseTableBak.class);
+                    tableBak.setWfCourseAdjustId(id);
+                    insertList.add(tableBak);
+                }
+            }
+
+            if(!insertList.isEmpty()){
+                courseTableBakService.saveBatch(insertList);
+            }
+        }catch (Exception e){
+            log.error(e.getMessage());
+        }
+    }
 }

+ 21 - 4
src/main/java/com/xjrsoft/module/schedule/util/DataUtil.java

@@ -3,6 +3,7 @@ package com.xjrsoft.module.schedule.util;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.db.Entity;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
@@ -15,6 +16,8 @@ import com.xjrsoft.module.base.entity.BaseGrade;
 import com.xjrsoft.module.base.entity.BaseLabel;
 import com.xjrsoft.module.base.entity.BaseSemester;
 import com.xjrsoft.module.organization.entity.Department;
+import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
+import com.xjrsoft.module.schedule.service.IWfCourseAdjustService;
 import com.xjrsoft.module.schedule.vo.StudentJianyuekbVo;
 import com.xjrsoft.module.teacher.entity.XjrUser;
 import lombok.extern.slf4j.Slf4j;
@@ -640,6 +643,7 @@ public class DataUtil {
             }
             serialNos.add(objectMap.get("jianyue_id").toString());
         }
+
         for (JsonElement jsonElement : data) {
             JsonObject asJsonObject = jsonElement.getAsJsonObject();
             JsonArray teachers = asJsonObject.get("teachers").getAsJsonArray();
@@ -654,6 +658,7 @@ public class DataUtil {
             String scheduleDate = asJsonObject.get("scheduleDate").getAsString();
             String courseClassId = coureseMap.get(asJsonObject.get("courseClassId").getAsString());
             String courseClassName = asJsonObject.get("courseClassName").getAsString();
+            String siteId = (classroomMap.get(asJsonObject.get("classRoomSerialNo").getAsString()) == null ? "0" : classroomMap.get(asJsonObject.get("classRoomSerialNo").getAsString()));
             List<String> teacherIds = new ArrayList<>();
             List<String> teacherNames = new ArrayList<>();
             List<String> teacher_serial_nos = new ArrayList<>();
@@ -676,12 +681,14 @@ public class DataUtil {
                 teacher_serial_no = teacher_serial_nos.toString().replace("[", "").replace("]", "");
             }
             String onlyKey = scheduleDate + classId + timeNumber;
+            String keyInfo = teacherId + "_" + classId + "_" + scheduleDate + "_" + courseClassId + "_" + siteId + "_" + timeNumber;
             if(oldDataMap.get(onlyKey) != null){
                 String updSql = "update course_table set teacher_serial_no = '" + teacher_serial_no + "'" +
                         ", teacher_id = '" + teacherId
                         + "', teacher_name = '" + teacherName + "', modify_date = now()" +
-                        " ,course_id = " + courseClassId + ", course_name = '" + courseClassName + "'" +
-                        " where schedule_date = '" + scheduleDate + "'and class_id = " + classId + " and time_number = " + timeNumber + ";";
+                        " ,course_id = " + courseClassId + ", course_name = '" + courseClassName
+                        + "',key_info = '" + keyInfo + "'" +
+                        " where schedule_date = '" + scheduleDate + "' and class_id = " + classId + " and time_number = " + timeNumber + ";";
                 updateSqlList.add(updSql);
                 continue;
             }
@@ -701,12 +708,13 @@ public class DataUtil {
             entity.set("weeks_cn", asJsonObject.get("dayOfWeekName").getAsString());
             entity.set("time_period", tmePeriod.get(asJsonObject.get("timeOption").getAsInt()));
             entity.set("time_number", timeNumber);
-            entity.set("site_id", (classroomMap.get(asJsonObject.get("classRoomSerialNo").getAsString()) == null ? 0 : classroomMap.get(asJsonObject.get("classRoomSerialNo").getAsString())));
+            entity.set("site_id", siteId);
             entity.set("site_name", asJsonObject.get("classRoomName").getAsString());
             entity.set("status", 1);
             entity.set("create_date", sdf.format(new Date()));
             entity.set("schedule_date", scheduleDate);
             entity.set("jianyue_id", asJsonObject.get("id").getAsString());
+            entity.set("key_info", keyInfo);
             entityList.add(entity);
         }
         if(!entityList.isEmpty()){
@@ -725,7 +733,6 @@ public class DataUtil {
      *
      */
     public void insertClassTime(JsonArray data) {
-
         Map<String, JsonObject> infoMap = new HashMap<>();
         Map<Integer, Integer> tmePeriod = ScheduleUtil.getTmePeriod();
         for (JsonElement jsonElement : data) {
@@ -771,6 +778,15 @@ public class DataUtil {
         }
     }
 
+    /**
+     * 保存节次数据
+     * @param infoMap
+     */
+    public void saveClassTime(Map<String, JsonObject> infoMap){
+
+    }
+
+
     /**
      * 插入记录表
      * @param tableName 表名字
@@ -789,4 +805,5 @@ public class DataUtil {
         }
     }
 
+
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/student/mapper/BaseStudentSchoolRollMapper.java

@@ -45,6 +45,9 @@ public interface BaseStudentSchoolRollMapper extends MPJBaseMapper<BaseStudentSc
     List<BaseStudentInfoCategoryVo> getStudyStatusCount(@Param("dto") BaseStudentInfoPageDto dto);
 
 
+    @Update("UPDATE base_student_school_roll SET class_id = #{classId},major_set_id=#{majorSetId} where user_id = #{userId}")
+    Boolean updateStudentClass1(Long classId,Long majorSetId, Long userId);
+
     @Update("UPDATE base_student_school_roll SET class_id = #{classId} where user_id = #{userId}")
     Boolean updateStudentClass(Long classId, Long userId);
 

+ 1 - 0
src/main/java/com/xjrsoft/module/student/service/IBaseStudentSchoolRollService.java

@@ -49,6 +49,7 @@ public interface IBaseStudentSchoolRollService extends MPJBaseService<BaseStuden
     MobileClassStatisticsVo getMobileClassStatistics(BaseStudentInfoPageDto dto);
 
     Boolean updateStudentClass(Long classId, Long userId);
+    Boolean updateStudentClass(Long classId,Long majorSetId, Long userId);
 
     List<BaseStudentSompleInfoVo> getInfosByParam(BaseStudentSimpleInfoDto dto);
 

+ 5 - 0
src/main/java/com/xjrsoft/module/student/service/impl/BaseStudentSchoolRollServiceImpl.java

@@ -197,6 +197,11 @@ public class BaseStudentSchoolRollServiceImpl extends MPJBaseServiceImpl<BaseStu
         return null;
     }
 
+    @Override
+    public Boolean updateStudentClass(Long classId,Long majorSetId, Long userId) {
+        return baseStudentSchoolRollMapper.updateStudentClass1(classId,majorSetId, userId);
+    }
+
     @Override
     public Boolean updateStudentClass(Long classId, Long userId) {
         return baseStudentSchoolRollMapper.updateStudentClass(classId, userId);

+ 9 - 0
src/main/java/com/xjrsoft/module/teacher/controller/TeacherbaseManagerController.java

@@ -16,7 +16,9 @@ import com.xjrsoft.common.page.PageOutput;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.hikvision.util.DataUtil;
 import com.xjrsoft.module.organization.entity.UserDeptRelation;
+import com.xjrsoft.module.organization.entity.UserPostRelation;
 import com.xjrsoft.module.organization.service.IUserDeptRelationService;
+import com.xjrsoft.module.organization.service.IUserPostRelationService;
 import com.xjrsoft.module.system.entity.DictionaryDetail;
 import com.xjrsoft.module.system.service.IDictionarydetailService;
 import com.xjrsoft.module.teacher.dto.AddXjrUserDto;
@@ -59,6 +61,7 @@ public class TeacherbaseManagerController {
     private final ITeacherbaseManagerService teacherbaseManagerService;
     private final IDictionarydetailService dictionarydetailService;
     private final IUserDeptRelationService userDeptRelationService;
+    private final IUserPostRelationService  userPostRelationService;
 
     @GetMapping(value = "/page")
     @ApiOperation(value="XjrUser列表(分页)")
@@ -116,6 +119,12 @@ public class TeacherbaseManagerController {
         String allDeptIdStr = StrUtil.join(StringPool.COMMA, deptIds);
         userVo.setDepartmentIds(allDeptIdStr);
 
+        List<Long> postIds = userPostRelationService.list(Wrappers.lambdaQuery(UserPostRelation.class)
+                .eq(UserPostRelation::getUserId,userVo.getId()))
+                .stream().map(UserPostRelation::getPostId).collect(Collectors.toList());
+        String allPostIdStr = StrUtil.join(StringPool.COMMA, postIds);
+        userVo.setPostIds(allPostIdStr);
+
         return R.ok(userVo);
     }
 

+ 3 - 0
src/main/java/com/xjrsoft/module/teacher/dto/AddXjrUserDto.java

@@ -136,4 +136,7 @@ public class AddXjrUserDto implements Serializable {
 
     @ApiModelProperty("部门id")
     private String departmentIds;
+
+    @ApiModelProperty("岗位id")
+    private String postIds;
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/teacher/dto/UpdateXjrUserDto.java

@@ -142,4 +142,7 @@ public class UpdateXjrUserDto implements Serializable {
 
     @ApiModelProperty("部门id")
     private String departmentIds;
+
+    @ApiModelProperty("岗位id")
+    private String postIds;
 }

+ 36 - 0
src/main/java/com/xjrsoft/module/teacher/service/impl/TeacherbaseManagerServiceImpl.java

@@ -14,10 +14,12 @@ import com.xjrsoft.common.utils.RedisUtil;
 import com.xjrsoft.config.CommonPropertiesConfig;
 import com.xjrsoft.module.organization.entity.User;
 import com.xjrsoft.module.organization.entity.UserDeptRelation;
+import com.xjrsoft.module.organization.entity.UserPostRelation;
 import com.xjrsoft.module.organization.entity.UserRoleRelation;
 import com.xjrsoft.module.organization.mapper.UserDeptRelationMapper;
 import com.xjrsoft.module.organization.mapper.UserRoleRelationMapper;
 import com.xjrsoft.module.organization.service.IUserDeptRelationService;
+import com.xjrsoft.module.organization.service.IUserPostRelationService;
 import com.xjrsoft.module.organization.service.IUserService;
 import com.xjrsoft.module.teacher.dto.AddXjrUserDto;
 import com.xjrsoft.module.teacher.dto.UpdateXjrUserDto;
@@ -73,6 +75,7 @@ public class TeacherbaseManagerServiceImpl extends MPJBaseServiceImpl<XjrUserMap
     private final UserDeptRelationMapper userDeptRelationMapper;
     private final IUserService userService;
     private final CommonPropertiesConfig propertiesConfig;
+    private final IUserPostRelationService userPostRelationService;
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean add(AddXjrUserDto dto) {
@@ -128,6 +131,22 @@ public class TeacherbaseManagerServiceImpl extends MPJBaseServiceImpl<XjrUserMap
             userDeptRelationService.saveBatch(userDeptRelationList);
         }
 
+        List<UserPostRelation> userPostRelationList = new ArrayList<>();
+        if (StrUtil.isNotBlank(dto.getPostIds())) {
+            String allPostIdStr = StrUtil.join(StringPool.COMMA, dto.getPostIds());
+            List<Long> postIds = Arrays.stream(allPostIdStr.split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
+            if (CollectionUtil.isNotEmpty(postIds)) {
+                for (Long postId : postIds) {
+                    //将用户所选岗位保存到关联表中
+                    UserPostRelation userPostRelation = new UserPostRelation();
+                    userPostRelation.setUserId(xjrUser.getId());
+                    userPostRelation.setPostId(postId);
+                    userPostRelationList.add(userPostRelation);
+                }
+            }
+            userPostRelationService.saveBatch(userPostRelationList);
+        }
+
         // 添加角色
         UserRoleRelation userRoleRelation = new UserRoleRelation();
         userRoleRelation.setUserId(xjrUser.getId());
@@ -174,6 +193,23 @@ public class TeacherbaseManagerServiceImpl extends MPJBaseServiceImpl<XjrUserMap
             userDeptRelationService.saveBatch(userDeptRelationList);
         }
 
+        userPostRelationService.remove(Wrappers.<UserPostRelation>query().lambda().eq(UserPostRelation::getUserId,xjrUser.getId()));
+        List<UserPostRelation> userPostRelationList = new ArrayList<>();
+        if (StrUtil.isNotBlank(dto.getPostIds())) {
+            String allPostIdStr = StrUtil.join(StringPool.COMMA, dto.getPostIds());
+            List<Long> postIds = Arrays.stream(allPostIdStr.split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
+            if (CollectionUtil.isNotEmpty(postIds)) {
+                for (Long postId : postIds) {
+                    //将用户所选岗位保存到关联表中
+                    UserPostRelation userPostRelation = new UserPostRelation();
+                    userPostRelation.setUserId(xjrUser.getId());
+                    userPostRelation.setPostId(postId);
+                    userPostRelationList.add(userPostRelation);
+                }
+            }
+            userPostRelationService.saveBatch(userPostRelationList);
+        }
+
         //********************************* BaseTeacher  增删改  开始 *******************************************/
         {
             // 查出所有子级的id

+ 3 - 0
src/main/java/com/xjrsoft/module/teacher/vo/XjrUserVo.java

@@ -140,4 +140,7 @@ public class XjrUserVo {
     @ApiModelProperty("部门id")
     private String departmentIds;
 
+    @ApiModelProperty("岗位id")
+    private String postIds;
+
 }

+ 35 - 2
src/main/java/com/xjrsoft/module/workflow/service/impl/WorkflowExecuteServiceImpl.java

@@ -1728,6 +1728,22 @@ public class WorkflowExecuteServiceImpl implements IWorkflowExecuteService {
             throw new MyException("找不到此任务!");
         }
 
+        Optional<HistoricProcessInstance> historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId());
+        HistoricProcessInstance historicProcess = historicProcessInstance.get();
+        //如果流程挂起了,报错
+        if (HistoricProcessInstance.STATE_SUSPENDED.equals(historicProcess.getState())) {
+            List<WorkflowRecord> recordList = workflowRecordMapper.selectList(
+                    new QueryWrapper<WorkflowRecord>().lambda()
+                            .eq(WorkflowRecord::getProcessId, task.getProcessInstanceId())
+                            .orderByDesc(WorkflowRecord::getRecordTime)
+            );
+            String message = "流程已挂起,无法审核";
+            if(!recordList.isEmpty()){
+                message = recordList.get(0).getMessage();
+            }
+            throw new MyException(message);
+        }
+
         //获取当前任务变量中的  schemaId
         Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
 
@@ -1840,7 +1856,7 @@ public class WorkflowExecuteServiceImpl implements IWorkflowExecuteService {
 
         List<LaunchAndApproveVo> result = new ArrayList<>();
 
-        Optional<HistoricProcessInstance> historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId());
+
 
         try {
             for (FormConfig formConfig : userTaskConfig.getFormConfigs()) {
@@ -3582,6 +3598,11 @@ public class WorkflowExecuteServiceImpl implements IWorkflowExecuteService {
                             .or()
                             .like(WorkflowExtra::getProcessName, dto.getKeyword()))
                     .orderByDesc(WorkflowExtra::getStartTime));
+            List<WorkflowFormRelation> relations = formRelationService.list(
+                    new QueryWrapper<WorkflowFormRelation>().lambda()
+                            .in(WorkflowFormRelation::getProcessId, processIds)
+            );
+            Map<String, String> stateMap = relations.stream().collect(Collectors.toMap(WorkflowFormRelation::getProcessId, WorkflowFormRelation::getCurrentState));
 
 
             for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
@@ -3617,7 +3638,19 @@ public class WorkflowExecuteServiceImpl implements IWorkflowExecuteService {
                             } else {
                                 vo.setCurrentProgress(e.getCurrentProgress());
                             }
-
+                            String currentState = stateMap.get(e.getProcessId());
+
+                            if(HistoricProcessInstance.STATE_SUSPENDED.equals(currentState)){
+                                vo.setState("挂起");
+                            }else if(HistoricProcessInstance.STATE_ACTIVE.equals(currentState)){
+                                vo.setState("审批中");
+                            }else if(HistoricProcessInstance.STATE_COMPLETED.equals(currentState)){
+                                vo.setState("审批完成");
+                            }else if(HistoricProcessInstance.STATE_EXTERNALLY_TERMINATED.equals(currentState)){
+                                vo.setState("外部终止");
+                            }else if(HistoricProcessInstance.STATE_INTERNALLY_TERMINATED.equals(currentState)){
+                                vo.setState("内部终止");
+                            }
                             result.add(vo);
                         });
             }

+ 3 - 0
src/main/java/com/xjrsoft/module/workflow/vo/MyProcessPageVo.java

@@ -73,4 +73,7 @@ public class MyProcessPageVo {
     @ApiModelProperty("是否已审批(0:否 1:是)")
     private Integer isApproval;
 
+    @ApiModelProperty("状态")
+    private String state;
+
 }

+ 2 - 1
src/main/resources/mapper/classtime/ClassTimeDeleteMapper.xml

@@ -4,7 +4,7 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.xjrsoft.module.classtime.mapper.ClassTimeDeleteMapper">
     <select id="getPage" parameterType="com.xjrsoft.module.classtime.dto.ClassTimeDeletePageDto" resultType="com.xjrsoft.module.classtime.vo.ClassTimeDeletePageVo">
-        SELECT t1.id, t2.name AS class_name,t3.name AS type_cn,t1.type,t4.name AS operation_user_name,t1.remark,
+        SELECT t1.id, t2.name AS class_name,t3.name AS type_cn,t1.type,t4.name AS operation_user_name,t1.remark,t1.time_period,
         t1.start_date,t1.end_date,t1.status,IFNULL(t1.modify_date,t1.create_date) AS operation_time FROM class_time_delete t1
         INNER JOIN base_class t2 ON t1.class_id = t2.id
         LEFT JOIN xjr_dictionary_detail t3 ON t1.type = t3.code
@@ -19,6 +19,7 @@
         <if test="dto.enabledMark != null">
             and t1.status = #{dto.enabledMark}
         </if>
+         order by t1.create_date desc
     </select>
 
 </mapper>

+ 3 - 3
src/main/resources/mapper/classtime/ClassTimeStatisticsMapper.xml

@@ -17,7 +17,7 @@
     </select>
 
     <select id="getCourseList" parameterType="com.xjrsoft.module.classtime.entity.ClassTimeStatistics" resultType="com.xjrsoft.module.classtime.vo.CourseListVo">
-        SELECT t1.class_id, t1.teacher_id, t2.short_name,t1.adjust_type,t4.reason,t1.schedule_date,t1.class_name,t1.course_name FROM course_table t1
+        SELECT t1.class_id, t1.teacher_id, t2.short_name,t1.adjust_type,t4.reason,t1.schedule_date,t1.class_name,t1.course_name,t1.time_number FROM course_table t1
         LEFT JOIN class_time t2 ON t1.time_period = t2.time_period AND t1.time_number = t2.number
         LEFT JOIN course_table_bak t3 ON t1.id = t3.id
         LEFT JOIN wf_course_adjust t4 ON t4.id = t3.wf_course_adjust_id
@@ -29,7 +29,7 @@
     </select>
 
     <select id="getHolidayReplaceCourseList" parameterType="com.xjrsoft.module.classtime.entity.ClassTimeStatistics" resultType="com.xjrsoft.module.classtime.vo.CourseListVo">
-        SELECT t1.class_id, t1.teacher_id, t2.short_name,t1.adjust_type,t4.reason,t1.schedule_date,t1.class_name,t1.course_name FROM course_table t1
+        SELECT t1.class_id, t1.teacher_id, t2.short_name,t1.adjust_type,t4.reason,t1.schedule_date,t1.class_name,t1.course_name,t1.time_number FROM course_table t1
         LEFT JOIN class_time t2 ON t1.time_period = t2.time_period AND t1.time_number = t2.number
         LEFT JOIN course_table_bak t3 ON t1.id = t3.id
         LEFT JOIN wf_course_adjust t4 ON t4.id = t3.wf_course_adjust_id
@@ -42,7 +42,7 @@
     </select>
 
     <select id="getReplaceCourseList" parameterType="com.xjrsoft.module.classtime.entity.ClassTimeStatistics" resultType="com.xjrsoft.module.classtime.vo.CourseListVo">
-        SELECT t1.class_id, t1.teacher_id, t2.short_name,t1.adjust_type,t4.reason,t1.schedule_date FROM course_table t1
+        SELECT t1.class_id, t1.teacher_id, t2.short_name,t1.adjust_type,t4.reason,t1.schedule_date,t1.time_number FROM course_table t1
         LEFT JOIN class_time t2 ON t1.time_period = t2.time_period AND t1.time_number = t2.number
         LEFT JOIN course_table_bak t3 ON t1.id = t3.id
         LEFT JOIN wf_course_adjust t4 ON t4.id = t3.wf_course_adjust_id

+ 15 - 0
src/main/resources/mapper/courseTable/CourseTable.xml

@@ -44,6 +44,7 @@
         <if test="dto.classId != null">
             and t5.id = #{dto.classId}
         </if>
+
     </select>
     <select id="getAdjustList" parameterType="com.xjrsoft.module.schedule.dto.CourseTableAdjustDto" resultType="com.xjrsoft.module.schedule.vo.CourseListVo">
         SELECT t1.time_period,t4.short_name as time_number,t1.course_name,t2.name AS class_name,t3.name AS classroom_name,t1.id,t2.id as class_id FROM course_table t1
@@ -61,7 +62,21 @@
         <if test="dto.classId != null and dto.classId != ''">
             and t1.class_id = #{dto.classId}
         </if>
+        <if test="dto.exceptCourseList != null and dto.exceptCourseList.size > 0">
+            AND t1.id not in
+            <foreach item="courseId" collection="dto.exceptCourseList" open="(" separator="," close=")">
+                #{courseId}
+            </foreach>
+        </if>
+        order by t4.number asc
     </select>
+    <select id="getExceptCourseList" parameterType="java.lang.Long" resultType="com.xjrsoft.module.schedule.entity.WfCourseAdjust">
+        SELECT a1.* FROM wf_course_adjust a1
+        INNER JOIN xjr_workflow_form_relation a2 ON a1.id = a2.form_key_value
+        WHERE a1.delete_mark = 0 AND a2.current_state IN ('COMPLETED','ACTIVE')
+        and a1.user_id = #{userId}
+    </select>
+
     <select id="getClassListByTeacherId" parameterType="com.xjrsoft.module.schedule.dto.ClassOptionDto" resultType="com.xjrsoft.module.schedule.vo.ClassOptionVo">
         SELECT id,name FROM base_class WHERE delete_mark = 0 AND id IN (
             SELECT DISTINCT class_id FROM course_table WHERE teacher_id like concat('%', #{dto.userId},'%')

+ 0 - 2
src/main/resources/mapper/personnel/BasePersonnelLabourCapitalMapper.xml

@@ -26,7 +26,6 @@
     </select>
 
     <select id="getYearPage" parameterType="com.xjrsoft.module.personnel.dto.BasePersonnelLabourCapitalYearPageDto" resultType="com.xjrsoft.module.personnel.vo.BasePersonnelLabourCapitalYearPageVo">
-        <if test="dto.year != null and dto.project != null">
         SELECT
             t.id,
             t.name,
@@ -46,7 +45,6 @@
             t.delete_mark = 0
         and YEAR(t1.date_of_issue) = #{dto.year}
         and t1.name = #{dto.project}
-        </if>
     </select>
 </mapper>
         <!--    SELECT-->

+ 69 - 0
src/main/resources/sqlScript/20240911_sql.sql

@@ -0,0 +1,69 @@
+-- ---------------------------------------------------------------------------------
+-- 上课时间表增加字段
+-- ---------------------------------------------------------------------------------
+ALTER TABLE `class_time`   
+  ADD COLUMN `create_user_id` BIGINT NULL   COMMENT '创建人id' AFTER `modify_date`,
+  ADD COLUMN `modify_user_id` BIGINT NULL   COMMENT '修改人id' AFTER `create_user_id`;
+
+  
+-- ---------------------------------------------------------------------------------
+-- 物品申购增加购买事项字段
+-- ---------------------------------------------------------------------------------
+ALTER TABLE `wf_subscription`   
+  ADD COLUMN `item_content` VARCHAR(2000) NULL   COMMENT '购买事项' AFTER `status`;
+
+-- ---------------------------------------------------------------------------------
+-- 教师听课
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS wf_teacher_listen;
+CREATE TABLE `wf_teacher_listen` (
+  `id` BIGINT NOT NULL COMMENT '主键',
+  `user_id` BIGINT DEFAULT NULL COMMENT '听课教师(xjr_user)',
+  `class_id` BIGINT DEFAULT NULL COMMENT '听课班级(base_class)',
+  `course_name` VARCHAR(50) DEFAULT NULL COMMENT '上课课程名称',
+  `teacher_id` BIGINT DEFAULT NULL COMMENT '上课老师(xjr_user)',
+  `schedule_date` DATE DEFAULT NULL COMMENT '上课日期',
+  `weeks` INT DEFAULT NULL COMMENT '星期几(1-7)',
+  `weeks_cn` VARCHAR(200) DEFAULT NULL COMMENT '星期中文',
+  `time_number` INT NOT NULL COMMENT '节次',
+  `folder_id` BIGINT DEFAULT NULL COMMENT '附件图片',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='教师听课';
+
+-- ---------------------------------------------------------------------------------
+-- 课时补充
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS wf_teacher_course_time;
+CREATE TABLE `wf_teacher_course_time` (
+  `id` BIGINT NOT NULL COMMENT '主键',
+  `apply_user_id` BIGINT DEFAULT NULL COMMENT '教师(xjr_user)',
+  `dept_id` BIGINT DEFAULT NULL COMMENT '部门id(xjr_department)',
+  `course_time_type` VARCHAR(50) DEFAULT NULL COMMENT '课时类型(xjr_dictionary_item[course_time_type])',
+  `course_time` DOUBLE(6,2) DEFAULT NULL COMMENT '补充课时',
+  `schedule_date` DATE DEFAULT NULL COMMENT '上课日期',
+  `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
+  `explains` VARCHAR(500) DEFAULT NULL COMMENT '说明',
+  `teacher_ids` LONGTEXT DEFAULT NULL COMMENT '补课人员',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课时补充';
+
+ALTER TABLE `course_table`   
+  ADD COLUMN `adjust_type` VARCHAR(50) NULL   COMMENT '调课顶课(顶课:course_substitute 调课:course_exchange)';
+
+ALTER TABLE `wf_course_adjust` 
+CHANGE `course_id` `course_id` VARCHAR(500) NULL COMMENT '课程id(base_course_subject)', 
+CHANGE `exchange_course_id` `exchange_course_id` VARCHAR(500) NULL COMMENT '对调课程id(base_course_subject)';
+
+-- ---------------------------------------------------------------------------------
+-- 学生留宿申请增加class_id
+-- ---------------------------------------------------------------------------------
+ALTER TABLE `wf_room_stay_overnight`   
+  ADD COLUMN `class_id` BIGINT DEFAULT 0  NULL   COMMENT '班级id' AFTER `status`;
+  
+-- ---------------------------------------------------------------------------------
+-- 海康推送表增加字段
+-- ---------------------------------------------------------------------------------
+ALTER TABLE `hikvision_data`   
+  ADD COLUMN `send_data` TEXT NULL   COMMENT '发送数据' AFTER `hikvision_id`;
+
+ 

+ 139 - 0
src/main/resources/sqlScript/20240926_sql.sql

@@ -0,0 +1,139 @@
+-- ---------------------------------------------------------------------------------
+-- 课时统计
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS class_time_statistics;
+CREATE TABLE `class_time_statistics` (
+  `id` BIGINT NOT NULL COMMENT '主键编号',
+  `create_user_id` BIGINT DEFAULT NULL COMMENT '创建人',
+  `create_date` DATETIME DEFAULT NULL COMMENT '创建时间',
+  `modify_user_id` BIGINT DEFAULT NULL COMMENT '修改人',
+  `modify_date` DATETIME DEFAULT NULL COMMENT '修改时间',
+  `delete_mark` INT NOT NULL COMMENT '删除标记',
+  `enabled_mark` INT NOT NULL COMMENT '有效标志',
+  `year` INT DEFAULT NULL COMMENT '统计年份',
+  `month` INT DEFAULT NULL COMMENT '统计月份',
+  `start_date` DATE DEFAULT NULL COMMENT '开始日期',
+  `end_date` DATE DEFAULT NULL COMMENT '结束日期',
+  `all_class_time` DOUBLE(8,1) DEFAULT NULL COMMENT '总课时',
+  `total_amount` DOUBLE(8,2) DEFAULT NULL COMMENT '总金额',
+  `class_time_amount` DOUBLE(8,2)  DEFAULT NULL COMMENT '总课时费用',
+  `beyond_class_time_amount` DOUBLE(8,2)  DEFAULT NULL COMMENT '总外聘教师超课时费',
+  `status` INT DEFAULT 0 COMMENT '状态(0:数据统计中 1:统计完成 2:已解锁 3:已锁定)',
+  `weight_set_json` LONGTEXT DEFAULT NULL COMMENT '权重json',
+  `cost_set_json` LONGTEXT DEFAULT NULL COMMENT '权重json',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课时统计';
+
+
+-- ---------------------------------------------------------------------------------
+-- 课时统计-教师详情
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS class_time_statistics_record;
+CREATE TABLE `class_time_statistics_record` (
+  `id` BIGINT NOT NULL COMMENT '主键编号',
+  `create_user_id` BIGINT DEFAULT NULL COMMENT '创建人',
+  `create_date` DATETIME DEFAULT NULL COMMENT '创建时间',
+  `modify_user_id` BIGINT DEFAULT NULL COMMENT '修改人',
+  `modify_date` DATETIME DEFAULT NULL COMMENT '修改时间',
+  `delete_mark` INT NOT NULL COMMENT '删除标记',
+  `enabled_mark` INT NOT NULL COMMENT '有效标志',
+  `class_time_statistics_id` BIGINT DEFAULT NULL COMMENT '课时统计(class_time_statistics)',
+  `user_id` BIGINT DEFAULT NULL COMMENT '教师id(xjr_user)',
+  `employ_type` VARCHAR(20) DEFAULT NULL COMMENT '聘用类型',
+  `all_class_time` DOUBLE(8,1) DEFAULT NULL COMMENT '总课时',
+  `total_amount` DOUBLE(8,2) DEFAULT NULL COMMENT '总金额',
+  `class_time_amount` DOUBLE(8,2)  DEFAULT NULL COMMENT '课时费用',
+  `beyond_class_time_amount` DOUBLE(8,2)  DEFAULT NULL COMMENT '外聘教师超课时费',
+  `week_data` LONGTEXT DEFAULT NULL COMMENT '每周数据',
+  
+  `class_time1` FLOAT(4,1) DEFAULT NULL COMMENT '教研会',
+  `class_time2` FLOAT(4,1) DEFAULT NULL COMMENT '督导听课',
+  `class_time3` FLOAT(4,1) DEFAULT NULL COMMENT '临近三年退休政策',
+  `class_time4` FLOAT(4,1) DEFAULT NULL COMMENT '出题',
+  `class_time5` FLOAT(4,1) DEFAULT NULL COMMENT '阅卷',
+  `class_time6` FLOAT(4,1) DEFAULT NULL COMMENT '周末培优',
+  `class_time7` FLOAT(4,1) DEFAULT NULL COMMENT '早自习',
+  `class_time8` FLOAT(4,1) DEFAULT NULL COMMENT '正课(包含调顶课时)',
+  `class_time9` FLOAT(4,1) DEFAULT NULL COMMENT '晚辅(包含调顶课时)',
+  `class_time10` FLOAT(4,1) DEFAULT NULL COMMENT '顶课',
+  `class_time11` FLOAT(4,1) DEFAULT NULL COMMENT '调课',
+
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课时统计-教师详情';
+
+
+-- ---------------------------------------------------------------------------------
+-- 课时统计-设置
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS class_time_statistics_set;
+CREATE TABLE `class_time_statistics_set` (
+  `id` BIGINT NOT NULL COMMENT '主键编号',
+  `create_user_id` BIGINT DEFAULT NULL COMMENT '创建人',
+  `create_date` DATETIME DEFAULT NULL COMMENT '创建时间',
+  `modify_user_id` BIGINT DEFAULT NULL COMMENT '修改人',
+  `modify_date` DATETIME DEFAULT NULL COMMENT '修改时间',
+  `delete_mark` INT NOT NULL COMMENT '删除标记',
+  `enabled_mark` INT NOT NULL COMMENT '有效标志',
+  `json_content` TEXT DEFAULT NULL COMMENT '权重内容',
+  `category` INT DEFAULT NULL COMMENT '类别(1:权重 2:费用设置)',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课时统计-设置';
+
+
+-- ---------------------------------------------------------------------------------
+-- 课时删除
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS class_time_delete;
+CREATE TABLE `class_time_delete` (
+  `id` BIGINT NOT NULL COMMENT '主键编号',
+  `create_user_id` BIGINT DEFAULT NULL COMMENT '创建人',
+  `create_date` DATETIME DEFAULT NULL COMMENT '创建时间',
+  `modify_user_id` BIGINT DEFAULT NULL COMMENT '修改人',
+  `modify_date` DATETIME DEFAULT NULL COMMENT '修改时间',
+  `delete_mark` INT NOT NULL COMMENT '删除标记',
+  `enabled_mark` INT NOT NULL COMMENT '有效标志',
+  `type` VARCHAR(50) DEFAULT NULL COMMENT '删除类型(xjr_dictionary_item[class_time_delete])',
+  `class_id` BIGINT DEFAULT NULL COMMENT '班级id',
+  `remark` VARCHAR(500) DEFAULT NULL COMMENT '删除说明',
+  `start_date` DATE DEFAULT NULL COMMENT '开始日期',
+  `end_date` DATE DEFAULT NULL COMMENT '结束日期',
+  `status` INT DEFAULT 0 COMMENT '状态(0:生效 1:锁定 2:作废)',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课时删除';
+
+-- ---------------------------------------------------------------------------------
+-- 节假日调课设置
+-- ---------------------------------------------------------------------------------
+DROP TABLE IF EXISTS class_time_calendar;
+CREATE TABLE `class_time_calendar` (
+  `id` BIGINT NOT NULL COMMENT '主键编号',
+  `create_user_id` BIGINT DEFAULT NULL COMMENT '创建人',
+  `create_date` DATETIME DEFAULT NULL COMMENT '创建时间',
+  `modify_user_id` BIGINT DEFAULT NULL COMMENT '修改人',
+  `modify_date` DATETIME DEFAULT NULL COMMENT '修改时间',
+  `delete_mark` INT NOT NULL COMMENT '删除标记',
+  `enabled_mark` INT NOT NULL COMMENT '有效标志',
+  `supplement_date` DATE DEFAULT NULL COMMENT '补班日期',
+  `replace_date` DATE DEFAULT NULL COMMENT '补课日期',
+  `status` INT DEFAULT 0 COMMENT '状态(0:生效 1:锁定 2:作废)',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='节假日调课设置';
+
+
+ALTER TABLE `base_student_assessment_inspection`   
+  CHANGE `assessment_date` `assessment_date` DATE NULL   COMMENT '考核时间';
+
+ALTER TABLE `base_student_assessment_inspection`   
+  ADD COLUMN `total_score` DOUBLE NULL   COMMENT '扣除总分' AFTER `personal_student_user_ids`;
+
+ALTER TABLE `base_student_assessment_student_relation`   
+  ADD COLUMN `score` DOUBLE DEFAULT 0  NULL   COMMENT '被扣分数' AFTER `major_name`;
+
+
+ALTER TABLE `class_time_statistics_record`   
+  ADD COLUMN `all_class_time_data` LONGTEXT NULL   COMMENT '总课时数据' AFTER `class_time11`;
+
+
+ALTER TABLE `wf_teacher_course_time`   
+  ADD COLUMN `enabled_mark` INT DEFAULT 1  NULL   COMMENT '状态(0:作废 1:生效 2:锁定)' AFTER `teacher_ids`;
+

+ 666 - 0
src/test/java/com/xjrsoft/module/job/JianyuekbScheduleTaskTest2.java

@@ -0,0 +1,666 @@
+package com.xjrsoft.module.job;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+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.XjrSoftApplication;
+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.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 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.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author dzx
+ * @date 2024/10/15
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = XjrSoftApplication.class)
+class JianyuekbScheduleTaskTest2 {
+    @Autowired
+    private IBaseClassService classService;
+
+    private final static String taskKey = "jianyuekbScheduleTask";
+
+    @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;
+
+    private final static String wechatTemplate = "OO5Ryu9_6Hh5LQW0aKG7qu3g5uV8VxvBusq1i5UFesk";
+
+    @Autowired
+    private IWeChatService weChatService;
+
+    @Autowired
+    private CommonPropertiesConfig commonPropertiesConfig;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IWorkflowExtraService workflowExtraService;
+
+    @Test
+    public void execute(){
+        doExecute();
+    }
+    public void doExecute() {
+        String sql = "SELECT * FROM course_receive_msg WHERE delete_mark = 0 AND is_callback IS NULL";
+        List<Map<String, Object>> receiveMsgs = SqlRunnerAdapter.db().selectList(sql);
+        if(receiveMsgs.isEmpty()){
+            return;
+        }
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        //查询出传入排课系统的年级和班级
+        List<String> eduYearSerialNo1 = receiveMsgs.stream().map(x -> "'" + x.get("edu_year_serial_no").toString() + "'").collect(Collectors.toList());
+
+        //查询出传入排课系统的年级和班级
+        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<Map<String, Object>> jianyueData = SqlRunnerAdapter.db().selectList(sql);
+        Map<String, List<BaseClass>> gradeClassMaps = new HashMap<>();//存入对应年级的所有班级id
+        for (Map<String, Object> el : jianyueData) {
+            String gradeId = el.get("source_id").toString();
+            String orgId = null;
+            if(gradeId.contains("_")){
+                String[] split = el.get("source_id").toString().split("_");
+                gradeId = split[1];
+                orgId = split[0];
+            }
+            List<BaseClass> classList = classService.list(
+                    new QueryWrapper<BaseClass>().lambda()
+                            .eq(BaseClass::getGradeId, gradeId)
+                            .eq(BaseClass::getOrgId, orgId)
+            );
+            gradeClassMaps.put(el.get("jianyue_id").toString(), classList);
+        }
+        LocalDate today = LocalDate.now();
+
+        DataUtil dataUtil = new DataUtil();
+        Set<String> ongoing = redisUtil.get(taskKey, new TypeReference<Set<String>>() {});//正在进行中的
+        if(ongoing == null){
+            ongoing = new HashSet<>();
+        }
+
+        Map<String, Map<String, String>> dataMap = initDataMap();
+        for (Map<String, Object> 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<BaseClass> classList = gradeClassMaps.get(eduYearSerialNo);
+                List<Long> classIdList = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+                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<String> processIds = suspendedCourseAdjust(classList, 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);
+                //恢复挂起的流程
+                restoreCourseAdjust(processIds);
+                //处理该日期内已经审批通过的调课和顶课申请
+                handleCourseAdjust(classList, startDateStr, endDateStr);
+            }catch (Exception e){
+                Log.error(e.getMessage(), e);
+                ongoing.remove(eduYearSerialNo);
+                redisUtil.set(taskKey, ongoing);
+            }
+        }
+    }
+
+    void insertCourse(JsonArray scheduleInfo, Map<String, Map<String, String>> dataMap, DataUtil dataUtil){
+        //获取年级
+        String tableName = "base_grade";
+//            Map<String, Long> gradeMap = dataMap.get(tableName);
+        //获取学期
+        tableName = "base_semester";
+        Map<String, String> semesterMap = dataMap.get(tableName);
+        //获取课程
+        tableName = "base_course_subject";
+        Map<String, String> courseMap = dataMap.get(tableName);
+        //获取教职工
+        tableName = "base_teacher";
+        Map<String, String> teacherMap = dataMap.get(tableName);
+        //获取行政班
+        tableName = "base_class";
+        Map<String, String> classMap = dataMap.get(tableName);
+
+        tableName = "base_classroom";
+        Map<String, String> classroomMap = dataMap.get(tableName);
+
+        dataUtil.insertCourseTableEntiy(scheduleInfo, classroomMap, courseMap, semesterMap, teacherMap, classMap);
+        dataUtil.insertClassTime(scheduleInfo);
+    }
+
+    Map<String, Map<String, String>> initDataMap(){
+        Map<String, Map<String, String>> dataMap = new HashMap<>();
+        String sql = "SELECT distinct table_name FROM jianyue_data WHERE 1 = 1";
+        List<Map<String, Object>> query = SqlRunnerAdapter.db().selectList(sql);
+        Set<String> tables = new HashSet<>();
+        for (Map<String, Object> jianyueData : query) {
+            tables.add(jianyueData.get("table_name").toString());
+        }
+        sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''";
+        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
+
+        for (String table : tables) {
+            Map<String, String> tableData = new HashMap<>();
+            for (Map<String, Object> 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、筛选出课表变化了的调课和顶课申请,通知发起人
+     */
+    public void handleCourseAdjust(List<BaseClass> classList, String startDate, String endDate){
+        List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+        Map<Long, String> classMap = classList.stream().collect(Collectors.toMap(BaseClass::getId, BaseClass::getName));
+        List<CourseTableBak> bakList = courseTableBakService.list(
+                new QueryWrapper<CourseTableBak>().lambda()
+                        .in(CourseTableBak::getClassId, classIds)
+                        .between(CourseTableBak::getScheduleDate, startDate, endDate)
+        );
+        Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
+        List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
+        List<WfCourseAdjust> list = adjustService.list(
+                new MPJLambdaWrapper<WfCourseAdjust>()
+                        .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)
+                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
+                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED)
+        );
+        List<WfCourseAdjust> cancelList = new ArrayList<>();//需要作废的申请
+
+        List<Long> userIds = list.stream().map(WfCourseAdjust::getUserId).collect(Collectors.toList());
+        List<User> userList = userService.list(
+                new MPJLambdaWrapper<User>()
+                        .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<Long, String> userOpenIdMap = new HashMap<>();
+        for (User user : userList) {
+            userOpenIdMap.put(user.getId(), user.getOpenId());
+        }
+
+        for (WfCourseAdjust courseAdjust : list) {
+            List<CourseTable> courseList = courseTableService.list(
+                    new MPJLambdaWrapper<CourseTable>()
+                            .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;
+            }
+            if(courseList.size() != courseCount){
+                //表明课程变化了,需要重新申请,需要将原来的申请作废并进行微信消息通知
+                courseAdjust.setEnabledMark(EnabledMark.DISABLED.getCode());
+                courseAdjust.setCancelReason("由于课表更新,当前调/顶课课程发生变化,该调顶课已失效,请重新发起调顶课");
+                cancelList.add(courseAdjust);
+                List<String> thing16Str = new ArrayList<>();
+                List<String> 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);
+        }
+        if(!cancelList.isEmpty()){
+            adjustService.updateBatchById(cancelList);
+        }
+
+        List<WorkflowFormRelation> activeList = formRelationService.list(
+                new MPJLambdaWrapper<WorkflowFormRelation>()
+                        .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)
+                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
+                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
+        );
+        for (WorkflowFormRelation relation : activeList) {
+            List<CourseTable> courseList = courseTableService.list(
+                    new MPJLambdaWrapper<CourseTable>()
+                            .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<CourseTableBak> thisbakList = courseTableBakService.list(
+                    new QueryWrapper<CourseTableBak>().lambda()
+                            .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue())
+            );
+            if(courseList.size() == thisbakList.size()){
+                continue;
+            }
+            WfCourseAdjust courseAdjust = adjustService.getById(relation.getFormKeyValue());
+            //表明课程变化了,进行内部终止
+            List<String> thing16Str = new ArrayList<>();
+            List<String> 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<WorkflowExtra> extraList = workflowExtraService.list(
+                    new QueryWrapper<WorkflowExtra>().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<Task> 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> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
+            historicProcessInstance.ifPresent(item -> {
+                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
+                    setProcessId(processId);
+                    setCurrentState(item.getState());
+                    setStartTime(item.getStartTime());
+                    setEndTime(item.getEndTime());
+                }});
+            });
+        }
+    }
+
+
+    /**
+     * 挂起未通过的流程
+     */
+    List<String> suspendedCourseAdjust(List<BaseClass> classList, String startDate, String endDate) {
+        List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+        List<CourseTableBak> bakList = courseTableBakService.list(
+                new QueryWrapper<CourseTableBak>().lambda()
+                        .in(CourseTableBak::getClassId, classIds)
+                        .between(CourseTableBak::getScheduleDate, startDate, endDate)
+        );
+        Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
+
+        List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
+        List<WorkflowFormRelation> list = formRelationService.list(
+                new MPJLambdaWrapper<WorkflowFormRelation>()
+                        .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<String> processIds = new ArrayList<>();
+        for (WorkflowFormRelation relation : list) {
+            String processId = relation.getProcessId();
+            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
+            List<Task> 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> 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<String> processIds){
+        for (String processId : processIds) {
+            List<Task> 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> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
+            historicProcessInstance.ifPresent(item -> {
+                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
+                    setProcessId(processId);
+                    setCurrentState(item.getState());
+                    setStartTime(item.getStartTime());
+                    setEndTime(item.getEndTime());
+                }});
+            });
+        }
+    }
+}