1. 提高 databus api 的网络失败重试次数,避免复用旧链接导致的 connection reset 错误

2. 兼容顶级组织同步时的组织编码生成逻辑
This commit is contained in:
chenbowen
2025-11-04 14:43:53 +08:00
parent b98f605dfd
commit 811270a4c5
6 changed files with 209 additions and 18 deletions

View File

@@ -57,7 +57,7 @@ public interface ErrorCodeConstants {
ErrorCode USER_REGISTER_DISABLED = new ErrorCode(1_002_003_011, "注册功能已关闭");
// ========== 部门模块 1-002-004-000 ==========
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "当前上级部门已存在同名子部门");
ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1_002_004_001,"父级部门不存在");
ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "机构不存在或当前账号无权限修改");
ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");

View File

@@ -71,9 +71,16 @@ public class DeptServiceImpl implements DeptService {
// 校验部门名的唯一性
validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
// 生成并校验部门编码
String generatedCode = generateDeptCode(createReqVO.getParentId());
createReqVO.setCode(generatedCode);
validateDeptCodeUnique(null, generatedCode);
Long effectiveParentId = normalizeParentId(createReqVO.getParentId());
boolean isTopLevel = Objects.equals(effectiveParentId, DeptDO.PARENT_ID_ROOT);
String resolvedCode;
if (isTopLevel) {
resolvedCode = resolveTopLevelCode(null, createReqVO.getCode());
} else {
resolvedCode = generateDeptCode(effectiveParentId);
validateDeptCodeUnique(null, resolvedCode);
}
createReqVO.setCode(resolvedCode);
// 插入部门
DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class);
@@ -104,10 +111,25 @@ public class DeptServiceImpl implements DeptService {
Long oldParentId = normalizeParentId(originalDept.getParentId());
boolean parentChanged = !Objects.equals(newParentId, oldParentId);
if (parentChanged) {
String newCode = generateDeptCode(updateReqVO.getParentId());
String newCode;
if (Objects.equals(newParentId, DeptDO.PARENT_ID_ROOT)) {
newCode = resolveTopLevelCode(updateReqVO.getId(), updateReqVO.getCode());
} else {
newCode = generateDeptCode(updateReqVO.getParentId());
validateDeptCodeUnique(updateReqVO.getId(), newCode);
}
updateReqVO.setCode(newCode);
} else {
updateReqVO.setCode(originalDept.getCode());
if (Objects.equals(newParentId, DeptDO.PARENT_ID_ROOT)) {
String requestedCode = updateReqVO.getCode();
if (StrUtil.isNotBlank(requestedCode) && !StrUtil.equals(requestedCode.trim(), originalDept.getCode())) {
updateReqVO.setCode(resolveTopLevelCode(updateReqVO.getId(), requestedCode));
} else {
updateReqVO.setCode(originalDept.getCode());
}
} else {
updateReqVO.setCode(originalDept.getCode());
}
}
// 更新部门
@@ -189,7 +211,11 @@ public class DeptServiceImpl implements DeptService {
@VisibleForTesting
void validateDeptNameUnique(Long id, Long parentId, String name) {
DeptDO dept = deptMapper.selectByParentIdAndName(parentId, name);
Long effectiveParentId = normalizeParentId(parentId);
if (Objects.equals(effectiveParentId, DeptDO.PARENT_ID_ROOT)) {
return;
}
DeptDO dept = deptMapper.selectByParentIdAndName(effectiveParentId, name);
if (dept == null) {
return;
}
@@ -312,6 +338,18 @@ public class DeptServiceImpl implements DeptService {
deptMapper.updateById(update);
}
private String resolveTopLevelCode(Long currentDeptId, String requestedCode) {
String candidate = requestedCode;
if (candidate != null) {
candidate = candidate.trim();
}
if (StrUtil.isBlank(candidate)) {
candidate = generateDeptCode(DeptDO.PARENT_ID_ROOT);
}
validateDeptCodeUnique(currentDeptId, candidate);
return candidate;
}
@Override
public DeptDO getDept(Long id) {
return deptMapper.selectById(id);

View File

@@ -84,6 +84,45 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
assertEquals(parentDept.getCode() + "001", childDept.getCode());
}
@Test
public void testCreateDept_topLevelAutoCodeAndDuplicates() {
DeptSaveReqVO topLevelReq = new DeptSaveReqVO();
topLevelReq.setParentId(DeptDO.PARENT_ID_ROOT);
topLevelReq.setName("总部");
topLevelReq.setSort(1);
topLevelReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
topLevelReq.setDeptSource(1);
Long topLevelId = deptService.createDept(topLevelReq);
DeptDO firstTop = deptMapper.selectById(topLevelId);
assertEquals("ZT001", firstTop.getCode());
DeptSaveReqVO secondTopLevelReq = new DeptSaveReqVO();
secondTopLevelReq.setParentId(DeptDO.PARENT_ID_ROOT);
secondTopLevelReq.setName("总部");
secondTopLevelReq.setSort(2);
secondTopLevelReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
secondTopLevelReq.setDeptSource(1);
Long secondTopId = deptService.createDept(secondTopLevelReq);
DeptDO secondTop = deptMapper.selectById(secondTopId);
assertEquals("ZT002", secondTop.getCode());
}
@Test
public void testCreateDept_topLevelRespectCustomCode() {
String customCode = "ROOT-001";
DeptSaveReqVO topLevelReq = new DeptSaveReqVO();
topLevelReq.setParentId(DeptDO.PARENT_ID_ROOT);
topLevelReq.setName("集团");
topLevelReq.setSort(1);
topLevelReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
topLevelReq.setDeptSource(1);
topLevelReq.setCode(customCode);
Long deptId = deptService.createDept(topLevelReq);
DeptDO created = deptMapper.selectById(deptId);
assertEquals(customCode, created.getCode());
}
@Test
public void testUpdateDept() {
// mock 数据
@@ -205,20 +244,68 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
@Test
public void testValidateNameUnique_duplicate() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class).setDeptSource(null);
// mock 上级部门
DeptDO parentDept = randomPojo(DeptDO.class, o -> {
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}).setDeptSource(null);
deptMapper.insert(parentDept);
// mock 同级重名部门
String duplicateName = randomString(6);
DeptDO deptDO = randomPojo(DeptDO.class, o -> {
o.setParentId(parentDept.getId());
o.setName(duplicateName);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}).setDeptSource(null);
deptMapper.insert(deptDO);
// 准备参数
Long id = randomLongId();
Long parentId = deptDO.getParentId();
String name = deptDO.getName();
// 调用, 并断言异常
assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name),
assertServiceException(() -> deptService.validateDeptNameUnique(randomLongId(), parentDept.getId(), duplicateName),
DEPT_NAME_DUPLICATE);
}
@Test
public void testValidateDeptNameUnique_topLevelDuplicateAllowed() {
// mock 顶级部门
String duplicateName = randomString(6);
DeptDO topLevelDept = randomPojo(DeptDO.class, o -> {
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setName(duplicateName);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}).setDeptSource(null);
deptMapper.insert(topLevelDept);
// 调用, 验证不会抛出异常
assertDoesNotThrow(() -> deptService.validateDeptNameUnique(null, DeptDO.PARENT_ID_ROOT, duplicateName));
}
@Test
public void testValidateDeptNameUnique_differentParentAllowed() {
// mock 不同上级部门
DeptDO parentA = randomPojo(DeptDO.class, o -> {
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}).setDeptSource(null);
deptMapper.insert(parentA);
DeptDO parentB = randomPojo(DeptDO.class, o -> {
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}).setDeptSource(null);
deptMapper.insert(parentB);
String duplicateName = randomString(6);
DeptDO childUnderA = randomPojo(DeptDO.class, o -> {
o.setParentId(parentA.getId());
o.setName(duplicateName);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}).setDeptSource(null);
deptMapper.insert(childUnderA);
// 调用, 验证不同父级可以重名
assertDoesNotThrow(() -> deptService.validateDeptNameUnique(null, parentB.getId(), duplicateName));
}
@Test
public void testGetDept() {
// mock 数据