package com.xjrsoft.module.base.service.impl; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.support.ExcelTypeEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.base.MPJBaseServiceImpl; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.xjrsoft.common.enums.ArchivesStatusEnum; import com.xjrsoft.common.enums.DeleteMark; import com.xjrsoft.common.enums.UseSemesterTypeEnum; import com.xjrsoft.common.exception.MyException; import com.xjrsoft.common.utils.VoToColumnUtil; import com.xjrsoft.module.base.dto.BaseClassCoursePageDto; import com.xjrsoft.module.base.dto.ClassCourseReuseDto; import com.xjrsoft.module.base.entity.*; import com.xjrsoft.module.base.mapper.BaseClassCourseMapper; import com.xjrsoft.module.base.mapper.BaseClassMapper; import com.xjrsoft.module.base.service.IBaseClassCourseService; import com.xjrsoft.module.base.vo.BaseClassCourseExportListVo; import com.xjrsoft.module.base.vo.BaseClassCoursePageVo; import com.xjrsoft.module.generator.entity.ImportConfig; import com.xjrsoft.module.organization.entity.Department; import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll; import com.xjrsoft.module.student.mapper.BaseStudentSchoolRollMapper; import com.xjrsoft.module.base.dto.ClassCourseTextbookExportQueryDto; import com.xjrsoft.module.base.vo.ClassCourseTextbookExportQueryVo; import com.xjrsoft.module.system.entity.DictionaryDetail; import com.xjrsoft.module.textbook.entity.Textbook; import com.xjrsoft.module.textbook.entity.TextbookStudentClaim; import com.xjrsoft.module.textbook.mapper.TextbookStudentClaimMapper; import lombok.AllArgsConstructor; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; import static com.xjrsoft.module.veb.util.ImportExcelUtil.allFields; import static com.xjrsoft.module.veb.util.ImportExcelUtil.createHead; /** * @title: 班级课程 * @Author brealinxx * @Date: 2024-06-04 * @Version 1.0 */ @Service @AllArgsConstructor public class BaseClassCourseServiceImpl extends MPJBaseServiceImpl implements IBaseClassCourseService { private final BaseClassCourseMapper baseClassCourseMapper; private final BaseStudentSchoolRollMapper baseStudentSchoolRollMapper; private final TextbookStudentClaimMapper textbookStudentClaimMapper; private final BaseClassMapper baseClassMapper; @Override public Page getPage(Page page, BaseClassCoursePageDto dto) { return baseClassCourseMapper.getPage(page, dto); } @Override public List getAllCourseBook(Long[] classIds, Long subjectGroupId, Long semester){ return baseClassCourseMapper.getAllCourseBook(classIds, subjectGroupId, semester); } @Override public List getSelectedCourseBook(Long[] subjectGroupId, Long semester){ return baseClassCourseMapper.getSelectedCourseBook(subjectGroupId, semester); } @Override @Transactional public Boolean updateAddCourseBook(ClassCourseTextbook dto){ if (dto.getClassIds() == null || dto.getClassIds().length == 0 || dto.getBaseSemesterId() == null || dto.getBaseSemesterId() == 0) { return false; } boolean isSuccess = false; List classIdList = Arrays.asList(dto.getClassIds()); //删除班级的这学期的所有课程教材 LambdaQueryWrapper baseClassCourseLambdaQueryWrapper = new LambdaQueryWrapper<>(); baseClassCourseLambdaQueryWrapper .in(BaseClassCourse::getClassId, classIdList) .eq(BaseClassCourse::getBaseSemesterId, dto.getBaseSemesterId()) ; isSuccess = this.remove(baseClassCourseLambdaQueryWrapper); // 获取所有班级的所有学生 LambdaQueryWrapper baseStudentSchoolRollLambdaQueryWrapper = new LambdaQueryWrapper<>(); baseStudentSchoolRollLambdaQueryWrapper .in(BaseStudentSchoolRoll::getClassId, classIdList) .eq(BaseStudentSchoolRoll::getArchivesStatus, ArchivesStatusEnum.FB2901.getCode()) ; List baseStudentSchoolRolls = baseStudentSchoolRollMapper.selectList(baseStudentSchoolRollLambdaQueryWrapper); Map> userIdsMap = baseStudentSchoolRolls.stream() .filter(student -> student.getClassId() != null && student.getUserId() != null) .collect(Collectors.groupingBy( BaseStudentSchoolRoll::getClassId, // 根据classId分组 Collectors.mapping(BaseStudentSchoolRoll::getUserId, // 提取userId Collectors.toList()) // 收集到List ) ); List baseClassCourseList = new ArrayList<>(); List textbookStudentClaimList = new ArrayList<>(); for (Long classId : dto.getClassIds()) { for (String id : dto.getIds()) { String[] idArr = id.split("_"); if (idArr[0].equals("") || idArr[1].equals("")) { continue; } Long courseId = Long.parseLong(idArr[0]); Long textbookId = Long.parseLong(idArr[1]); baseClassCourseList.add(new BaseClassCourse() {{ setBaseSemesterId(dto.getBaseSemesterId()); setClassId(classId); setCourseId(courseId); setTextbookId(textbookId); }}); // 添加学生领取教材数据 List userIds = userIdsMap.get(classId); for (Long userId : userIds) { textbookStudentClaimList.add(new TextbookStudentClaim() {{ setStudentUserId(userId); setBaseSemesterId(dto.getBaseSemesterId()); setClassId(classId); setTextbookId(textbookId); }}); } } } for (TextbookStudentClaim textbookStudentClaim : textbookStudentClaimList) { textbookStudentClaimMapper.insert(textbookStudentClaim); } return this.saveBatch(baseClassCourseList); } @Override public void updateRemoveCourseBook(Long classId, Long courseId, Long textbookId){ baseClassCourseMapper.updateRemoveClassCourseTextbooks(classId, courseId, textbookId); } @Override public void markExistingRecordsAsDeleted(Long newClassId, Long sourceClassId){ baseClassCourseMapper.markExistingRecordsAsDeleted(newClassId, sourceClassId); } @Override @Transactional public Boolean duplicateCourseBook(ClassCourseReuseDto dto){ LambdaQueryWrapper baseClassCourseLambdaQueryWrapper = new LambdaQueryWrapper<>(); baseClassCourseLambdaQueryWrapper .eq(dto.getOldClassId() != null && dto.getOldClassId() > 0, BaseClassCourse::getClassId, dto.getOldClassId()) .eq(dto.getOldBaseSemesterId() != null && dto.getOldBaseSemesterId() > 0, BaseClassCourse::getBaseSemesterId, dto.getOldBaseSemesterId()) ; List baseClassCourseList = this.list(baseClassCourseLambdaQueryWrapper); if(baseClassCourseList == null || baseClassCourseList.isEmpty()){ throw new MyException("该学期的该班级没有可以复用的课程!"); } boolean isSuccess = false; //删除班级的所有课程教材 LambdaQueryWrapper removeLambdaQueryWrapper = new LambdaQueryWrapper<>(); removeLambdaQueryWrapper .in(BaseClassCourse::getClassId, dto.getNewClassIds()) .eq(BaseClassCourse::getBaseSemesterId, dto.getNewBaseSemesterId()) ; isSuccess = this.remove(removeLambdaQueryWrapper); List newBaseClassCourseList = new ArrayList<>(); for (Long newClassId : dto.getNewClassIds()){ for (BaseClassCourse baseClassCourse : baseClassCourseList){ Long courseId = baseClassCourse.getCourseId(); Long textbookId = baseClassCourse.getTextbookId(); newBaseClassCourseList.add(new BaseClassCourse(){{ setBaseSemesterId(dto.getNewBaseSemesterId()); setClassId(newClassId); setCourseId(courseId); setTextbookId(textbookId); }}); } } isSuccess = this.saveBatch(newBaseClassCourseList); return isSuccess; //baseClassCourseMapper.insertClassCourseTextbookCombinations(newClassId, sourceClassId, semester); } @Override public Map> getSemesterTree() { List> semesterData = baseClassCourseMapper.getAllSemesterNames(); Map> tree = new TreeMap<>(); for (Map data : semesterData) { String name = (String) data.get("name"); String[] parts = name.split("年"); String year = parts[0]; // 年份 String semesterType = parts[1].substring(0, parts[1].length() - 1); // 学期类型(春期/秋期) Long id = Long.parseLong(data.get("id").toString()); if (!tree.containsKey(year + "年")) { tree.put(year + "年", new HashMap<>()); } Map yearMap = tree.get(year + "年"); if (semesterType.equals("春")) { yearMap.put("springName", name); yearMap.put("springId", id); } else if (semesterType.equals("秋")) { yearMap.put("autumnName", name); yearMap.put("autumnId", id); } } return tree; } @Override public Long GetClassIdByName(String name){ return baseClassCourseMapper.getClassIdByName(name); } @Override public Long GetCourseIdByName(String name){ return baseClassCourseMapper.getCourseIdByName(name); } @Override public Long GetTextbookIdByName(String name){ return baseClassCourseMapper.getBookIdByName(name); } @Override public Long GetBaseSemesterIdByName(String name) { return baseClassCourseMapper.getBaseSemesterIdByName(name); } @Override public boolean checkExits(Long classId,Long courseId,Long textbookId){ return baseClassCourseMapper.checkExits(classId, courseId, textbookId); } @Override public boolean checkExitsWithoutTextbook(Long classId, Long courseId) { return this.baseMapper.checkExitsWithoutTextbook(classId, courseId); } @Override public ByteArrayOutputStream classCourseTextbookExportQuery(ClassCourseTextbookExportQueryDto dto) throws IOException { MPJLambdaWrapper baseClassCourseMPJLambdaWrapper = new MPJLambdaWrapper<>(); baseClassCourseMPJLambdaWrapper .disableSubLogicDel() .selectAs(BaseSemester::getName, ClassCourseTextbookExportQueryVo::getSemester) .selectAs(Department::getName, ClassCourseTextbookExportQueryVo::getDeptName) .selectAs(BaseClass::getId, ClassCourseTextbookExportQueryVo::getClassId) .selectAs(BaseClass::getName, ClassCourseTextbookExportQueryVo::getClassName) .selectAs(BaseCourseSubject::getName, ClassCourseTextbookExportQueryVo::getCourseName) .selectAs(Textbook::getBookName, ClassCourseTextbookExportQueryVo::getTextbookName) .selectAs(Textbook::getUseType, ClassCourseTextbookExportQueryVo::getUseType) .selectAs(Textbook::getPrice, ClassCourseTextbookExportQueryVo::getPrice) .selectAs(Textbook::getDiscountPrice, ClassCourseTextbookExportQueryVo::getDiscountPrice) .leftJoin(BaseClassCourse.class, BaseClassCourse::getClassId, BaseClass::getId) .leftJoin(BaseSemester.class, BaseSemester::getId, BaseClassCourse::getBaseSemesterId) .leftJoin(BaseClass.class, BaseClass::getId, BaseClassCourse::getClassId) .leftJoin(Department.class, Department::getId, BaseClass::getOrgId) .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, BaseClassCourse::getCourseId) .leftJoin(Textbook.class, Textbook::getId, BaseClassCourse::getTextbookId) .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Textbook::getTextbookType, wrapper -> wrapper .selectAs(DictionaryDetail::getName, ClassCourseTextbookExportQueryVo::getTextbookType) ) .in(ObjectUtils.isNotEmpty(dto.getClassIds()) && !dto.getClassIds().isEmpty(), BaseClassCourse::getClassId, dto.getClassIds()) .like(StringUtils.isNotBlank(dto.getClassName()), BaseClass::getName, dto.getClassName()) .eq(ObjectUtils.isNotEmpty(dto.getDeptId()), Department::getId, dto.getDeptId()) .having(ObjectUtils.isNotEmpty(dto.getCourseSet()) && dto.getCourseSet() == 1, "HAVING LENGTH(course_name) > 0") .having(ObjectUtils.isNotEmpty(dto.getCourseSet()) && dto.getCourseSet() == 2, "HAVING COALESCE(LENGTH(course_name), 0) = 0") .and(ObjectUtils.isNotEmpty(dto.getSemester()), wrapper -> wrapper .eq(BaseClassCourse::getBaseSemesterId, dto.getSemester()) .or() .isNull(BaseClassCourse::getBaseSemesterId) ) .and(wrapper -> wrapper .eq(BaseClassCourse::getDeleteMark, DeleteMark.NODELETE.getCode()) .or() .isNull(BaseClassCourse::getDeleteMark) ) .eq(BaseClass::getDeleteMark, DeleteMark.NODELETE.getCode()) .orderByDesc(BaseCourseSubject::getName) .orderByDesc(Textbook::getBookName) ; List dataList = baseClassMapper.selectJoinList(ClassCourseTextbookExportQueryVo.class, baseClassCourseMPJLambdaWrapper); // 根据班级分组 Map> dataMapByClassId = dataList.stream() .collect(Collectors.groupingBy( ClassCourseTextbookExportQueryVo::getClassId, LinkedHashMap::new, // 指定使用LinkedHashMap来保持顺序 Collectors.toList() )); List classIds = dataList.stream() .filter(c -> ObjectUtils.isNotEmpty(c.getClassId())) .map(ClassCourseTextbookExportQueryVo::getClassId) .collect(Collectors.toList()); if(classIds.isEmpty()){ throw new MyException("导出数据中班级有误,请刷新重试"); } // 获取班级人数 MPJLambdaWrapper baseStudentSchoolRollMPJLambdaWrapper = new MPJLambdaWrapper<>(); baseStudentSchoolRollMPJLambdaWrapper .selectAs(BaseStudentSchoolRoll::getClassId, BaseStudentSchoolRoll::getClassId) .selectCount(BaseStudentSchoolRoll::getId, BaseStudentSchoolRoll::getDeleteMark) .in(BaseStudentSchoolRoll::getClassId, classIds) .eq(BaseStudentSchoolRoll::getArchivesStatus, ArchivesStatusEnum.FB2901.getCode()) .eq(BaseStudentSchoolRoll::getDeleteMark, DeleteMark.NODELETE.getCode()) .groupBy(BaseStudentSchoolRoll::getClassId) ; List baseStudentSchoolRolls = baseStudentSchoolRollMapper.selectJoinList(BaseStudentSchoolRoll.class, baseStudentSchoolRollMPJLambdaWrapper); Map stuNumMap = baseStudentSchoolRolls.stream() .collect(Collectors.toMap(BaseStudentSchoolRoll::getClassId, BaseStudentSchoolRoll::getDeleteMark, (k1,k2) -> k1)); // 处理数据 for (ClassCourseTextbookExportQueryVo c : dataList){ // 处理使用学期 if(ObjectUtils.isNotEmpty(c.getUseType())){ String useType = UseSemesterTypeEnum.getValue(c.getUseType()); c.setUseTypeCn(useType); }else { c.setUseTypeCn("未知"); } // 处理班级人数 Integer stuNum = stuNumMap.get(c.getClassId()); if(ObjectUtils.isNotEmpty(stuNum)){ c.setStudentNum(stuNum); // 处理总价 if(ObjectUtils.isNotEmpty(c.getDiscountPrice())){ BigDecimal totalPrices = c.getDiscountPrice().multiply(BigDecimal.valueOf(stuNum)); c.setTotalPrices(totalPrices); }else { c.setTotalPrices(BigDecimal.ZERO); } }else { c.setStudentNum(0); } } // 开始写入 Workbook workbook = new XSSFWorkbook(); // 创建一个工作表(sheet) String sheetName = "sheet1"; Sheet sheet = workbook.createSheet(sheetName); List importConfigs = allFields(new ClassCourseTextbookExportQueryVo()); // 表头 createHead(workbook, sheet, importConfigs, 0); // 内容 int dataRowNumber = 1; Font font = workbook.createFont(); font.setFontName("宋体"); font.setFontHeightInPoints((short)12); CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setFont(font); // 将字体应用到样式 cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); cellStyle.setAlignment(HorizontalAlignment.CENTER); for (Map.Entry> entry : dataMapByClassId.entrySet()){ Long key = entry.getKey(); List value = entry.getValue(); List> inList = new ArrayList<>(); // 小计合计 BigDecimal totalDiscountPrice = BigDecimal.ZERO; for (ClassCourseTextbookExportQueryVo c : value){ totalDiscountPrice = totalDiscountPrice.add(ObjectUtils.isNotEmpty(c.getDiscountPrice()) ? c.getDiscountPrice() : BigDecimal.ZERO); } for (ClassCourseTextbookExportQueryVo c : value){ c.setTotalDiscountPrice(totalDiscountPrice); } // 总价合计 BigDecimal totalPriceTotal = BigDecimal.ZERO; for (ClassCourseTextbookExportQueryVo c : value){ totalPriceTotal = totalPriceTotal.add(ObjectUtils.isNotEmpty(c.getTotalPrices()) ? c.getTotalPrices() : BigDecimal.ZERO); } for (ClassCourseTextbookExportQueryVo c : value){ c.setTotalPriceTotal(totalPriceTotal); } // 开始写入 for (ClassCourseTextbookExportQueryVo c : value){ List date = new ArrayList<>(); date.add(c.getSemester()); date.add(c.getDeptName()); date.add(c.getClassName()); date.add(c.getCourseName()); date.add(c.getTextbookName()); date.add(c.getUseTypeCn()); date.add(c.getTextbookType()); date.add(ObjectUtils.isNotEmpty(c.getPrice()) ? c.getPrice().toString() : "0"); date.add(ObjectUtils.isNotEmpty(c.getDiscountPrice()) ? c.getDiscountPrice().toString() : "0"); date.add(ObjectUtils.isNotEmpty(c.getTotalDiscountPrice()) ? c.getTotalDiscountPrice().toString() : "0"); date.add(c.getStudentNum() + ""); date.add(ObjectUtils.isNotEmpty(c.getTotalPrices()) ? c.getTotalPrices().toString() : "0"); date.add(ObjectUtils.isNotEmpty(c.getTotalPriceTotal()) ? c.getTotalPriceTotal().toString() : "0"); inList.add(date); } for (List rowData : inList) { Row dataRow = sheet.createRow(dataRowNumber); for (int i = 0; i < rowData.size(); i++) { sheet.autoSizeColumn(i); Cell cell = dataRow.createCell(i); cell.setCellValue(rowData.get(i)); cell.setCellStyle(cellStyle); } dataRowNumber++; } if(inList.size() > 1){ sheet.addMergedRegion(new CellRangeAddress(dataRowNumber - inList.size(), dataRowNumber - 1, 9, 9)); sheet.addMergedRegion(new CellRangeAddress(dataRowNumber - inList.size(), dataRowNumber - 1, 10, 10)); sheet.addMergedRegion(new CellRangeAddress(dataRowNumber - inList.size(), dataRowNumber - 1, 12, 12)); } } //写入文件 ByteArrayOutputStream bot = new ByteArrayOutputStream(); workbook.write(bot); return bot; } }