feat: 项目管理项目名称和编码唯一;生成编码sn

This commit is contained in:
caiyuchao
2025-06-30 17:43:19 +08:00
parent 4b7cc83f15
commit d07a7e761a
8 changed files with 132 additions and 27 deletions

View File

@@ -12,4 +12,6 @@ public interface ErrorCodeConstants {
ErrorCode CUSTOMER_NAME_DUPLICATE = new ErrorCode(1_100_001_002, "客户名称`{}`已存在");
ErrorCode CUSTOMER_CODE_DUPLICATE = new ErrorCode(1_100_001_003, "客户编号`{}`已存在");
ErrorCode PROJECT_NOT_EXISTS = new ErrorCode(1_100_002_001, "项目不存在");
ErrorCode PROJECT_NAME_DUPLICATE = new ErrorCode(1_100_001_002, "项目名称`{}`已存在");
ErrorCode PROJECT_CODE_DUPLICATE = new ErrorCode(1_100_001_003, "项目编号`{}`已存在");
}

View File

@@ -98,4 +98,23 @@ public class ProjectController {
TranslateUtils.translate(BeanUtils.toBean(list, ProjectRespVO.class)));
}
@GetMapping("/name-unique")
@Operation(summary = "校验项目名称是否唯一")
public CommonResult<Boolean> validateProjectNameUnique(@RequestParam(value = "name", required = false) String name, @RequestParam(value = "id", required = false) Long id) {
Boolean isExists = projectService.validateProjectNameUnique(name, id);
return success(isExists);
}
@GetMapping("/code-unique")
@Operation(summary = "校验项目编号是否唯一")
public CommonResult<Boolean> validateProjectCodeUnique(@RequestParam(value = "code", required = false) String code, @RequestParam(value = "id", required = false) Long id) {
Boolean isExists = projectService.validateProjectCodeUnique(code, id);
return success(isExists);
}
@GetMapping("/max-sn")
@Operation(summary = "返回当前最大项目sn")
public CommonResult<Integer> selectMaxCode() {
return success(projectService.selectMaxCode());
}
}

View File

@@ -37,7 +37,7 @@ public class ProjectRespVO implements VO {
@Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
@ExcelProperty("项目编号")
private String code;
private Long code;
@Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1111")
@ExcelProperty("合同编号")

View File

@@ -1,13 +1,11 @@
package org.agt.module.license.dal.mysql.project;
import java.util.*;
import org.agt.framework.common.pojo.PageResult;
import org.agt.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.agt.framework.mybatis.core.mapper.BaseMapperX;
import org.agt.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.agt.module.license.controller.admin.project.vo.ProjectPageReqVO;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
import org.apache.ibatis.annotations.Mapper;
import org.agt.module.license.controller.admin.project.vo.*;
/**
* 项目 Mapper
@@ -36,4 +34,13 @@ public interface ProjectMapper extends BaseMapperX<ProjectDO> {
.orderByDesc(ProjectDO::getId));
}
default ProjectDO selectByName(String name) {
return selectOne(ProjectDO::getName, name);
}
default ProjectDO selectByCode(String code) {
return selectOne(ProjectDO::getCode, code);
}
Integer selectMaxCode();
}

View File

@@ -81,7 +81,7 @@ public interface CustomerService {
/**
* 查询当前最大的sn号
*
* @return
* @return 最大sn号
*/
Integer selectMaxCode();
}

View File

@@ -1,11 +1,10 @@
package org.agt.module.license.service.project;
import java.util.*;
import jakarta.validation.*;
import org.agt.module.license.controller.admin.project.vo.*;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
import jakarta.validation.Valid;
import org.agt.framework.common.pojo.PageResult;
import org.agt.framework.common.pojo.PageParam;
import org.agt.module.license.controller.admin.project.vo.ProjectPageReqVO;
import org.agt.module.license.controller.admin.project.vo.ProjectSaveReqVO;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
/**
* 项目 Service 接口
@@ -52,4 +51,28 @@ public interface ProjectService {
*/
PageResult<ProjectDO> getProjectPage(ProjectPageReqVO pageReqVO);
/**
* 校验项目名称是否唯一
*
* @param name 项目名称
* @param id 项目id
* @return 是否存在
*/
Boolean validateProjectNameUnique(String name, Long id);
/**
* 校验项目编号是否唯一
*
* @param code 项目编号
* @param id 项目id
* @return 是否存在
*/
Boolean validateProjectCodeUnique(String code, Long id);
/**
* 查询当前最大的sn号
*
* @return 最大sn号
*/
Integer selectMaxCode();
}

