浏览代码

add:第八次教研分析更改

caozixuan 11 月之前
父节点
当前提交
558ef972a1

+ 7 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/contant/SystemConstant.java

@@ -118,11 +118,18 @@ public class SystemConstant {
     public static final long REDIS_CREATE_PDF_EXPIRE_TIME = 1 * 60L * 60L;//过期时间1小时
     public static final long REDIS_WHU_USER_AUTH_EXPIRE_TIME = 2 * 60L;//过期时间2分钟
 
+    /**
+     * redis mq
+     */
+    public static final String REDIS_LOCK_GRADE_COURSE_DELETE_PREFIX = "redis:lock:courseInfo:";
+
+
     /**
      * redis lock
      */
     public static final int MAX_RETRY_COUNT = 30;
     public static final long REDIS_CACHE_TIME_OUT = 60L;
+    public static final long REDIS_LOCK_BATCH_NO_TIME_OUT = 60L * 30;
 
     /**
      * aes相关

+ 48 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/params/TBExamCourseDeleteParams.java

@@ -0,0 +1,48 @@
+package com.qmth.teachcloud.report.business.bean.params;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description:
+ * @Author: CaoZixuan
+ * @Date:
+ */
+public class TBExamCourseDeleteParams {
+
+    @ApiModelProperty(value = "学校id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long schoolId;
+
+    @ApiModelProperty(value = "考试id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long examId;
+
+    @ApiModelProperty(value = "课程编号")
+    private String courseCode;
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+}

+ 3 - 1
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/SemesterEnum.java

@@ -23,7 +23,9 @@ public enum SemesterEnum {
 
     SIXTH("2022-2023学年度第2学期"),
 
-    SEVENTH("2023-2024学年度第1学期");
+    SEVENTH("2023-2024学年度第1学期"),
+
+    EIGHTH("2023-2024学年度第2学期");
 
     private final String title;
 

+ 48 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBExamCourseDeleteService.java

@@ -0,0 +1,48 @@
+package com.qmth.teachcloud.report.business.service;
+
+
+
+import com.qmth.teachcloud.report.business.bean.params.TBExamCourseDeleteParams;
+
+import java.util.List;
+
+/**
+ * @Description: 分析课程物理删除服务类
+ * @Author: CaoZixuan
+ * @Date: 2022-07-05
+ */
+public interface TBExamCourseDeleteService {
+
+    /**
+     * 删除基础表数据
+     *
+     * @param schoolId   学校id
+     * @param examId     考试id
+     * @param courseCode 课程编号
+     */
+    void deleteBasicTableData(Long schoolId, Long examId, String courseCode);
+
+    /**
+     * 删除分析表数据
+     *
+     * @param schoolId   学校id
+     * @param examId     考试id
+     * @param courseCode 课程编号
+     */
+    void deleteAnalyzeTableData(Long schoolId, Long examId, String courseCode);
+
+    /**
+     * 重算集合性的分析数据(比如考试概况会因为删除一个科目影响从而需要重算)
+     *
+     * @param schoolId 学校id
+     * @param examId   考试id
+     */
+    void repeatCalculateTotalTableData(Long schoolId, Long examId);
+
+    /**
+     * 分析课程删除总控
+     *
+     * @param tbExamCourseDeleteParamsList 分析课程删除集合
+     */
+    void deleteTBExamCourse(List<TBExamCourseDeleteParams> tbExamCourseDeleteParamsList);
+}

+ 10 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBExamCourseService.java

@@ -28,6 +28,16 @@ public interface TBExamCourseService extends IService<TBExamCourse> {
      */
     boolean verifyExamCourseCantRun(Long examId, Long schoolId, String courseCode, String courseName);
 
+    /**
+     * 校验考试科目是否不能删除
+     *
+     * @param examId     考试id
+     * @param schoolId   学校id
+     * @param courseCode 课程编号
+     * @return true:不能删除 || false:可以删除
+     */
+    boolean verifyExamCourseCantDelete(Long schoolId, Long examId, String courseCode);
+
     List<String> findEffectiveByExamId(Long examId, String courseCode);
 
     /**

+ 325 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBExamCourseDeleteServiceImpl.java

@@ -0,0 +1,325 @@
+package com.qmth.teachcloud.report.business.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.util.RedisUtil;
+import com.qmth.teachcloud.report.business.bean.params.TBExamCourseDeleteParams;
+import com.qmth.teachcloud.report.business.entity.*;
+import com.qmth.teachcloud.report.business.service.*;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 分析课程物理删除服务实现类
+ * @Author: CaoZixuan
+ * @Date: 2022-07-05
+ */
+@Service
+public class TBExamCourseDeleteServiceImpl implements TBExamCourseDeleteService {
+
+    // 无关联的基础表
+    @Resource
+    TBCommonLevelConfigService tbCommonLevelConfigService;
+
+    @Resource
+    TBCommonRankLevelConfigService tbCommonRankLevelConfigService;
+
+    @Resource
+    TBDimensionService tbDimensionService;
+
+    @Resource
+    TBExamCourseService tbExamCourseService;
+
+    @Resource
+    TBExamStudentService tbExamStudentService;
+
+    @Resource
+    TBModuleConfigService tbModuleConfigService;
+
+    @Resource
+    TBModuleProficiencyService tbModuleProficiencyService;
+
+    // 相关联的基础表
+    @Resource
+    TBPaperService tbPaperService;
+
+    @Resource
+    TBPaperStructService tbPaperStructService;
+
+    @Resource
+    TBExamRecordService tbExamRecordService;
+
+    @Resource
+    TBAnswerService tbAnswerService;
+
+    // 相关联的分析表
+    @Resource
+    TAExamCourseRecordService taExamCourseRecordService;
+
+    @Resource
+    TAExamCourseService taExamCourseService;
+
+    @Resource
+    TAExamCourseClazzService taExamCourseClazzService;
+
+    @Resource
+    TAExamCourseCollegeInspectService taExamCourseCollegeInspectService;
+
+    @Resource
+    TAExamCourseCollegeInspectDioService taExamCourseCollegeInspectDioService;
+
+    @Resource
+    TAExamCourseCollegePaperStructService taExamCourseCollegePaperStructService;
+
+    @Resource
+    TAExamCourseCollegeTeacherService taExamCourseCollegeTeacherService;
+
+    @Resource
+    TAExamCourseDifficultService taExamCourseDifficultService;
+
+    @Resource
+    TAExamCourseDioService taExamCourseDioService;
+
+    @Resource
+    TAExamCourseRecordDioService taExamCourseRecordDioService;
+
+    @Resource
+    TAExamCourseRecordModService taExamCourseRecordModService;
+
+    @Resource
+    TAExamCourseTeacherService taExamCourseTeacherService;
+
+    @Resource
+    TAExamCourseTeacherCollegeDifficultService taExamCourseTeacherCollegeDifficultService;
+
+    @Resource
+    TAExamCourseTeacherCollegeDioService taExamCourseTeacherCollegeDioService;
+
+    @Resource
+    TAExamCourseTeacherCollegePaperStructService taExamCourseTeacherCollegePaperStructService;
+
+    @Resource
+    TAExamCourseTeacherDifficultService taExamCourseTeacherDifficultService;
+
+    @Resource
+    TAExamCourseTeacherDioService taExamCourseTeacherDioService;
+
+    @Resource
+    TAExamCourseTeacherPaperStructService taExamCourseTeacherPaperStructService;
+
+    @Resource
+    TAPaperStructService taPaperStructService;
+
+    // 重算
+    @Resource
+    AnalyzeForReportService analyzeForReportService;
+
+    @Resource
+    RedisUtil redisUtil;
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void deleteBasicTableData(Long schoolId, Long examId, String courseCode) {
+        // 基础且无关联表删除
+        tbCommonLevelConfigService.remove(
+                new QueryWrapper<TBCommonLevelConfig>().lambda().eq(TBCommonLevelConfig::getExamId, examId).eq(TBCommonLevelConfig::getCourseCode, courseCode));
+        tbCommonRankLevelConfigService.remove(
+                new QueryWrapper<TBCommonRankLevelConfig>().lambda().eq(TBCommonRankLevelConfig::getExamId, examId).eq(TBCommonRankLevelConfig::getCourseCode, courseCode));
+        tbDimensionService.remove(new QueryWrapper<TBDimension>().lambda().eq(TBDimension::getExamId, examId)
+                .eq(TBDimension::getCourseCode, courseCode));
+        tbExamCourseService.remove(new QueryWrapper<TBExamCourse>().lambda().eq(TBExamCourse::getSchoolId, schoolId)
+                .eq(TBExamCourse::getExamId, examId).eq(TBExamCourse::getCourseCode, courseCode));
+        tbExamStudentService.remove(new QueryWrapper<TBExamStudent>().lambda().eq(TBExamStudent::getSchoolId, schoolId)
+                .eq(TBExamStudent::getExamId, examId).eq(TBExamStudent::getCourseCode, courseCode));
+        tbModuleConfigService.remove(new QueryWrapper<TBModuleConfig>().lambda().eq(TBModuleConfig::getExamId, examId)
+                .eq(TBModuleConfig::getCourseCode, courseCode));
+        tbModuleProficiencyService.remove(
+                new QueryWrapper<TBModuleProficiency>().lambda().eq(TBModuleProficiency::getExamId, examId).eq(TBModuleProficiency::getCourseCode, courseCode));
+
+        // 基础且关联表删除
+        List<TBPaper> tbPaperList = tbPaperService.list(
+                new QueryWrapper<TBPaper>().lambda().eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, courseCode));
+        if (tbPaperList != null && tbPaperList.size() > 0) {
+            if (tbPaperList.size() > 1) {
+                throw ExceptionResultEnum.ERROR.exception("考试id为【" + examId + "】,分析课程编号为【" + courseCode + "】存在多个试卷t_b_paper");
+            }
+            TBPaper tbPaper = tbPaperList.get(0);
+            Long paperId = tbPaper.getId();
+            List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(
+                    new QueryWrapper<TBPaperStruct>().lambda().eq(TBPaperStruct::getPaperId, paperId));
+            List<TBExamRecord> tbExamRecordList = tbExamRecordService.list(
+                    new QueryWrapper<TBExamRecord>().lambda().eq(TBExamRecord::getExamId, examId).eq(TBExamRecord::getPaperId, paperId));
+            List<Long> tbExamRecordIdList = tbExamRecordList.stream().map(TBExamRecord::getId).collect(Collectors.toList());
+            if (tbExamRecordIdList.size() > 0) {
+                List<TBAnswer> tbAnswerList = tbAnswerService.list(
+                        new QueryWrapper<TBAnswer>().lambda().in(TBAnswer::getExamRecordId, tbExamRecordIdList));
+                // 删除't_b_answer'表
+                tbAnswerService.removeByIds(tbAnswerList.stream().map(TBAnswer::getId).collect(Collectors.toList()));
+            }
+            // 删除't_b_exam_record'表
+            tbExamRecordService.removeByIds(tbExamRecordIdList);
+            // 删除't_b_paper_struct'表
+            tbPaperStructService.removeByIds(
+                    tbPaperStructList.stream().map(TBPaperStruct::getId).collect(Collectors.toList()));
+            // 删除't_b_paper'表
+            tbPaperService.removeById(tbPaper.getId());
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void deleteAnalyzeTableData(Long schoolId, Long examId, String courseCode) {
+        // 关联的分析表↓
+        // 删除't_a_exam_course_record'
+        List<TBPaper> tbPaperList = tbPaperService.list(
+                new QueryWrapper<TBPaper>().lambda().eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, courseCode));
+        if (tbPaperList != null && tbPaperList.size() > 0) {
+            if (tbPaperList.size() > 1) {
+                throw ExceptionResultEnum.ERROR.exception("考试id为【" + examId + "】,分析课程编号为【" + courseCode + "】存在多个试卷t_b_paper");
+            }
+            TBPaper tbPaper = tbPaperList.get(0);
+            Long paperId = tbPaper.getId();
+            List<TBExamRecord> tbExamRecordList = tbExamRecordService.list(
+                    new QueryWrapper<TBExamRecord>().lambda().eq(TBExamRecord::getExamId, examId).eq(TBExamRecord::getPaperId, paperId));
+            List<Long> tbExamRecordIdList = tbExamRecordList.stream().map(TBExamRecord::getId).collect(Collectors.toList());
+            if (tbExamRecordIdList.size() > 0) {
+                taExamCourseRecordService.remove(new QueryWrapper<TAExamCourseRecord>().lambda()
+                        .in(TAExamCourseRecord::getExamRecordId, tbExamRecordIdList));
+            }
+        }
+        // 独立的分析表↓
+        // 删除't_a_exam_course'
+        taExamCourseService.remove(new QueryWrapper<TAExamCourse>().lambda().eq(TAExamCourse::getSchoolId, schoolId)
+                .eq(TAExamCourse::getExamId, examId).eq(TAExamCourse::getCourseCode, courseCode));
+        // 删除't_a_exam_course_clazz'
+        taExamCourseClazzService.remove(
+                new QueryWrapper<TAExamCourseClazz>().lambda().eq(TAExamCourseClazz::getSchoolId, schoolId).eq(TAExamCourseClazz::getExamId, examId).eq(TAExamCourseClazz::getCourseCode, courseCode));
+        // 删除't_a_exam_course_college_inspect'
+        taExamCourseCollegeInspectService.remove(new QueryWrapper<TAExamCourseCollegeInspect>().lambda()
+                .eq(TAExamCourseCollegeInspect::getSchoolId, schoolId).eq(TAExamCourseCollegeInspect::getExamId, examId)
+                .eq(TAExamCourseCollegeInspect::getCourseCode, courseCode));
+        // 删除't_a_exam_course_college_inspect_dio'
+        taExamCourseCollegeInspectDioService.remove(new QueryWrapper<TAExamCourseCollegeInspectDio>().lambda()
+                .eq(TAExamCourseCollegeInspectDio::getSchoolId, schoolId)
+                .eq(TAExamCourseCollegeInspectDio::getExamId, examId)
+                .eq(TAExamCourseCollegeInspectDio::getCourseCode, courseCode));
+        // 删除't_a_exam_course_college_paper_struct'
+        taExamCourseCollegePaperStructService.remove(new QueryWrapper<TAExamCourseCollegePaperStruct>().lambda()
+                .eq(TAExamCourseCollegePaperStruct::getSchoolId, schoolId)
+                .eq(TAExamCourseCollegePaperStruct::getExamId, examId)
+                .eq(TAExamCourseCollegePaperStruct::getCourseCode, courseCode));
+        // 删除't_a_exam_course_college_teacher'
+        taExamCourseCollegeTeacherService.remove(new QueryWrapper<TAExamCourseCollegeTeacher>().lambda()
+                .eq(TAExamCourseCollegeTeacher::getSchoolId, schoolId).eq(TAExamCourseCollegeTeacher::getExamId, examId)
+                .eq(TAExamCourseCollegeTeacher::getCourseCode, courseCode));
+        // 删除't_a_exam_course_difficult'
+        taExamCourseDifficultService.remove(
+                new QueryWrapper<TAExamCourseDifficult>().lambda().eq(TAExamCourseDifficult::getSchoolId, schoolId)
+                        .eq(TAExamCourseDifficult::getExamId, examId).eq(TAExamCourseDifficult::getCourseCode, courseCode));
+        // 删除't_a_exam_course_dio'
+        taExamCourseDioService.remove(
+                new QueryWrapper<TAExamCourseDio>().lambda().eq(TAExamCourseDio::getSchoolId, schoolId).eq(TAExamCourseDio::getExamId, examId).eq(TAExamCourseDio::getCourseCode, courseCode));
+        // 删除't_a_exam_course_record_dio'
+        taExamCourseRecordDioService.remove(
+                new QueryWrapper<TAExamCourseRecordDio>().lambda().eq(TAExamCourseRecordDio::getSchoolId, schoolId)
+                        .eq(TAExamCourseRecordDio::getExamId, examId).eq(TAExamCourseRecordDio::getCourseCode, courseCode));
+        // 删除't_a_exam_course_record_mod'
+        taExamCourseRecordModService.remove(
+                new QueryWrapper<TAExamCourseRecordMod>().lambda().eq(TAExamCourseRecordMod::getSchoolId, schoolId)
+                        .eq(TAExamCourseRecordMod::getExamId, examId).eq(TAExamCourseRecordMod::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher'
+        taExamCourseTeacherService.remove(
+                new QueryWrapper<TAExamCourseTeacher>().lambda().eq(TAExamCourseTeacher::getSchoolId, schoolId).eq(TAExamCourseTeacher::getExamId, examId).eq(TAExamCourseTeacher::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher_college_difficult'
+        taExamCourseTeacherCollegeDifficultService.remove(new QueryWrapper<TAExamCourseTeacherCollegeDifficult>().lambda()
+                .eq(TAExamCourseTeacherCollegeDifficult::getSchoolId, schoolId)
+                .eq(TAExamCourseTeacherCollegeDifficult::getExamId, examId).eq(TAExamCourseTeacherCollegeDifficult::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher_college_dio'
+        taExamCourseTeacherCollegeDioService.remove(new QueryWrapper<TAExamCourseTeacherCollegeDio>().lambda()
+                .eq(TAExamCourseTeacherCollegeDio::getSchoolId, schoolId)
+                .eq(TAExamCourseTeacherCollegeDio::getExamId, examId)
+                .eq(TAExamCourseTeacherCollegeDio::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher_college_paper_struct'
+        taExamCourseTeacherCollegePaperStructService.remove(new QueryWrapper<TAExamCourseTeacherCollegePaperStruct>().lambda()
+                .eq(TAExamCourseTeacherCollegePaperStruct::getSchoolId, schoolId)
+                .eq(TAExamCourseTeacherCollegePaperStruct::getExamId, examId).eq(TAExamCourseTeacherCollegePaperStruct::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher_difficult'
+        taExamCourseTeacherDifficultService.remove(new QueryWrapper<TAExamCourseTeacherDifficult>().lambda()
+                .eq(TAExamCourseTeacherDifficult::getSchoolId, schoolId)
+                .eq(TAExamCourseTeacherDifficult::getExamId, examId)
+                .eq(TAExamCourseTeacherDifficult::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher_dio'
+        taExamCourseTeacherDioService.remove(
+                new QueryWrapper<TAExamCourseTeacherDio>().lambda().eq(TAExamCourseTeacherDio::getSchoolId, schoolId)
+                        .eq(TAExamCourseTeacherDio::getExamId, examId).eq(TAExamCourseTeacherDio::getCourseCode, courseCode));
+        // 删除't_a_exam_course_teacher_paper_struct'
+        taExamCourseTeacherPaperStructService.remove(new QueryWrapper<TAExamCourseTeacherPaperStruct>().lambda()
+                .eq(TAExamCourseTeacherPaperStruct::getSchoolId, schoolId)
+                .eq(TAExamCourseTeacherPaperStruct::getExamId, examId)
+                .eq(TAExamCourseTeacherPaperStruct::getCourseCode, courseCode));
+        // 删除't_a_paper_struct'
+        taPaperStructService.remove(new QueryWrapper<TAPaperStruct>().lambda().eq(TAPaperStruct::getSchoolId, schoolId)
+                .eq(TAPaperStruct::getExamId, examId).eq(TAPaperStruct::getCourseCode, courseCode));
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void repeatCalculateTotalTableData(Long schoolId, Long examId) {
+        analyzeForReportService.buildAnalyzeExamTotal(examId);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void deleteTBExamCourse(List<TBExamCourseDeleteParams> tbExamCourseDeleteParamsList) {
+        List<Long> schoolIdList = tbExamCourseDeleteParamsList.stream().map(TBExamCourseDeleteParams::getSchoolId).distinct().collect(Collectors.toList());
+        if (schoolIdList.size() != 1) {
+            throw ExceptionResultEnum.ERROR.exception("学校信息异常");
+        }
+        Long lockSchoolId = schoolIdList.get(0);
+
+        List<Long> examIdList = tbExamCourseDeleteParamsList.stream().map(TBExamCourseDeleteParams::getExamId).distinct().collect(Collectors.toList());
+        if (examIdList.size() != 1) {
+            throw ExceptionResultEnum.ERROR.exception("不能删除不同考试下的分析课程");
+        }
+        Long lockExamId = examIdList.get(0);
+        List<String> courseCodeList = tbExamCourseDeleteParamsList.stream().map(TBExamCourseDeleteParams::getCourseCode)
+                .distinct().sorted().collect(Collectors.toList());
+        String lockCourseCode = DigestUtils.md5Hex(JSON.toJSONString(courseCodeList));
+        String lockKey = SystemConstant.REDIS_LOCK_GRADE_COURSE_DELETE_PREFIX + lockSchoolId + SystemConstant.HYPHEN + lockExamId
+                + SystemConstant.HYPHEN + lockCourseCode;
+
+        boolean lock = redisUtil.lock(lockKey, SystemConstant.REDIS_LOCK_BATCH_NO_TIME_OUT);
+        if (!lock) {
+            throw ExceptionResultEnum.ERROR.exception("正在删除数据,请稍候再试!");
+        }
+        try {
+            for (TBExamCourseDeleteParams tbExamCourseDeleteParams : tbExamCourseDeleteParamsList) {
+                Long schoolId = tbExamCourseDeleteParams.getSchoolId();
+                Long examId = tbExamCourseDeleteParams.getExamId();
+                String courseCode = tbExamCourseDeleteParams.getCourseCode();
+                if (tbExamCourseService.list(
+                        new QueryWrapper<TBExamCourse>().lambda().eq(TBExamCourse::getSchoolId, schoolId)
+                                .eq(TBExamCourse::getExamId, examId).eq(TBExamCourse::getCourseCode, courseCode)).size()
+                        > 0) {
+                    // 教研分析有这个课程再删除,没有不删直接返回
+                    if (tbExamCourseService.verifyExamCourseCantDelete(schoolId, examId, courseCode)) {
+                        throw ExceptionResultEnum.ERROR.exception("考试id为【" + examId + "】,课程编号为【" + courseCode + "】的分析课程当前不能被删除");
+                    }
+                    // 先删分析表
+                    this.deleteAnalyzeTableData(schoolId, examId, courseCode);
+                    this.deleteBasicTableData(schoolId, examId, courseCode);
+                }
+            }
+            this.repeatCalculateTotalTableData(lockSchoolId, lockExamId);
+        } finally {
+            redisUtil.releaseLock(lockKey);
+        }
+    }
+}

+ 27 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBExamCourseServiceImpl.java

@@ -84,6 +84,33 @@ public class TBExamCourseServiceImpl extends ServiceImpl<TBExamCourseMapper, TBE
                 publishStatusEnum.equals(PublishStatusEnum.PUBLISH);
     }
 
+    @Override
+    public boolean verifyExamCourseCantDelete(Long schoolId, Long examId, String courseCode) {
+        QueryWrapper<BasicCourse> schoolCourseQuery = new QueryWrapper<>();
+        schoolCourseQuery.lambda()
+                .eq(BasicCourse::getSchoolId, schoolId)
+                .eq(BasicCourse::getCode, courseCode);
+        List<BasicCourse> tbSchoolCourseList = basicCourseService.list(schoolCourseQuery);
+        if (tbSchoolCourseList.size() != 1) {
+            throw ExceptionResultEnum.ERROR.exception("学校课程基础数据异常");
+        }
+
+        QueryWrapper<TBExamCourse> examCourseQuery = new QueryWrapper<>();
+        examCourseQuery.lambda()
+                .eq(TBExamCourse::getExamId, examId)
+                .eq(TBExamCourse::getCourseCode, courseCode);
+        List<TBExamCourse> tbExamCourseList = this.list(examCourseQuery);
+        if (tbExamCourseList.size() != 1) {
+            throw ExceptionResultEnum.ERROR.exception("缺少要分析的课程");
+        }
+        TBExamCourse tbExamCourse = tbExamCourseList.get(0);
+        TestStatusEnum testStatusEnum = tbExamCourse.getTestStatus();
+        PublishStatusEnum publishStatusEnum = tbExamCourse.getPublishStatus();
+        // 已发布的和计算中的 分析课程不能被删除
+        return testStatusEnum.equals(TestStatusEnum.TEST) || testStatusEnum.equals(TestStatusEnum.CHECKED) ||
+                publishStatusEnum.equals(PublishStatusEnum.PUBLISH) || publishStatusEnum.equals(PublishStatusEnum.COMPUTING);
+    }
+
     @Override
     public List<String> findEffectiveByExamId(Long examId, String courseCode) {
         List<PublishStatusEnum> publishStatusEnumList = new ArrayList<>();

+ 19 - 0
teachcloud-report/src/main/java/com/qmth/teachcloud/report/api/BasicDatasourceController.java

@@ -24,6 +24,7 @@ import com.qmth.teachcloud.report.business.bean.dto.CombineDto;
 import com.qmth.teachcloud.report.business.bean.dto.excel.*;
 import com.qmth.teachcloud.report.business.bean.dto.query.*;
 import com.qmth.teachcloud.report.business.bean.params.CollegeCombineParams;
+import com.qmth.teachcloud.report.business.bean.params.TBExamCourseDeleteParams;
 import com.qmth.teachcloud.report.business.entity.*;
 import com.qmth.teachcloud.report.business.enums.AssignEnum;
 import com.qmth.teachcloud.report.business.enums.ExamCloudDataEnum;
@@ -110,6 +111,8 @@ public class BasicDatasourceController {
     private TBTeacherService tbTeacherService;
     @Resource
     private CourseUnitOperateService courseUnitOperateService;
+    @Resource
+    private TBExamCourseDeleteService tbExamCourseDeleteService;
 
     @ApiOperation(value = "试卷数据导入")
     @RequestMapping(value = "/paper/import", method = RequestMethod.POST)
@@ -1483,6 +1486,22 @@ public class BasicDatasourceController {
         return ResultUtil.ok();
     }
 
+    @ApiOperation(value = "删除课程")
+    @RequestMapping(value = "/course/delete", method = RequestMethod.POST)
+    @Transactional(rollbackFor = Exception.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
+    public Result courseDelete(@RequestParam Long examId, @RequestParam Long schoolId, @RequestParam List<String> courseCodeList) {
+        List<TBExamCourseDeleteParams> tbExamCourseDeleteParamsList = courseCodeList.stream().flatMap(e -> {
+            TBExamCourseDeleteParams tbExamCourseDeleteParams = new TBExamCourseDeleteParams();
+            tbExamCourseDeleteParams.setCourseCode(e);
+            tbExamCourseDeleteParams.setExamId(examId);
+            tbExamCourseDeleteParams.setSchoolId(schoolId);
+            return Stream.of(tbExamCourseDeleteParams);
+        }).collect(Collectors.toList());
+        tbExamCourseDeleteService.deleteTBExamCourse(tbExamCourseDeleteParamsList);
+        return ResultUtil.ok();
+    }
+
     /**
      * 更新或新增专业信息
      *