Browse Source

代码生成:增加主子表 erp 模式的示例

YunaiV 1 year ago
parent
commit
ee918a6d3f
18 changed files with 349 additions and 191 deletions
  1. 3 0
      yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java
  2. 103 22
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/Demo03StudentController.java
  3. 1 1
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentPageReqVO.java
  4. 1 1
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentRespVO.java
  5. 1 1
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentSaveReqVO.java
  6. 1 3
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/package-info.java
  7. 11 2
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java
  8. 9 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java
  9. 1 1
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java
  10. 3 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
  11. 85 5
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentService.java
  12. 84 13
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java
  13. 11 0
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm
  14. 0 1
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm
  15. 24 3
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm
  16. 2 1
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm
  17. 9 1
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm
  18. 0 136
      yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo03/Demo03StudentServiceImplTest.java

+ 3 - 0
yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java

@@ -67,4 +67,7 @@ public interface ErrorCodeConstants {
     ErrorCode DEMO02_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_001_201_005, "已经存在该名字的示例分类");
     ErrorCode DEMO02_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_001_201_006, "不能设置自己的子示例分类为父示例分类");
     ErrorCode DEMO03_STUDENT_NOT_EXISTS = new ErrorCode(1_001_201_007, "学生不存在");
+    ErrorCode DEMO03_GRADE_NOT_EXISTS = new ErrorCode(1_001_201_008, "学生班级不存在");
+    ErrorCode DEMO03_GRADE_EXISTS = new ErrorCode(1_001_201_009, "学生班级已存在");
+
 }

+ 103 - 22
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/Demo03StudentController.java

@@ -1,34 +1,33 @@
-package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal;
-
-import org.springframework.web.bind.annotation.*;
-import javax.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.security.access.prepost.PreAuthorize;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Operation;
-
-import javax.validation.*;
-import javax.servlet.http.*;
-import java.util.*;
-import java.io.IOException;
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;
 
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
-
-import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo.*;
-import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentRespVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
 import cn.iocoder.yudao.module.infra.service.demo.demo03.Demo03StudentService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Tag(name = "管理后台 - 学生")
 @RestController
@@ -95,6 +94,47 @@ public class Demo03StudentController {
 
     // ==================== 子表(学生课程) ====================
 
+    @GetMapping("/demo03-course/page")
+    @Operation(summary = "获得学生课程分页")
+    @Parameter(name = "studentId", description = "学生编号")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<PageResult<Demo03CourseDO>> getDemo03CoursePage(PageParam pageReqVO,
+                                                                        @RequestParam("studentId") Long studentId) {
+        return success(demo03StudentService.getDemo03CoursePage(pageReqVO, studentId));
+    }
+
+    @PostMapping("/demo03-course/create")
+    @Operation(summary = "创建学生课程")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
+    public CommonResult<Long> createDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) {
+        return success(demo03StudentService.createDemo03Course(demo03Course));
+    }
+
+    @PutMapping("/demo03-course/update")
+    @Operation(summary = "更新学生课程")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
+    public CommonResult<Boolean> updateDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) {
+        demo03StudentService.updateDemo03Course(demo03Course);
+        return success(true);
+    }
+
+    @DeleteMapping("/demo03-course/delete")
+    @Parameter(name = "id", description = "编号", required = true)
+    @Operation(summary = "删除学生课程")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
+    public CommonResult<Boolean> deleteDemo03Course(@RequestParam("id") Long id) {
+        demo03StudentService.deleteDemo03Course(id);
+        return success(true);
+    }
+
+    @GetMapping("/demo03-course/get")
+    @Operation(summary = "获得学生课程")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<Demo03CourseDO> getDemo03Course(@RequestParam("id") Long id) {
+        return success(demo03StudentService.getDemo03Course(id));
+    }
+
     @GetMapping("/demo03-course/list-by-student-id")
     @Operation(summary = "获得学生课程列表")
     @Parameter(name = "studentId", description = "学生编号")
