TCPaperStructController.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package com.qmth.distributed.print.api;
  2. import com.google.gson.reflect.TypeToken;
  3. import com.qmth.boot.api.constant.ApiConstant;
  4. import com.qmth.boot.api.exception.ApiException;
  5. import com.qmth.distributed.print.business.bean.dto.CourseWeightDto;
  6. import com.qmth.distributed.print.business.bean.excel.PaperStructDto;
  7. import com.qmth.distributed.print.business.bean.params.report.PaperStructParams;
  8. import com.qmth.distributed.print.business.bean.result.CourseWeightResult;
  9. import com.qmth.distributed.print.business.bean.result.EditResult;
  10. import com.qmth.distributed.print.business.bean.result.report.PaperStructDimensionResult;
  11. import com.qmth.distributed.print.business.entity.TCPaperStruct;
  12. import com.qmth.distributed.print.business.service.PrintCommonService;
  13. import com.qmth.distributed.print.business.service.TCFinalScoreService;
  14. import com.qmth.distributed.print.business.service.TCPaperStructService;
  15. import com.qmth.distributed.print.business.service.TRBasicInfoService;
  16. import com.qmth.teachcloud.common.annotation.OperationLogDetail;
  17. import com.qmth.teachcloud.common.contant.SystemConstant;
  18. import com.qmth.teachcloud.common.entity.MarkQuestion;
  19. import com.qmth.teachcloud.common.entity.SysUser;
  20. import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
  21. import com.qmth.teachcloud.common.enums.log.CustomizedOperationTypeEnum;
  22. import com.qmth.teachcloud.common.util.*;
  23. import com.qmth.teachcloud.mark.entity.MarkPaper;
  24. import com.qmth.teachcloud.mark.service.MarkQuestionService;
  25. import io.swagger.annotations.*;
  26. import org.apache.commons.collections4.CollectionUtils;
  27. import org.slf4j.Logger;
  28. import org.slf4j.LoggerFactory;
  29. import org.springframework.beans.BeanUtils;
  30. import org.springframework.transaction.annotation.Transactional;
  31. import org.springframework.validation.BindingResult;
  32. import org.springframework.web.bind.annotation.*;
  33. import org.springframework.web.multipart.MultipartFile;
  34. import javax.annotation.Resource;
  35. import javax.validation.Valid;
  36. import java.io.IOException;
  37. import java.math.BigDecimal;
  38. import java.util.ArrayList;
  39. import java.util.List;
  40. import java.util.Map;
  41. import java.util.Objects;
  42. import java.util.stream.Collectors;
  43. /**
  44. * <p>
  45. * 试卷结构 前端控制器
  46. * </p>
  47. *
  48. * @author wangliang
  49. * @since 2024-02-18
  50. */
  51. @Api(tags = "课程目标达成度-成绩管理-试卷结构Controller")
  52. @RestController
  53. @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_COURSE_DEGREE)
  54. public class TCPaperStructController {
  55. private final static Logger log = LoggerFactory.getLogger(TCPaperStructController.class);
  56. @Resource
  57. MarkQuestionService markQuestionService;
  58. @Resource
  59. TCPaperStructService tcPaperStructService;
  60. @Resource
  61. TRBasicInfoService trBasicInfoService;
  62. @Resource
  63. PrintCommonService printCommonService;
  64. @Resource
  65. RedisUtil redisUtil;
  66. @ApiOperation(value = "导入试卷结构")
  67. @RequestMapping(value = "/final_score/paper_struct/import", method = RequestMethod.POST)
  68. @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.IMPORT)
  69. @ApiResponses({@ApiResponse(code = 200, message = "导入成功", response = EditResult.class)})
  70. public Result finalScorePaperStructImport(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,
  71. @ApiParam(value = "考试id", required = true) @RequestParam Long examId,
  72. @ApiParam(value = "科目编码", required = true) @RequestParam String courseCode,
  73. @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) throws IOException {
  74. printCommonService.getLock(examId, courseCode, paperNumber);
  75. String lockKey = SystemConstant.REDIS_PAPER_STRUCT_FLOW_PREFIX + SystemConstant.IMPORT + examId + "_" + courseCode + "_" + paperNumber;
  76. Map<String, String> map = null;
  77. try {
  78. map = tcPaperStructService.paperStructExcelImport(file, examId, courseCode, paperNumber);
  79. } catch (Exception e) {
  80. log.error(SystemConstant.LOG_ERROR, e);
  81. if (e instanceof ApiException) {
  82. ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
  83. } else {
  84. ResultUtil.error(e.getMessage());
  85. }
  86. } finally {
  87. redisUtil.releaseLock(lockKey);
  88. }
  89. return ResultUtil.ok(map);
  90. }
  91. @ApiOperation(value = "同步试卷蓝图结构")
  92. @RequestMapping(value = "/final_score/paper_struct_dimension/sync", method = RequestMethod.POST)
  93. @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.PUSH)
  94. @ApiResponses({@ApiResponse(code = 200, message = "同步成功", response = EditResult.class)})
  95. public Result finalScorePaperStructDimensionSync(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
  96. @ApiParam(value = "科目编码", required = true) @RequestParam String courseCode,
  97. @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) throws IOException {
  98. printCommonService.getLock(examId, courseCode, paperNumber);
  99. String lockKey = SystemConstant.REDIS_PAPER_STRUCT_FLOW_PREFIX + SystemConstant.SYNC + examId + "_" + courseCode + "_" + paperNumber;
  100. Map<String, String> map = null;
  101. try {
  102. // map = tcFinalScoreService.finalScoreExcelSync(examId, courseCode, paperNumber);
  103. } catch (Exception e) {
  104. log.error(SystemConstant.LOG_ERROR, e);
  105. if (e instanceof ApiException) {
  106. ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
  107. } else {
  108. ResultUtil.error(e.getMessage());
  109. }
  110. } finally {
  111. redisUtil.releaseLock(lockKey);
  112. }
  113. return ResultUtil.ok(map);
  114. }
  115. @ApiOperation(value = "期末成绩试卷蓝图保存")
  116. @RequestMapping(value = "/final_score/paper_struct/save", method = RequestMethod.POST)
  117. @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.UPDATE)
  118. @ApiResponses({@ApiResponse(code = 200, message = "试卷蓝图保存", response = Object.class)})
  119. @Transactional
  120. public Result finalScorePaperStructSave(@ApiParam(value = "试卷蓝图结构", required = true) @Valid @RequestBody PaperStructParams paperStructParams, BindingResult bindingResult) throws IOException {
  121. if (bindingResult.hasErrors()) {
  122. return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
  123. }
  124. printCommonService.getLock(paperStructParams.getExamId(), paperStructParams.getCourseCode(), paperStructParams.getPaperNumber());
  125. CourseWeightResult courseWeightResult = trBasicInfoService.findCourseWeightResultRmi(paperStructParams.getExamId(), paperStructParams.getCourseCode());
  126. for (CourseWeightDto c : courseWeightResult.getSubmitForm()) {
  127. for (PaperStructDimensionResult paperStructDimensionResult : paperStructParams.getPaperStruct()) {
  128. Objects.requireNonNull(paperStructDimensionResult.getMainNumber(), "大题号为空");
  129. Objects.requireNonNull(paperStructDimensionResult.getSubNumber(), "小题号为空");
  130. if (!CollectionUtils.isEmpty(paperStructDimensionResult.getTargetList()) && paperStructDimensionResult.getTargetList().size() > 1) {
  131. throw ExceptionResultEnum.ERROR.exception("一个题只能属于一个目标");
  132. }
  133. }
  134. List<PaperStructDimensionResult> paperStructDimensionResultList = paperStructParams.getPaperStruct();
  135. Double score = paperStructDimensionResultList.stream().filter(s -> Objects.equals(s.getCourseTargetName(), c.getCourseTargetName())).mapToDouble(PaperStructDimensionResult::getScore).sum();
  136. if (new BigDecimal(score).compareTo(c.getTotalWeight()) == 1) {
  137. throw ExceptionResultEnum.ERROR.exception("[" + c.getCourseTargetName() + "]知识点小题总分大于该课程目标分,请重新设置");
  138. }
  139. paperStructDimensionResultList.stream().filter(s -> {
  140. if (Objects.equals(s.getCourseTargetName(), c.getCourseTargetName())) {
  141. s.getTargetList().stream().peek(e -> e.setFinalScoreQuestionScoreSum(score)).collect(Collectors.toList());
  142. return true;
  143. }
  144. return false;
  145. }).collect(Collectors.toList());
  146. }
  147. SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
  148. TCPaperStruct tcPaperStructDb = tcPaperStructService.queryByExamIdAndCourseCodeAndPaperNumber(paperStructParams.getExamId(), paperStructParams.getCourseCode(), paperStructParams.getPaperNumber());
  149. if (Objects.isNull(tcPaperStructDb)) {
  150. MarkPaper markPaper = printCommonService.getMarkPaper(paperStructParams.getExamId(), paperStructParams.getPaperNumber());
  151. tcPaperStructDb = new TCPaperStruct(paperStructParams.getExamId(), paperStructParams.getCourseCode(), markPaper.getCourseName(), paperStructParams.getPaperNumber(), JacksonUtil.parseJson(paperStructParams.getPaperStruct()), sysUser.getId(), courseWeightResult.getDimensionSign());
  152. tcPaperStructService.save(tcPaperStructDb);
  153. } else {
  154. TCPaperStruct tcPaperStructSource = new TCPaperStruct();
  155. BeanUtils.copyProperties(tcPaperStructDb, tcPaperStructSource);
  156. tcPaperStructDb.updateInfo(JacksonUtil.parseJson(paperStructParams.getPaperStruct()), sysUser.getId());
  157. if (!tcPaperStructDb.equals(tcPaperStructSource)) {
  158. trBasicInfoService.clearReportData(tcPaperStructDb.getExamId(), tcPaperStructDb.getCourseCode(), tcPaperStructDb.getPaperNumber(), false);
  159. tcPaperStructDb.setDimensionSign(courseWeightResult.getDimensionSign());
  160. tcPaperStructService.updateById(tcPaperStructDb);
  161. }
  162. }
  163. return ResultUtil.ok(true);
  164. }
  165. @ApiOperation(value = "期末成绩试卷蓝图查询")
  166. @RequestMapping(value = "/final_score/paper_struct/query", method = RequestMethod.POST)
  167. @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
  168. @ApiResponses({@ApiResponse(code = 200, message = "试卷蓝图保存", response = PaperStructDimensionResult.class)})
  169. public Result finalScorePaperStructQuery(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
  170. @ApiParam(value = "科目编码", required = true) @RequestParam String courseCode,
  171. @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) throws IOException {
  172. printCommonService.getLock(examId, courseCode, paperNumber);
  173. List<PaperStructDimensionResult> paperStructDimensionResultList = null;
  174. TCPaperStruct tcPaperStruct = tcPaperStructService.queryByExamIdAndCourseCodeAndPaperNumber(examId, courseCode, paperNumber);
  175. if (Objects.isNull(tcPaperStruct) || Objects.isNull(tcPaperStruct.getPaperStruct())) {
  176. List<MarkQuestion> markQuestionList = markQuestionService.listQuestionByExamIdAndPaperNumberAndPaperType(examId, paperNumber, null);
  177. if (CollectionUtils.isEmpty(markQuestionList)) {
  178. throw ExceptionResultEnum.ERROR.exception("未找到试卷结构");
  179. }
  180. paperStructDimensionResultList = new ArrayList<>(markQuestionList.size());
  181. for (MarkQuestion markQuestion : markQuestionList) {
  182. paperStructDimensionResultList.add(new PaperStructDimensionResult(markQuestion.getMainNumber(), markQuestion.getSubNumber(), markQuestion.getTotalScore()));
  183. }
  184. } else {
  185. CourseWeightResult courseWeightResult = trBasicInfoService.findCourseWeightResultRmi(examId, courseCode);
  186. if (Objects.nonNull(tcPaperStruct.getDimensionSign()) && tcPaperStruct.getDimensionSign().longValue() != courseWeightResult.getDimensionSign().longValue()) {
  187. trBasicInfoService.clearReportData(examId, courseCode, paperNumber, false);
  188. paperStructDimensionResultList = this.getPaperStructDimensionResult(tcPaperStruct, paperStructDimensionResultList);
  189. } else {
  190. paperStructDimensionResultList = this.getPaperStructDimensionResult(tcPaperStruct, paperStructDimensionResultList);
  191. }
  192. }
  193. return ResultUtil.ok(paperStructDimensionResultList);
  194. }
  195. /**
  196. * 获取试卷结构蓝图数据
  197. *
  198. * @param tcPaperStruct
  199. * @param paperStructDimensionResultList
  200. * @return
  201. */
  202. protected List<PaperStructDimensionResult> getPaperStructDimensionResult(TCPaperStruct tcPaperStruct,
  203. List<PaperStructDimensionResult> paperStructDimensionResultList) {
  204. if (Objects.nonNull(tcPaperStruct.getPaperStructDimension())) {
  205. paperStructDimensionResultList = GsonUtil.fromJson(tcPaperStruct.getPaperStructDimension(), new TypeToken<List<PaperStructDimensionResult>>() {
  206. }.getType());
  207. } else if (Objects.nonNull(tcPaperStruct.getPaperStruct())) {
  208. List<PaperStructDto> paperStructDtoList = GsonUtil.fromJson(tcPaperStruct.getPaperStruct(), new TypeToken<List<PaperStructDto>>() {
  209. }.getType());
  210. paperStructDimensionResultList = new ArrayList<>(paperStructDtoList.size());
  211. for (PaperStructDto paperStructDto : paperStructDtoList) {
  212. paperStructDimensionResultList.add(new PaperStructDimensionResult(paperStructDto.getMainNumber(), paperStructDto.getSubNumber(), paperStructDto.getScore()));
  213. }
  214. }
  215. return paperStructDimensionResultList;
  216. }
  217. }