View File

@@ -1,21 +1,20 @@
package org.agt.module.license.service.project;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import org.agt.module.license.controller.admin.project.vo.*;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
import org.agt.framework.common.pojo.PageResult;
import org.agt.framework.common.pojo.PageParam;
import org.agt.framework.common.util.object.BeanUtils;
import org.agt.module.license.controller.admin.project.vo.ProjectPageReqVO;
import org.agt.module.license.controller.admin.project.vo.ProjectSaveReqVO;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
import org.agt.module.license.dal.mysql.project.ProjectMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
import static org.agt.module.license.enums.ErrorCodeConstants.*;
import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_CODE_DUPLICATE;
import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_NAME_DUPLICATE;
import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_NOT_EXISTS;
/**
* 项目 Service 实现类
@@ -31,6 +30,8 @@ public class ProjectServiceImpl implements ProjectService {
@Override
public Long createProject(ProjectSaveReqVO createReqVO) {
// 校验项目名称和编号是否唯一
validateProjectNameAndCodeUnique(createReqVO.getName(), createReqVO.getCode(), createReqVO.getId());
// 插入
ProjectDO project = BeanUtils.toBean(createReqVO, ProjectDO.class);
projectMapper.insert(project);
@@ -40,6 +41,8 @@ public class ProjectServiceImpl implements ProjectService {
@Override
public void updateProject(ProjectSaveReqVO updateReqVO) {
// 校验项目名称和编号是否唯一
validateProjectNameAndCodeUnique(updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getId());
// 校验存在
validateProjectExists(updateReqVO.getId());
// 更新
@@ -61,6 +64,17 @@ public class ProjectServiceImpl implements ProjectService {
}
}
private void validateProjectNameAndCodeUnique(String name, String code, Long id) {
Boolean isNameUnique = validateProjectNameUnique(name, id);
if (!isNameUnique) {
throw exception(PROJECT_NAME_DUPLICATE, name);
}
Boolean isCodeUnique = validateProjectCodeUnique(code, id);
if (!isCodeUnique) {
throw exception(PROJECT_CODE_DUPLICATE, code);
}
}
@Override
public ProjectDO getProject(Long id) {
return projectMapper.selectById(id);
@@ -71,4 +85,47 @@ public class ProjectServiceImpl implements ProjectService {
return projectMapper.selectPage(pageReqVO);
}
@Override
public Boolean validateProjectNameUnique(String name, Long id) {
if (StrUtil.isBlank(name)) {
return true;
}
ProjectDO project = projectMapper.selectByName(name);
if (project == null) {
return true;
}
// 如果 id 为空,说明不用比较是否为相同 id 的客户
if (id == null) {
return false;
}
if (!project.getId().equals(id)) {
return false;
}
return true;
}
@Override
public Boolean validateProjectCodeUnique(String code, Long id) {
if (StrUtil.isBlank(code)) {
return true;
}
ProjectDO project = projectMapper.selectByCode(code);
if (project == null) {
return true;
}
// 如果 id 为空,说明不用比较是否为相同 id 的客户
if (id == null) {
return false;
}
if (!project.getId().equals(id)) {
return false;
}
return true;
}
@Override
public Integer selectMaxCode() {
Integer maxCode = projectMapper.selectMaxCode();
return maxCode == null || maxCode < 2000 ? 2000 : maxCode + 1;
}
}

View File

@@ -2,11 +2,8 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.agt.module.license.dal.mysql.project.ProjectMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectMaxCode" resultType="Integer">
SELECT max(`code` + 0) from lic_project;
</select>
</mapper>