@@ -105,6 +145,47 @@ public class Demo03StudentController {
 
     // ==================== 子表(学生班级) ====================
 
+    @GetMapping("/demo03-grade/page")
+    @Operation(summary = "获得学生班级分页")
+    @Parameter(name = "studentId", description = "学生编号")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<PageResult<Demo03GradeDO>> getDemo03GradePage(PageParam pageReqVO,
+                                                                      @RequestParam("studentId") Long studentId) {
+        return success(demo03StudentService.getDemo03GradePage(pageReqVO, studentId));
+    }
+
+    @PostMapping("/demo03-grade/create")
+    @Operation(summary = "创建学生班级")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
+    public CommonResult<Long> createDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) {
+        return success(demo03StudentService.createDemo03Grade(demo03Grade));
+    }
+
+    @PutMapping("/demo03-grade/update")
+    @Operation(summary = "更新学生班级")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
+    public CommonResult<Boolean> updateDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) {
+        demo03StudentService.updateDemo03Grade(demo03Grade);
+        return success(true);
+    }
+
+    @DeleteMapping("/demo03-grade/delete")
+    @Parameter(name = "id", description = "编号", required = true)
+    @Operation(summary = "删除学生班级")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
+    public CommonResult<Boolean> deleteDemo03Grade(@RequestParam("id") Long id) {
+        demo03StudentService.deleteDemo03Grade(id);
+        return success(true);
+    }
+
+    @GetMapping("/demo03-grade/get")
+    @Operation(summary = "获得学生班级")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<Demo03GradeDO> getDemo03Grade(@RequestParam("id") Long id) {
+        return success(demo03StudentService.getDemo03Grade(id));
+    }
+
     @GetMapping("/demo03-grade/get-by-student-id")
     @Operation(summary = "获得学生班级")
     @Parameter(name = "studentId", description = "学生编号")

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentPageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo;
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
 
 import lombok.*;
 import io.swagger.v3.oas.annotations.media.Schema;

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentRespVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo;
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentSaveReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo;
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;

+ 1 - 3
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/package-info.java

@@ -3,8 +3,6 @@
  *
  * 1. demo01:单表(增删改查)
  * 2. demo02:单表(树形结构)
- * 3.1 demo03/normal:主子表(标准模式)
- * 3.2 demo03/erp:主子表(ERP 模式)
- * 3.3 demo03/inner:主子表(内嵌模式)
+ * 3. demo03:主子表(标准模式)+ 主子表(ERP 模式)+ 主子表(内嵌模式)
  */
 package cn.iocoder.yudao.module.infra.controller.admin.demo;

+ 11 - 2
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java

@@ -1,11 +1,14 @@
 package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03;
 
-import java.util.*;
-
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * 学生课程 Mapper
  *
@@ -14,6 +17,12 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface Demo03CourseMapper extends BaseMapperX<Demo03CourseDO> {
 
+    default PageResult<Demo03CourseDO> selectPage(PageParam reqVO, Long studentId) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<Demo03CourseDO>()
+                .eq(Demo03CourseDO::getStudentId, studentId)
+                .orderByDesc(Demo03CourseDO::getId));
+    }
+
     default List<Demo03CourseDO> selectListByStudentId(Long studentId) {
         return selectList(Demo03CourseDO::getStudentId, studentId);
     }

+ 9 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java

@@ -1,6 +1,9 @@
 package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03;
 
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
 import org.apache.ibatis.annotations.Mapper;
 
@@ -12,6 +15,12 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface Demo03GradeMapper extends BaseMapperX<Demo03GradeDO> {
 
+    default PageResult<Demo03GradeDO> selectPage(PageParam reqVO, Long studentId) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<Demo03GradeDO>()
+                .eq(Demo03GradeDO::getStudentId, studentId)
+                .orderByDesc(Demo03GradeDO::getId));
+    }
+
     default Demo03GradeDO selectByStudentId(Long studentId) {
         return selectOne(Demo03GradeDO::getStudentId, studentId);
     }

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
 import org.apache.ibatis.annotations.Mapper;
