部门:优化父部门的校验逻辑,为代码生成做个铺垫?!

This commit is contained in:
YunaiV 2023-11-16 12:55:43 +08:00
parent a2f7067494
commit f5ea270be3
4 changed files with 48 additions and 55 deletions

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.system.enums.dept;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 部门编号枚举
*/
@Getter
@AllArgsConstructor
public enum DeptIdEnum {
/**
* 根节点
*/
ROOT(0L);
private final Long id;
}

View File

@ -21,6 +21,8 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public class DeptDO extends TenantBaseDO {
public static final Long PARENT_ID_ROOT = 0L;
/**
* 部门ID
*/

View File

@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.system.convert.dept.DeptConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
@ -42,14 +41,17 @@ public class DeptServiceImpl implements DeptService {
@Override
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
allEntries = true) // allEntries 清空所有缓存因为操作一个部门涉及到多个缓存
public Long createDept(DeptCreateReqVO reqVO) {
// 校验正确性
if (reqVO.getParentId() == null) {
reqVO.setParentId(DeptIdEnum.ROOT.getId());
public Long createDept(DeptCreateReqVO createReqVO) {
if (createReqVO.getParentId() == null) {
createReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
}
validateForCreateOrUpdate(null, reqVO.getParentId(), reqVO.getName());
// 校验父部门的有效性
validateParentDept(null, createReqVO.getParentId());
// 校验部门名的唯一性
validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
// 插入部门
DeptDO dept = DeptConvert.INSTANCE.convert(reqVO);
DeptDO dept = DeptConvert.INSTANCE.convert(createReqVO);
deptMapper.insert(dept);
return dept.getId();
}
@ -57,14 +59,19 @@ public class DeptServiceImpl implements DeptService {
@Override
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
allEntries = true) // allEntries 清空所有缓存因为操作一个部门涉及到多个缓存
public void updateDept(DeptUpdateReqVO reqVO) {
// 校验正确性
if (reqVO.getParentId() == null) {
reqVO.setParentId(DeptIdEnum.ROOT.getId());
public void updateDept(DeptUpdateReqVO updateReqVO) {
if (updateReqVO.getParentId() == null) {
updateReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
}
validateForCreateOrUpdate(reqVO.getId(), reqVO.getParentId(), reqVO.getName());
// 校验自己存在
validateDeptExists(updateReqVO.getId());
// 校验父部门的有效性
validateParentDept(updateReqVO.getId(), updateReqVO.getParentId());
// 校验部门名的唯一性
validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
// 更新部门
DeptDO updateObj = DeptConvert.INSTANCE.convert(reqVO);
DeptDO updateObj = DeptConvert.INSTANCE.convert(updateReqVO);
deptMapper.updateById(updateObj);
}
@ -82,15 +89,6 @@ public class DeptServiceImpl implements DeptService {
deptMapper.deleteById(id);
}
private void validateForCreateOrUpdate(Long id, Long parentId, String name) {
// 校验自己存在
validateDeptExists(id);
// 校验父部门的有效性
validateParentDept(id, parentId);
// 校验部门名的唯一性
validateDeptNameUnique(id, parentId, name);
}
@VisibleForTesting
void validateDeptExists(Long id) {
if (id == null) {
@ -104,23 +102,37 @@ public class DeptServiceImpl implements DeptService {
@VisibleForTesting
void validateParentDept(Long id, Long parentId) {
if (parentId == null || DeptIdEnum.ROOT.getId().equals(parentId)) {
if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) {
return;
}
// 不能设置自己为父部门
if (parentId.equals(id)) {
// 1. 不能设置自己为父部门
if (Objects.equals(id, parentId)) {
throw exception(DEPT_PARENT_ERROR);
}
// 父岗位不存在
DeptDO dept = deptMapper.selectById(parentId);
if (dept == null) {
// 2. 父部门不存在
DeptDO parentDept = deptMapper.selectById(parentId);
if (parentDept == null) {
throw exception(DEPT_PARENT_NOT_EXITS);
}
// 父部门不能是原来的子部门
List<DeptDO> children = getChildDeptList(id);
if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) {
// 3. 递归校验父部门如果父部门是自己的子部门则报错避免形成环路
if (id == null) { // id 为空说明新增不需要考虑环路
return;
}
for (int i = 0; i < Short.MAX_VALUE; i++) {
// 3.1 校验环路
parentId = parentDept.getParentId();
if (Objects.equals(id, parentId)) {
throw exception(DEPT_PARENT_IS_CHILD);
}
// 3.2 继续递归下一级父部门
if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) {
break;
}
parentDept = deptMapper.selectById(parentId);
if (parentDept == null) {
break;
}
}
}
@VisibleForTesting

View File

@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqV
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
@ -41,7 +40,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
public void testCreateDept() {
// 准备参数
DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> {
o.setParentId(DeptIdEnum.ROOT.getId());
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setStatus(randomCommonStatus());
});
@ -62,7 +61,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
// 准备参数
DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> {
// 设置更新的 ID
o.setParentId(DeptIdEnum.ROOT.getId());
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setId(dbDeptDO.getId());
o.setStatus(randomCommonStatus());
});