Sfoglia il codice sorgente

教材模块重构-教材基本信息,教材征订

大数据与最优化研究所 1 anno fa
parent
commit
550de324cf
37 ha cambiato i file con 2185 aggiunte e 675 eliminazioni
  1. 1 0
      src/main/java/com/xjrsoft/module/base/service/IBaseClassCourseService.java
  2. 1 2
      src/main/java/com/xjrsoft/module/base/service/impl/BaseClassCourseServiceImpl.java
  3. 57 8
      src/main/java/com/xjrsoft/module/textbook/controller/TextbookController.java
  4. 213 0
      src/main/java/com/xjrsoft/module/textbook/controller/TextbookSubscriptionController.java
  5. 0 1
      src/main/java/com/xjrsoft/module/textbook/controller/TextbookWarehouseRecordController.java
  6. 25 26
      src/main/java/com/xjrsoft/module/textbook/controller/WfTextbookSubscriptionController.java
  7. 5 0
      src/main/java/com/xjrsoft/module/textbook/dto/AddTextbookSubscriptionDto.java
  8. 0 5
      src/main/java/com/xjrsoft/module/textbook/dto/AddTextbookWarehouseRecordDto.java
  9. 5 4
      src/main/java/com/xjrsoft/module/textbook/dto/BaseclassPageDto.java
  10. 2 2
      src/main/java/com/xjrsoft/module/textbook/dto/TextbookInstockroomDto.java
  11. 20 1
      src/main/java/com/xjrsoft/module/textbook/dto/TextbookInstockroomListDto.java
  12. 18 0
      src/main/java/com/xjrsoft/module/textbook/dto/TextbookInstockroomOnceListDto.java
  13. 47 0
      src/main/java/com/xjrsoft/module/textbook/dto/TextbookSubscriptionItemPageDto.java
  14. 38 0
      src/main/java/com/xjrsoft/module/textbook/dto/TextbookSubscriptionPageDto.java
  15. 33 0
      src/main/java/com/xjrsoft/module/textbook/dto/UpdateTextbookSubscriptionDto.java
  16. 5 0
      src/main/java/com/xjrsoft/module/textbook/entity/TextbookSubscription.java
  17. 4 7
      src/main/java/com/xjrsoft/module/textbook/service/ITextbookService.java
  18. 78 0
      src/main/java/com/xjrsoft/module/textbook/service/ITextbookSubscriptionService.java
  19. 1 0
      src/main/java/com/xjrsoft/module/textbook/service/ITextbookWarehouseRecordService.java
  20. 142 30
      src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookServiceImpl.java
  21. 483 0
      src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookSubscriptionServiceImpl.java
  22. 12 0
      src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookWarehouseRecordServiceImpl.java
  23. 11 11
      src/main/java/com/xjrsoft/module/textbook/service/impl/WfTextbookSubscriptionServiceImpl.java
  24. 29 18
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookInstockroomListVo.java
  25. 38 0
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookInstockroomOnceListVo.java
  26. 43 0
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionDetailVo.java
  27. 137 0
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionItemPageVo.java
  28. 116 0
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionItemVo.java
  29. 66 0
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionPageVo.java
  30. 64 0
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionVo.java
  31. 62 71
      src/main/java/com/xjrsoft/module/textbook/vo/TextbookVo.java
  32. 3 154
      src/main/java/com/xjrsoft/module/veb/controller/ImportRubAndHandController.java
  33. 0 2
      src/main/java/com/xjrsoft/module/veb/service/ImportRubAndHandService.java
  34. 11 291
      src/main/java/com/xjrsoft/module/veb/service/impl/ImportRubAndHandServiceImpl.java
  35. 337 0
      src/main/java/com/xjrsoft/module/veb/util/ImportExcelUtil.java
  36. 52 41
      src/main/resources/sqlScript/textbook_sql.sql
  37. 26 1
      src/test/java/com/xjrsoft/xjrsoftboot/FreeMarkerGeneratorTest.java

+ 1 - 0
src/main/java/com/xjrsoft/module/base/service/IBaseClassCourseService.java

@@ -30,6 +30,7 @@ public interface IBaseClassCourseService extends MPJBaseService<BaseClassCourse>
 
 
     Boolean updateAddCourseBook(ClassCourseTextbook dto);
+
     void updateRemoveCourseBook(Long classId, Long courseId, Long textbookId);
 
     void markExistingRecordsAsDeleted(Long newClassId, Long sourceClassId);

+ 1 - 2
src/main/java/com/xjrsoft/module/base/service/impl/BaseClassCourseServiceImpl.java

@@ -87,8 +87,7 @@ public class BaseClassCourseServiceImpl extends MPJBaseServiceImpl<BaseClassCour
 
         isSuccess = this.saveBatch(baseClassCourseList);
 
-
-        // 课程教材添加成功,添加领取状态
+        // TODO 课程教材添加成功,添加领取状态
 
 
         return isSuccess;

+ 57 - 8
src/main/java/com/xjrsoft/module/textbook/controller/TextbookController.java

@@ -7,11 +7,14 @@ import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import com.xjrsoft.common.enums.TextbookTypeEnum;
+import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.common.model.result.R;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.base.entity.BaseCourseSubject;
+import com.xjrsoft.module.generator.entity.ImportConfig;
 import com.xjrsoft.module.student.entity.BaseClassMajorSet;
 import com.xjrsoft.module.textbook.dto.*;
 import com.xjrsoft.module.textbook.entity.Textbook;
@@ -20,14 +23,22 @@ import com.xjrsoft.module.textbook.entity.TextbookStudentClaim;
 import com.xjrsoft.module.textbook.service.ITextbookService;
 import com.xjrsoft.module.textbook.service.ITextbookStudentClaimService;
 import com.xjrsoft.module.textbook.vo.*;