-import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo.*;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.*;
 
 /**
  * 学生 Mapper

+ 3 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java

@@ -344,6 +344,7 @@ public class CodegenEngine {
             List<String> subJoinColumnStrikeCases = new ArrayList<>();
             List<String> subSimpleClassNames = new ArrayList<>();
             List<String> subClassNameVars = new ArrayList<>();
+            List<String> simpleClassNameUnderlineCases = new ArrayList<>();
             List<String> subSimpleClassNameStrikeCases = new ArrayList<>();
             for (int i = 0; i < subTables.size(); i++) {
                 CodegenTableDO subTable = subTables.get(i);
@@ -356,6 +357,7 @@ public class CodegenEngine {
                 // className 相关
                 String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName()));
                 subSimpleClassNames.add(subSimpleClassName);
+                simpleClassNameUnderlineCases.add(toUnderlineCase(subSimpleClassName)); // 将 DictType 转换成 dict_type
                 subClassNameVars.add(lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType,用于变量
                 subSimpleClassNameStrikeCases.add(toSymbolCase(subSimpleClassName, '-')); // 将 DictType 转换成 dict-type
             }
@@ -363,6 +365,7 @@ public class CodegenEngine {
             bindingMap.put("subJoinColumns", subJoinColumns);
             bindingMap.put("subJoinColumn_strikeCases", subJoinColumnStrikeCases);
             bindingMap.put("subSimpleClassNames", subSimpleClassNames);
+            bindingMap.put("simpleClassNameUnderlineCases", simpleClassNameUnderlineCases);
             bindingMap.put("subClassNameVars", subClassNameVars);
             bindingMap.put("subSimpleClassName_strikeCases", subSimpleClassNameStrikeCases);
         }

+ 85 - 5
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentService.java

@@ -1,12 +1,15 @@
 package cn.iocoder.yudao.module.infra.service.demo.demo03;
 
-import java.util.*;
-import javax.validation.*;
-import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo.*;
-import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
 import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+
+import javax.validation.Valid;
+import java.util.List;
 
 /**
  * 学生 Service 接口
@@ -64,6 +67,44 @@ public interface Demo03StudentService {
      */
     List<Demo03CourseDO> getDemo03CourseListByStudentId(Long studentId);
 
+    /**
+     * 获得学生课程分页
+     *
+     * @param pageReqVO 分页查询
+     * @param studentId 学生编号
+     * @return 学生课程分页
+     */
+    PageResult<Demo03CourseDO> getDemo03CoursePage(PageParam pageReqVO, Long studentId);
+
+    /**
+     * 创建学生课程
+     *
+     * @param demo03Course 创建信息
+     * @return 编号
+     */
+    Long createDemo03Course(@Valid Demo03CourseDO demo03Course);
+
+    /**
+     * 更新学生课程
+     *
+     * @param demo03Course 更新信息
+     */
+    void updateDemo03Course(@Valid Demo03CourseDO demo03Course);
+
+    /**
+     * 删除学生课程
+     *
+     * @param id 编号
+     */
+    void deleteDemo03Course(Long id);
+
+    /**
+     * 获得学生课程
+     *
+     * @param id 编号
+     * @return 学生课程
+     */
+    Demo03CourseDO getDemo03Course(Long id);
 
     // ==================== 子表(学生班级) ====================
 
@@ -75,4 +116,43 @@ public interface Demo03StudentService {
      */
     Demo03GradeDO getDemo03GradeByStudentId(Long studentId);
 
+    /**
+     * 获得学生班级分页
+     *
+     * @param pageReqVO 分页查询
+     * @param studentId 学生编号
+     * @return 学生班级分页
+     */
+    PageResult<Demo03GradeDO> getDemo03GradePage(PageParam pageReqVO, Long studentId);
+
+    /**
+     * 创建学生班级
+     *
+     * @param demo03Grade 创建信息
+     * @return 编号
+     */
+    Long createDemo03Grade(@Valid Demo03GradeDO demo03Grade);
+
+    /**
+     * 更新学生班级
+     *
+     * @param demo03Grade 更新信息
+     */
+    void updateDemo03Grade(@Valid Demo03GradeDO demo03Grade);
+
+    /**
+     * 删除学生班级
+     *
+     * @param id 编号
+     */
+    void deleteDemo03Grade(Long id);
+
+    /**
+     * 获得学生班级
+     *
+     * @param id 编号
+     * @return 学生班级
+     */
+    Demo03GradeDO getDemo03Grade(Long id);
+
 }

+ 84 - 13
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java

@@ -1,21 +1,22 @@
 package cn.iocoder.yudao.module.infra.service.demo.demo03;
 
-import org.springframework.stereotype.Service;
-import javax.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo.*;
-import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
-import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
-import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-
-import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
 import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03CourseMapper;
 import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03GradeMapper;
+import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
@@ -101,7 +102,9 @@ public class Demo03StudentServiceImpl implements Demo03StudentService {
     }
 
     private void createDemo03CourseList(Long studentId, List<Demo03CourseDO> list) {
-        list.forEach(o -> o.setStudentId(studentId));
+        if (list != null) {
+            list.forEach(o -> o.setStudentId(studentId));
+        }
         demo03CourseMapper.insertBatch(list);
     }
 
