diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/common/ErrorCodeConstants.java b/dl-module-base/src/main/java/cn/iocoder/yudao/common/ErrorCodeConstants.java new file mode 100644 index 00000000..7a1c402d --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/common/ErrorCodeConstants.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.common; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +public interface ErrorCodeConstants { + ErrorCode BASE_TYPE_NOT_EXISTS = new ErrorCode(500, "配置类型不存在"); + ErrorCode BASE_TYPE_EXITS_CHILDREN = new ErrorCode(500, "存在存在子配置类型,无法删除"); + ErrorCode BASE_TYPE_PARENT_NOT_EXITS = new ErrorCode(500,"父级配置类型不存在"); + ErrorCode BASE_TYPE_PARENT_ERROR = new ErrorCode(500, "不能设置自己为父配置类型"); + ErrorCode BASE_TYPE_NAME_DUPLICATE = new ErrorCode(500, "已经存在该分类名称的配置类型"); + ErrorCode BASE_TYPE_PARENT_IS_CHILD = new ErrorCode(500, "不能设置自己的子BaseType为父BaseType"); +} diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/controller/admin/BaseTypeController.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/controller/admin/BaseTypeController.java new file mode 100644 index 00000000..1f56da92 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/controller/admin/BaseTypeController.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.conf.controller.admin; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.conf.entity.BaseType; +import cn.iocoder.yudao.module.conf.service.BaseTypeService; +import cn.iocoder.yudao.module.conf.vo.BaseTypeListReqVO; +import cn.iocoder.yudao.module.conf.vo.BaseTypeRespVO; +import cn.iocoder.yudao.module.conf.vo.BaseTypeSaveReqVO; +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.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 配置类型") +@RestController +@RequestMapping("/conf/baseType") +@Validated +public class BaseTypeController { + + @Resource + private BaseTypeService baseTypeService; + + @PostMapping("/create") + @Operation(summary = "创建配置类型") + @PreAuthorize("@ss.hasPermission('conf:base-type:create')") + public CommonResult createBaseType(@Valid @RequestBody BaseTypeSaveReqVO createReqVO) { + return success(baseTypeService.createBaseType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新配置类型") + @PreAuthorize("@ss.hasPermission('conf:base-type:update')") + public CommonResult updateBaseType(@Valid @RequestBody BaseTypeSaveReqVO updateReqVO) { + baseTypeService.updateBaseType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除配置类型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('conf:base-type:delete')") + public CommonResult deleteBaseType(@RequestParam("id") String id) { + baseTypeService.deleteBaseType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得配置类型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('conf:base-type:query')") + public CommonResult getBaseType(@RequestParam("id") String id) { + BaseType baseType = baseTypeService.getBaseType(id); + return success(BeanUtils.toBean(baseType, BaseTypeRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得配置类型列表") + @PreAuthorize("@ss.hasPermission('conf:base-type:query')") + public CommonResult> getBaseTypeList(@Valid BaseTypeListReqVO listReqVO) { + List list = baseTypeService.getBaseTypeList(listReqVO); + return success(BeanUtils.toBean(list, BaseTypeRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出配置类型 Excel") + @PreAuthorize("@ss.hasPermission('conf:base-type:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportBaseTypeExcel(@Valid BaseTypeListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = baseTypeService.getBaseTypeList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "配置类型.xls", "数据", BaseTypeRespVO.class, + BeanUtils.toBean(list, BaseTypeRespVO.class)); + } + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/entity/BaseType.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/entity/BaseType.java new file mode 100644 index 00000000..500da7d7 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/entity/BaseType.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.conf.entity; + +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 配置类型 DO + * + * @author pqz + */ +@TableName("dl_base_type") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BaseType extends TenantBaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 主键标识 + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + /** + * 父iid + */ + private String parentId; + /** + * 分类名称 + */ + private String name; + /** + * 分类编码 + */ + private String code; + /** + * 类型(01账目分类;02配件分类;03服务分类) + */ + private String type; + /** + * 备注 + */ + private String remark; + /** + * 关联供应商id + */ + private String corpId; + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/mapper/BaseTypeMapper.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/mapper/BaseTypeMapper.java new file mode 100644 index 00000000..93e1540b --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/mapper/BaseTypeMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.conf.mapper; + +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.conf.entity.BaseType; +import cn.iocoder.yudao.module.conf.vo.BaseTypeListReqVO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 配置类型 Mapper + * + * @author pqz + */ +@Mapper +public interface BaseTypeMapper extends BaseMapper { + + default List selectList(BaseTypeListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(BaseType::getParentId, reqVO.getParentId()) + .likeIfPresent(BaseType::getName, reqVO.getName()) + .eqIfPresent(BaseType::getCode, reqVO.getCode()) + .eqIfPresent(BaseType::getType, reqVO.getType()) + .eqIfPresent(BaseType::getRemark, reqVO.getRemark()) + .eqIfPresent(BaseType::getCorpId, reqVO.getCorpId()) + .betweenIfPresent(BaseType::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(BaseType::getId)); + } + + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/service/BaseTypeService.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/service/BaseTypeService.java new file mode 100644 index 00000000..01bf3ad1 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/service/BaseTypeService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.conf.service; + +import cn.iocoder.yudao.module.conf.entity.BaseType; +import cn.iocoder.yudao.module.conf.vo.BaseTypeListReqVO; +import cn.iocoder.yudao.module.conf.vo.BaseTypeSaveReqVO; +import com.baomidou.mybatisplus.extension.service.IService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 配置类型 Service 接口 + * + * @author pqz + */ +public interface BaseTypeService extends IService { + + /** + * 创建配置类型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + String createBaseType(@Valid BaseTypeSaveReqVO createReqVO); + + /** + * 更新配置类型 + * + * @param updateReqVO 更新信息 + */ + void updateBaseType(@Valid BaseTypeSaveReqVO updateReqVO); + + /** + * 删除配置类型 + * + * @param id 编号 + */ + void deleteBaseType(String id); + + /** + * 获得配置类型 + * + * @param id 编号 + * @return 配置类型 + */ + BaseType getBaseType(String id); + + /** + * 获得配置类型列表 + * + * @param listReqVO 查询条件 + * @return 配置类型列表 + */ + List getBaseTypeList(BaseTypeListReqVO listReqVO); + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/service/impl/BaseTypeServiceImpl.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/service/impl/BaseTypeServiceImpl.java new file mode 100644 index 00000000..f26c5a60 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/service/impl/BaseTypeServiceImpl.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.conf.service.impl; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.conf.entity.BaseType; +import cn.iocoder.yudao.module.conf.mapper.BaseTypeMapper; +import cn.iocoder.yudao.module.conf.service.BaseTypeService; +import cn.iocoder.yudao.module.conf.vo.BaseTypeListReqVO; +import cn.iocoder.yudao.module.conf.vo.BaseTypeSaveReqVO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.common.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; + +/** + * 配置类型 Service 实现类 + * + * @author pqz + */ +@Service +@Validated +public class BaseTypeServiceImpl extends ServiceImpl implements BaseTypeService { + + @Resource + private BaseTypeMapper baseTypeMapper; + + @Override + public String createBaseType(BaseTypeSaveReqVO createReqVO) { + // 校验父iid的有效性 + validateParentBaseType(null, createReqVO.getParentId()); + // 校验分类名称的唯一性 + validateBaseTypeNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + BaseType baseType = BeanUtils.toBean(createReqVO, BaseType.class); + baseTypeMapper.insert(baseType); + // 返回 + return baseType.getId(); + } + + @Override + public void updateBaseType(BaseTypeSaveReqVO updateReqVO) { + // 校验存在 + validateBaseTypeExists(updateReqVO.getId()); + // 校验父iid的有效性 + validateParentBaseType(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验分类名称的唯一性 + validateBaseTypeNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + BaseType updateObj = BeanUtils.toBean(updateReqVO, BaseType.class); + baseTypeMapper.updateById(updateObj); + } + + @Override + public void deleteBaseType(String id) { + // 校验存在 + validateBaseTypeExists(id); + // 校验是否有子配置类型 + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(BaseType::getParentId,id); + List list = list(lambdaQueryWrapper); + if (list.size() > 0) { + throw exception(BASE_TYPE_EXITS_CHILDREN); + } + // 删除 + baseTypeMapper.deleteById(id); + } + + private void validateBaseTypeExists(String id) { + if (baseTypeMapper.selectById(id) == null) { + throw exception(BASE_TYPE_NOT_EXISTS); + } + } + + private void validateParentBaseType(String id, String parentId) { + if (parentId == null ) { + return; + } + // 1. 不能设置自己为父配置类型 + if (Objects.equals(id, parentId)) { + throw exception(BASE_TYPE_PARENT_ERROR); + } + // 2. 父配置类型不存在 + BaseType parentBaseType = baseTypeMapper.selectById(parentId); + if (parentBaseType == null) { + throw exception(BASE_TYPE_PARENT_NOT_EXITS); + } + // 3. 递归校验父配置类型,如果父配置类型是自己的子配置类型,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentBaseType.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(BASE_TYPE_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父配置类型 + if (parentId == null ) { + break; + } + parentBaseType = baseTypeMapper.selectById(parentId); + if (parentBaseType == null) { + break; + } + } + } + + private void validateBaseTypeNameUnique(String id, String parentId, String name) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(BaseType::getParentId,parentId).eq(BaseType::getName,name); + BaseType baseType = getOne(lambdaQueryWrapper); + if (baseType == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的配置类型 + if (id == null) { + throw exception(BASE_TYPE_NAME_DUPLICATE); + } + if (!Objects.equals(baseType.getId(), id)) { + throw exception(BASE_TYPE_NAME_DUPLICATE); + } + } + + @Override + public BaseType getBaseType(String id) { + return baseTypeMapper.selectById(id); + } + + @Override + public List getBaseTypeList(BaseTypeListReqVO listReqVO) { + return baseTypeMapper.selectList(listReqVO); + } + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeListReqVO.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeListReqVO.java new file mode 100644 index 00000000..2fd188d4 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeListReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.conf.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.time.LocalDateTime; +import org.springframework.format.annotation.DateTimeFormat; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 配置类型列表 Request VO") +@Data +public class BaseTypeListReqVO { + + @Schema(description = "父iid", example = "21252") + private String parentId; + + @Schema(description = "分类名称", example = "赵六") + private String name; + + @Schema(description = "分类编码") + private String code; + + @Schema(description = "类型(01账目分类;02配件分类;03服务分类)", example = "1") + private String type; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "关联供应商id", example = "14355") + private String corpId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeRespVO.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeRespVO.java new file mode 100644 index 00000000..c57594c9 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeRespVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.conf.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 配置类型 Response VO") +@Data +@ExcelIgnoreUnannotated +public class BaseTypeRespVO { + + @Schema(description = "父iid", example = "21252") + @ExcelProperty("父iid") + private String parentId; + + @Schema(description = "分类名称", example = "赵六") + @ExcelProperty("分类名称") + private String name; + + @Schema(description = "分类编码") + @ExcelProperty("分类编码") + private String code; + + @Schema(description = "类型(01账目分类;02配件分类;03服务分类)", example = "1") + @ExcelProperty("类型(01账目分类;02配件分类;03服务分类)") + private String type; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "关联供应商id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14355") + @ExcelProperty("关联供应商id") + private String corpId; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeSaveReqVO.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeSaveReqVO.java new file mode 100644 index 00000000..ea360410 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/conf/vo/BaseTypeSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.conf.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 配置类型新增/修改 Request VO") +@Data +public class BaseTypeSaveReqVO { + + private String id; + @Schema(description = "父iid", example = "21252") + private String parentId; + + @Schema(description = "分类名称", example = "赵六") + private String name; + + @Schema(description = "分类编码") + private String code; + + @Schema(description = "类型(01账目分类;02配件分类;03服务分类)", example = "1") + private String type; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + @NotEmpty(message = "备注不能为空") + private String remark; + + @Schema(description = "关联供应商id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14355") + @NotEmpty(message = "关联供应商id不能为空") + private String corpId; + +} \ No newline at end of file diff --git a/dl-module-base/src/main/resources/mapper/baseType/BaseTypeMapper.xml b/dl-module-base/src/main/resources/mapper/baseType/BaseTypeMapper.xml new file mode 100644 index 00000000..f3d151eb --- /dev/null +++ b/dl-module-base/src/main/resources/mapper/baseType/BaseTypeMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file