BaseClassCourseServiceImpl.java 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. package com.xjrsoft.module.base.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import com.alibaba.excel.EasyExcel;
  4. import com.alibaba.excel.support.ExcelTypeEnum;
  5. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  7. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  8. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  9. import com.github.yulichang.base.MPJBaseServiceImpl;
  10. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  11. import com.xjrsoft.common.enums.ArchivesStatusEnum;
  12. import com.xjrsoft.common.enums.DeleteMark;
  13. import com.xjrsoft.common.enums.UseSemesterTypeEnum;
  14. import com.xjrsoft.common.exception.MyException;
  15. import com.xjrsoft.common.utils.VoToColumnUtil;
  16. import com.xjrsoft.module.base.dto.*;
  17. import com.xjrsoft.module.base.entity.*;
  18. import com.xjrsoft.module.base.mapper.BaseClassAdminCourseMapper;
  19. import com.xjrsoft.module.base.mapper.BaseClassCourseMapper;
  20. import com.xjrsoft.module.base.mapper.BaseClassMapper;
  21. import com.xjrsoft.module.base.service.IBaseClassCourseService;
  22. import com.xjrsoft.module.base.vo.*;
  23. import com.xjrsoft.module.generator.entity.ImportConfig;
  24. import com.xjrsoft.module.organization.entity.Department;
  25. import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
  26. import com.xjrsoft.module.student.mapper.BaseStudentSchoolRollMapper;
  27. import com.xjrsoft.module.system.entity.DictionaryDetail;
  28. import com.xjrsoft.module.textbook.entity.Textbook;
  29. import com.xjrsoft.module.textbook.entity.TextbookStudentClaim;
  30. import com.xjrsoft.module.textbook.mapper.TextbookStudentClaimMapper;
  31. import lombok.AllArgsConstructor;
  32. import org.apache.commons.lang3.ObjectUtils;
  33. import org.apache.commons.lang3.StringUtils;
  34. import org.apache.poi.ss.usermodel.*;
  35. import org.apache.poi.ss.util.CellRangeAddress;
  36. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  37. import org.springframework.stereotype.Service;
  38. import org.springframework.transaction.annotation.Transactional;
  39. import java.io.ByteArrayOutputStream;
  40. import java.io.IOException;
  41. import java.math.BigDecimal;
  42. import java.util.*;
  43. import java.util.stream.Collectors;
  44. import static com.xjrsoft.module.veb.util.ImportExcelUtil.allFields;
  45. import static com.xjrsoft.module.veb.util.ImportExcelUtil.createHead;
  46. /**
  47. * @title: 班级课程
  48. * @Author brealinxx
  49. * @Date: 2024-06-04
  50. * @Version 1.0
  51. */
  52. @Service
  53. @AllArgsConstructor
  54. public class BaseClassCourseServiceImpl extends MPJBaseServiceImpl<BaseClassCourseMapper, BaseClassCourse> implements IBaseClassCourseService {
  55. private final BaseClassCourseMapper baseClassCourseMapper;
  56. private final BaseStudentSchoolRollMapper baseStudentSchoolRollMapper;
  57. private final TextbookStudentClaimMapper textbookStudentClaimMapper;
  58. private final BaseClassMapper baseClassMapper;
  59. private final BaseClassAdminCourseMapper baseClassAdminCourseMapper;
  60. @Override
  61. public Page<BaseClassCoursePageVo> getPage(Page<BaseClassCoursePageVo> page, BaseClassCoursePageDto dto) {
  62. return baseClassCourseMapper.getPage(page, dto);
  63. }
  64. @Override
  65. public List<BaseClassCourseListVo> oneClassClassCourseList(BaseClassCourseListDto dto) {
  66. MPJLambdaWrapper<BaseClassAdminCourse> baseClassCourseMPJLambdaWrapper = new MPJLambdaWrapper<>();
  67. baseClassCourseMPJLambdaWrapper
  68. .disableSubLogicDel()
  69. .select(BaseClassCourse::getId)
  70. .selectAs(BaseClass::getName, BaseClassCourseListVo::getClassIdCn)
  71. .selectAs(BaseCourseSubject::getName, BaseClassCourseListVo::getCourseIdCn)
  72. .selectAs(Textbook::getBookName, BaseClassCourseListVo::getTextbookIdCn)
  73. .selectAs(BaseSemester::getName, BaseClassCourseListVo::getBaseSemesterIdCn)
  74. .select(BaseClassCourse.class, x -> VoToColumnUtil.fieldsToColumns(BaseClassCourseListVo.class).contains(x.getProperty()))
  75. .innerJoin(BaseClassCourse.class, BaseClassCourse::getClassId, BaseClassAdminCourse::getId)
  76. .leftJoin(BaseClass.class, BaseClass::getId, BaseClassAdminCourse::getClassId)
  77. .leftJoin(BaseSemester.class, BaseSemester::getId, BaseClassAdminCourse::getBaseSemesterId)
  78. .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, BaseClassCourse::getCourseId)
  79. .leftJoin(Textbook.class, Textbook::getId, BaseClassCourse::getTextbookId)
  80. .eq(dto.getBaseSemesterId() != null && dto.getBaseSemesterId() > 0, BaseClassAdminCourse::getBaseSemesterId, dto.getBaseSemesterId())
  81. .eq(dto.getClassId() != null && dto.getClassId() > 0, BaseClassAdminCourse::getClassId, dto.getClassId())
  82. .eq(BaseClassCourse::getDeleteMark, DeleteMark.NODELETE.getCode())
  83. ;
  84. return baseClassAdminCourseMapper.selectJoinList(BaseClassCourseListVo.class, baseClassCourseMPJLambdaWrapper);
  85. }
  86. @Override
  87. public List<BaseClassCourseMobileListVo> mobileOneClassClassCourseList(BaseClassCourseListDto dto) {
  88. MPJLambdaWrapper<BaseClassAdminCourse> baseClassCourseMPJLambdaWrapper = new MPJLambdaWrapper<>();
  89. baseClassCourseMPJLambdaWrapper
  90. .disableSubLogicDel()
  91. .select(BaseClassCourse::getId)
  92. .selectAs(BaseCourseSubject::getName, BaseClassCourseMobileListVo::getCourseName)
  93. .selectAs(Textbook::getBookName, BaseClassCourseMobileListVo::getBookName)
  94. .selectAs(Textbook::getPrice, BaseClassCourseMobileListVo::getPrice)
  95. .selectAs(DictionaryDetail::getName, BaseClassCourseMobileListVo::getTextbookTypeName)
  96. .select(BaseClassCourse.class, x -> VoToColumnUtil.fieldsToColumns(BaseClassCourseMobileListVo.class).contains(x.getProperty()))
  97. .innerJoin(BaseClassCourse.class, BaseClassCourse::getClassId, BaseClassAdminCourse::getId)
  98. .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, BaseClassCourse::getCourseId)
  99. .leftJoin(Textbook.class, Textbook::getId, BaseClassCourse::getTextbookId)
  100. .leftJoin(DictionaryDetail.class,DictionaryDetail::getCode,Textbook::getTextbookType)
  101. .eq(dto.getBaseSemesterId() != null && dto.getBaseSemesterId() > 0, BaseClassAdminCourse::getBaseSemesterId, dto.getBaseSemesterId())
  102. .eq(dto.getClassId() != null && dto.getClassId() > 0, BaseClassAdminCourse::getClassId, dto.getClassId())
  103. .eq(BaseClassCourse::getDeleteMark, DeleteMark.NODELETE.getCode())
  104. ;
  105. return baseClassAdminCourseMapper.selectJoinList(BaseClassCourseMobileListVo.class, baseClassCourseMPJLambdaWrapper);
  106. }
  107. @Override
  108. public List<CourseBookInfo> getAllCourseBook(Long[] classIds, Long subjectGroupId, Long semester){
  109. return baseClassCourseMapper.getAllCourseBook(classIds, subjectGroupId, semester);
  110. }
  111. @Override
  112. public List<CourseBookInfo> getSelectedCourseBook(Long[] classIds, Long semester){
  113. return baseClassCourseMapper.getSelectedCourseBook(classIds, semester);
  114. }
  115. @Override
  116. @Transactional
  117. public Boolean oneUpdateClassCoursesAndTextbooks(ClassCourseTextbook dto) {
  118. return updateAddCourseBook(dto);
  119. }
  120. @Override
  121. @Transactional
  122. public Boolean updateAddCourseBook(ClassCourseTextbook dto){
  123. if (ObjectUtils.isEmpty(dto.getBaseClassAdminCourseIds())) {
  124. throw new MyException("添加课程的班级无效,请刷新重试");
  125. }
  126. // 根据班级id查出班级已经存在的课程和教程
  127. LambdaQueryWrapper<BaseClassCourse> baseClassCourseLambdaQueryWrapper = new LambdaQueryWrapper<>();
  128. baseClassCourseLambdaQueryWrapper
  129. .in(BaseClassCourse::getClassId, dto.getBaseClassAdminCourseIds())
  130. .eq(BaseClassCourse::getDeleteMark, DeleteMark.NODELETE.getCode())
  131. ;
  132. List<BaseClassCourse> oldList = this.list(baseClassCourseLambdaQueryWrapper);
  133. // 使用Stream API和Lambda表达式生成所需的字符串列表
  134. Map<Long, List<String>> courseIdTextbookIdMap = oldList.stream()
  135. .collect(Collectors.groupingBy(
  136. BaseClassCourse::getClassId,
  137. Collectors.mapping(
  138. course -> course.getCourseId() + "_" + course.getTextbookId(),
  139. Collectors.toList()
  140. )
  141. ));
  142. // 处理所有需要新增的教材
  143. Map<String, BaseClassCourse> newClassCourseTextbookMap = new HashMap<>();
  144. for (String id : dto.getIds()) {
  145. String[] idArr = id.split("_");
  146. if (idArr[0].isEmpty() || idArr[1].isEmpty()) {
  147. continue;
  148. }
  149. Long courseId = Long.parseLong(idArr[0]);
  150. Long textbookId = Long.parseLong(idArr[1]);
  151. newClassCourseTextbookMap.put(id, new BaseClassCourse() {{
  152. setCourseId(courseId);
  153. setTextbookId(textbookId);
  154. setCreateDate(new Date());
  155. }});
  156. }
  157. // 处理每一个班需要新增的课程
  158. List<BaseClassCourse> baseClassCourseList = new ArrayList<>();
  159. for (Long classId : dto.getBaseClassAdminCourseIds()) {
  160. // 判断当前的班级是否已经有了该课程和教材
  161. List<String> tourseIdTextbookIdList = null;
  162. if(ObjectUtils.isNotEmpty(courseIdTextbookIdMap)){
  163. tourseIdTextbookIdList = courseIdTextbookIdMap.get(classId);
  164. }
  165. for (Map.Entry<String, BaseClassCourse> entry : newClassCourseTextbookMap.entrySet()) {
  166. String key = entry.getKey();
  167. BaseClassCourse value = entry.getValue();
  168. if(ObjectUtils.isNotEmpty(tourseIdTextbookIdList) && !tourseIdTextbookIdList.isEmpty() && tourseIdTextbookIdList.contains(key)){
  169. continue;
  170. }
  171. value.setClassId(classId);
  172. baseClassCourseList.add(value);
  173. }
  174. }
  175. return this.saveBatch(baseClassCourseList);
  176. }
  177. @Override
  178. @Transactional
  179. public Boolean updateRemoveCourseBook(ClassCourseTextbook dto){
  180. if (ObjectUtils.isEmpty(dto.getBaseClassAdminCourseIds())) {
  181. throw new MyException("移除课程的班级无效,请刷新重试");
  182. }
  183. Map<String, BaseClassCourse> newClassCourseTextbookMap = new HashMap<>();
  184. for (String id : dto.getIds()) {
  185. String[] idArr = id.split("_");
  186. if (idArr[0].isEmpty() || idArr[1].isEmpty()) {
  187. continue;
  188. }
  189. Long courseId = Long.parseLong(idArr[0]);
  190. Long textbookId = Long.parseLong(idArr[1]);
  191. newClassCourseTextbookMap.put(id, new BaseClassCourse() {{
  192. setCourseId(courseId);
  193. setTextbookId(textbookId);
  194. }});
  195. }
  196. for (Long classId : dto.getBaseClassAdminCourseIds()) {
  197. for (Map.Entry<String, BaseClassCourse> entry : newClassCourseTextbookMap.entrySet()) {
  198. BaseClassCourse value = entry.getValue();
  199. if(ObjectUtils.isNotEmpty(value)){
  200. // 移除
  201. LambdaUpdateWrapper<BaseClassCourse> baseClassCourseLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
  202. baseClassCourseLambdaUpdateWrapper
  203. .eq(BaseClassCourse::getClassId, classId)
  204. .eq(BaseClassCourse::getCourseId, value.getCourseId())
  205. .eq(BaseClassCourse::getTextbookId, value.getTextbookId())
  206. ;
  207. this.remove(baseClassCourseLambdaUpdateWrapper);
  208. }
  209. }
  210. }
  211. return true;
  212. }
  213. @Override
  214. public void markExistingRecordsAsDeleted(Long newClassId, Long sourceClassId){
  215. baseClassCourseMapper.markExistingRecordsAsDeleted(newClassId, sourceClassId);
  216. }
  217. @Override
  218. @Transactional
  219. public Boolean duplicateCourseBook(ClassCourseReuseDto dto){
  220. // 根据旧的学期和班级找到所有的课程
  221. MPJLambdaWrapper<BaseClassAdminCourse> baseClassCourseLambdaQueryWrapper = new MPJLambdaWrapper<>();
  222. baseClassCourseLambdaQueryWrapper
  223. .select(BaseClassCourse.class, x -> VoToColumnUtil.fieldsToColumns(BaseClassCourse.class).contains(x.getProperty()))
  224. .innerJoin(BaseClassCourse.class, BaseClassCourse::getClassId, BaseClassAdminCourse::getId)
  225. .eq(BaseClassAdminCourse::getClassId, dto.getOldClassId())
  226. .eq(BaseClassAdminCourse::getBaseSemesterId, dto.getOldBaseSemesterId())
  227. ;
  228. List<BaseClassCourse> baseClassCourseList = baseClassAdminCourseMapper.selectJoinList(BaseClassCourse.class, baseClassCourseLambdaQueryWrapper);
  229. if(baseClassCourseList == null || baseClassCourseList.isEmpty()){
  230. throw new MyException("被复用的学期的被复用班级没有可以复用的课程!");
  231. }
  232. // 已经维护了课程教材信息的班级和所在学期
  233. List<BaseClassAdminCourse> baseClassAdminCourses = baseClassAdminCourseMapper.selectList(
  234. Wrappers.lambdaQuery(BaseClassAdminCourse.class)
  235. .eq(BaseClassAdminCourse::getDeleteMark, DeleteMark.NODELETE.getCode())
  236. );
  237. Map<String, Long> classSemester = new HashMap<>();
  238. for (BaseClassAdminCourse baseClassAdminCourse : baseClassAdminCourses) {
  239. classSemester.put(baseClassAdminCourse.getClassId() + "_" + baseClassAdminCourse.getBaseSemesterId(), baseClassAdminCourse.getId());
  240. }
  241. // 判断复用的学期复用的班级是否已经进入了班级课程列表
  242. // 判断本学期本班级是否已经加入课程管理的班级中
  243. List<Long> classAdminCourseIds = new ArrayList<>();
  244. for (Long classId : dto.getNewClassIds()){
  245. String newClassSemester = classId + "_" + dto.getNewBaseSemesterId();
  246. Long classAdminCourseId = null;
  247. BaseClassAdminCourse baseClassAdminCourse = null;
  248. if(ObjectUtils.isNotEmpty(classSemester) && ObjectUtils.isNotEmpty(classSemester.get(newClassSemester))){
  249. classAdminCourseId = classSemester.get(newClassSemester);
  250. } else {
  251. baseClassAdminCourse = new BaseClassAdminCourse();
  252. baseClassAdminCourse.setClassId(classId);
  253. baseClassAdminCourse.setBaseSemesterId(dto.getNewBaseSemesterId());
  254. baseClassAdminCourseMapper.insert(baseClassAdminCourse);
  255. classAdminCourseId = baseClassAdminCourse.getId();
  256. classSemester.put(newClassSemester, classAdminCourseId);
  257. }
  258. classAdminCourseIds.add(classAdminCourseId);
  259. }
  260. //删除班级的所有课程教材
  261. LambdaQueryWrapper<BaseClassCourse> removeLambdaQueryWrapper = new LambdaQueryWrapper<>();
  262. removeLambdaQueryWrapper
  263. .in(BaseClassCourse::getClassId, classAdminCourseIds)
  264. ;
  265. this.remove(removeLambdaQueryWrapper);
  266. List<BaseClassCourse> newBaseClassCourseList = new ArrayList<>();
  267. for (Long classAdminCourseId : classAdminCourseIds){
  268. for (BaseClassCourse baseClassCourse : baseClassCourseList){
  269. Long courseId = baseClassCourse.getCourseId();
  270. Long textbookId = baseClassCourse.getTextbookId();
  271. newBaseClassCourseList.add(new BaseClassCourse(){{
  272. setClassId(classAdminCourseId);
  273. setCourseId(courseId);
  274. setTextbookId(textbookId);
  275. setCreateDate(new Date());
  276. }});
  277. }
  278. }
  279. this.saveBatch(newBaseClassCourseList);
  280. return true;
  281. }
  282. @Override
  283. @Transactional
  284. public Boolean settingUpClasses(AddBaseClassAdminCourseDto dto) {
  285. if(ObjectUtils.isEmpty(dto.getBaseSemesterId())){
  286. throw new MyException("请选择需要设置课程的学期");
  287. }
  288. if(ObjectUtils.isEmpty(dto.getClassIds()) || dto.getClassIds().isEmpty()){
  289. throw new MyException("请选择需要设置课程的班级");
  290. }
  291. BaseClassAdminCourse baseClassAdminCourse;
  292. for(Long classId : dto.getClassIds()){
  293. baseClassAdminCourse = new BaseClassAdminCourse();
  294. baseClassAdminCourse.setBaseSemesterId(dto.getBaseSemesterId());
  295. baseClassAdminCourse.setClassId(classId);
  296. baseClassAdminCourseMapper.insert(baseClassAdminCourse);
  297. }
  298. return true;
  299. }
  300. @Override
  301. @Transactional
  302. public Boolean deleteSettingUpClasses(List<Long> ids) {
  303. // 先移除已经添加的课程数据
  304. LambdaUpdateWrapper<BaseClassCourse> baseClassCourseLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
  305. baseClassCourseLambdaUpdateWrapper
  306. .in(BaseClassCourse::getClassId, ids)
  307. ;
  308. this.remove(baseClassCourseLambdaUpdateWrapper);
  309. baseClassAdminCourseMapper.deleteBatchIds(ids);
  310. return true;
  311. }
  312. @Override
  313. public Map<String, Map<String, Object>> getSemesterTree() {
  314. List<Map<String, Object>> semesterData = baseClassCourseMapper.getAllSemesterNames();
  315. Map<String, Map<String, Object>> tree = new TreeMap<>();
  316. for (Map<String, Object> data : semesterData) {
  317. String name = (String) data.get("name");
  318. String[] parts = name.split("年");
  319. String year = parts[0]; // 年份
  320. String semesterType = parts[1].substring(0, parts[1].length() - 1); // 学期类型(春期/秋期)
  321. Long id = Long.parseLong(data.get("id").toString());
  322. if (!tree.containsKey(year + "年")) {
  323. tree.put(year + "年", new HashMap<>());
  324. }
  325. Map<String, Object> yearMap = tree.get(year + "年");
  326. if (semesterType.equals("春")) {
  327. yearMap.put("springName", name);
  328. yearMap.put("springId", id);
  329. } else if (semesterType.equals("秋")) {
  330. yearMap.put("autumnName", name);
  331. yearMap.put("autumnId", id);
  332. }
  333. }
  334. return tree;
  335. }
  336. @Override
  337. public Long GetClassIdByName(String name){
  338. return baseClassCourseMapper.getClassIdByName(name);
  339. }
  340. @Override
  341. public Long GetCourseIdByName(String name){
  342. return baseClassCourseMapper.getCourseIdByName(name);
  343. }
  344. @Override
  345. public Long GetTextbookIdByName(String name){
  346. return baseClassCourseMapper.getBookIdByName(name);
  347. }
  348. @Override
  349. public Long GetBaseSemesterIdByName(String name) {
  350. return baseClassCourseMapper.getBaseSemesterIdByName(name);
  351. }
  352. @Override
  353. public boolean checkExits(Long classId,Long courseId,Long textbookId){
  354. return baseClassCourseMapper.checkExits(classId, courseId, textbookId);
  355. }
  356. @Override
  357. public boolean checkExitsWithoutTextbook(Long classId, Long courseId) {
  358. return this.baseMapper.checkExitsWithoutTextbook(classId, courseId);
  359. }
  360. @Override
  361. public ByteArrayOutputStream classCourseTextbookExportQuery(ClassCourseTextbookExportQueryDto dto) throws IOException {
  362. MPJLambdaWrapper<BaseClassAdminCourse> baseClassCourseMPJLambdaWrapper = new MPJLambdaWrapper<>();
  363. baseClassCourseMPJLambdaWrapper
  364. .disableSubLogicDel()
  365. .selectAs(BaseSemester::getName, ClassCourseTextbookExportQueryVo::getSemester)
  366. .selectAs(Department::getName, ClassCourseTextbookExportQueryVo::getDeptName)
  367. .selectAs(BaseClass::getId, ClassCourseTextbookExportQueryVo::getClassId)
  368. .selectAs(BaseClass::getName, ClassCourseTextbookExportQueryVo::getClassName)
  369. .selectAs(BaseCourseSubject::getName, ClassCourseTextbookExportQueryVo::getCourseName)
  370. .selectAs(Textbook::getBookName, ClassCourseTextbookExportQueryVo::getTextbookName)
  371. .selectAs(Textbook::getUseType, ClassCourseTextbookExportQueryVo::getUseType)
  372. .selectAs(Textbook::getPrice, ClassCourseTextbookExportQueryVo::getPrice)
  373. .selectAs(Textbook::getDiscountPrice, ClassCourseTextbookExportQueryVo::getDiscountPrice)
  374. .leftJoin(BaseClassCourse.class,
  375. wrapper -> wrapper
  376. .eq(BaseClassCourse::getClassId, BaseClassAdminCourse::getId)
  377. .eq(BaseClassCourse::getDeleteMark, DeleteMark.NODELETE.getCode())
  378. )
  379. .leftJoin(BaseSemester.class, BaseSemester::getId, BaseClassAdminCourse::getBaseSemesterId)
  380. .leftJoin(BaseClass.class, BaseClass::getId, BaseClassAdminCourse::getClassId)
  381. .leftJoin(Department.class, Department::getId, BaseClass::getOrgId)
  382. .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, BaseClassCourse::getCourseId)
  383. .leftJoin(Textbook.class, Textbook::getId, BaseClassCourse::getTextbookId)
  384. .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Textbook::getTextbookType,
  385. wrapper -> wrapper
  386. .selectAs(DictionaryDetail::getName, ClassCourseTextbookExportQueryVo::getTextbookType)
  387. )
  388. .in(ObjectUtils.isNotEmpty(dto.getClassIds()) && !dto.getClassIds().isEmpty(), BaseClassAdminCourse::getClassId, dto.getClassIds())
  389. .like(StringUtils.isNotBlank(dto.getClassName()), BaseClass::getName, dto.getClassName())
  390. .eq(ObjectUtils.isNotEmpty(dto.getDeptId()), Department::getId, dto.getDeptId())
  391. // .having(ObjectUtils.isNotEmpty(dto.getCourseSet()) && dto.getCourseSet() == 1, "HAVING LENGTH(course_name) > 0")
  392. // .having(ObjectUtils.isNotEmpty(dto.getCourseSet()) && dto.getCourseSet() == 2, "HAVING COALESCE(LENGTH(course_name), 0) = 0")
  393. .eq(ObjectUtils.isNotEmpty(dto.getSemester()),BaseClassAdminCourse::getBaseSemesterId, dto.getSemester())
  394. .orderByDesc(BaseCourseSubject::getName)
  395. .orderByDesc(Textbook::getBookName)
  396. ;
  397. List<ClassCourseTextbookExportQueryVo> dataList = baseClassAdminCourseMapper.selectJoinList(ClassCourseTextbookExportQueryVo.class, baseClassCourseMPJLambdaWrapper);
  398. // 根据班级分组
  399. Map<Long, List<ClassCourseTextbookExportQueryVo>> dataMapByClassId = dataList.stream()
  400. .collect(Collectors.groupingBy(
  401. ClassCourseTextbookExportQueryVo::getClassId,
  402. LinkedHashMap::new, // 指定使用LinkedHashMap来保持顺序
  403. Collectors.toList()
  404. ));
  405. List<Long> classIds = dataList.stream()
  406. .filter(c -> ObjectUtils.isNotEmpty(c.getClassId()))
  407. .map(ClassCourseTextbookExportQueryVo::getClassId)
  408. .collect(Collectors.toList());
  409. if(classIds.isEmpty()){
  410. throw new MyException("导出数据中班级有误,请刷新重试");
  411. }
  412. // 获取班级人数
  413. MPJLambdaWrapper<BaseStudentSchoolRoll> baseStudentSchoolRollMPJLambdaWrapper = new MPJLambdaWrapper<>();
  414. baseStudentSchoolRollMPJLambdaWrapper
  415. .selectAs(BaseStudentSchoolRoll::getClassId, BaseStudentSchoolRoll::getClassId)
  416. .selectCount(BaseStudentSchoolRoll::getId, BaseStudentSchoolRoll::getDeleteMark)
  417. .in(BaseStudentSchoolRoll::getClassId, classIds)
  418. .eq(BaseStudentSchoolRoll::getArchivesStatus, ArchivesStatusEnum.FB2901.getCode())
  419. .eq(BaseStudentSchoolRoll::getDeleteMark, DeleteMark.NODELETE.getCode())
  420. .groupBy(BaseStudentSchoolRoll::getClassId)
  421. ;
  422. List<BaseStudentSchoolRoll> baseStudentSchoolRolls = baseStudentSchoolRollMapper.selectJoinList(BaseStudentSchoolRoll.class, baseStudentSchoolRollMPJLambdaWrapper);
  423. Map<Long, Integer> stuNumMap = baseStudentSchoolRolls.stream()
  424. .collect(Collectors.toMap(BaseStudentSchoolRoll::getClassId, BaseStudentSchoolRoll::getDeleteMark, (k1,k2) -> k1));
  425. // 处理数据
  426. for (ClassCourseTextbookExportQueryVo c : dataList){
  427. // 处理使用学期
  428. if(ObjectUtils.isNotEmpty(c.getUseType())){
  429. String useType = UseSemesterTypeEnum.getValue(c.getUseType());
  430. c.setUseTypeCn(useType);
  431. }else {
  432. c.setUseTypeCn("未知");
  433. }
  434. // 处理班级人数
  435. Integer stuNum = stuNumMap.get(c.getClassId());
  436. if(ObjectUtils.isNotEmpty(stuNum)){
  437. c.setStudentNum(stuNum);
  438. // 处理总价
  439. if(ObjectUtils.isNotEmpty(c.getDiscountPrice())){
  440. BigDecimal totalPrices = c.getDiscountPrice().multiply(BigDecimal.valueOf(stuNum));
  441. c.setTotalPrices(totalPrices);
  442. }else {
  443. c.setTotalPrices(BigDecimal.ZERO);
  444. }
  445. }else {
  446. c.setStudentNum(0);
  447. }
  448. }
  449. // 开始写入
  450. Workbook workbook = new XSSFWorkbook();
  451. // 创建一个工作表(sheet)
  452. String sheetName = "sheet1";
  453. Sheet sheet = workbook.createSheet(sheetName);
  454. List<ImportConfig> importConfigs = allFields(new ClassCourseTextbookExportQueryVo());
  455. // 表头
  456. createHead(workbook, sheet, importConfigs, 0);
  457. // 内容
  458. int dataRowNumber = 1;
  459. Font font = workbook.createFont();
  460. font.setFontName("宋体");
  461. font.setFontHeightInPoints((short)12);
  462. CellStyle cellStyle = workbook.createCellStyle();
  463. cellStyle.setFont(font); // 将字体应用到样式
  464. cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  465. cellStyle.setAlignment(HorizontalAlignment.CENTER);
  466. List<List<String>> inList = new ArrayList<>();
  467. List<Integer> mergeStepList = new ArrayList<>();
  468. for (Map.Entry<Long, List<ClassCourseTextbookExportQueryVo>> entry : dataMapByClassId.entrySet()){
  469. Long key = entry.getKey();
  470. List<ClassCourseTextbookExportQueryVo> value = entry.getValue();
  471. // 小计合计
  472. BigDecimal totalDiscountPrice = BigDecimal.ZERO;
  473. for (ClassCourseTextbookExportQueryVo c : value){
  474. totalDiscountPrice = totalDiscountPrice.add(ObjectUtils.isNotEmpty(c.getDiscountPrice()) ? c.getDiscountPrice() : BigDecimal.ZERO);
  475. }
  476. // 总价合计
  477. BigDecimal totalPriceTotal = BigDecimal.ZERO;
  478. for (ClassCourseTextbookExportQueryVo c : value){
  479. totalPriceTotal = totalPriceTotal.add(ObjectUtils.isNotEmpty(c.getTotalPrices()) ? c.getTotalPrices() : BigDecimal.ZERO);
  480. }
  481. for (ClassCourseTextbookExportQueryVo c : value){
  482. c.setTotalDiscountPrice(totalDiscountPrice);
  483. c.setTotalPriceTotal(totalPriceTotal);
  484. }
  485. // 开始写入
  486. for (ClassCourseTextbookExportQueryVo c : value){
  487. List<String> date = new ArrayList<>();
  488. date.add(c.getSemester());
  489. date.add(c.getDeptName());
  490. date.add(c.getClassName());
  491. date.add(c.getCourseName());
  492. date.add(c.getTextbookName());
  493. date.add(c.getUseTypeCn());
  494. date.add(c.getTextbookType());
  495. date.add(ObjectUtils.isNotEmpty(c.getPrice()) ? c.getPrice().toString() : "0");
  496. date.add(ObjectUtils.isNotEmpty(c.getDiscountPrice()) ? c.getDiscountPrice().toString() : "0");
  497. date.add(ObjectUtils.isNotEmpty(c.getTotalDiscountPrice()) ? c.getTotalDiscountPrice().toString() : "0");
  498. date.add(c.getStudentNum() + "");
  499. date.add(ObjectUtils.isNotEmpty(c.getTotalPrices()) ? c.getTotalPrices().toString() : "0");
  500. date.add(ObjectUtils.isNotEmpty(c.getTotalPriceTotal()) ? c.getTotalPriceTotal().toString() : "0");
  501. inList.add(date);
  502. }
  503. mergeStepList.add(value.size());
  504. }
  505. Cell cell;
  506. for (List<String> rowData : inList) {
  507. Row dataRow = sheet.createRow(dataRowNumber);
  508. int size = rowData.size();
  509. for (int i = 0; i < size; i++) {
  510. cell = dataRow.createCell(i);
  511. cell.setCellValue(rowData.get(i));
  512. cell.setCellStyle(cellStyle);
  513. }
  514. dataRowNumber++;
  515. }
  516. // 合并
  517. dataRowNumber = 1;
  518. for (Integer step : mergeStepList){
  519. if(step == 1){
  520. dataRowNumber++;
  521. }
  522. if(step > 1){
  523. sheet.addMergedRegion(new CellRangeAddress(dataRowNumber, dataRowNumber + step - 1, 9, 9));
  524. sheet.addMergedRegion(new CellRangeAddress(dataRowNumber, dataRowNumber + step - 1, 10, 10));
  525. sheet.addMergedRegion(new CellRangeAddress(dataRowNumber, dataRowNumber + step - 1, 12, 12));
  526. dataRowNumber = dataRowNumber + step;
  527. }
  528. }
  529. for (int i = 0; i < importConfigs.size(); i++) {
  530. sheet.autoSizeColumn(i);
  531. }
  532. //写入文件
  533. ByteArrayOutputStream bot = new ByteArrayOutputStream();
  534. workbook.write(bot);
  535. return bot;
  536. }
  537. }