@@ -115,6 +118,32 @@ public class Demo03StudentServiceImpl implements Demo03StudentService {
         demo03CourseMapper.deleteByStudentId(studentId);
     }
 
+    @Override
+    public PageResult<Demo03CourseDO> getDemo03CoursePage(PageParam pageReqVO, Long studentId) {
+        return demo03CourseMapper.selectPage(pageReqVO, studentId);
+    }
+
+    @Override
+    public Long createDemo03Course(Demo03CourseDO demo03Course) {
+        demo03CourseMapper.insert(demo03Course);
+        return demo03Course.getId();
+    }
+
+    @Override
+    public void updateDemo03Course(Demo03CourseDO demo03Course) {
+        demo03CourseMapper.updateById(demo03Course);
+    }
+
+    @Override
+    public void deleteDemo03Course(Long id) {
+        demo03CourseMapper.deleteById(id);
+    }
+
+    @Override
+    public Demo03CourseDO getDemo03Course(Long id) {
+        return demo03CourseMapper.selectById(id);
+    }
+
     // ==================== 子表(学生班级) ====================
 
     @Override
@@ -143,4 +172,46 @@ public class Demo03StudentServiceImpl implements Demo03StudentService {
         demo03GradeMapper.deleteByStudentId(studentId);
     }
 
+    @Override
+    public PageResult<Demo03GradeDO> getDemo03GradePage(PageParam pageReqVO, Long studentId) {
+        return demo03GradeMapper.selectPage(pageReqVO, studentId);
+    }
+
+    @Override
+    public Long createDemo03Grade(Demo03GradeDO demo03Grade) {
+        // 校验是否已经存在
+        if (demo03GradeMapper.selectByStudentId(demo03Grade.getStudentId()) != null) {
+            throw exception(DEMO03_GRADE_EXISTS);
+        }
+        demo03GradeMapper.insert(demo03Grade);
+        return demo03Grade.getId();
+    }
+
+    @Override
+    public void updateDemo03Grade(Demo03GradeDO demo03Grade) {
+        // 校验存在
+        validateDemo03GradeExists(demo03Grade.getId());
+        // 更新
+        demo03GradeMapper.updateById(demo03Grade);
+    }
+
+    @Override
+    public void deleteDemo03Grade(Long id) {
+        // 校验存在
+        validateDemo03GradeExists(id);
+        // 删除
+        demo03GradeMapper.deleteById(id);
+    }
+
+    @Override
+    public Demo03GradeDO getDemo03Grade(Long id) {
+        return demo03GradeMapper.selectById(id);
+    }
+
+    private void validateDemo03GradeExists(Long id) {
+        if (demo03GradeMapper.selectById(id) == null) {
+            throw exception(DEMO03_GRADE_NOT_EXISTS);
+        }
+    }
+
 }

+ 11 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm

@@ -8,4 +8,15 @@ ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS = new
 ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父${table.classComment}");
 ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该${treeNameColumn.columnComment}的${table.classComment}");
 ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD = new ErrorCode(TODO 补充编号, "不能设置自己的子${table.className}为父${table.className}");