+import com.xjrsoft.module.veb.util.ImportExcelUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.validation.Valid;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -217,14 +228,6 @@ public class TextbookController {
 //        return RT.fileStream(bot.toByteArray(), "Textbook" + ExcelTypeEnum.XLSX.getValue());
 //    }
 
-    @PostMapping("deliver-warehouse")
-    @ApiOperation(value = "教材管理入库")
-    @SaCheckPermission("textbook:add")
-    public RT<Boolean> deliverWarehouse(@Valid @RequestBody AddTextbookWarehouseRecordDto dto){
-        Boolean isSuccess = textbookService.deliverWarehouse(dto);
-        return RT.ok(isSuccess);
-    }
-
     @PostMapping("/textbook-standing-export-query")
     @ApiOperation(value = "台账条件导出")
     public ResponseEntity<byte[]> textbookStandingExportQuery(@Valid @RequestBody TextbookStandingExportQuerytDto dto) {
@@ -267,4 +270,50 @@ public class TextbookController {
 //        return R.ok(textbookService.excelImport(inputStream));
 //    }
 
+    @PostMapping("/textbook-import")
+    @ApiOperation(value = "教材信息导入")
+    public RT<Boolean> textbook(@RequestParam MultipartFile file) throws IOException, IllegalAccessException {
+        String result = textbookService.textbook(file);
+        if (!result.isEmpty()) {
+            throw new MyException(result);
+        }
+        return RT.ok("全部成功", true);
+    }
+
+    @PostMapping("/textbook-template-download")
+    @ApiOperation(value = "教材信息模板下载")
+    public ResponseEntity<byte[]> textbookTemplate() throws IOException {
+//    @GetMapping("/textbook-template")
+//    @ApiOperation(value = "教材信息模板下载")
+//    public ResponseEntity<byte[]> textbookTemplate() throws IOException {
+        TextbookImportDto obj = new TextbookImportDto();
+        // 开始写入
+        Workbook workbook = new XSSFWorkbook();
+        // 创建一个工作表(sheet)
+        String sheetName = "sheet1";
+        Sheet sheet = workbook.createSheet(sheetName);
+
+        List<ImportConfig> importConfigs = ImportExcelUtil.allFields(obj);
+
+        // 标题
+        String title = "教材信息导入模板";
+        ImportExcelUtil.createCautionHead(workbook, sheet, 0, title, importConfigs.size() - 1, 36);
+
+        // 提示必填
+        String content = "说明:红底为必填项,白底为非必填项;只有教材分类为教材时才需要填写学科组和对应课程,学科组和课程必须是系统中已添加的信息,且学科组和课程已建立绑定关系;导入时请将示例数据删除,避免导入失败!";
+        ImportExcelUtil.createCautionHead(workbook, sheet, 1, content, importConfigs.size() - 1, 12);
+
+        // 表头
+        ImportExcelUtil.createHead(workbook, sheet, importConfigs, 2);
+
+        //写入文件
+        ByteArrayOutputStream bot = new ByteArrayOutputStream();
+        workbook.write(bot);
+
+
+        String fileName = "教材信息导入模板";
+        fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
+        return R.fileStream(bot.toByteArray(), fileName + ExcelTypeEnum.XLSX.getValue());
+    }
+
 }

+ 213 - 0
src/main/java/com/xjrsoft/module/textbook/controller/TextbookSubscriptionController.java

@@ -0,0 +1,213 @@
+package com.xjrsoft.module.textbook.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.support.ExcelTypeEnum;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.model.result.RT;
+import com.xjrsoft.common.page.ConventPage;
+import com.xjrsoft.common.page.PageOutput;
+import com.xjrsoft.common.utils.VoToColumnUtil;
+import com.xjrsoft.module.base.entity.BaseClass;
+import com.xjrsoft.module.base.entity.BaseGrade;
+import com.xjrsoft.module.base.entity.BaseSemester;
+import com.xjrsoft.module.base.service.IBaseClassService;
+import com.xjrsoft.module.student.entity.BaseClassMajorSet;
+import com.xjrsoft.module.teacher.entity.XjrUser;
+import com.xjrsoft.module.textbook.dto.*;
+import com.xjrsoft.module.textbook.entity.TextbookSubscription;
+import com.xjrsoft.module.textbook.entity.TextbookSubscriptionClass;
+import com.xjrsoft.module.textbook.entity.WfTextbookSubscription;
+import com.xjrsoft.module.textbook.service.ITextbookSubscriptionService;
+import com.xjrsoft.module.textbook.vo.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.Valid;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+* @title: 教材教辅征订记录表
+* @Author dzx
+* @Date: 2024-12-16
+* @Version 1.0
+*/
+@RestController
+@RequestMapping("/textbook" + "/textbookSubscription")
+@Api(value = "/textbook"  + "/textbookSubscription",tags = "教材教辅征订记录表代码")
+@AllArgsConstructor
+public class TextbookSubscriptionController {
+
+
+    private final ITextbookSubscriptionService textbookSubscriptionService;
+
+    private final IBaseClassService baseClassService;
+
+    @GetMapping(value = "/page")
+    @ApiOperation(value="教材教辅征订记录列表(分页)")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<PageOutput<TextbookSubscriptionPageVo>> page(@Valid TextbookSubscriptionPageDto dto){
+        IPage<TextbookSubscriptionPageVo> page = textbookSubscriptionService.pageRubAndHand(dto);
+        PageOutput<TextbookSubscriptionPageVo> pageOutput = ConventPage.getPageOutput(page, TextbookSubscriptionPageVo.class);
+        return RT.ok(pageOutput);
+    }
+
+    @GetMapping(value = "/list")
+    @ApiOperation(value="教材教辅征订记录表列表(不分页)")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<List<TextbookSubscriptionListVo>> list(@Valid TextbookSubscriptionListDto dto){
+
+        LambdaQueryWrapper<TextbookSubscription> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper
+                    .orderByDesc(TextbookSubscription::getId)
+                    .select(TextbookSubscription.class,x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionListVo.class).contains(x.getProperty()));
+
+        List<TextbookSubscription> list = textbookSubscriptionService.list(queryWrapper);
+        List<TextbookSubscriptionListVo> listVos = BeanUtil.copyToList(list, TextbookSubscriptionListVo.class);
+        return RT.ok(listVos);
+    }
+
+    @GetMapping(value = "/instockroom-list")
+    @ApiOperation(value = "教材教辅征订入库用页面")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<List<TextbookInstockroomListVo>> instockroomList(@Valid TextbookInstockroomListDto dto) {
+        List<TextbookInstockroomListVo> list = textbookSubscriptionService.instockroomList(dto);
+        return RT.ok(list);
+    }
+
+    @GetMapping(value = "/every-instockroom-list")
+    @ApiOperation(value = "教材教辅征订每次入库详情")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<List<TextbookInstockroomOnceListVo>> everyInstockroomList(@Valid TextbookInstockroomOnceListDto dto) {
+        List<TextbookInstockroomOnceListVo> list = textbookSubscriptionService.everyInstockroomList(dto);
+        return RT.ok(list);
+    }
+
+    @GetMapping(value = "/baseclass-page")
+    @ApiOperation(value="征订班级列表(分页)")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<PageOutput<BaseclassPageVo>> baseclassPage(@Valid BaseclassPageDto dto){
+        MPJLambdaWrapper<BaseClass> baseClassMPJLambdaWrapper = new MPJLambdaWrapper<>();
+        baseClassMPJLambdaWrapper
+                .selectAs(BaseGrade::getName, BaseclassPageVo::getGradeIdCn)
+                .selectAs(XjrUser::getName, BaseclassPageVo::getTeacherIdCn)
+                .selectAs(BaseClassMajorSet::getTotalStudent, BaseclassPageVo::getTotalStudent)
+                .select(BaseClass.class,x -> VoToColumnUtil.fieldsToColumns(BaseclassPageVo.class).contains(x.getProperty()))
+                .innerJoin(TextbookSubscriptionClass.class, TextbookSubscriptionClass::getBaseClassId, BaseClass::getId)
+                .leftJoin(BaseGrade.class, BaseGrade::getId, BaseClass::getGradeId)
+                .leftJoin(XjrUser.class, XjrUser::getId, BaseClass::getTeacherId)
+                .leftJoin(BaseClassMajorSet.class, BaseClassMajorSet::getClassId, BaseClass::getId)
+                .eq(TextbookSubscriptionClass::getTextbookSubscriptionId, dto.getId())
+        ;
+        IPage<BaseclassPageVo> baseclassPageVos = baseClassService.selectJoinListPage(ConventPage.getPage(dto), BaseclassPageVo.class, baseClassMPJLambdaWrapper);
+        PageOutput<BaseclassPageVo> pageOutput = ConventPage.getPageOutput(baseclassPageVos, BaseclassPageVo.class);
+        return RT.ok(pageOutput);
+    }
+
+    @GetMapping(value = "/info")
+    @ApiOperation(value="根据id查询教材教辅征订记录表信息")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<TextbookSubscriptionVo> info(@RequestParam Long id){
+        TextbookSubscriptionVo textbookSubscriptionVo = textbookSubscriptionService.infoRubAndHand(id);
+        if (textbookSubscriptionVo == null) {
+           return RT.error("找不到此数据!");
+        }
+        return RT.ok(textbookSubscriptionVo);
+    }
+
+    @GetMapping(value = "/detail")
+    @ApiOperation(value="根据id查询教材教辅征订详情")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<TextbookSubscriptionDetailVo> detail(@RequestParam Long id){
+        TextbookSubscriptionDetailVo textbookSubscriptionDetailVo = textbookSubscriptionService.detail(id);
+        if (textbookSubscriptionDetailVo == null) {
+            return RT.error("找不到此数据!");
+        }
+        return RT.ok(textbookSubscriptionDetailVo);
+    }
+
+    @GetMapping(value = "/item-page")
+    @ApiOperation(value="教材教辅征订明细列表(分页)")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<PageOutput<TextbookSubscriptionItemPageVo>> itemPage(@Valid TextbookSubscriptionItemPageDto dto){
+        IPage<TextbookSubscriptionItemPageVo> page = textbookSubscriptionService.itemPage(dto);
+        PageOutput<TextbookSubscriptionItemPageVo> pageOutput = ConventPage.getPageOutput(page, TextbookSubscriptionItemPageVo.class);
+        return RT.ok(pageOutput);
+    }
+
+    @PostMapping
+    @ApiOperation(value = "新增教材教辅征订记录表")
+    @SaCheckPermission("textbooksubscription:add")
+    public RT<Boolean> add(@Valid @RequestBody AddTextbookSubscriptionDto dto){
+        TextbookSubscription textbookSubscription = BeanUtil.toBean(dto, TextbookSubscription.class);
+        boolean isSuccess = textbookSubscriptionService.add(textbookSubscription);
+    return RT.ok(isSuccess);
+    }
+
+    @PutMapping
+    @ApiOperation(value = "修改教材教辅征订记录表")
+    @SaCheckPermission("textbooksubscription:edit")
+    public RT<Boolean> update(@Valid @RequestBody UpdateTextbookSubscriptionDto dto){
+
+        TextbookSubscription textbookSubscription = BeanUtil.toBean(dto, TextbookSubscription.class);
+        return RT.ok(textbookSubscriptionService.update(textbookSubscription));
+
+    }
+
+    @PutMapping(value = "/change-status")
+    @ApiOperation(value = "修改征订状态")
+    @SaCheckPermission("textbooksubscription:edit")
+    public RT<Boolean> changeStatus(@Valid @RequestBody UpdateWfTextbookSubscriptionDto dto){
+        return RT.ok(textbookSubscriptionService.changeStatus(dto));
+    }
+
+    @PostMapping(value = "/instockroom")
+    @ApiOperation(value="手动填写入库")
+    @SaCheckPermission("textbooksubscription:detail")
+    public RT<Boolean> instockroom(@Valid @RequestBody  List<TextbookInstockroomDto> dtos){
+        return RT.ok(textbookSubscriptionService.instockroom(dtos));
+    }
+
+    @PostMapping("/instockroom-excel-import")
+    @ApiOperation(value = "导入入库")
+    public RT<String> excelImport(@RequestParam("file") MultipartFile file,  @RequestParam(value = "textbookSubscriptionId") Long textbookSubscriptionId) throws IOException {
+        InputStream inputStream = file.getInputStream();
+        return RT.ok(textbookSubscriptionService.instockroomExcelImport(inputStream, textbookSubscriptionId));
+    }
+
+    @DeleteMapping
+    @ApiOperation(value = "删除教材教辅征订记录表")
+    @SaCheckPermission("textbooksubscription:delete")
+    public RT<Boolean> delete(@Valid @RequestBody List<Long> ids){
+        return RT.ok(textbookSubscriptionService.delete(ids));
+    }
+
+    @PostMapping("/import")
+    @ApiOperation(value = "导入")
+    public RT<Boolean> importData(@RequestParam MultipartFile file) throws IOException {
+        List<TextbookSubscriptionListVo> savedDataList = EasyExcel.read(file.getInputStream()).head(TextbookSubscriptionListVo.class).sheet().doReadSync();
+        Boolean result = textbookSubscriptionService.saveBatch(BeanUtil.copyToList(savedDataList, TextbookSubscription.class));
+        return RT.ok(result);
+    }
+
+    @GetMapping("/export")
+    @ApiOperation(value = "导出")
+    public ResponseEntity<byte[]> exportData(@Valid TextbookSubscriptionListDto dto, @RequestParam(defaultValue = "false") Boolean isTemplate) {
+        List<TextbookSubscriptionListVo> customerList = (List<TextbookSubscriptionListVo>) list(dto).getData();
+        ByteArrayOutputStream bot = new ByteArrayOutputStream();
+        EasyExcel.write(bot, TextbookSubscriptionListVo.class).automaticMergeHead(false).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(customerList);
+
+        return RT.fileStream(bot.toByteArray(), "TextbookSubscription" + ExcelTypeEnum.XLSX.getValue());
+    }
+}

+ 0 - 1
src/main/java/com/xjrsoft/module/textbook/controller/TextbookWarehouseRecordController.java

@@ -69,7 +69,6 @@ public class TextbookWarehouseRecordController {
         return RT.ok(BeanUtil.toBean(textbookWarehouseRecord, TextbookWarehouseRecordVo.class));
     }
 
-
     @PostMapping
     @ApiOperation(value = "新增教材入库")
     @SaCheckPermission("textbookclasswarehouse:add")

+ 25 - 26
src/main/java/com/xjrsoft/module/textbook/controller/WfTextbookSubscriptionController.java

@@ -122,31 +122,31 @@ public class WfTextbookSubscriptionController {
         return RT.ok(pageOutput);
     }
 
-    @GetMapping(value = "/baseclass-page")
-    @ApiOperation(value="征订班级列表(分页)")
-    @SaCheckPermission("wftextbooksubscription:detail")
-    public RT<PageOutput<BaseclassPageVo>> baseclassPage(@Valid BaseclassPageDto dto){
-        if(dto.getClassIds() == null || dto.getClassIds().equals("")){
-            return RT.ok(null);
-        }
-        String classIds = dto.getClassIds();
-        String[] classIdArr = classIds.split(",");
-        List<String> classIdList = Arrays.asList(classIdArr);
-        MPJLambdaWrapper<BaseClass> baseClassMPJLambdaWrapper = new MPJLambdaWrapper<>();
-        baseClassMPJLambdaWrapper
-                .selectAs(BaseGrade::getName, BaseclassPageVo::getGradeIdCn)
-                .selectAs(XjrUser::getName, BaseclassPageVo::getTeacherIdCn)
-                .selectAs(BaseClassMajorSet::getTotalStudent, BaseclassPageVo::getTotalStudent)
-                .select(BaseClass.class,x -> VoToColumnUtil.fieldsToColumns(BaseclassPageVo.class).contains(x.getProperty()))
-                .leftJoin(BaseGrade.class, BaseGrade::getId, BaseClass::getGradeId)
-                .leftJoin(XjrUser.class, XjrUser::getId, BaseClass::getTeacherId)
-                .leftJoin(BaseClassMajorSet.class, BaseClassMajorSet::getClassId, BaseClass::getId)
-                .in(BaseClass::getId, classIdList)
-                ;
-        IPage<BaseclassPageVo> baseclassPageVos = baseClassService.selectJoinListPage(ConventPage.getPage(dto), BaseclassPageVo.class, baseClassMPJLambdaWrapper);
-        PageOutput<BaseclassPageVo> pageOutput = ConventPage.getPageOutput(baseclassPageVos, BaseclassPageVo.class);
-        return RT.ok(pageOutput);
-    }
+//    @GetMapping(value = "/baseclass-page")
+//    @ApiOperation(value="征订班级列表(分页)")
+//    @SaCheckPermission("wftextbooksubscription:detail")
+//    public RT<PageOutput<BaseclassPageVo>> baseclassPage(@Valid BaseclassPageDto dto){
+//        if(dto.getClassIds() == null || dto.getClassIds().equals("")){
+//            return RT.ok(null);
+//        }
+//        String classIds = dto.getClassIds();
+//        String[] classIdArr = classIds.split(",");
+//        List<String> classIdList = Arrays.asList(classIdArr);
+//        MPJLambdaWrapper<BaseClass> baseClassMPJLambdaWrapper = new MPJLambdaWrapper<>();
+//        baseClassMPJLambdaWrapper
+//                .selectAs(BaseGrade::getName, BaseclassPageVo::getGradeIdCn)
+//                .selectAs(XjrUser::getName, BaseclassPageVo::getTeacherIdCn)
+//                .selectAs(BaseClassMajorSet::getTotalStudent, BaseclassPageVo::getTotalStudent)
+//                .select(BaseClass.class,x -> VoToColumnUtil.fieldsToColumns(BaseclassPageVo.class).contains(x.getProperty()))
+//                .leftJoin(BaseGrade.class, BaseGrade::getId, BaseClass::getGradeId)
+//                .leftJoin(XjrUser.class, XjrUser::getId, BaseClass::getTeacherId)
+//                .leftJoin(BaseClassMajorSet.class, BaseClassMajorSet::getClassId, BaseClass::getId)
+//                .in(BaseClass::getId, classIdList)
+//                ;
+//        IPage<BaseclassPageVo> baseclassPageVos = baseClassService.selectJoinListPage(ConventPage.getPage(dto), BaseclassPageVo.class, baseClassMPJLambdaWrapper);
+//        PageOutput<BaseclassPageVo> pageOutput = ConventPage.getPageOutput(baseclassPageVos, BaseclassPageVo.class);
+//        return RT.ok(pageOutput);
+//    }
 
     @GetMapping(value = "/history-list")
     @ApiOperation(value="教材教辅征订历史列表(分页)")
@@ -219,7 +219,6 @@ public class WfTextbookSubscriptionController {
         return RT.ok(wfTextbookSubscriptionService.alteration(dto));
     }
 
-
     @PutMapping(value = "/change-status")
     @ApiOperation(value = "修改教材教辅征订状态")
     @SaCheckPermission("wftextbooksubscription:edit")

+ 5 - 0
src/main/java/com/xjrsoft/module/textbook/dto/AddTextbookSubscriptionDto.java

@@ -45,6 +45,11 @@ public class AddTextbookSubscriptionDto implements Serializable {
     */
     @ApiModelProperty("征订方式(1:按班级征订 2:按教材征订)")
     private Integer subscriptionMethod;
+    /**
+     * 按班级征订征订的班级主键(base_class)
+     */
+    @ApiModelProperty("按班级征订征订的班级主键(base_class)")
+    private String baseClassIds;
     /**
     * 征订教材总数
     */

+ 0 - 5
src/main/java/com/xjrsoft/module/textbook/dto/AddTextbookWarehouseRecordDto.java

@@ -18,11 +18,6 @@ public class AddTextbookWarehouseRecordDto implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    /**
-    * 序号
-    */
-    @ApiModelProperty("序号")
-    private Integer sortCode;
     /**
     * 教材管理编号
     */

+ 5 - 4
src/main/java/com/xjrsoft/module/textbook/dto/BaseclassPageDto.java

@@ -16,10 +16,11 @@ import lombok.Data;
 @Data
 public class BaseclassPageDto extends PageInput {
     /**
-     * 使用班级
+     * 主键编号
      */
     @ContentStyle(dataFormat = 49)
-    @ExcelProperty("使用班级")
-    @ApiModelProperty("使用班级")
-    private String classIds;
+    @ExcelProperty("主键编号")
+    @ApiModelProperty("主键编号")
+    private String id;
+
 }

+ 2 - 2
src/main/java/com/xjrsoft/module/textbook/dto/TextbookInstockroomDto.java

@@ -16,12 +16,12 @@ public class TextbookInstockroomDto {
      * 教材教辅征订编号
      */
     @ApiModelProperty("教材教辅征订编号")
-    private Long wfTextbookSubscriptionId;
+    private Long textbookSubscriptionId;
     /**
      * 教材教辅征订项编号
      */
     @ApiModelProperty("教材教辅征订项编号")
-    private Long id;
+    private Long textbookSubscriptionItemId;
     /**
      * 国际标准刊号
      */

+ 20 - 1
src/main/java/com/xjrsoft/module/textbook/dto/TextbookInstockroomListDto.java

@@ -1,5 +1,7 @@
 package com.xjrsoft.module.textbook.dto;
 
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
@@ -16,5 +18,22 @@ public class TextbookInstockroomListDto {
      * 教材教辅征订编号
      */
     @ApiModelProperty("教材教辅征订编号")
-    private Long wfTextbookSubscriptionId;
+    private Long textbookSubscriptionId;
+    /**
+     * 课程
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("课程")
+    @ApiModelProperty("课程")
+    private String courseName;
+    /**
+     * 书名
+     */
+    @ApiModelProperty("书名")
+    private String bookName;
+    /**
+     * 教材类型(xjr_dictionary_item[textbook_type])
+     */
+    @ApiModelProperty("教材类型(xjr_dictionary_item[textbook_type])")
+    private String textbookType;
 }

+ 18 - 0
src/main/java/com/xjrsoft/module/textbook/dto/TextbookInstockroomOnceListDto.java

@@ -0,0 +1,18 @@
+package com.xjrsoft.module.textbook.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+* @title: 教材管理分页查询入参
+* @Author szs
+* @Date: 2023-12-25
+* @Version 1.0
+*/
+@Data
+public class TextbookInstockroomOnceListDto extends TextbookInstockroomListDto {
+
+}

+ 47 - 0
src/main/java/com/xjrsoft/module/textbook/dto/TextbookSubscriptionItemPageDto.java

@@ -0,0 +1,47 @@
+package com.xjrsoft.module.textbook.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import com.xjrsoft.common.page.PageInput;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import java.util.Date;
+
+
+/**
+* @title: 教材征订记录详情表分页查询入参
+* @Author dzx
+* @Date: 2024-12-17
+* @Version 1.0
+*/
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class TextbookSubscriptionItemPageDto extends PageInput {
+
+    /**
+     * 教材教辅增订记录表主键(textbook_subscription)
+     */
+    @ApiModelProperty("教材教辅增订记录表主键(textbook_subscription)")
+    private Long textbookSubscriptionId;
+    /**
+     * 课程编号(base_course_subject)
+     */
+    @ApiModelProperty("课程编号(base_course_subject)")
+    private String courseSubjectIdCn;
+    /**
+     * 书名
+     */
+    @ApiModelProperty("书名")
+    private String bookName;
+    /**
+     * 教材分类(xjr_dictionary_item[textbook_type])
+     */
+    @ApiModelProperty("教材分类(xjr_dictionary_item[textbook_type])")
+    private String textbookType;
+}

+ 38 - 0
src/main/java/com/xjrsoft/module/textbook/dto/TextbookSubscriptionPageDto.java

@@ -0,0 +1,38 @@
+package com.xjrsoft.module.textbook.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import com.xjrsoft.common.page.PageInput;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+* @title: 教材教辅征订分页查询入参
+* @Author szs
+* @Date: 2024-06-04
+* @Version 1.0
+*/
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class TextbookSubscriptionPageDto extends PageInput {
+
+    /**
+     * 学期ID(base_semester)
+     */
+    @ApiModelProperty("学期ID(base_semester)")
+    private Long baseSemesterId;
+    /**
+     * 征订方式(1:结束 2:未结束)
+     */
+    @ApiModelProperty("征订方式(1:按班级征订 2:按教材征订)")
+    private Integer subscriptionMethod;
+    /**
+     * 主键编号
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("主键编号")
+    @ApiModelProperty("主键编号")
+    private String id;
+}

+ 33 - 0
src/main/java/com/xjrsoft/module/textbook/dto/UpdateTextbookSubscriptionDto.java

@@ -0,0 +1,33 @@
+package com.xjrsoft.module.textbook.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.io.Serializable;
+
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.List;
+import java.util.Date;
+import com.xjrsoft.module.textbook.entity.TextbookSubscriptionItem;
+
+
+
+/**
+* @title: 教材教辅征订记录表
+* @Author dzx
+* @Date: 2024-12-16
+* @Version 1.0
+*/
+@Data
+public class UpdateTextbookSubscriptionDto extends AddTextbookSubscriptionDto {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+    * 主键编号
+    */
+    @ApiModelProperty("主键编号")
+    private Long id;
+}

+ 5 - 0
src/main/java/com/xjrsoft/module/textbook/entity/TextbookSubscription.java

@@ -93,6 +93,11 @@ public class TextbookSubscription implements Serializable {
     */
     @ApiModelProperty("征订方式(1:按班级征订 2:按教材征订)")
     private Integer subscriptionMethod;
+    /**
+     * 按班级征订征订的班级主键(base_class)
+     */
+    @ApiModelProperty("按班级征订征订的班级主键(base_class)")
+    private String baseClassIds;
     /**
     * 征订教材总数
     */

+ 4 - 7
src/main/java/com/xjrsoft/module/textbook/service/ITextbookService.java

@@ -7,8 +7,10 @@ import com.xjrsoft.module.textbook.dto.*;
 import com.xjrsoft.module.textbook.entity.Textbook;
 import com.xjrsoft.module.textbook.entity.TextbookClassRelation;
 import com.xjrsoft.module.textbook.vo.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 
@@ -84,13 +86,6 @@ public interface ITextbookService extends MPJBaseService<Textbook> {
      */
     TextbookVo getInfoByissn(String issn);
 
-    /**
-     * 教材管理入库
-     * @param dto
-     * @return
-     */
-    Boolean deliverWarehouse(AddTextbookWarehouseRecordDto dto);
-
     /**
      * 入库记录
      * @param id
@@ -134,4 +129,6 @@ public interface ITextbookService extends MPJBaseService<Textbook> {
 //    Boolean excelImport(InputStream inputStream);
 
     IPage<TextbookSubscriptionListVo> getSubscriptionPageByClass(TextbookSubscriptionListDto dto);
+
+    String textbook(MultipartFile file) throws IOException, IllegalAccessException;
 }

+ 78 - 0
src/main/java/com/xjrsoft/module/textbook/service/ITextbookSubscriptionService.java

@@ -0,0 +1,78 @@
+package com.xjrsoft.module.textbook.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.yulichang.base.MPJBaseService;
+import com.xjrsoft.module.textbook.dto.*;
+import com.xjrsoft.module.textbook.entity.TextbookSubscription;
+import com.xjrsoft.module.textbook.vo.*;
+
+import java.io.InputStream;
+import java.util.List;
+
+/**
+* @title: 教材教辅征订记录表
+* @Author dzx
+* @Date: 2024-12-16
+* @Version 1.0
+*/
+
+public interface ITextbookSubscriptionService extends MPJBaseService<TextbookSubscription> {
+
+    /**
+     * 手搓证订分页
+     * @param dto
+     * @return
+     */
+    IPage<TextbookSubscriptionPageVo> pageRubAndHand(TextbookSubscriptionPageDto dto);
+
+    /**
+     * 入库页面
+     * @param dto
+     * @return
+     */
+    List<TextbookInstockroomListVo> instockroomList(TextbookInstockroomListDto dto);
+
+    List<TextbookInstockroomOnceListVo> everyInstockroomList(TextbookInstockroomOnceListDto dto);
+
+    TextbookSubscriptionVo infoRubAndHand(Long id);
+
+    TextbookSubscriptionDetailVo detail(Long id);
+
+    IPage<TextbookSubscriptionItemPageVo> itemPage(TextbookSubscriptionItemPageDto dto);
+
+    /**
+    * 新增
+    *
+    * @param textbookSubscription
+    * @return
+    */
+    Boolean add(TextbookSubscription textbookSubscription);
+
+    /**
+     * 入库
+     * @param dtos
+     * @return
+     */
+    Boolean instockroom(List<TextbookInstockroomDto> dtos);
+
+    String instockroomExcelImport(InputStream inputStream, Long textbookSubscriptionId);
+
+
+    /**
+    * 更新
+    *
+    * @param textbookSubscription
+    * @return
+    */
+    Boolean update(TextbookSubscription textbookSubscription);
+
+    Boolean changeStatus(UpdateWfTextbookSubscriptionDto dto);
+
+    /**
+    * 删除
+    *
+    * @param ids
+    * @return
+    */
+    Boolean delete(List<Long> ids);
+}

+ 1 - 0
src/main/java/com/xjrsoft/module/textbook/service/ITextbookWarehouseRecordService.java

@@ -2,6 +2,7 @@ package com.xjrsoft.module.textbook.service;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.yulichang.base.MPJBaseService;
+import com.xjrsoft.module.textbook.dto.AddTextbookWarehouseRecordDto;
 import com.xjrsoft.module.textbook.dto.TextbookWarehouseRecordExportDto;
 import com.xjrsoft.module.textbook.dto.TextbookWarehouseRecordPageDto;
 import com.xjrsoft.module.textbook.entity.TextbookWarehouseRecord;

+ 142 - 30
src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookServiceImpl.java

@@ -28,10 +28,13 @@ import com.xjrsoft.module.base.entity.BaseClassCourse;
 import com.xjrsoft.module.base.entity.BaseCourseSubject;
 import com.xjrsoft.module.base.entity.BaseSemester;
 import com.xjrsoft.module.base.mapper.BaseClassCourseMapper;
+import com.xjrsoft.module.base.mapper.BaseCourseSubjectMapper;
 import com.xjrsoft.module.base.mapper.BaseSemesterMapper;
 import com.xjrsoft.module.base.service.IBaseClassService;
 import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
 import com.xjrsoft.module.system.entity.DictionaryDetail;
+import com.xjrsoft.module.system.mapper.DictionarydetailMapper;
+import com.xjrsoft.module.system.mapper.DictionaryitemMapper;
 import com.xjrsoft.module.teacher.entity.XjrUser;
 import com.xjrsoft.module.textbook.dto.*;
 import com.xjrsoft.module.textbook.entity.*;
@@ -40,20 +43,27 @@ import com.xjrsoft.module.textbook.service.ITextbookService;
 import com.xjrsoft.module.textbook.service.ITextbookWarehouseRecordService;
 import com.xjrsoft.module.textbook.service.IWfExerciseBookService;
 import com.xjrsoft.module.textbook.vo.*;
+import com.xjrsoft.module.veb.util.ImportExcelUtil;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.ss.usermodel.BorderStyle;
 import org.apache.poi.ss.usermodel.HorizontalAlignment;
 import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
 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.*;
+import static com.xjrsoft.module.veb.util.ImportExcelUtil.validateAndSetString2LongField;
+
 /**
  * @title: 教材管理
  * @Author szs
@@ -83,6 +93,14 @@ public class TextbookServiceImpl extends MPJBaseServiceImpl<TextbookMapper, Text
 
     private final BaseClassCourseMapper baseClassCourseMapper;
 
+    private final DictionaryitemMapper dictionaryitemMapper;
+
+    private final DictionarydetailMapper dictionarydetailMapper;
+
+    private final SubjectGroupMapper subjectGroupMapper;
+
+    private final BaseCourseSubjectMapper baseCourseSubjectMapper;
+
     private final TextbookSubscriptionItemMapper textbookSubscriptionItemMapper;
 
     @Override
@@ -506,7 +524,6 @@ public class TextbookServiceImpl extends MPJBaseServiceImpl<TextbookMapper, Text
         List<TextbookClassRelation> classRelationList = textbookTextbookClassRelationMapper.selectList(
                 new QueryWrapper<TextbookClassRelation>().lambda().eq(TextbookClassRelation::getTextbookId, infoByissn.getId())
         );
-        infoByissn.setTextbookClassRelationList(BeanUtil.copyToList(classRelationList, TextbookClassRelationVo.class));
         return infoByissn;
     }
 
@@ -1093,38 +1110,133 @@ public class TextbookServiceImpl extends MPJBaseServiceImpl<TextbookMapper, Text
 //    }
 
     @Override
-    @Transactional
-    public Boolean deliverWarehouse(AddTextbookWarehouseRecordDto dto) {
-        //根据id获取教材管理记录
-        Textbook textbook = this.getById(dto.getTextbookId());
-        if (ObjectUtils.isEmpty(textbook)) {
-            throw new MyException("入库失败,该教材不存在");
+    @Transactional(rollbackFor = Exception.class)
+    public String textbook(MultipartFile file) throws IOException, IllegalAccessException {
+        List<TextbookImportDto> excelDataList = EasyExcel.read(file.getInputStream()).headRowNumber(3).head(TextbookImportDto.class).sheet().doReadSync();
+        StringBuilder sb = new StringBuilder();
+
+        List<String> codeList = new ArrayList<>();
+        codeList.add("textbook_type");
+        codeList.add("textbook_category");
+
+        Map<String, String> dictionary = ImportExcelUtil.initDictionary(codeList, dictionaryitemMapper, dictionarydetailMapper);
+
+        //查询所有需要的数据
+        //学科组
+        List<SubjectGroup> subjectGroupList = subjectGroupMapper.selectList(
+                Wrappers
+                        .lambdaQuery(SubjectGroup.class)
+                        .eq(SubjectGroup::getDeleteMark, DeleteMark.NODELETE.getCode()));
+        Map<String, Long> subjectGroupNameAndIdMap = subjectGroupList.stream().collect(Collectors.toMap(SubjectGroup::getGroupName, SubjectGroup::getId, (k1, k2) -> k1));
+
+        //使用课程
+        List<BaseCourseSubject> baseCourseSubjectList = baseCourseSubjectMapper.selectList(
+                Wrappers
+                        .lambdaQuery(BaseCourseSubject.class)
+                        .eq(BaseCourseSubject::getDeleteMark, DeleteMark.NODELETE.getCode())
+        );
+        Map<String, Long> baseCourseSubjectNameAndIdMap = baseCourseSubjectList.stream().collect(Collectors.toMap(BaseCourseSubject::getName, BaseCourseSubject::getId, (k1, k2) -> k1));
+
+        List<Textbook> insertTextbooks = new ArrayList<>();
+        List<Textbook> updateTextbooks = new ArrayList<>();
+        for (int i = 0; i < excelDataList.size(); i++) {
+            TextbookImportDto dto = excelDataList.get(i);
+            if (isRequiredFieldsFilled(dto,
+                    sb,
+                    i)) {
+                return sb.toString();
+            }
+
+            Textbook textbook = new Textbook();
+            BeanUtils.copyProperties(dto, textbook);
+
+            // 验证字段的合理性
+            // 字典类型
+            if (validateAndSetDictionaryField(dto::getTextbookTypeCn,
+                    "textbook_type",
+                    "教材分类(教材、辅材、作业本)",
+                    dictionary,
+                    textbook::setTextbookType,
+                    sb,
+                    i)) {
+                return sb.toString();
+            }
+            if (validateAndSetDictionaryField(dto::getTextbookCategory,
+                    "textbook_category",
+                    "教材类型(纸质教材、数字教材、纸质与数字资源结合教材)",
+                    dictionary,
+                    textbook::setTextbookCategory,
+                    sb,
+                    i)) {
+                return sb.toString();
+            }
+
+            // 关联表
+            if (validateAndSetString2LongField(dto::getGroupName,
+                    "学科组(必须是系统中已有的学科组名称)",
+                    subjectGroupNameAndIdMap,
+                    textbook::setSubjectGroupId,
+                    sb,
+                    i
+            )) {
+                return sb.toString();
+            }
+            if (validateAndSetString2LongField(dto::getCourseName,
+                    "对应课程(必须是系统中已有的课程名称)",
+                    baseCourseSubjectNameAndIdMap,
+                    textbook::setCourseSubjectId,
+                    sb,
+                    i
+            )) {
+                return sb.toString();
+            }
+
+            // 处理是否教材计划字段
+            String isTextbookPlanCn = dto.getIsTextbookPlanCn();
+            Integer isTextbookPlan = Optional.ofNullable(isTextbookPlanCn)
+                    .filter("是"::equals)
+                    .map(s -> 1)
+                    .orElse(0);
+            textbook.setIsTextbookPlan(isTextbookPlan);
+
+            String isSecd = dto.getIsSecd();
+            Integer isSecdI = Optional.ofNullable(isSecd)
+                    .filter("是"::equals)
+                    .map(s -> 1)
+                    .orElse(0);
+            textbook.setIsSecd(isSecdI);
+
+            // 判断导入的教材是否已经存在,根据教材的 ISSN 码和使用的学科组和课程判断
+            LambdaQueryWrapper<Textbook> textbookLambdaQueryWrapper = new LambdaQueryWrapper<>();
+            textbookLambdaQueryWrapper
+                    .eq(Textbook::getIssn, textbook.getIssn())
+                    .eq(Textbook::getSubjectGroupId, textbook.getSubjectGroupId())
+                    .eq(Textbook::getCourseSubjectId, textbook.getCourseSubjectId())
+                    .eq(Textbook::getDeleteMark, DeleteMark.NODELETE.getCode())
+            ;
+
+            Textbook verifyTextbook = this.getOne(textbookLambdaQueryWrapper);
+            if(ObjectUtils.isNotEmpty(verifyTextbook)){
+                textbook.setId(verifyTextbook.getId());
+                updateTextbooks.add(textbook);
+            }else {
+                insertTextbooks.add(textbook);
+            }
         }
 
-//        BigDecimal price = ObjectUtil.isNull(dto.getPrice()) ? new BigDecimal(0) : dto.getPrice();
-//        double discount = ObjectUtil.isNull(dto.getDiscount()) ? 10 : dto.getDiscount();
-//        BigDecimal subtotal = price.multiply(new BigDecimal(discount / 10));
-        //更新总的库存数量
-        this.updateById(new Textbook() {
-            {
-                setId(textbook.getId());
-//                setPrice(price);
-//                setDiscount(discount);
-//                setSubtotal(subtotal);
-                setModifyDate(new Date());
+        //批量新增
+        if (!insertTextbooks.isEmpty()) {
+            for (Textbook textbook : insertTextbooks) {
+                this.save(textbook);
             }
-        });
-        //添加入库记录
-        TextbookWarehouseRecord textbookWarehouseRecord = BeanUtil.toBean(dto, TextbookWarehouseRecord.class);
-        textbookWarehouseRecord.setWarehouseMode(WarehouseModeEnum.WmManual.getCode());
-        textbookWarehouseRecord.setDiscount(textbook.getDiscount());
-        textbookWarehouseRecord.setCreateDate(new Date());
-        QueryWrapper<TextbookWarehouseRecord> queryWrapperSortcode = new QueryWrapper<>();
-        queryWrapperSortcode.select("IFNULL(MAX(sort_code),0) as sortCode");
-        TextbookWarehouseRecord t = textbookClassWarehouseService.getOne(queryWrapperSortcode);
-        textbookWarehouseRecord.setSortCode(t.getSortCode() + 1);
-        textbookClassWarehouseService.save(textbookWarehouseRecord);
+        }
 
-        return true;
+        //批量修改
+        if (!updateTextbooks.isEmpty()) {
+            for (Textbook textbook : updateTextbooks) {
+                this.updateById(textbook);
+            }
+        }
+        return sb.toString();
     }
 }

+ 483 - 0
src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookSubscriptionServiceImpl.java

@@ -0,0 +1,483 @@
+package com.xjrsoft.module.textbook.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.yulichang.base.MPJBaseServiceImpl;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.enums.DeleteMark;
+import com.xjrsoft.common.enums.WarehouseModeEnum;
+import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.common.page.ConventPage;
+import com.xjrsoft.common.utils.VoToColumnUtil;
+import com.xjrsoft.module.base.entity.BaseCourseSubject;
+import com.xjrsoft.module.base.entity.BaseSemester;
+import com.xjrsoft.module.base.entity.CourseSubjectDetail;
+import com.xjrsoft.module.system.entity.DictionaryDetail;
+import com.xjrsoft.module.textbook.dto.*;
+import com.xjrsoft.module.textbook.entity.*;
+import com.xjrsoft.module.textbook.mapper.TextbookSubscriptionClassMapper;
+import com.xjrsoft.module.textbook.mapper.TextbookSubscriptionItemMapper;
+import com.xjrsoft.module.textbook.mapper.TextbookSubscriptionMapper;
+import com.xjrsoft.module.textbook.mapper.TextbookWarehouseRecordMapper;
+import com.xjrsoft.module.textbook.service.ITextbookSubscriptionService;
+import com.xjrsoft.module.textbook.service.ITextbookWarehouseRecordService;
+import com.xjrsoft.module.textbook.vo.*;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * @title: 教材教辅征订记录表
+ * @Author dzx
+ * @Date: 2024-12-16
+ * @Version 1.0
+ */
+@Service
+@AllArgsConstructor
+public class TextbookSubscriptionServiceImpl extends MPJBaseServiceImpl<TextbookSubscriptionMapper, TextbookSubscription> implements ITextbookSubscriptionService {
+
+    private final TextbookSubscriptionMapper textbookSubscriptionTextbookSubscriptionMapper;
+
+    private final TextbookSubscriptionItemMapper textbookSubscriptionTextbookSubscriptionItemMapper;
+
+    private final TextbookSubscriptionClassMapper textbookSubscriptionClassMapper;
+
+    private final TextbookSubscriptionClassMapper textbookService;
+
+    private final TextbookWarehouseRecordMapper textbookWarehouseRecordMapper;
+
+    @Override
+    public IPage<TextbookSubscriptionPageVo> pageRubAndHand(TextbookSubscriptionPageDto dto) {
+        MPJLambdaWrapper<TextbookSubscription> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper
+                .select(TextbookSubscription::getId)
+                .selectAs(BaseSemester::getName, TextbookSubscriptionPageVo::getBaseSemesterIdCn)
+                .select(TextbookSubscription.class, x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionPageVo.class).contains(x.getProperty()))
+                .leftJoin(BaseSemester.class, BaseSemester::getId, TextbookSubscription::getBaseSemesterId)
+                .eq(dto.getBaseSemesterId() != null && dto.getBaseSemesterId() > 0, TextbookSubscription::getBaseSemesterId, dto.getBaseSemesterId())
+                .eq(dto.getSubscriptionMethod() != null && dto.getSubscriptionMethod() > 0, TextbookSubscription::getSubscriptionMethod, dto.getSubscriptionMethod())
+                .eq(StringUtils.isNotBlank(dto.getId()), TextbookSubscription::getId, dto.getId())
+                .orderByDesc(TextbookSubscription::getCreateDate)
+        ;
+        IPage<TextbookSubscriptionPageVo> page = this.selectJoinListPage(ConventPage.getPage(dto), TextbookSubscriptionPageVo.class, queryWrapper);
+        return page;
+    }
+
+    @Override
+    public List<TextbookInstockroomListVo> instockroomList(TextbookInstockroomListDto dto) {
+        MPJLambdaWrapper<TextbookSubscriptionItem> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper
+                .select(TextbookSubscriptionItem::getId)
+                .select(Textbook.class, x -> VoToColumnUtil.fieldsToColumns(TextbookInstockroomListVo.class).contains(x.getProperty()))
+                .select(TextbookSubscriptionItem.class, x -> VoToColumnUtil.fieldsToColumns(TextbookInstockroomListVo.class).contains(x.getProperty()))
+                .leftJoin(Textbook.class, Textbook::getId, TextbookSubscriptionItem::getTextbookId)
+                .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, Textbook::getCourseSubjectId,
+                        wrapper -> wrapper
+                                .selectAs(BaseCourseSubject::getName, TextbookInstockroomListVo::getCourseName)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Textbook::getTextbookType,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, TextbookInstockroomListVo::getTextbookTypeCn)
+                )
+                .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, dto.getTextbookSubscriptionId())
+                .orderByAsc(TextbookSubscriptionItem::getInStockNum)
+        ;
+
+        return textbookSubscriptionTextbookSubscriptionItemMapper.selectJoinList(TextbookInstockroomListVo.class, queryWrapper);
+    }
+
+    @Override
+    public List<TextbookInstockroomOnceListVo> everyInstockroomList(TextbookInstockroomOnceListDto dto) {
+        MPJLambdaWrapper<TextbookSubscriptionItem> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper
+                .select(TextbookSubscriptionItem::getId)
+                .select(Textbook.class, x -> VoToColumnUtil.fieldsToColumns(TextbookInstockroomOnceListVo.class).contains(x.getProperty()))
+                .select(TextbookSubscriptionItem.class, x -> VoToColumnUtil.fieldsToColumns(TextbookInstockroomOnceListVo.class).contains(x.getProperty()))
+                .leftJoin(Textbook.class, Textbook::getId, TextbookSubscriptionItem::getTextbookId)
+                .leftJoin(TextbookWarehouseRecord.class, TextbookWarehouseRecord::getDataItemId, TextbookSubscriptionItem::getId,
+                        wrapper -> wrapper
+                                .selectAs(TextbookWarehouseRecord::getWarehouseNumber, TextbookInstockroomOnceListVo::getOnceInStockNum)
+                                .selectAs(TextbookWarehouseRecord::getCreateDate, TextbookInstockroomOnceListVo::getCreateDate)
+                                .selectAs(TextbookWarehouseRecord::getCreateUserId, TextbookInstockroomOnceListVo::getCreateUserId)
+                )
+                .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, Textbook::getCourseSubjectId,
+                        wrapper -> wrapper
+                                .selectAs(BaseCourseSubject::getName, TextbookInstockroomOnceListVo::getCourseName)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Textbook::getTextbookType,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, TextbookInstockroomOnceListVo::getTextbookTypeCn)
+                )
+                .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, dto.getTextbookSubscriptionId())
+                .orderByAsc(TextbookSubscriptionItem::getInStockNum)
+        ;
+
+        return textbookSubscriptionTextbookSubscriptionItemMapper.selectJoinList(TextbookInstockroomOnceListVo.class, queryWrapper);
+    }
+
+    @Override
+    public TextbookSubscriptionVo infoRubAndHand(Long id) {
+        TextbookSubscription textbookSubscription = this.getById(id);
+        TextbookSubscriptionVo textbookSubscriptionVo = BeanUtil.toBean(textbookSubscription, TextbookSubscriptionVo.class);
+
+        MPJLambdaWrapper<TextbookSubscriptionItem> textbookSubscriptionItemMPJLambdaWrapper = new MPJLambdaWrapper<>();
+        textbookSubscriptionItemMPJLambdaWrapper
+                .select(TextbookSubscriptionItem::getId)
+                .select(TextbookSubscriptionItem.class,x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionItemVo.class).contains(x.getProperty()))
+                .leftJoin(Textbook.class, Textbook::getId, TextbookSubscriptionItem::getTextbookId,
+                        wrapper -> wrapper
+                                .select(Textbook.class,x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionItemVo.class).contains(x.getProperty()))
+                                .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, Textbook::getCourseSubjectId,
+                                        wp -> wp
+                                                .selectAs(BaseCourseSubject::getName, TextbookSubscriptionItemVo::getCourseSubjectIdCn)
+                                )
+                                .leftJoin(DictionaryDetail.class, DictionaryDetail::getId, Textbook::getTextbookType,
+                                        wp -> wp
+                                                .selectAs(DictionaryDetail::getName, TextbookSubscriptionItemVo::getTextbookTypeCn)
+                                )
+                )
+                .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, id)
+        ;
+        List<TextbookSubscriptionItemVo> list = textbookSubscriptionTextbookSubscriptionItemMapper.selectJoinList(TextbookSubscriptionItemVo.class, textbookSubscriptionItemMPJLambdaWrapper);
+
+        textbookSubscriptionVo.setTextbookSubscriptionItemList(list);
+        return textbookSubscriptionVo;
+    }
+
+    @Override
+    public TextbookSubscriptionDetailVo detail(Long id) {
+        TextbookSubscription textbookSubscription = this.getById(id);
+        if (ObjectUtils.isEmpty(textbookSubscription)) {
+            throw new MyException("证订记录被修改,请刷新重试");
+        }
+
+        // 获取所有的证订项目
+        LambdaQueryWrapper<TextbookSubscriptionItem> subscriptionItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        subscriptionItemLambdaQueryWrapper
+                .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, id)
+                .eq(TextbookSubscriptionItem::getDeleteMark, DeleteMark.NODELETE.getCode())
+        ;
+        List<TextbookSubscriptionItem> textbookSubscriptionItemList = textbookSubscriptionTextbookSubscriptionItemMapper.selectList(subscriptionItemLambdaQueryWrapper);
+        int stuNum = 0;
+        int teaNum = 0;
+        BigDecimal totalPrice = BigDecimal.valueOf(0);
+        for (TextbookSubscriptionItem textbookSubscriptionItem : textbookSubscriptionItemList) {
+            stuNum += textbookSubscriptionItem.getStudentNum();
+            teaNum += textbookSubscriptionItem.getTeacherNum();
+
+            totalPrice.add(textbookSubscriptionItem.getPrice()
+                            .multiply(BigDecimal.valueOf(textbookSubscriptionItem.getDiscount()))
+                            .divide(BigDecimal.valueOf(10))
+                            .multiply(BigDecimal.valueOf(textbookSubscriptionItem.getTeacherNum() + textbookSubscriptionItem.getStudentNum())));
+
+        }
+        TextbookSubscriptionDetailVo textbookSubscriptionDetailVo = new TextbookSubscriptionDetailVo();
+        textbookSubscriptionDetailVo.setId(String.valueOf(id));
+        textbookSubscriptionDetailVo.setStudentTatolNum(stuNum);
+        textbookSubscriptionDetailVo.setTeacherTatolNum(teaNum);
+        textbookSubscriptionDetailVo.setSum(stuNum + teaNum);
+        textbookSubscriptionDetailVo.setSumPrice(totalPrice);
+        return textbookSubscriptionDetailVo;
+    }
+
+    @Override
+    public IPage<TextbookSubscriptionItemPageVo> itemPage(TextbookSubscriptionItemPageDto dto) {
+        MPJLambdaWrapper<TextbookSubscriptionItem> textbookSubscriptionItemMPJLambdaWrapper = new MPJLambdaWrapper<>();
+        textbookSubscriptionItemMPJLambdaWrapper
+                .select(TextbookSubscriptionItem::getId)
+                .select(TextbookSubscriptionItem.class,x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionItemPageVo.class).contains(x.getProperty()))
+                .leftJoin(Textbook.class, Textbook::getId, TextbookSubscriptionItem::getTextbookId,
+                        wrapper -> wrapper
+                                .select(Textbook.class,x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionItemPageVo.class).contains(x.getProperty()))
+                                .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, Textbook::getCourseSubjectId,
+                                        wp -> wp
+                                                .selectAs(BaseCourseSubject::getName, TextbookSubscriptionItemPageVo::getCourseSubjectIdCn)
+                                                .like(StringUtils.isNotBlank(dto.getCourseSubjectIdCn()), BaseCourseSubject::getName, dto.getCourseSubjectIdCn())
+                                )
+                                .leftJoin(DictionaryDetail.class, DictionaryDetail::getId, Textbook::getTextbookType,
+                                        wp -> wp
+                                                .selectAs(DictionaryDetail::getName, TextbookSubscriptionItemPageVo::getTextbookTypeCn)
+                                )
+                                .like(StringUtils.isNotBlank(dto.getBookName()), Textbook::getBookName, dto.getBookName())
+                                .eq(StringUtils.isNotBlank(dto.getTextbookType()), Textbook::getTextbookType, dto.getTextbookType())
+                        )
+                .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, dto.getTextbookSubscriptionId())
+                ;
+        IPage<TextbookSubscriptionItemPageVo> page = textbookSubscriptionTextbookSubscriptionItemMapper.selectJoinPage(ConventPage.getPage(dto), TextbookSubscriptionItemPageVo.class, textbookSubscriptionItemMPJLambdaWrapper);
+        return page;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean add(TextbookSubscription textbookSubscription) {
+        // 处理征订表
+        int sum = 0;
+        for (TextbookSubscriptionItem textbookSubscriptionItem : textbookSubscription.getTextbookSubscriptionItemList()) {
+            sum += textbookSubscriptionItem.getStudentNum() + textbookSubscriptionItem.getTeacherNum();
+        }
+        textbookSubscriptionTextbookSubscriptionMapper.insert(textbookSubscription);
+
+        // 处理征订和班级关联表
+        if (ObjectUtils.isNotEmpty(textbookSubscription.getSubscriptionMethod())
+                && textbookSubscription.getSubscriptionMethod() == 1
+                && StringUtils.isNotBlank(textbookSubscription.getBaseClassIds())
+        ) {
+            String[] classIdArr = textbookSubscription.getBaseClassIds().split(",");
+            List<String> classIdList = Arrays.asList(classIdArr);
+            for (String str : classIdList) {
+                TextbookSubscriptionClass textbookSubscriptionClass = new TextbookSubscriptionClass();
+                textbookSubscriptionClass.setTextbookSubscriptionId(textbookSubscription.getId());
+                textbookSubscriptionClass.setBaseClassId(Long.parseLong(str));
+                textbookSubscriptionClassMapper.insert(textbookSubscriptionClass);
+            }
+        }
+
+        // 处理征订表子表
+        for (TextbookSubscriptionItem textbookSubscriptionItem : textbookSubscription.getTextbookSubscriptionItemList()) {
+            textbookSubscriptionItem.setTextbookSubscriptionId(textbookSubscription.getId());
+            textbookSubscriptionTextbookSubscriptionItemMapper.insert(textbookSubscriptionItem);
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean instockroom(List<TextbookInstockroomDto> dtos) {
+        if (dtos.isEmpty()) {
+            return false;
+        }
+
+        List<Long> textbookSubscriptionItemIds = new ArrayList<>();
+        for (TextbookInstockroomDto dto : dtos) {
+            textbookSubscriptionItemIds.add(dto.getTextbookSubscriptionItemId());
+        }
+
+        if (textbookSubscriptionItemIds.isEmpty()) {
+            throw new MyException("请选择需要入库的教材");
+        }
+
+        //获取需要修改的list
+        MPJLambdaWrapper<TextbookSubscriptionItem> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper
+                .select(TextbookSubscriptionItem::getId)
+                .select(TextbookSubscriptionItem.class, x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionItem.class).contains(x.getProperty()))
+                .leftJoin(Textbook.class, Textbook::getId, TextbookSubscriptionItem::getTextbookId)
+                .eq(TextbookSubscriptionItem::getId, textbookSubscriptionItemIds)
+                .eq(TextbookSubscriptionItem::getDeleteMark, DeleteMark.NODELETE.getCode())
+        ;
+        List<TextbookSubscriptionItem> textbookSubscriptionItemList = textbookSubscriptionTextbookSubscriptionItemMapper.selectJoinList(TextbookSubscriptionItem.class, queryWrapper);
+
+        if (textbookSubscriptionItemList.isEmpty()) {
+            throw new MyException("证订信息已经修改,请刷新重试");
+        }
+
+        Map<Long, TextbookSubscriptionItem> itemByIdMap = new HashMap<>();
+        for (TextbookSubscriptionItem el : textbookSubscriptionItemList) {
+            itemByIdMap.put(el.getId(), el);
+        }
+
+        for (TextbookInstockroomDto dto : dtos) {
+            TextbookSubscriptionItem old = null;
+            if (dto.getTextbookSubscriptionItemId() != null && dto.getTextbookSubscriptionItemId() > 0) {
+                old = itemByIdMap.get(dto.getTextbookSubscriptionItemId());
+            }
+
+            if (old == null) {
+                continue;
+            }
+
+            TextbookSubscriptionItem updateItem = new TextbookSubscriptionItem();
+            updateItem.setId(old.getId());
+            updateItem.setInStockNum(old.getInStockNum() + dto.getInNum());
+            textbookSubscriptionTextbookSubscriptionItemMapper.updateById(updateItem);
+
+            //新增入库记录
+            TextbookWarehouseRecord textbookWarehouseRecord = new TextbookWarehouseRecord();
+            textbookWarehouseRecord.setTextbookId(old.getTextbookId());
+            textbookWarehouseRecord.setDataId(dto.getTextbookSubscriptionId());
+            textbookWarehouseRecord.setDataItemId(dto.getTextbookSubscriptionItemId());
+            textbookWarehouseRecord.setWarehouseNumber(dto.getInNum());
+            textbookWarehouseRecord.setWarehouseMode(WarehouseModeEnum.WmManual.getCode());
+            textbookWarehouseRecordMapper.insert(textbookWarehouseRecord);
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String instockroomExcelImport(InputStream inputStream, Long textbookSubscriptionId) {
+        AtomicReference<Map<String, Object>> atomicMap = new AtomicReference<>(new HashMap<>());
+        List<Map<Integer, Object>> excalDataList = EasyExcel.read(inputStream).sheet().headRowNumber(1).doReadSync();
+        String regex = "\\d+";
+        Pattern pattern = Pattern.compile(regex);
+        List<TextbookInstockroomImportDto> dataList = new ArrayList<>();
+        for (Map<Integer, Object> integerObjectMap : excalDataList) {
+            Matcher matcher = pattern.matcher(integerObjectMap.get(11).toString());
+            int inNum = 0;
+            if (matcher.find()) {
+                inNum = Integer.parseInt(integerObjectMap.get(11).toString());
+            }
+            TextbookInstockroomImportDto importDto = new TextbookInstockroomImportDto();
+            importDto.setInNum(inNum);
+            importDto.setIssn(integerObjectMap.get(2).toString());
+            dataList.add(importDto);
+        }
+
+        //获取需要修改的list
+        MPJLambdaWrapper<TextbookSubscriptionItem> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper
+                .select(TextbookSubscriptionItem::getId)
+                .selectAs(Textbook::getIssn, TextbookSubscriptionItemVo::getIssn)
+                .select(TextbookSubscriptionItem.class, x -> VoToColumnUtil.fieldsToColumns(TextbookSubscriptionItemVo.class).contains(x.getProperty()))
+                .leftJoin(Textbook.class, Textbook::getId, TextbookSubscriptionItem::getTextbookId)
+                .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, textbookSubscriptionId)
+                .eq(TextbookSubscriptionItem::getDeleteMark, DeleteMark.NODELETE.getCode())
+        ;
+        List<TextbookSubscriptionItemVo> textbookSubscriptionItemVos = textbookSubscriptionTextbookSubscriptionItemMapper.selectJoinList(TextbookSubscriptionItemVo.class, queryWrapper);
+
+        if (textbookSubscriptionItemVos.isEmpty()) {
+            return null;
+        }
+
+        Map<String, TextbookSubscriptionItemVo> itemByIssnMap = new HashMap<>();
+        for (TextbookSubscriptionItemVo el : textbookSubscriptionItemVos) {
+            itemByIssnMap.put(el.getIssn(), el);
+        }
+
+        int successNum = 0;
+        int instockroomNum = 0;
+        for (TextbookInstockroomImportDto item : dataList) {
+            if (StringUtils.isBlank(item.getIssn())) {
+                continue;
+            }
+            TextbookSubscriptionItemVo old = itemByIssnMap.get(item.getIssn());
+            if (old == null) {
+                continue;
+            }
+
+            TextbookSubscriptionItem updateItem = new TextbookSubscriptionItem();
+            updateItem.setId(old.getId());
+            updateItem.setInStockNum(old.getInStockNum() + item.getInNum());
+            textbookSubscriptionTextbookSubscriptionItemMapper.updateById(updateItem);
+
+            //新增入库记录
+            TextbookWarehouseRecord textbookWarehouseRecord = new TextbookWarehouseRecord();
+            textbookWarehouseRecord.setTextbookId(old.getTextbookId());
+            textbookWarehouseRecord.setDataId(textbookSubscriptionId);
+            textbookWarehouseRecord.setDataItemId(old.getId());
+            textbookWarehouseRecord.setWarehouseNumber(item.getInNum());
+            textbookWarehouseRecord.setWarehouseMode(WarehouseModeEnum.WmManual.getCode());
+            textbookWarehouseRecordMapper.insert(textbookWarehouseRecord);
+            successNum++;
+            successNum += item.getInNum();
+        }
+        return "成功入库" + successNum + "样,成功入库" + successNum + "本";
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean update(TextbookSubscription textbookSubscription) {
+        textbookSubscriptionTextbookSubscriptionMapper.updateById(textbookSubscription);
+        //********************************* TextbookSubscriptionItem  增删改  开始 *******************************************/
+        {
+            // 查出所有子级的id
+            List<TextbookSubscriptionItem> textbookSubscriptionItemList = textbookSubscriptionTextbookSubscriptionItemMapper.selectList(
+                    Wrappers.lambdaQuery(TextbookSubscriptionItem.class)
+                            .eq(TextbookSubscriptionItem::getTextbookSubscriptionId, textbookSubscription.getId())
+                            .select(TextbookSubscriptionItem::getId));
+            List<Long> textbookSubscriptionItemIds = textbookSubscriptionItemList.stream()
+                    .map(TextbookSubscriptionItem::getId)
+                    .collect(Collectors.toList());
+            //原有子表单 没有被删除的主键
+            List<Long> textbookSubscriptionItemOldIds = textbookSubscription.getTextbookSubscriptionItemList().stream()
+                    .map(TextbookSubscriptionItem::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            //找到需要删除的id
+            List<Long> textbookSubscriptionItemRemoveIds = textbookSubscriptionItemIds.stream()
+                    .filter(item -> !textbookSubscriptionItemOldIds.contains(item))
+                    .collect(Collectors.toList());
+
+            for (TextbookSubscriptionItem textbookSubscriptionItem : textbookSubscription.getTextbookSubscriptionItemList()) {
+                //如果不等于空则修改
+                if (textbookSubscriptionItem.getId() != null) {
+                    textbookSubscriptionTextbookSubscriptionItemMapper.updateById(textbookSubscriptionItem);
+                }
+                //如果等于空 则新增
+                else {
+                    //已经不存在的id 删除
+                    textbookSubscriptionItem.setTextbookSubscriptionId(textbookSubscription.getId());
+                    textbookSubscriptionTextbookSubscriptionItemMapper.insert(textbookSubscriptionItem);
+                }
+            }
+            //已经不存在的id 删除
+            if (textbookSubscriptionItemRemoveIds.size() > 0) {
+                textbookSubscriptionTextbookSubscriptionItemMapper.deleteBatchIds(textbookSubscriptionItemRemoveIds);
+            }
+        }
+        //********************************* TextbookSubscriptionItem  增删改  结束 *******************************************/
+
+        //********************************* TextbookSubscriptionClass  增删改  开始 *******************************************/
+        LambdaUpdateWrapper<TextbookSubscriptionClass> textbookSubscriptionClassLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+        textbookSubscriptionClassLambdaUpdateWrapper
+                .eq(TextbookSubscriptionClass::getTextbookSubscriptionId, textbookSubscription.getId())
+        ;
+        textbookSubscriptionClassMapper.delete(textbookSubscriptionClassLambdaUpdateWrapper);
+
+        if (ObjectUtils.isNotEmpty(textbookSubscription.getSubscriptionMethod())
+                && textbookSubscription.getSubscriptionMethod() == 1
+                && StringUtils.isNotBlank(textbookSubscription.getBaseClassIds())
+        ) {
+            String[] classIdArr = textbookSubscription.getBaseClassIds().split(",");
+            List<String> classIdList = Arrays.asList(classIdArr);
+            for (String str : classIdList) {
+                TextbookSubscriptionClass textbookSubscriptionClass = new TextbookSubscriptionClass();
+                textbookSubscriptionClass.setTextbookSubscriptionId(textbookSubscription.getId());
+                textbookSubscriptionClass.setBaseClassId(Long.parseLong(str));
+                textbookSubscriptionClassMapper.insert(textbookSubscriptionClass);
+            }
+        }
+        //********************************* TextbookSubscriptionClass  增删改  结束 *******************************************/
+
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean changeStatus(UpdateWfTextbookSubscriptionDto dto) {
+        TextbookSubscription textbookSubscription = this.getById(dto.getId());
+        if (textbookSubscription == null) {
+            return false;
+        }
+
+        TextbookSubscription newT = new TextbookSubscription();
+        newT.setId(textbookSubscription.getId());
+        newT.setStatus(dto.getStatus());
+
+        return this.updateById(newT);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean delete(List<Long> ids) {
+        textbookSubscriptionTextbookSubscriptionMapper.deleteBatchIds(ids);
+        textbookSubscriptionTextbookSubscriptionItemMapper.delete(Wrappers.lambdaQuery(TextbookSubscriptionItem.class).in(TextbookSubscriptionItem::getTextbookSubscriptionId, ids));
+        textbookSubscriptionClassMapper.delete(Wrappers.lambdaQuery(TextbookSubscriptionClass.class).in(TextbookSubscriptionClass::getTextbookSubscriptionId, ids));
+        return true;
+    }
+}

+ 12 - 0
src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookWarehouseRecordServiceImpl.java

@@ -1,16 +1,26 @@
 package com.xjrsoft.module.textbook.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.yulichang.base.MPJBaseServiceImpl;
+import com.xjrsoft.common.enums.WarehouseModeEnum;
+import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.module.textbook.dto.AddTextbookWarehouseRecordDto;
 import com.xjrsoft.module.textbook.dto.TextbookWarehouseRecordExportDto;
 import com.xjrsoft.module.textbook.dto.TextbookWarehouseRecordPageDto;
+import com.xjrsoft.module.textbook.entity.Textbook;
 import com.xjrsoft.module.textbook.entity.TextbookWarehouseRecord;
+import com.xjrsoft.module.textbook.mapper.TextbookMapper;
 import com.xjrsoft.module.textbook.mapper.TextbookWarehouseRecordMapper;
 import com.xjrsoft.module.textbook.service.ITextbookWarehouseRecordService;
 import com.xjrsoft.module.textbook.vo.TextbookWarehouseRecordPageVo;
 import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -22,7 +32,9 @@ import java.util.List;
 @Service
 @AllArgsConstructor
 public class TextbookWarehouseRecordServiceImpl extends MPJBaseServiceImpl<TextbookWarehouseRecordMapper, TextbookWarehouseRecord> implements ITextbookWarehouseRecordService {
+
     private final TextbookWarehouseRecordMapper textbookWarehouseRecordMapper;
+
     @Override
     public Page<TextbookWarehouseRecordPageVo> getPage(Page<TextbookWarehouseRecordPageDto> page, TextbookWarehouseRecordPageDto dto) {
         return textbookWarehouseRecordMapper.getPage(page, dto);

+ 11 - 11
src/main/java/com/xjrsoft/module/textbook/service/impl/WfTextbookSubscriptionServiceImpl.java

@@ -346,7 +346,7 @@ public class WfTextbookSubscriptionServiceImpl extends MPJBaseServiceImpl<WfText
                 .leftJoin(Textbook.class, Textbook::getId, WfTextbookSubscriptionItem::getTextbookId)
                 .leftJoin(BaseCourseSubject.class, BaseCourseSubject::getId, Textbook::getCourseSubjectId)
                 .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Textbook::getTextbookType)
-                .eq(WfTextbookSubscriptionItem::getWfTextbookSubscriptionId, dto.getWfTextbookSubscriptionId())
+                .eq(WfTextbookSubscriptionItem::getWfTextbookSubscriptionId, dto.getTextbookSubscriptionId())
                 .orderByAsc(WfTextbookSubscriptionItem::getInStockroomNum)
         ;
 
@@ -386,7 +386,7 @@ public class WfTextbookSubscriptionServiceImpl extends MPJBaseServiceImpl<WfText
         List<TextbookInstockroomDto> textbookInstockroomDtoList = new ArrayList<>();
         for (TextbookInstockroomImportDto item : dataList){
             textbookInstockroomDtoList.add(new TextbookInstockroomDto(){{
-                setWfTextbookSubscriptionId(wfTextbookSubscriptionId);
+                setTextbookSubscriptionId(wfTextbookSubscriptionId);
                 setIssn(item.getIssn());
                 setInNum(item.getInNum());
             }});
@@ -409,7 +409,7 @@ public class WfTextbookSubscriptionServiceImpl extends MPJBaseServiceImpl<WfText
                 .selectAs(Textbook::getIssn, WfTextbookSubscriptionItem::getIssn)
                 .select(WfTextbookSubscriptionItem.class, x -> VoToColumnUtil.fieldsToColumns(WfTextbookSubscriptionItem.class).contains(x.getProperty()))
                 .leftJoin(Textbook.class, Textbook::getId, WfTextbookSubscriptionItem::getTextbookId)
-                .eq(WfTextbookSubscriptionItem::getWfTextbookSubscriptionId, dtos.get(0).getWfTextbookSubscriptionId())
+                .eq(WfTextbookSubscriptionItem::getWfTextbookSubscriptionId, dtos.get(0).getTextbookSubscriptionId())
                 .eq(WfTextbookSubscriptionItem::getDeleteMark, DeleteMark.NODELETE.getCode())
         ;
         List<WfTextbookSubscriptionItem> wfTextbookSubscriptionItemList = wfTextbookSubscriptionWfTextbookSubscriptionItemMapper.selectList(queryWrapper);
@@ -432,8 +432,8 @@ public class WfTextbookSubscriptionServiceImpl extends MPJBaseServiceImpl<WfText
         Long loginId = StpUtil.getLoginIdAsLong();
         for (TextbookInstockroomDto dto : dtos) {
             WfTextbookSubscriptionItem old;
-            if(dto.getId() != null && dto.getId() > 0){
-                old = itemByIdMap.get(dto.getId());
+            if(dto.getTextbookSubscriptionItemId() != null && dto.getTextbookSubscriptionItemId() > 0){
+                old = itemByIdMap.get(dto.getTextbookSubscriptionItemId());
             } else {
                 old = itemByIssnMap.get(dto.getIssn());
             }
@@ -450,12 +450,12 @@ public class WfTextbookSubscriptionServiceImpl extends MPJBaseServiceImpl<WfText
             wfTextbookSubscriptionWfTextbookSubscriptionItemMapper.updateById(updateItem);
 
             //新增入库记录
-            textbookService.deliverWarehouse(new AddTextbookWarehouseRecordDto() {{
-                setTextbookId(old.getTextbookId());
-                setWarehouseNumber(dto.getInNum());
-                setSource("wm_manual");
-            }});
-            successNum++;
+//            textbookService.deliverWarehouse(new AddTextbookWarehouseRecordDto() {{
+//                setTextbookId(old.getTextbookId());
+//                setWarehouseNumber(dto.getInNum());
+//                setSource("wm_manual");
+//            }});
+//            successNum++;
             instockroomNum += dto.getInNum();
         }
         result.put("allNum", dtos.size());

+ 29 - 18
src/main/java/com/xjrsoft/module/textbook/vo/TextbookInstockroomListVo.java

@@ -5,6 +5,8 @@ import com.alibaba.excel.annotation.write.style.ContentStyle;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 /**
 * @title: 教材管理表单出参
 * @Author szs
@@ -18,12 +20,12 @@ public class TextbookInstockroomListVo {
      * 教材教辅征订编号
      */
     @ApiModelProperty("教材教辅征订编号")
-    private Long wfTextbookSubscriptionId;
+    private String textbookSubscriptionId;
     /**
     * 征订项编号
     */
     @ApiModelProperty("征订项编号")
-    private String id;
+    private String textbookSubscriptionItemId;
     /**
      * 教材编号
      */
@@ -33,7 +35,7 @@ public class TextbookInstockroomListVo {
      * 课程编号(base_course_subject)
      */
     @ApiModelProperty("课程编号(base_course_subject)")
-    private Long courseSubjectId;
+    private String courseSubjectId;
     /**
      * 课程
      */
@@ -71,6 +73,26 @@ public class TextbookInstockroomListVo {
      */
     @ApiModelProperty("教材类型(xjr_dictionary_item[textbook_type])")
     private String textbookTypeCn;
+    /**
+     * 使用类型(单位:学期)
+     */
+    @ApiModelProperty("使用类型(单位:学期)")
+    private Integer useType;
+    /**
+     * 定价(元)
+     */
+    @ApiModelProperty("定价(元)")
+    private BigDecimal price;
+    /**
+     * 实际折扣
+     */
+    @ApiModelProperty("实际折扣")
+    private Double discount;
+    /**
+     * 实际价格(元)
+     */
+    @ApiModelProperty("实际价格(元)")
+    private BigDecimal actualPrice;
     /**
      * 学生用书征订数量
      */
@@ -87,20 +109,9 @@ public class TextbookInstockroomListVo {
     @ApiModelProperty("教材征订总数量")
     private Integer subscriptionNumber;
     /**
-     * 已入库数量
-     */
-    @ApiModelProperty("已入库数量")
-    private Integer inStockroomNum;
-    /**
-     * 使用类型(单位:学期)
-     */
-    @ApiModelProperty("使用类型(单位:学期)")
-    private Integer useType;
-    /**
-     * 版本
+     * 当前征订任务征订项入库数量
      */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("版本")
-    @ApiModelProperty("版本")
-    private String version;
+    @ApiModelProperty("当前征订任务征订项总入库数量")
+    private Integer inStockNum;
+
 }

+ 38 - 0
src/main/java/com/xjrsoft/module/textbook/vo/TextbookInstockroomOnceListVo.java

@@ -0,0 +1,38 @@
+package com.xjrsoft.module.textbook.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+* @title: 教材管理表单出参
+* @Author szs
+* @Date: 2023-12-25
+* @Version 1.0
+*/
+@Data
+public class TextbookInstockroomOnceListVo extends TextbookInstockroomListVo {
+    /**
+     * 单次入库数量
+     */
+    @ApiModelProperty("单次入库数量")
+    private Integer onceInStockNum;
+    /**
+     * 创建人
+     */
+    @ApiModelProperty("创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUserId;
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createDate;
+}

+ 43 - 0
src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionDetailVo.java

@@ -0,0 +1,43 @@
+package com.xjrsoft.module.textbook.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+* @title: 教材教辅征订记录表表单出参
+* @Author dzx
+* @Date: 2024-12-16
+* @Version 1.0
+*/
+@Data
+public class TextbookSubscriptionDetailVo {
+
+    /**
+    * 证订记录主键编号
+    */
+    @ApiModelProperty("证订记录主键编号")
+    private String id;
+    /**
+     * 学生用书征订数量
+     */
+    @ApiModelProperty("学生用书征订数量")
+    private Integer studentTatolNum;
+    /**
+     * 教师用书征订数量
+     */
+    @ApiModelProperty("教师用书征订数量")
+    private Integer teacherTatolNum;
+    /**
+    * 征订教材总数
+    */
+    @ApiModelProperty("征订教材总数")
+    private Integer sum;
+    /**
+     * 征订教材总数
+     */
+    @ApiModelProperty("总金额")
+    private BigDecimal sumPrice;
+}

+ 137 - 0
src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionItemPageVo.java

@@ -0,0 +1,137 @@
+package com.xjrsoft.module.textbook.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import com.xjrsoft.common.annotation.Trans;
+import com.xjrsoft.common.enums.TransType;
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+* @title: 教材征订记录详情表分页列表出参
+* @Author dzx
+* @Date: 2024-12-17
+* @Version 1.0
+*/
+@Data
+public class TextbookSubscriptionItemPageVo {
+
+    /**
+    * 主键编号
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("主键编号")
+    @ApiModelProperty("主键编号")
+    private String id;
+    /**
+    * 教材教辅增订记录表主键(textbook_subscription)
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("教材教辅增订记录表主键(textbook_subscription)")
+    @ApiModelProperty("教材教辅增订记录表主键(textbook_subscription)")
+    private Long textbookSubscriptionId;
+    /**
+    * 教材表主键(textbook)
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("教材表主键(textbook)")
+    @ApiModelProperty("教材表主键(textbook)")
+    private Long textbookId;
+    /**
+     * 课程编号(base_course_subject)
+     */
+    @ApiModelProperty("课程编号(base_course_subject)")
+    private Long courseSubjectId;
+    /**
+     * 课程编号(base_course_subject)
+     */
+    @ApiModelProperty("课程编号(base_course_subject)")
+    private String courseSubjectIdCn;
+    /**
+     * 书名
+     */
+    @ApiModelProperty("书名")
+    private String bookName;
+    /**
+     * 国际标准刊号
+     */
+    @ApiModelProperty("国际标准刊号")
+    private String issn;
+    /**
+     * 出版社
+     */
+    @ApiModelProperty("出版社")
+    private String publishingHouse;
+    /**
+     * 主编
+     */
+    @ApiModelProperty("主编")
+    private String editorInChief;
+    /**
+     * 教材分类(xjr_dictionary_item[textbook_type])
+     */
+    @ApiModelProperty("教材分类(xjr_dictionary_item[textbook_type])")
+    private String textbookType;
+    /**
+     * 教材分类(xjr_dictionary_item[textbook_type])
+     */
+    @ApiModelProperty("教材分类(xjr_dictionary_item[textbook_type])")
+    private String textbookTypeCn;
+    /**
+    * 学生用书征订数量
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("学生用书征订数量")
+    @ApiModelProperty("学生用书征订数量")
+    private Integer studentNum;
+    /**
+    * 教师用书征订数量
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("教师用书征订数量")
+    @ApiModelProperty("教师用书征订数量")
+    private Integer teacherNum;
+    /**
+    * 实际折扣
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("实际折扣")
+    @ApiModelProperty("实际折扣")
+    private Double discount;
+    /**
+    * 实际价格(元)
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("实际价格(元)")
+    @ApiModelProperty("实际价格(元)")
+    private BigDecimal price;
+    /**
+    * 当前征订任务征订项入库数量
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("当前征订任务征订项入库数量")
+    @ApiModelProperty("当前征订任务征订项入库数量")
+    private Integer inStockNum;
+    /**
+    * 当前征订任务征订项出库数量
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("当前征订任务征订项出库数量")
+    @ApiModelProperty("当前征订任务征订项出库数量")
+    private Integer outStockNum;
+    /**
+    * 变更类型(0:未变更,1:变更征订数量,2:变更课程)
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("变更类型(0:未变更,1:变更征订数量,2:变更课程)")
+    @ApiModelProperty("变更类型(0:未变更,1:变更征订数量,2:变更课程)")
+    private Integer alterationType;
+
+}

+ 116 - 0
src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionItemVo.java

@@ -0,0 +1,116 @@
+package com.xjrsoft.module.textbook.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Date;
+
+/**
+* @title: 教材征订记录详情表表单出参
+* @Author dzx
+* @Date: 2024-12-16
+* @Version 1.0
+*/
+@Data
+public class TextbookSubscriptionItemVo {
+
+    /**
+    * 主键编号
+    */
+    @ApiModelProperty("主键编号")
+    private Long id;
+    /**
+    * 序号
+    */
+    @ApiModelProperty("序号")
+    private Integer sortCode;
+    /**
+    * 教材教辅增订记录表主键(textbook_subscription)
+    */
+    @ApiModelProperty("教材教辅增订记录表主键(textbook_subscription)")
+    private Long textbookSubscriptionId;
+    /**
+    * 教材表主键(textbook)
+    */
+    @ApiModelProperty("教材表主键(textbook)")
+    private Long textbookId;
+    /**
+     * 课程编号(base_course_subject)
+     */
+    @ApiModelProperty("课程编号(base_course_subject)")
+    private Long courseSubjectId;
+    /**
+     * 课程编号(base_course_subject)
+     */
+    @ApiModelProperty("课程编号(base_course_subject)")
+    private String courseSubjectIdCn;
+    /**
+     * 书名
+     */
+    @ApiModelProperty("书名")
+    private String bookName;
+    /**
+     * 国际标准刊号
+     */
+    @ApiModelProperty("国际标准刊号")
+    private String issn;
+    /**
+     * 出版社
+     */
+    @ApiModelProperty("出版社")
+    private String publishingHouse;
+    /**
+     * 主编
+     */
+    @ApiModelProperty("主编")
+    private String editorInChief;
+    /**
+     * 教材分类(xjr_dictionary_item[textbook_type])
+     */
+    @ApiModelProperty("教材分类(xjr_dictionary_item[textbook_type])")
+    private String textbookType;
+    /**
+     * 教材分类(xjr_dictionary_item[textbook_type])
+     */
+    @ApiModelProperty("教材分类(xjr_dictionary_item[textbook_type])")
+    private String textbookTypeCn;
+    /**
+    * 学生用书征订数量
+    */
+    @ApiModelProperty("学生用书征订数量")
+    private Integer studentNum;
+    /**
+    * 教师用书征订数量
+    */
+    @ApiModelProperty("教师用书征订数量")
+    private Integer teacherNum;
+    /**
+    * 实际折扣
+    */
+    @ApiModelProperty("实际折扣")
+    private Double discount;
+    /**
+    * 实际价格(元)
+    */
+    @ApiModelProperty("实际价格(元)")
+    private BigDecimal price;
+    /**
+    * 当前征订任务征订项入库数量
+    */
+    @ApiModelProperty("当前征订任务征订项入库数量")
+    private Integer inStockNum;
+    /**
+    * 当前征订任务征订项出库数量
+    */
+    @ApiModelProperty("当前征订任务征订项出库数量")
+    private Integer outStockNum;
+    /**
+    * 变更类型(0:未变更,1:变更征订数量,2:变更课程)
+    */
+    @ApiModelProperty("变更类型(0:未变更,1:变更征订数量,2:变更课程)")
+    private Integer alterationType;
+}

+ 66 - 0
src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionPageVo.java

@@ -0,0 +1,66 @@
+package com.xjrsoft.module.textbook.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+* @title: 教材教辅征订分页列表出参
+* @Author szs
+* @Date: 2024-06-04
+* @Version 1.0
+*/
+@Data
+public class TextbookSubscriptionPageVo {
+
+    /**
+    * 主键编号
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("主键编号")
+    @ApiModelProperty("主键编号")
+    private String id;
+    /**
+    * 学期ID(base_semester)
+    */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("学期ID(base_semester)")
+    @ApiModelProperty("学期ID(base_semester)")
+    private Long baseSemesterId;
+    /**
+     * 学期ID(base_semester)
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("学期ID(base_semester)")
+    @ApiModelProperty("学期ID(base_semester)")
+    private String baseSemesterIdCn;
+    /**
+     * 征订方式(1:按班级征订 2:按教材征订)
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("征订方式(1:按班级征订 2:按教材征订)")
+    @ApiModelProperty("征订方式(1:按班级征订 2:按教材征订)")
+    private Integer subscriptionMethod;
+    /**
+     * 备注
+     */
+    @ApiModelProperty("备注")
+    private String remark;
+    /**
+     * 征订教材总数
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("征订教材总数")
+    @ApiModelProperty("征订教材总数")
+    private Integer sum;
+    /**
+     * 状态(1:结束 0:未结束)
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("状态(1:待发起 2:征订中 3:待入库 4:已入库)")
+    @ApiModelProperty("状态(1:待发起 2:征订中 3:待入库 4:已入库)")
+    private Integer status;
+}

+ 64 - 0
src/main/java/com/xjrsoft/module/textbook/vo/TextbookSubscriptionVo.java

@@ -0,0 +1,64 @@
+package com.xjrsoft.module.textbook.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Date;
+import com.xjrsoft.module.textbook.entity.TextbookSubscriptionItem;
+
+/**
+* @title: 教材教辅征订记录表表单出参
+* @Author dzx
+* @Date: 2024-12-16
+* @Version 1.0
+*/
+@Data
+public class TextbookSubscriptionVo {
+
+    /**
+    * 主键编号
+    */
+    @ApiModelProperty("主键编号")
+    private Long id;
+    /**
+    * 序号
+    */
+    @ApiModelProperty("序号")
+    private Integer sortCode;
+    /**
+    * 备注
+    */
+    @ApiModelProperty("备注")
+    private String remark;
+    /**
+    * 学期id(base_semester)
+    */
+    @ApiModelProperty("学期id(base_semester)")
+    private Long baseSemesterId;
+    /**
+    * 征订方式(1:按班级征订 2:按教材征订)
+    */
+    @ApiModelProperty("征订方式(1:按班级征订 2:按教材征订)")
+    private Integer subscriptionMethod;
+    /**
+    * 征订教材总数
+    */
+    @ApiModelProperty("征订教材总数")
+    private Integer sum;
+    /**
+    * 征订状态(1:结束 0:未结束)
+    */
+    @ApiModelProperty("征订状态(1:结束 0:未结束)")
+    private Integer status;
+
+    /**
+    * textbookSubscriptionItem
+    */
+    @ApiModelProperty("textbookSubscriptionItem子表")
+    private List<TextbookSubscriptionItemVo> textbookSubscriptionItemList;
+
+}

+ 62 - 71
src/main/java/com/xjrsoft/module/textbook/vo/TextbookVo.java

@@ -3,14 +3,16 @@ package com.xjrsoft.module.textbook.vo;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.time.LocalTime;
+import java.time.LocalDateTime;
 import java.math.BigDecimal;
-import java.util.Date;
 import java.util.List;
+import java.util.Date;
 
 /**
-* @title: 教材管理表单出参
-* @Author szs
-* @Date: 2023-12-25
+* @title: 教材基础信息表表单出参
+* @Author dzx
+* @Date: 2024-12-17
 * @Version 1.0
 */
 @Data
@@ -22,11 +24,36 @@ public class TextbookVo {
     @ApiModelProperty("主键编号")
     private Long id;
     /**
+    * 序号
+    */
+    @ApiModelProperty("序号")
+    private Integer sortCode;
+    /**
+    * 学科组管理编号(subject_group)
+    */
+    @ApiModelProperty("学科组管理编号(subject_group)")
+    private Long subjectGroupId;
+    /**
+    * 课程编号(base_course_subject)
+    */
+    @ApiModelProperty("课程编号(base_course_subject)")
+    private Long courseSubjectId;
+    /**
+    * 使用类型(单位:学期)
+    */
+    @ApiModelProperty("使用类型(单位:学期)")
+    private Integer useType;
+    /**
     * 国际标准刊号
     */
     @ApiModelProperty("国际标准刊号")
     private String issn;
     /**
+    * 国际标准书号
+    */
+    @ApiModelProperty("国际标准书号")
+    private String isbn;
+    /**
     * 书名
     */
     @ApiModelProperty("书名")
@@ -42,34 +69,19 @@ public class TextbookVo {
     @ApiModelProperty("主编")
     private String editorInChief;
     /**
-    * 学科组管理编号(subject_group)
-    */
-    @ApiModelProperty("学科组管理编号(subject_group)")
-    private Long subjectGroupId;
-    /**
-    * 学期ID(base_semester)
-    */
-    @ApiModelProperty("学期ID(base_semester)")
-    private Long baseSemesterId;
-    /**
-    * 课程编号(base_course_subject)
-    */
-    @ApiModelProperty("课程编号(base_course_subject)")
-    private Long courseSubjectId;
-    /**
     * 版本
     */
     @ApiModelProperty("版本")
     private String version;
     /**
-    * 是否为规划教材(xjr_dictionary_item[judgment_method_1])
+    * 是否为规划教材
     */
-    @ApiModelProperty("是否为规划教材(xjr_dictionary_item[judgment_method_1])")
-    private String isTextbookPlan;
+    @ApiModelProperty("是否为规划教材")
+    private Integer isTextbookPlan;
     /**
-    * 教材类(xjr_dictionary_item[textbook_type])
+    * 教材分类(xjr_dictionary_item[textbook_type])
     */
-    @ApiModelProperty("教材类(xjr_dictionary_item[textbook_type])")
+    @ApiModelProperty("教材分类(xjr_dictionary_item[textbook_type])")
     private String textbookType;
     /**
     * 规格型号
@@ -77,64 +89,43 @@ public class TextbookVo {
     @ApiModelProperty("规格型号")
     private String specificationsModels;
     /**
-    * 估价(元)
-    */
-    @ApiModelProperty("估价(元)")
-    private BigDecimal appraisalPrice;
-    /**
-    * 定价(元)
-    */
-    @ApiModelProperty("定价(元)")
-    private BigDecimal price;
-    /**
-    * 折扣
+    * 出版日期
     */
-    @ApiModelProperty("折扣")
-    private Double discount;
-    /**
-    * 小计(元)
-    */
-    @ApiModelProperty("小计(元)")
-    private BigDecimal subtotal;
+    @ApiModelProperty("出版日期")
+    private Date publishingDate;
     /**
-    * 库存
+    * 是否校企合作开发教材
     */
-    @ApiModelProperty("库存")
-    private Integer stock;
-
-    /**
-     * 入学年级(base_grade)
-     */
-    @ApiModelProperty("入学年级(base_grade)")
-    private Long gradeId;
-
-    /**
-     * 入学年级(base_grade)
-     */
-    @ApiModelProperty("使用班级")
-    private List<TextbookClassRelationVo> textbookClassRelationList;
-
-    /**
-     * 使用类型(单位:学期)
-     */
-    @ApiModelProperty("使用类型(单位:学期)")
-    private Integer useType;
-
     @ApiModelProperty("是否校企合作开发教材")
     private Integer isSecd;
-
-    @ApiModelProperty("出版日期")
-    private Date publishingDate;
-
+    /**
+    * 分类号
+    */
     @ApiModelProperty("分类号")
     private String category;
-
+    /**
+    * 规划批次
+    */
     @ApiModelProperty("规划批次")
     private String planBatch;
-
+    /**
+    * 编著作总数
+    */
     @ApiModelProperty("编著作总数")
     private Integer workTotalCount;
-
+    /**
+    * 教材类型
+    */
     @ApiModelProperty("教材类型")
     private String textbookCategory;
+    /**
+    * 定价(元)
+    */
+    @ApiModelProperty("定价(元)")
+    private BigDecimal price;
+    /**
+    * 预估折扣
+    */
+    @ApiModelProperty("预估折扣")
+    private Double discount;
 }

+ 3 - 154
src/main/java/com/xjrsoft/module/veb/controller/ImportRubAndHandController.java

@@ -9,6 +9,7 @@ import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.module.generator.entity.ImportConfig;
 import com.xjrsoft.module.textbook.dto.TextbookImportDto;
 import com.xjrsoft.module.veb.service.ImportRubAndHandService;
+import com.xjrsoft.module.veb.util.ImportExcelUtil;
 import com.xjrsoft.module.veb.vo.BaseCourseSubjectImportVo;
 import com.xjrsoft.module.veb.vo.InternshipPlanImportVo;
 import io.swagger.annotations.Api;
@@ -67,7 +68,7 @@ public class ImportRubAndHandController {
     @ApiOperation(value = "课程信息模板下载")
     public ResponseEntity<byte[]> courseSubjectTemplate() throws IOException {
         BaseCourseSubjectImportVo obj = new BaseCourseSubjectImportVo();
-        ByteArrayOutputStream bot = writeTemplateSheet(obj);
+        ByteArrayOutputStream bot = ImportExcelUtil.writeTemplateSheet(obj);
         return R.fileStream(bot.toByteArray(), System.currentTimeMillis() + ExcelTypeEnum.XLSX.getValue());
     }
 
@@ -88,160 +89,8 @@ public class ImportRubAndHandController {
 //    @ApiOperation(value = "实习信息模板下载")
 //    public ResponseEntity<byte[]> internshipPlanTemplate() throws IOException {
         InternshipPlanImportVo obj = new InternshipPlanImportVo();
-        ByteArrayOutputStream bot = writeTemplateSheet(obj);
+        ByteArrayOutputStream bot = ImportExcelUtil.writeTemplateSheet(obj);
         return R.fileStream(bot.toByteArray(), System.currentTimeMillis() + ExcelTypeEnum.XLSX.getValue());
     }
 
-    @PostMapping("/textbook")
-    @ApiOperation(value = "教材信息导入")
-    public RT<Boolean> textbook(@RequestParam MultipartFile file) throws IOException, IllegalAccessException {
-        String result = importRubAndHandService.textbook(file);
-        if (!result.isEmpty()) {
-            throw new MyException(result);
-        }
-        return RT.ok("全部成功", true);
-    }
-
-    @PostMapping("/textbook-template")
-    @ApiOperation(value = "教材信息模板下载")
-    public ResponseEntity<byte[]> textbookTemplate() throws IOException {
-//    @GetMapping("/textbook-template")
-//    @ApiOperation(value = "教材信息模板下载")
-//    public ResponseEntity<byte[]> textbookTemplate() throws IOException {
-        TextbookImportDto obj = new TextbookImportDto();
-        // 开始写入
-        Workbook workbook = new XSSFWorkbook();
-        // 创建一个工作表(sheet)
-        String sheetName = "sheet1";
-        Sheet sheet = workbook.createSheet(sheetName);
-
-        List<ImportConfig> importConfigs = allFields(obj);
-
-        // 标题
-        String title = "教材信息导入模板";
-        createCautionHead(workbook, sheet, 0, title, importConfigs.size() - 1, 36);
-
-        // 提示必填
-        String content = "说明:红底为必填项,白底为非必填项;只有教材分类为教材时才需要填写学科组和对应课程,学科组和课程必须是系统中已添加的信息,且学科组和课程已建立绑定关系;导入时请将示例数据删除,避免导入失败!";
-        createCautionHead(workbook, sheet, 1, content, importConfigs.size() - 1, 12);
-
-        // 表头
-        createHead(workbook, sheet, importConfigs, 2);
-
-        //写入文件
-        ByteArrayOutputStream bot = new ByteArrayOutputStream();
-        workbook.write(bot);
-
-
-        String fileName = "教材信息导入模板";
-        fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
-        return R.fileStream(bot.toByteArray(), fileName + ExcelTypeEnum.XLSX.getValue());
-    }
-
-    private ByteArrayOutputStream writeTemplateSheet(Object obj) throws IOException {
-        // 开始写入
-        Workbook workbook = new XSSFWorkbook();
-        // 创建一个工作表(sheet)
-        String sheetName = "sheet1";
-        Sheet sheet = workbook.createSheet(sheetName);
-
-        List<ImportConfig> importConfigs = allFields(obj);
-
-        // 表头
-        createHead(workbook, sheet, importConfigs, 0);
-
-        // 提示必填
-        String content = "红色背景为必填项,导入时请删除本行。";
-        createCautionHead(workbook, sheet, 1, content, importConfigs.size() - 1, 12);
-
-        //写入文件
-        ByteArrayOutputStream bot = new ByteArrayOutputStream();
-        workbook.write(bot);
-        return bot;
-    }
-
-    private List<ImportConfig> allFields(Object obj) {
-        List<ImportConfig> importConfigs = new ArrayList<>();
-        if (obj == null) {
-            return importConfigs;
-        }
-
-        Class<?> clazz = obj.getClass();
-        Field[] fields = clazz.getDeclaredFields();
-
-        for (int i = 0; i < fields.length; i++) {
-            Field field = fields[i];
-            ImportConfig importConfig = new ImportConfig();
-            field.setAccessible(true); // 访问私有字段
-            if (field.isAnnotationPresent(Required.class)) {
-                Required required = field.getAnnotation(Required.class);
-                Boolean value = required.value();
-                importConfig.setRequired(value);
-            }
-
-            if (field.isAnnotationPresent(ExcelProperty.class)) {
-                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
-                String[] annotationValues = excelProperty.value();
-                importConfig.setLabel(annotationValues.length > 0 ? annotationValues[0] : "");
-            }
-            importConfig.setFieldName(field.getName());
-            importConfig.setSortCode(i);
-            importConfig.setWidth(0);
-            importConfigs.add(importConfig);
-        }
-
-        return importConfigs;
-    }
-
-    private void createHead(Workbook workbook, Sheet sheet, List<ImportConfig> importConfigs, int rowNumber) {
-        Font font = workbook.createFont();
-        font.setFontName("宋体");
-        font.setFontHeightInPoints((short)12);
-
-        // 正常样式
-        CellStyle normalCellStyle = workbook.createCellStyle();
-        normalCellStyle.setFont(font); // 将字体应用到样式
-        normalCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
-        normalCellStyle.setAlignment(HorizontalAlignment.CENTER);
-
-        // 必填样式
-        CellStyle requiredCellStyle = workbook.createCellStyle();
-        requiredCellStyle.setFont(font); // 将字体应用到样式
-        requiredCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
-        requiredCellStyle.setAlignment(HorizontalAlignment.CENTER);
-        requiredCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());//设置背景颜色
-        requiredCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);//设置填充模式
-
-        // 所在行
-        Row row = sheet.createRow(rowNumber);
-
-        // 每一列
-        for (ImportConfig importConfig : importConfigs){
-            Cell cell = row.createCell(importConfig.getSortCode());
-            String content = importConfig.getLabel();
-            cell.setCellValue(content);
-            if(ObjectUtils.isNotEmpty(importConfig.getRequired()) && importConfig.getRequired()){
-                cell.setCellStyle(requiredCellStyle);
-            }
-            if(ObjectUtils.isEmpty(importConfig.getRequired()) || !importConfig.getRequired()) {
-                cell.setCellStyle(normalCellStyle);
-            }
-        }
-    }
-
-    private void createCautionHead(Workbook workbook, Sheet sheet, int rowNumber, String content, int lastCol, int size) {
-        Font font = workbook.createFont();
-        font.setFontName("宋体");
-        font.setFontHeightInPoints((short)size);
-        font.setColor(IndexedColors.RED.getIndex());
-
-        CellStyle cellStyle = workbook.createCellStyle();
-        cellStyle.setFont(font); // 将字体应用到样式
-
-        Row row = sheet.createRow(rowNumber);
-        Cell cell = row.createCell(0);
-        cell.setCellValue(content);
-        cell.setCellStyle(cellStyle);
-        sheet.addMergedRegion(new CellRangeAddress(rowNumber, rowNumber, 0, lastCol));
-    }
 }

+ 0 - 2
src/main/java/com/xjrsoft/module/veb/service/ImportRubAndHandService.java

@@ -12,6 +12,4 @@ public interface ImportRubAndHandService {
 
     String internshipPlan(MultipartFile file) throws IOException, IllegalAccessException;
 
-    String textbook(MultipartFile file) throws IOException, IllegalAccessException;
-
 }

+ 11 - 291
src/main/java/com/xjrsoft/module/veb/service/impl/ImportRubAndHandServiceImpl.java

@@ -3,36 +3,14 @@ package com.xjrsoft.module.veb.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.IdUtil;
 import com.alibaba.excel.EasyExcel;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.github.yulichang.wrapper.MPJLambdaWrapper;
-import com.xjrsoft.common.annotation.Required;
 import com.xjrsoft.common.enums.DeleteMark;
-import com.xjrsoft.common.enums.YesOrNoEnum;
-import com.xjrsoft.common.utils.VoToColumnUtil;
-import com.xjrsoft.module.base.entity.BaseClass;
-import com.xjrsoft.module.base.entity.BaseCourseSubject;
-import com.xjrsoft.module.base.entity.BaseMajorSet;
-import com.xjrsoft.module.base.entity.BaseSemester;
-import com.xjrsoft.module.base.entity.CourseSubjectDetail;
-import com.xjrsoft.module.base.mapper.BaseClassMapper;
-import com.xjrsoft.module.base.mapper.BaseCourseSubjectMapper;
-import com.xjrsoft.module.base.mapper.BaseMajorSetMapper;
-import com.xjrsoft.module.base.mapper.BaseSemesterMapper;
-import com.xjrsoft.module.base.mapper.CourseSubjectDetailMapper;
+import com.xjrsoft.module.base.entity.*;
+import com.xjrsoft.module.base.mapper.*;
 import com.xjrsoft.module.organization.entity.User;
 import com.xjrsoft.module.organization.mapper.UserMapper;
-import com.xjrsoft.module.system.entity.DictionaryDetail;
-import com.xjrsoft.module.system.entity.DictionaryItem;
 import com.xjrsoft.module.system.mapper.DictionarydetailMapper;
 import com.xjrsoft.module.system.mapper.DictionaryitemMapper;
-import com.xjrsoft.module.textbook.dto.TextbookImportDto;
-import com.xjrsoft.module.textbook.entity.SubjectGroup;
-import com.xjrsoft.module.textbook.entity.Textbook;
-import com.xjrsoft.module.textbook.mapper.SubjectGroupMapper;
-import com.xjrsoft.module.textbook.mapper.TextbookMapper;
 import com.xjrsoft.module.veb.entity.InternshipPlanManage;
 import com.xjrsoft.module.veb.entity.InternshipPlanManageParticipant;
 import com.xjrsoft.module.veb.entity.TrainingOutside;
@@ -42,22 +20,23 @@ import com.xjrsoft.module.veb.mapper.InternshipPlanManageParticipantMapper;
 import com.xjrsoft.module.veb.mapper.TrainingOutsideMapper;
 import com.xjrsoft.module.veb.mapper.TrainingSchoolMapper;
 import com.xjrsoft.module.veb.service.ImportRubAndHandService;
+import com.xjrsoft.module.veb.util.ImportExcelUtil;
 import com.xjrsoft.module.veb.vo.BaseCourseSubjectImportVo;
 import com.xjrsoft.module.veb.vo.InternshipPlanImportVo;
 import lombok.AllArgsConstructor;
-import org.apache.commons.lang3.ObjectUtils;
-import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.*;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
+import static com.xjrsoft.module.veb.util.ImportExcelUtil.*;
+
 /**
  * 手搓导入
  */
@@ -89,10 +68,6 @@ public class ImportRubAndHandServiceImpl implements ImportRubAndHandService {
 
     private final BaseClassMapper baseClassMapper;
 
-    private final SubjectGroupMapper subjectGroupMapper;
-
-    private final TextbookMapper textbookMapper;
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public String courseSubject(MultipartFile file) throws IOException, IllegalAccessException {
@@ -107,7 +82,7 @@ public class ImportRubAndHandServiceImpl implements ImportRubAndHandService {
         codeList.add("subject_quality");
         codeList.add("course_resource");
 
-        Map<String, String> dictionary = initDictionary(codeList);
+        Map<String, String> dictionary = ImportExcelUtil.initDictionary(codeList, dictionaryitemMapper, dictionarydetailMapper);
 
         List<BaseCourseSubject> baseCourseSubjects = new ArrayList<>();
         List<CourseSubjectDetail> courseSubjectDetails = new ArrayList<>();
@@ -228,7 +203,7 @@ public class ImportRubAndHandServiceImpl implements ImportRubAndHandService {
         codeList.add("internship_site_type");
         codeList.add("unit_source");
 
-        Map<String, String> dictionary = initDictionary(codeList);
+        Map<String, String> dictionary = ImportExcelUtil.initDictionary(codeList, dictionaryitemMapper, dictionarydetailMapper);
 
         // 学期
         List<BaseSemester> baseSemesters = baseSemesterMapper.selectList(
@@ -472,259 +447,4 @@ public class ImportRubAndHandServiceImpl implements ImportRubAndHandService {
         }
         return sb.toString();
     }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public String textbook(MultipartFile file) throws IOException, IllegalAccessException {
-        List<TextbookImportDto> excelDataList = EasyExcel.read(file.getInputStream()).headRowNumber(3).head(TextbookImportDto.class).sheet().doReadSync();
-        StringBuilder sb = new StringBuilder();
-
-        List<String> codeList = new ArrayList<>();
-        codeList.add("textbook_type");
-        codeList.add("textbook_category");
-
-        Map<String, String> dictionary = initDictionary(codeList);
-
-        //查询所有需要的数据
-        //学科组
-        List<SubjectGroup> subjectGroupList = subjectGroupMapper.selectList(
-                Wrappers
-                        .lambdaQuery(SubjectGroup.class)
-                        .eq(SubjectGroup::getDeleteMark, DeleteMark.NODELETE.getCode()));
-        Map<String, Long> subjectGroupNameAndIdMap = subjectGroupList.stream().collect(Collectors.toMap(SubjectGroup::getGroupName, SubjectGroup::getId, (k1, k2) -> k1));
-
-        //使用课程
-        List<BaseCourseSubject> baseCourseSubjectList = baseCourseSubjectMapper.selectList(
-                Wrappers
-                        .lambdaQuery(BaseCourseSubject.class)
-                        .eq(BaseCourseSubject::getDeleteMark, DeleteMark.NODELETE.getCode())
-        );
-        Map<String, Long> baseCourseSubjectNameAndIdMap = baseCourseSubjectList.stream().collect(Collectors.toMap(BaseCourseSubject::getName, BaseCourseSubject::getId, (k1, k2) -> k1));
-
-        List<Textbook> insertTextbooks = new ArrayList<>();
-        List<Textbook> updateTextbooks = new ArrayList<>();
-        for (int i = 0; i < excelDataList.size(); i++) {
-            TextbookImportDto dto = excelDataList.get(i);
-            if (isRequiredFieldsFilled(dto,
-                    sb,
-                    i)) {
-                return sb.toString();
-            }
-
-            Textbook textbook = new Textbook();
-            BeanUtils.copyProperties(dto, textbook);
-
-            // 验证字段的合理性
-            // 字典类型
-            if (validateAndSetDictionaryField(dto::getTextbookTypeCn,
-                    "textbook_type",
-                    "教材分类(教材、辅材、作业本)",
-                    dictionary,
-                    textbook::setTextbookType,
-                    sb,
-                    i)) {
-                return sb.toString();
-            }
-            if (validateAndSetDictionaryField(dto::getTextbookCategory,
-                    "textbook_category",
-                    "教材类型(纸质教材、数字教材、纸质与数字资源结合教材)",
-                    dictionary,
-                    textbook::setTextbookCategory,
-                    sb,
-                    i)) {
-                return sb.toString();
-            }
-
-            // 关联表
-            if (validateAndSetString2LongField(dto::getGroupName,
-                    "学科组(必须是系统中已有的学科组名称)",
-                    subjectGroupNameAndIdMap,
-                    textbook::setSubjectGroupId,
-                    sb,
-                    i
-            )) {
-                return sb.toString();
-            }
-            if (validateAndSetString2LongField(dto::getCourseName,
-                    "对应课程(必须是系统中已有的课程名称)",
-                    baseCourseSubjectNameAndIdMap,
-                    textbook::setCourseSubjectId,
-                    sb,
-                    i
-            )) {
-                return sb.toString();
-            }
-
-            // 处理是否教材计划字段
-            String isTextbookPlanCn = dto.getIsTextbookPlanCn();
-            Integer isTextbookPlan = Optional.ofNullable(isTextbookPlanCn)
-                    .filter("是"::equals)
-                    .map(s -> 1)
-                    .orElse(0);
-            textbook.setIsTextbookPlan(isTextbookPlan);
-
-            String isSecd = dto.getIsSecd();
-            Integer isSecdI = Optional.ofNullable(isSecd)
-                    .filter("是"::equals)
-                    .map(s -> 1)
-                    .orElse(0);
-            textbook.setIsSecd(isSecdI);
-
-            // 判断导入的教材是否已经存在,根据教材的 ISSN 码和使用的学科组和课程判断
-            LambdaQueryWrapper<Textbook> textbookLambdaQueryWrapper = new LambdaQueryWrapper<>();
-            textbookLambdaQueryWrapper
-                    .eq(Textbook::getIssn, textbook.getIssn())
-                    .eq(Textbook::getSubjectGroupId, textbook.getSubjectGroupId())
-                    .eq(Textbook::getCourseSubjectId, textbook.getCourseSubjectId())
-                    .eq(Textbook::getDeleteMark, DeleteMark.NODELETE.getCode())
-            ;
-
-            Textbook verifyTextbook = textbookMapper.selectOne(textbookLambdaQueryWrapper);
-            if(ObjectUtils.isNotEmpty(verifyTextbook)){
-                textbook.setId(verifyTextbook.getId());
-                updateTextbooks.add(textbook);
-            }else {
-                insertTextbooks.add(textbook);
-            }
-        }
-
-        //批量新增
-        if (!insertTextbooks.isEmpty()) {
-            for (Textbook textbook : insertTextbooks) {
-                textbookMapper.insert(textbook);
-            }
-        }
-
-        //批量修改
-        if (!updateTextbooks.isEmpty()) {
-            for (Textbook textbook : updateTextbooks) {
-                textbookMapper.updateById(textbook);
-            }
-        }
-        return sb.toString();
-    }
-
-    private boolean validateAndSetString2LongField(Supplier<String> getter,
-                                                   String fieldName,
-                                                   Map<String, Long> string2Long,
-                                                   Consumer<Long> setter,
-                                                   StringBuilder sb, int i) {
-        String value = getter.get();
-        if (value != null && !value.trim().isEmpty()) {
-            Long sublistValue = string2Long.get(value);
-            if (sublistValue != null) {
-                setter.accept(sublistValue);
-                return false;
-            } else {
-                sb.append("第");
-                sb.append(i + 2);
-                sb.append("行的");
-                sb.append(fieldName);
-                sb.append("列的值不存在于系统对应基础数据中,请到基础数据维护");
-                return true;
-            }
-        }
-        return false; // 字段为空,不进行验证
-    }
-
-    private boolean validateAndSetBooleanField(Supplier<String> getter,
-                                               String fieldName,
-                                               Consumer<Integer> setter,
-                                               StringBuilder sb, int i) {
-        String value = getter.get();
-        if (value != null && !value.trim().isEmpty()) {
-            Integer booleanValue = YesOrNoEnum.getCode(value);
-            if (booleanValue != null) {
-                setter.accept(booleanValue);
-                return false;
-            } else {
-                sb.append("第");
-                sb.append(i + 2);
-                sb.append("行的");
-                sb.append(fieldName);
-                sb.append("列的值不符合,该列的值只能为是或否");
-                return true;
-            }
-        }
-        return false; // 字段为空,不进行验证
-    }
-
-    private boolean validateAndSetDictionaryField(Supplier<String> getter,
-                                                  String prefix,
-                                                  String fieldName,
-                                                  Map<String, String> dictionary,
-                                                  Consumer<String> setter,
-                                                  StringBuilder sb, int i) {
-        String value = getter.get();
-        if (value != null && !value.trim().isEmpty()) {
-            String dictValue = dictionary.get(prefix + value.trim());
-            if (dictValue != null && !dictValue.trim().isEmpty()) {
-                setter.accept(dictValue.trim());
-                return false;
-            } else {
-                sb.append("第");
-                sb.append(i + 2);
-                sb.append("行的");
-                sb.append(fieldName);
-                sb.append("列的值不存在于字典中,请到字典中维护");
-                return true;
-            }
-        }
-        return false; // 字段为空,不进行验证
-    }
-
-    private Map<String, String> initDictionary(List<String> codeList) {
-        List<DictionaryDetail> detailList = dictionarydetailMapper.selectJoinList(DictionaryDetail.class,
-                new MPJLambdaWrapper<DictionaryDetail>()
-                        .select(DictionaryDetail::getId)
-                        .select(DictionaryDetail.class, x -> VoToColumnUtil.fieldsToColumns(DictionaryDetail.class).contains(x.getProperty()))
-                        .leftJoin(DictionaryItem.class, DictionaryItem::getId, DictionaryDetail::getItemId)
-                        .in(DictionaryItem::getCode, codeList)
-        );
-
-        List<DictionaryItem> dictionaryItemList = dictionaryitemMapper.selectList(
-                new QueryWrapper<DictionaryItem>().lambda()
-                        .eq(DictionaryItem::getDeleteMark, DeleteMark.NODELETE.getCode())
-        );
-        Map<Long, String> itemMap = new HashMap<>();
-        for (DictionaryItem dictionaryItem : dictionaryItemList) {
-            itemMap.put(dictionaryItem.getId(), dictionaryItem.getCode());
-        }
-
-        Map<String, String> resultMap = new HashMap<>();
-        for (DictionaryDetail dictionaryDetail : detailList) {
-            resultMap.put(itemMap.get(dictionaryDetail.getItemId()) + dictionaryDetail.getName(), dictionaryDetail.getCode());
-        }
-        return resultMap;
-    }
-
-    private boolean isRequiredFieldsFilled(Object instance,
-                                           StringBuilder sb,
-                                           int i)
-            throws IllegalAccessException {
-        if (instance == null) {
-            return true; // 如果对象本身为 null,则认为没有通过验证
-        }
-
-        for (Field field : instance.getClass().getDeclaredFields()) {
-            Required required = field.getAnnotation(Required.class);
-            if (required != null) { // 如果字段被 @Required 标记
-                field.setAccessible(true); // 允许访问私有字段
-                Object value = field.get(instance); // 获取字段的值
-                if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {
-                    sb.append("第");
-                    sb.append(i + 2);
-                    sb.append("行的");
-                    if (field.isAnnotationPresent(ExcelProperty.class)) {
-                        ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
-                        String[] annotationValues = excelProperty.value();
-                        sb.append(annotationValues.length > 0 ? annotationValues[0] : "");
-                    }
-                    sb.append("列的值为必填");
-                    return true; // 如果任何必需字段为空,则返回 true
-                }
-            }
-        }
-        return false; // 所有必需字段都不为空
-    }
 }

+ 337 - 0
src/main/java/com/xjrsoft/module/veb/util/ImportExcelUtil.java

@@ -0,0 +1,337 @@
+package com.xjrsoft.module.veb.util;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.annotation.Required;
+import com.xjrsoft.common.enums.DeleteMark;
+import com.xjrsoft.common.enums.YesOrNoEnum;
+import com.xjrsoft.common.utils.VoToColumnUtil;
+import com.xjrsoft.module.generator.entity.ImportConfig;
+import com.xjrsoft.module.system.entity.DictionaryDetail;
+import com.xjrsoft.module.system.entity.DictionaryItem;
+import com.xjrsoft.module.system.mapper.DictionarydetailMapper;
+import com.xjrsoft.module.system.mapper.DictionaryitemMapper;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * @author dzx
+ * @Description 导入工具类
+ * 2023/12/5
+ */
+public class ImportExcelUtil {
+
+    /**
+     * 下载模板写入
+     * @param obj
+     * @return
+     * @throws IOException
+     */
+    public static ByteArrayOutputStream writeTemplateSheet(Object obj) throws IOException {
+        // 开始写入
+        Workbook workbook = new XSSFWorkbook();
+        // 创建一个工作表(sheet)
+        String sheetName = "sheet1";
+        Sheet sheet = workbook.createSheet(sheetName);
+
+        List<ImportConfig> importConfigs = allFields(obj);
+
+        // 表头
+        createHead(workbook, sheet, importConfigs, 0);
+
+        // 提示必填
+        String content = "红色背景为必填项,导入时请删除本行。";
+        createCautionHead(workbook, sheet, 1, content, importConfigs.size() - 1, 12);
+
+        //写入文件
+        ByteArrayOutputStream bot = new ByteArrayOutputStream();
+        workbook.write(bot);
+        return bot;
+    }
+
+    /**
+     * 获取写入对象的所有字段
+     * @param obj
+     * @return
+     */
+    public static List<ImportConfig> allFields(Object obj) {
+        List<ImportConfig> importConfigs = new ArrayList<>();
+        if (obj == null) {
+            return importConfigs;
+        }
+
+        Class<?> clazz = obj.getClass();
+        Field[] fields = clazz.getDeclaredFields();
+
+        for (int i = 0; i < fields.length; i++) {
+            Field field = fields[i];
+            ImportConfig importConfig = new ImportConfig();
+            field.setAccessible(true); // 访问私有字段
+            if (field.isAnnotationPresent(Required.class)) {
+                Required required = field.getAnnotation(Required.class);
+                Boolean value = required.value();
+                importConfig.setRequired(value);
+            }
+
+            if (field.isAnnotationPresent(ExcelProperty.class)) {
+                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+                String[] annotationValues = excelProperty.value();
+                importConfig.setLabel(annotationValues.length > 0 ? annotationValues[0] : "");
+            }
+            importConfig.setFieldName(field.getName());
+            importConfig.setSortCode(i);
+            importConfig.setWidth(0);
+            importConfigs.add(importConfig);
+        }
+
+        return importConfigs;
+    }
+
+    /**
+     * 写标题行
+     * @param workbook
+     * @param sheet
+     * @param importConfigs
+     * @param rowNumber
+     */
+    public static void createHead(Workbook workbook, Sheet sheet, List<ImportConfig> importConfigs, int rowNumber) {
+        Font font = workbook.createFont();
+        font.setFontName("宋体");
+        font.setFontHeightInPoints((short)12);
+
+        // 正常样式
+        CellStyle normalCellStyle = workbook.createCellStyle();
+        normalCellStyle.setFont(font); // 将字体应用到样式
+        normalCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        normalCellStyle.setAlignment(HorizontalAlignment.CENTER);
+
+        // 必填样式
+        CellStyle requiredCellStyle = workbook.createCellStyle();
+        requiredCellStyle.setFont(font); // 将字体应用到样式
+        requiredCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        requiredCellStyle.setAlignment(HorizontalAlignment.CENTER);
+        requiredCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());//设置背景颜色
+        requiredCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);//设置填充模式
+
+        // 所在行
+        Row row = sheet.createRow(rowNumber);
+
+        // 每一列
+        for (ImportConfig importConfig : importConfigs){
+            Cell cell = row.createCell(importConfig.getSortCode());
+            String content = importConfig.getLabel();
+            cell.setCellValue(content);
+            if(ObjectUtils.isNotEmpty(importConfig.getRequired()) && importConfig.getRequired()){
+                cell.setCellStyle(requiredCellStyle);
+            }
+            if(ObjectUtils.isEmpty(importConfig.getRequired()) || !importConfig.getRequired()) {
+                cell.setCellStyle(normalCellStyle);
+            }
+        }
+    }
+
+    /**
+     * 写提示行
+     * @param workbook
+     * @param sheet
+     * @param rowNumber
+     * @param content
+     * @param lastCol
+     * @param size
+     */
+    public static void createCautionHead(Workbook workbook, Sheet sheet, int rowNumber, String content, int lastCol, int size) {
+        Font font = workbook.createFont();
+        font.setFontName("宋体");
+        font.setFontHeightInPoints((short)size);
+        font.setColor(IndexedColors.RED.getIndex());
+
+        CellStyle cellStyle = workbook.createCellStyle();
+        cellStyle.setFont(font); // 将字体应用到样式
+
+        Row row = sheet.createRow(rowNumber);
+        Cell cell = row.createCell(0);
+        cell.setCellValue(content);
+        cell.setCellStyle(cellStyle);
+        sheet.addMergedRegion(new CellRangeAddress(rowNumber, rowNumber, 0, lastCol));
+    }
+
+    /**
+     * 验证子表字段值的合理性并转换为对应的主键
+     * @param getter
+     * @param fieldName
+     * @param string2Long
+     * @param setter
+     * @param sb
+     * @param i
+     * @return
+     */
+    public static boolean validateAndSetString2LongField(Supplier<String> getter,
+                                                   String fieldName,
+                                                   Map<String, Long> string2Long,
+                                                   Consumer<Long> setter,
+                                                   StringBuilder sb, int i) {
+        String value = getter.get();
+        if (value != null && !value.trim().isEmpty()) {
+            Long sublistValue = string2Long.get(value);
+            if (sublistValue != null) {
+                setter.accept(sublistValue);
+                return false;
+            } else {
+                sb.append("第");
+                sb.append(i + 2);
+                sb.append("行的");
+                sb.append(fieldName);
+                sb.append("列的值不存在于系统对应基础数据中,请到基础数据维护");
+                return true;
+            }
+        }
+        return false; // 字段为空,不进行验证
+    }
+
+    /**
+     * 验证boolean值的合理性并转换为数值
+     * @param getter
+     * @param fieldName
+     * @param setter
+     * @param sb
+     * @param i
+     * @return
+     */
+    public static boolean validateAndSetBooleanField(Supplier<String> getter,
+                                               String fieldName,
+                                               Consumer<Integer> setter,
+                                               StringBuilder sb, int i) {
+        String value = getter.get();
+        if (value != null && !value.trim().isEmpty()) {
+            Integer booleanValue = YesOrNoEnum.getCode(value);
+            if (booleanValue != null) {
+                setter.accept(booleanValue);
+                return false;
+            } else {
+                sb.append("第");
+                sb.append(i + 2);
+                sb.append("行的");
+                sb.append(fieldName);
+                sb.append("列的值不符合,该列的值只能为是或否");
+                return true;
+            }
+        }
+        return false; // 字段为空,不进行验证
+    }
+
+    /**
+     * 验证字典值的合理性并转换为字典的code
+     * @param getter
+     * @param prefix
+     * @param fieldName
+     * @param dictionary
+     * @param setter
+     * @param sb
+     * @param i
+     * @return
+     */
+    public static boolean validateAndSetDictionaryField(Supplier<String> getter,
+                                                  String prefix,
+                                                  String fieldName,
+                                                  Map<String, String> dictionary,
+                                                  Consumer<String> setter,
+                                                  StringBuilder sb, int i) {
+        String value = getter.get();
+        if (value != null && !value.trim().isEmpty()) {
+            String dictValue = dictionary.get(prefix + value.trim());
+            if (dictValue != null && !dictValue.trim().isEmpty()) {
+                setter.accept(dictValue.trim());
+                return false;
+            } else {
+                sb.append("第");
+                sb.append(i + 2);
+                sb.append("行的");
+                sb.append(fieldName);
+                sb.append("列的值不存在于字典中,请到字典中维护");
+                return true;
+            }
+        }
+        return false; // 字段为空,不进行验证
+    }
+
+    /**
+     * 获取所有的字典值映射
+     * @param codeList
+     * @return
+     */
+    public static Map<String, String> initDictionary(List<String> codeList, DictionaryitemMapper dictionaryitemMapper, DictionarydetailMapper dictionarydetailMapper) {
+        List<DictionaryDetail> detailList = dictionarydetailMapper.selectJoinList(DictionaryDetail.class,
+                new MPJLambdaWrapper<DictionaryDetail>()
+                        .select(DictionaryDetail::getId)
+                        .select(DictionaryDetail.class, x -> VoToColumnUtil.fieldsToColumns(DictionaryDetail.class).contains(x.getProperty()))
+                        .leftJoin(DictionaryItem.class, DictionaryItem::getId, DictionaryDetail::getItemId)
+                        .in(DictionaryItem::getCode, codeList)
+        );
+
+        List<DictionaryItem> dictionaryItemList = dictionaryitemMapper.selectList(
+                new QueryWrapper<DictionaryItem>().lambda()
+                        .eq(DictionaryItem::getDeleteMark, DeleteMark.NODELETE.getCode())
+        );
+        Map<Long, String> itemMap = new HashMap<>();
+        for (DictionaryItem dictionaryItem : dictionaryItemList) {
+            itemMap.put(dictionaryItem.getId(), dictionaryItem.getCode());
+        }
+
+        Map<String, String> resultMap = new HashMap<>();
+        for (DictionaryDetail dictionaryDetail : detailList) {
+            resultMap.put(itemMap.get(dictionaryDetail.getItemId()) + dictionaryDetail.getName(), dictionaryDetail.getCode());
+        }
+        return resultMap;
+    }
+
+    /**
+     * 判断属性是否为必填属性
+     * @param instance
+     * @param sb
+     * @param i
+     * @return
+     * @throws IllegalAccessException
+     */
+    public static boolean isRequiredFieldsFilled(Object instance,
+                                           StringBuilder sb,
+                                           int i)
+            throws IllegalAccessException {
+        if (instance == null) {
+            return true; // 如果对象本身为 null,则认为没有通过验证
+        }
+
+        for (Field field : instance.getClass().getDeclaredFields()) {
+            Required required = field.getAnnotation(Required.class);
+            if (required != null) { // 如果字段被 @Required 标记
+                field.setAccessible(true); // 允许访问私有字段
+                Object value = field.get(instance); // 获取字段的值
+                if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {
+                    sb.append("第");
+                    sb.append(i + 2);
+                    sb.append("行的");
+                    if (field.isAnnotationPresent(ExcelProperty.class)) {
+                        ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+                        String[] annotationValues = excelProperty.value();
+                        sb.append(annotationValues.length > 0 ? annotationValues[0] : "");
+                    }
+                    sb.append("列的值为必填");
+                    return true; // 如果任何必需字段为空,则返回 true
+                }
+            }
+        }
+        return false; // 所有必需字段都不为空
+    }
+}

+ 52 - 41
src/main/resources/sqlScript/textbook_sql.sql

@@ -155,26 +155,60 @@ create table `textbook_subscription_item_history`
   default charset = utf8mb4
   collate = utf8mb4_0900_ai_ci comment ='教材教辅征订项变更历史';
 
-
-drop table if exists textbook_subscription_record;
-create table `textbook_subscription_record`
+-- ----------------------------
+-- 2024-12-13 14:36
+-- 教材入库记录
+-- ----------------------------
+drop table if exists textbook_warehouse_record;
+create table `textbook_warehouse_record`
 (
-    id                               bigint   not null comment '主键编号'
+    id               bigint         not null comment '主键编号'
         primary key,
-    create_user_id                   bigint   null comment '创建人',
-    create_date                      datetime null comment '创建时间',
-    modify_user_id                   bigint   null comment '修改人',
-    modify_date                      datetime null comment '修改时间',
-    delete_mark                      int      not null comment '删除标记',
-    enabled_mark                     int      not null comment '有效标志',
-    sort_code                        int      null comment '序号',
-
-    textbook_subscription_id      bigint   null comment '教材征订编号',
-    textbook_subscription_item_id bigint   null comment '教材征订项编号'
-) engine = innodb
-  default charset = utf8mb4
-  collate = utf8mb4_0900_ai_ci comment ='教材征订记录';
+    create_user_id   bigint         null comment '创建人',
+    create_date      datetime       null comment '创建时间',
+    modify_user_id   bigint         null comment '修改人',
+    modify_date      datetime       null comment '修改时间',
+    delete_mark      int            not null comment '删除标记',
+    enabled_mark     int            not null comment '有效标志',
+    sort_code        int            null comment '序号',
+
+    warehouse_mode   varchar(20)    null comment '入库方式(xjr_dictionary_item[warehouse_mode])',
+    data_id          bigint         null comment '数据编号(根据入库方式,编号来自不同数据表)',
+    data_item_id     bigint         null comment '数据项项编号(根据入库方式,编号来自不同数据表)',
+
+    textbook_id      bigint         null comment '教材管理编号',
+    price            decimal(10, 2) null comment '定价(元)',
+
+    warehouse_number int            null comment '入库数量',
+    source           varchar(200)   null comment '来源',
 
+    discount         float          null comment '实际折扣',
+    subtotal         decimal(10, 2) null comment '实际价格(元)',
+    total_price      decimal(10, 2) null comment '总价(元)',
+
+    remark           varchar(1000)  null comment '备注'
+)engine = innodb
+ default charset = utf8mb4
+ collate = utf8mb4_0900_ai_ci comment ='教材入库记录';
+
+# drop table if exists textbook_subscription_record;
+# create table `textbook_subscription_record`
+# (
+#     id                               bigint   not null comment '主键编号'
+#         primary key,
+#     create_user_id                   bigint   null comment '创建人',
+#     create_date                      datetime null comment '创建时间',
+#     modify_user_id                   bigint   null comment '修改人',
+#     modify_date                      datetime null comment '修改时间',
+#     delete_mark                      int      not null comment '删除标记',
+#     enabled_mark                     int      not null comment '有效标志',
+#     sort_code                        int      null comment '序号',
+#
+#     textbook_subscription_id      bigint   null comment '教材征订编号',
+#     textbook_subscription_item_id bigint   null comment '教材征订项编号'
+# ) engine = innodb
+#   default charset = utf8mb4
+#   collate = utf8mb4_0900_ai_ci comment ='教材征订记录';
 
 create table if not exists tl.textbook_claim_user
 (
@@ -271,30 +305,7 @@ create table if not exists tl.textbook_student_claim
 )
     comment '学生教材认领记录';
 
-create table if not exists tl.textbook_warehouse_record
-(
-    id               bigint         not null comment '主键编号'
-        primary key,
-    create_user_id   bigint         null comment '创建人',
-    create_date      datetime       null comment '创建时间',
-    modify_user_id   bigint         null comment '修改人',
-    modify_date      datetime       null comment '修改时间',
-    delete_mark      int            not null comment '删除标记',
-    enabled_mark     int            not null comment '有效标志',
-    sort_code        int            null comment '序号',
-    textbook_id      bigint         null comment '教材管理编号',
-    data_id          bigint         null comment '数据编号(根据入库方式,编号来自不同数据表)',
-    data_item_id     bigint         null comment '数据项项编号(根据入库方式,编号来自不同数据表)',
-    warehouse_number int            null comment '入库数量',
-    source           varchar(200)   null comment '来源',
-    price            decimal(10, 2) null comment '定价(元)',
-    discount         float          null comment '折扣',
-    subtotal         decimal(10, 2) null comment '小计(元)',
-    total_price      decimal(10, 2) null comment '总价(元)',
-    warehouse_mode   varchar(20)    null comment '入库方式(xjr_dictionary_item[warehouse_mode])',
-    remark           varchar(1000)  null comment '备注'
-)
-    comment '教材入库记录';
+
 
 create table if not exists tl.wf_textbook_claim
 (

+ 26 - 1
src/test/java/com/xjrsoft/xjrsoftboot/FreeMarkerGeneratorTest.java

@@ -1261,7 +1261,7 @@ public class FreeMarkerGeneratorTest {
         params.setPackageName("textbook");//包名
         params.setTableConfigs(tableConfigs);
         params.setPage(true);//是否生成分页接口
-        params.setImport(false);//是否生成导入接口
+        params.setImport(true);//是否生成导入接口
         params.setExport(true);//是否生成导出接口
         params.setOutMainDir(false);//是否生成在主目录,前期测试可设置成false
         params.setDs(ds);
@@ -4121,4 +4121,29 @@ public class FreeMarkerGeneratorTest {
 
         apiGeneratorService.generateCodes(params);
     }
+
+    @Test
+    public void gcTextbookSubscriptionItem() throws IOException {
+        List<TableConfig> tableConfigs = new ArrayList<>();
+        TableConfig mainTable = new TableConfig();
+        mainTable.setTableName("textbook_subscription_item");//init_sql中的表名
+        mainTable.setIsMain(true);//是否是主表,一般默认为true
+        mainTable.setPkField(GlobalConstant.DEFAULT_PK);//设置主键
+        mainTable.setPkType(GlobalConstant.DEFAULT_PK_TYPE);//设置主键类型
+        tableConfigs.add(mainTable);
+
+        ApiGenerateCodesDto params = new ApiGenerateCodesDto();
+        params.setAuthor("dzx");//作者名称
+        params.setPackageName("textbook");//包名
+        params.setTableConfigs(tableConfigs);
+        params.setPage(true);//是否生成分页接口
+        params.setImport(true);//是否生成导入接口
+        params.setExport(true);//是否生成导出接口
+        params.setOutMainDir(false);//是否生成在主目录,前期测试可设置成false
+        params.setDs(ds);
+
+        IApiGeneratorService apiGeneratorService = new ApiGeneratorServiceImpl();
+
+        apiGeneratorService.generateCodes(params);
+    }
 }