+#end
+## 特殊:主子表专属逻辑
+#if ( $table.templateType == 11 )## 特殊:ERP 情况
+#foreach ($subTable in $subTables)
+#set ($index = $foreach.count - 1)
+#set ($simpleClassNameUnderlineCase = $simpleClassNameUnderlineCases.get($index))
+ErrorCode ${simpleClassNameUnderlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${subTable.classComment}不存在");
+#if ( !$subTable.subJoinMany )
+ErrorCode ${simpleClassNameUnderlineCase.toUpperCase()}_EXISTS = new ErrorCode(TODO 补充编号, "${subTable.classComment}已存在");
+#end
+#end
 #end

+ 0 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm

@@ -75,7 +75,6 @@ public interface ${table.className}Service {
 #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
 #set ($subClassNameVar = $subClassNameVars.get($index))
-
     // ==================== 子表($subTable.classComment) ====================
 
 ## 情况一:MASTER_ERP 时,需要分查询页子表

+ 24 - 3
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm

@@ -235,6 +235,7 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
 #foreach ($subTable in $subTables)
 #set ($index = $foreach.count - 1)
 #set ($subSimpleClassName = $subSimpleClassNames.get($index))
+#set ($simpleClassNameUnderlineCase = $simpleClassNameUnderlineCases.get($index))
 #set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
 #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
@@ -268,24 +269,44 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
 #if ( $table.templateType == 11 )
     @Override
     public ${subPrimaryColumn.javaType} create${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) {
+## 特殊:一对一时,需要保证只有一条,不能重复插入
+#if ( !$subTable.subJoinMany)
+        // 校验是否已经存在
+        if (${subClassNameVars.get($index)}Mapper.selectBy${SubJoinColumnName}(${subClassNameVar}.get${SubJoinColumnName}()) != null) {
+            throw exception(${simpleClassNameUnderlineCase.toUpperCase()}_EXISTS);
+        }
+        // 插入
+#end
         ${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar});
         return ${subClassNameVar}.getId();
     }
 
     @Override
     public void update${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) {
+        // 校验存在
+        validate${subSimpleClassName}Exists(${subClassNameVar}.getId());
+        // 更新
         ${subClassNameVars.get($index)}Mapper.updateById(${subClassNameVar});
     }
 
     @Override
     public void delete${subSimpleClassName}(${subPrimaryColumn.javaType} id) {
+        // 校验存在
+        validate${subSimpleClassName}Exists(id);
+        // 删除
         ${subClassNameVars.get($index)}Mapper.deleteById(id);
     }
 
-	@Override
-	public ${subTable.className}DO get${subSimpleClassName}(${subPrimaryColumn.javaType} id) {
+    @Override
+    public ${subTable.className}DO get${subSimpleClassName}(${subPrimaryColumn.javaType} id) {
         return ${subClassNameVars.get($index)}Mapper.selectById(id);
-	}
+    }
+
+    private void validate${subSimpleClassName}Exists(${subPrimaryColumn.javaType} id) {
+        if (${subClassNameVar}Mapper.selectById(id) == null) {
+            throw exception(${simpleClassNameUnderlineCase.toUpperCase()}_NOT_EXISTS);
+        }
+    }
 
 ## 情况二:非 MASTER_ERP 时,支持批量的新增、修改操作
 #else

+ 2 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm

@@ -25,7 +25,8 @@
         #elseif ($javaType == "Boolean")
             #set ($dictMethod = "getBoolDictOptions")
         #end
-        #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 TODO 芋艿:这里要忽略下 join 字段;
+        #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
+        #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
       <el-form-item label="${comment}" prop="${javaField}">
         <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
       </el-form-item>

+ 9 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm

@@ -118,7 +118,7 @@
 #end
     </el-form>
 ## 特殊:主子表专属逻辑
-#if ( $subTables && $subTables.size() > 0 )
+#if ( $table.templateType == 10 || $table.templateType == 12 )
     <!-- 子表的表单 -->
     <el-tabs v-model="subTabsName">
     #foreach ($subTable in $subTables)
@@ -146,9 +146,11 @@ import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.busine
 import { defaultProps, handleTree } from '@/utils/tree'
 #end
 ## 特殊:主子表专属逻辑
+#if ( $table.templateType == 10 || $table.templateType == 12 )
 #foreach ($subSimpleClassName in $subSimpleClassNames)
 import ${subSimpleClassName}Form from './components/${subSimpleClassName}Form.vue'
 #end
+#end
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
@@ -182,6 +184,7 @@ const formRef = ref() // 表单 Ref
 const ${classNameVar}Tree = ref() // 树形结构
 #end
 ## 特殊:主子表专属逻辑
+#if ( $table.templateType == 10 || $table.templateType == 12 )
 #if ( $subTables && $subTables.size() > 0 )
 
 /** 子表的表单 */
@@ -190,6 +193,7 @@ const subTabsName = ref('$subClassNameVars.get(0)')
 const ${subClassNameVar}FormRef = ref()
 #end
 #end
+#end
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
@@ -219,6 +223,7 @@ const submitForm = async () => {
   // 校验表单
   await formRef.value.validate()
 ## 特殊:主子表专属逻辑
+#if ( $table.templateType == 10 || $table.templateType == 12 )
 #if ( $subTables && $subTables.size() > 0 )
   // 校验子表单
   #foreach ($subTable in $subTables)
@@ -232,11 +237,13 @@ const submitForm = async () => {
   }
   #end
 #end
+#end
   // 提交请求
   formLoading.value = true
   try {
     const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO
 ## 特殊:主子表专属逻辑
+#if ( $table.templateType == 10 || $table.templateType == 12 )
 #if ( $subTables && $subTables.size() > 0 )
     // 拼接子表的数据
   #foreach ($subTable in $subTables)
@@ -245,6 +252,7 @@ const submitForm = async () => {
     data.${subClassNameVar}#if ( $subTable.subJoinMany)s#end = ${subClassNameVar}FormRef.value.getData()
   #end
 #end
+#end
     if (formType.value === 'create') {
       await ${simpleClassName}Api.create${simpleClassName}(data)
       message.success(t('common.createSuccess'))

+ 0 - 136
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo03/Demo03StudentServiceImplTest.java

@@ -1,136 +0,0 @@
-package cn.iocoder.yudao.module.infra.service.demo03;
-
-import cn.iocoder.yudao.module.infra.service.demo.demo03.Demo03StudentServiceImpl;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import javax.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo.*;
-import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
-import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link Demo03StudentServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(Demo03StudentServiceImpl.class)
-public class Demo03StudentServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private Demo03StudentServiceImpl demo03StudentService;
-
-    @Resource
-    private Demo03StudentMapper demo03StudentMapper;
-
-    @Test
-    public void testCreateDemo03Student_success() {
-        // 准备参数
-        Demo03StudentSaveReqVO createReqVO = randomPojo(Demo03StudentSaveReqVO.class).setId(null);
-
-        // 调用
-        Long demo03StudentId = demo03StudentService.createDemo03Student(createReqVO);
-        // 断言
-        assertNotNull(demo03StudentId);
-        // 校验记录的属性是否正确
-        Demo03StudentDO demo03Student = demo03StudentMapper.selectById(demo03StudentId);
-        assertPojoEquals(createReqVO, demo03Student, "id");
-    }
-
-    @Test
-    public void testUpdateDemo03Student_success() {
-        // mock 数据
-        Demo03StudentDO dbDemo03Student = randomPojo(Demo03StudentDO.class);
-        demo03StudentMapper.insert(dbDemo03Student);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Demo03StudentSaveReqVO updateReqVO = randomPojo(Demo03StudentSaveReqVO.class, o -> {
-            o.setId(dbDemo03Student.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        demo03StudentService.updateDemo03Student(updateReqVO);
-        // 校验是否更新正确
-        Demo03StudentDO demo03Student = demo03StudentMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, demo03Student);
-    }
-
-    @Test
-    public void testUpdateDemo03Student_notExists() {
-        // 准备参数
-        Demo03StudentSaveReqVO updateReqVO = randomPojo(Demo03StudentSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> demo03StudentService.updateDemo03Student(updateReqVO), DEMO03_STUDENT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteDemo03Student_success() {
-        // mock 数据
-        Demo03StudentDO dbDemo03Student = randomPojo(Demo03StudentDO.class);
-        demo03StudentMapper.insert(dbDemo03Student);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbDemo03Student.getId();
-
-        // 调用
-        demo03StudentService.deleteDemo03Student(id);
-       // 校验数据不存在了
-       assertNull(demo03StudentMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteDemo03Student_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> demo03StudentService.deleteDemo03Student(id), DEMO03_STUDENT_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetDemo03StudentPage() {
-       // mock 数据
-       Demo03StudentDO dbDemo03Student = randomPojo(Demo03StudentDO.class, o -> { // 等会查询到
-           o.setName(null);
-           o.setSex(null);
-           o.setDescription(null);
-           o.setCreateTime(null);
-       });
-       demo03StudentMapper.insert(dbDemo03Student);
-       // 测试 name 不匹配
-       demo03StudentMapper.insert(cloneIgnoreId(dbDemo03Student, o -> o.setName(null)));
-       // 测试 sex 不匹配
-       demo03StudentMapper.insert(cloneIgnoreId(dbDemo03Student, o -> o.setSex(null)));
-       // 测试 description 不匹配
-       demo03StudentMapper.insert(cloneIgnoreId(dbDemo03Student, o -> o.setDescription(null)));
-       // 测试 createTime 不匹配
-       demo03StudentMapper.insert(cloneIgnoreId(dbDemo03Student, o -> o.setCreateTime(null)));
-       // 准备参数
-       Demo03StudentPageReqVO reqVO = new Demo03StudentPageReqVO();
-       reqVO.setName(null);
-       reqVO.setSex(null);
-       reqVO.setDescription(null);
-       reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
-
-       // 调用
-       PageResult<Demo03StudentDO> pageResult = demo03StudentService.getDemo03StudentPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbDemo03Student, pageResult.getList().get(0));
-    }
-
-}