1. 新增生成自有组织 CODE,同步其他系统额外生成编码映射关系
This commit is contained in:
@@ -16,11 +16,17 @@ import java.nio.charset.Charset;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLParameters;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可直接运行的示例,演示如何使用 appId=test 与对应密钥调用本地 Databus API。
|
* 可直接运行的示例,演示如何使用 appId=test 与对应密钥调用本地 Databus API。
|
||||||
@@ -37,12 +43,12 @@ public final class DatabusApiInvocationExample {
|
|||||||
// private static final String TARGET_API = "http://172.16.46.63:30081/admin-api/databus/api/portal/callback/v1";
|
// private static final String TARGET_API = "http://172.16.46.63:30081/admin-api/databus/api/portal/callback/v1";
|
||||||
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
|
private static final String TARGET_API = "https://jygk.chncopper.com:30078/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/callback/v1";
|
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/callback/v1";
|
||||||
private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/testcbw/456";
|
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/testcbw/456";
|
||||||
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
|
// ⚠️ 仅用于联调:信任所有证书 + 关闭主机名校验,生产环境请改为受信 CA 或自定义 truststore。
|
||||||
.connectTimeout(Duration.ofSeconds(5))
|
private static final HttpClient HTTP_CLIENT = buildUnsafeHttpClient();
|
||||||
.build();
|
|
||||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
private static final PrintStream OUT = buildConsolePrintStream();
|
private static final PrintStream OUT = buildConsolePrintStream();
|
||||||
public static final String ZT_APP_ID = "ZT-App-Id";
|
public static final String ZT_APP_ID = "ZT-App-Id";
|
||||||
@@ -55,6 +61,45 @@ public final class DatabusApiInvocationExample {
|
|||||||
private DatabusApiInvocationExample() {
|
private DatabusApiInvocationExample() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅用于联调:信任所有证书并关闭主机名校验,生产环境请使用受信 CA 或自定义 truststore。
|
||||||
|
*/
|
||||||
|
private static HttpClient buildUnsafeHttpClient() {
|
||||||
|
try {
|
||||||
|
TrustManager[] trustAll = new TrustManager[]{
|
||||||
|
new X509TrustManager() {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new X509Certificate[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, trustAll, new SecureRandom());
|
||||||
|
|
||||||
|
SSLParameters sslParameters = new SSLParameters();
|
||||||
|
// 关闭主机名校验
|
||||||
|
sslParameters.setEndpointIdentificationAlgorithm("");
|
||||||
|
|
||||||
|
return HttpClient.newBuilder()
|
||||||
|
.sslContext(sslContext)
|
||||||
|
.sslParameters(sslParameters)
|
||||||
|
.connectTimeout(Duration.ofSeconds(5))
|
||||||
|
.build();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalStateException("Failed to build unsafe HttpClient", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
OUT.println("=== GET 请求示例 ===");
|
OUT.println("=== GET 请求示例 ===");
|
||||||
// executeGetExample();
|
// executeGetExample();
|
||||||
|
|||||||
@@ -36,4 +36,13 @@ public class DeptSaveReqDTO {
|
|||||||
@Schema(description = "状态,见 CommonStatusEnum 枚举0 开启 1 关闭", example = "0")
|
@Schema(description = "状态,见 CommonStatusEnum 枚举0 开启 1 关闭", example = "0")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统标识,用于建立编码映射", example = "ERP")
|
||||||
|
private String externalSystemCode;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统组织编码,用于建立映射", example = "ERP-001")
|
||||||
|
private String externalDeptCode;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统组织名称", example = "ERP总部")
|
||||||
|
private String externalDeptName;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -23,4 +23,6 @@ public interface DictTypeConstants {
|
|||||||
String SMS_SEND_STATUS = "system_sms_send_status"; // 短信发送状态
|
String SMS_SEND_STATUS = "system_sms_send_status"; // 短信发送状态
|
||||||
String SMS_RECEIVE_STATUS = "system_sms_receive_status"; // 短信接收状态
|
String SMS_RECEIVE_STATUS = "system_sms_receive_status"; // 短信接收状态
|
||||||
|
|
||||||
|
String DEPT_EXTERNAL_SYSTEM = "system_dept_external_system"; // 部门外部系统标识
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,15 @@ public class DeptSaveReqVO {
|
|||||||
@Size(max = 50, message = "部门编码长度不能超过 50 个字符")
|
@Size(max = 50, message = "部门编码长度不能超过 50 个字符")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统标识,用于建立编码映射", example = "ERP")
|
||||||
|
private String externalSystemCode;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统组织编码,用于建立映射", example = "ERP-001")
|
||||||
|
private String externalDeptCode;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统组织名称", example = "ERP总部")
|
||||||
|
private String externalDeptName;
|
||||||
|
|
||||||
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ZT")
|
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ZT")
|
||||||
@NotBlank(message = "部门名称不能为空")
|
@NotBlank(message = "部门名称不能为空")
|
||||||
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
|
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ public interface DeptExternalCodeMapper extends BaseMapperX<DeptExternalCodeDO>
|
|||||||
return selectList(DeptExternalCodeDO::getDeptId, deptId);
|
return selectList(DeptExternalCodeDO::getDeptId, deptId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default int deleteByDeptId(Long deptId) {
|
||||||
|
return delete(DeptExternalCodeDO::getDeptId, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
default List<DeptExternalCodeDO> selectListBySystemCode(String systemCode) {
|
default List<DeptExternalCodeDO> selectListBySystemCode(String systemCode) {
|
||||||
return selectList(DeptExternalCodeDO::getSystemCode, systemCode);
|
return selectList(DeptExternalCodeDO::getSystemCode, systemCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ public interface RedisKeyConstants {
|
|||||||
*/
|
*/
|
||||||
String DEPT_CHILDREN_ID_LIST = "dept_children_ids";
|
String DEPT_CHILDREN_ID_LIST = "dept_children_ids";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定部门的外部组织编码映射列表缓存
|
||||||
|
* <p>
|
||||||
|
* KEY 格式:dept_external_code_list:{deptId}
|
||||||
|
* VALUE 数据类型:String 映射列表
|
||||||
|
*/
|
||||||
|
String DEPT_EXTERNAL_CODE_LIST = "dept_external_code_list";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色的缓存
|
* 角色的缓存
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -49,6 +49,26 @@ public interface DeptExternalCodeService {
|
|||||||
*/
|
*/
|
||||||
List<DeptExternalCodeDO> getDeptExternalCodeListByDeptId(Long deptId);
|
List<DeptExternalCodeDO> getDeptExternalCodeListByDeptId(Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据部门与外部系统保存/更新映射(存在则更新,不存在则创建)
|
||||||
|
*
|
||||||
|
* @param deptId 本系统部门 ID
|
||||||
|
* @param systemCode 外部系统标识
|
||||||
|
* @param externalDeptCode 外部系统组织编码
|
||||||
|
* @param externalDeptName 外部系统组织名称(可选)
|
||||||
|
* @param status 状态,默认启用
|
||||||
|
* @return 映射记录 ID
|
||||||
|
*/
|
||||||
|
Long saveOrUpdateDeptExternalCode(Long deptId, String systemCode, String externalDeptCode, String externalDeptName,
|
||||||
|
Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据部门删除全部外部编码映射
|
||||||
|
*
|
||||||
|
* @param deptId 部门编号
|
||||||
|
*/
|
||||||
|
void deleteDeptExternalCodesByDeptId(Long deptId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据外部系统与外部组织编码查询映射
|
* 根据外部系统与外部组织编码查询映射
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.DeptEx
|
|||||||
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.dept.DeptExternalCodeDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptExternalCodeDO;
|
||||||
import com.zt.plat.module.system.dal.mysql.dept.DeptExternalCodeMapper;
|
import com.zt.plat.module.system.dal.mysql.dept.DeptExternalCodeMapper;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
||||||
|
import com.zt.plat.module.system.dal.redis.RedisKeyConstants;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -28,9 +33,12 @@ public class DeptExternalCodeServiceImpl implements DeptExternalCodeService {
|
|||||||
@Resource
|
@Resource
|
||||||
private DeptExternalCodeMapper deptExternalCodeMapper;
|
private DeptExternalCodeMapper deptExternalCodeMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private DeptService deptService;
|
private DeptMapper deptMapper;
|
||||||
|
@Resource
|
||||||
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST, key = "#createReqVO.deptId", beforeInvocation = false)
|
||||||
public Long createDeptExternalCode(DeptExternalCodeSaveReqVO createReqVO) {
|
public Long createDeptExternalCode(DeptExternalCodeSaveReqVO createReqVO) {
|
||||||
normalizeRequest(createReqVO);
|
normalizeRequest(createReqVO);
|
||||||
validateForCreateOrUpdate(null, createReqVO.getDeptId(), createReqVO.getSystemCode(),
|
validateForCreateOrUpdate(null, createReqVO.getDeptId(), createReqVO.getSystemCode(),
|
||||||
@@ -57,12 +65,15 @@ public class DeptExternalCodeServiceImpl implements DeptExternalCodeService {
|
|||||||
updateObj.setStatus(exists.getStatus() == null ? CommonStatusEnum.ENABLE.getStatus() : exists.getStatus());
|
updateObj.setStatus(exists.getStatus() == null ? CommonStatusEnum.ENABLE.getStatus() : exists.getStatus());
|
||||||
}
|
}
|
||||||
deptExternalCodeMapper.updateById(updateObj);
|
deptExternalCodeMapper.updateById(updateObj);
|
||||||
|
evictCacheSafely(exists.getDeptId());
|
||||||
|
evictCacheSafely(updateObj.getDeptId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteDeptExternalCode(Long id) {
|
public void deleteDeptExternalCode(Long id) {
|
||||||
validateExists(id);
|
DeptExternalCodeDO exists = validateExists(id);
|
||||||
deptExternalCodeMapper.deleteById(id);
|
deptExternalCodeMapper.deleteById(id);
|
||||||
|
evictCacheSafely(exists.getDeptId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,6 +87,7 @@ public class DeptExternalCodeServiceImpl implements DeptExternalCodeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Cacheable(cacheNames = RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST, key = "#deptId")
|
||||||
public List<DeptExternalCodeDO> getDeptExternalCodeListByDeptId(Long deptId) {
|
public List<DeptExternalCodeDO> getDeptExternalCodeListByDeptId(Long deptId) {
|
||||||
return deptExternalCodeMapper.selectListByDeptId(deptId);
|
return deptExternalCodeMapper.selectListByDeptId(deptId);
|
||||||
}
|
}
|
||||||
@@ -96,6 +108,48 @@ public class DeptExternalCodeServiceImpl implements DeptExternalCodeService {
|
|||||||
return deptExternalCodeMapper.selectBySystemCodeAndDeptId(systemCode.trim(), deptId);
|
return deptExternalCodeMapper.selectBySystemCodeAndDeptId(systemCode.trim(), deptId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long saveOrUpdateDeptExternalCode(Long deptId, String systemCode, String externalDeptCode,
|
||||||
|
String externalDeptName, Integer status) {
|
||||||
|
if (StrUtil.hasEmpty(systemCode, externalDeptCode) || deptId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String normalizedSystemCode = systemCode.trim();
|
||||||
|
String normalizedExternalCode = externalDeptCode.trim();
|
||||||
|
String normalizedExternalName = StrUtil.blankToDefault(StrUtil.trimToNull(externalDeptName), null);
|
||||||
|
|
||||||
|
// 如果存在则更新,否则创建
|
||||||
|
DeptExternalCodeDO exists = deptExternalCodeMapper.selectBySystemCodeAndDeptId(normalizedSystemCode, deptId);
|
||||||
|
if (exists != null) {
|
||||||
|
DeptExternalCodeSaveReqVO updateReqVO = new DeptExternalCodeSaveReqVO();
|
||||||
|
updateReqVO.setId(exists.getId());
|
||||||
|
updateReqVO.setDeptId(deptId);
|
||||||
|
updateReqVO.setSystemCode(normalizedSystemCode);
|
||||||
|
updateReqVO.setExternalDeptCode(normalizedExternalCode);
|
||||||
|
updateReqVO.setExternalDeptName(normalizedExternalName);
|
||||||
|
updateReqVO.setStatus(status == null ? exists.getStatus() : status);
|
||||||
|
updateDeptExternalCode(updateReqVO);
|
||||||
|
return exists.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
DeptExternalCodeSaveReqVO createReqVO = new DeptExternalCodeSaveReqVO();
|
||||||
|
createReqVO.setDeptId(deptId);
|
||||||
|
createReqVO.setSystemCode(normalizedSystemCode);
|
||||||
|
createReqVO.setExternalDeptCode(normalizedExternalCode);
|
||||||
|
createReqVO.setExternalDeptName(normalizedExternalName);
|
||||||
|
createReqVO.setStatus(status == null ? CommonStatusEnum.ENABLE.getStatus() : status);
|
||||||
|
return createDeptExternalCode(createReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDeptExternalCodesByDeptId(Long deptId) {
|
||||||
|
if (deptId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deptExternalCodeMapper.deleteByDeptId(deptId);
|
||||||
|
evictCacheSafely(deptId);
|
||||||
|
}
|
||||||
|
|
||||||
private DeptExternalCodeDO validateExists(Long id) {
|
private DeptExternalCodeDO validateExists(Long id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw exception(DEPT_EXTERNAL_RELATION_NOT_EXISTS);
|
throw exception(DEPT_EXTERNAL_RELATION_NOT_EXISTS);
|
||||||
@@ -109,7 +163,7 @@ public class DeptExternalCodeServiceImpl implements DeptExternalCodeService {
|
|||||||
|
|
||||||
private void validateForCreateOrUpdate(Long id, Long deptId, String systemCode, String externalDeptCode) {
|
private void validateForCreateOrUpdate(Long id, Long deptId, String systemCode, String externalDeptCode) {
|
||||||
// 校验部门存在
|
// 校验部门存在
|
||||||
DeptDO dept = deptService.getDept(deptId);
|
DeptDO dept = deptMapper.selectById(deptId);
|
||||||
if (dept == null) {
|
if (dept == null) {
|
||||||
throw exception(DEPT_NOT_FOUND);
|
throw exception(DEPT_NOT_FOUND);
|
||||||
}
|
}
|
||||||
@@ -148,4 +202,17 @@ public class DeptExternalCodeServiceImpl implements DeptExternalCodeService {
|
|||||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void evictCacheSafely(Long deptId) {
|
||||||
|
if (deptId == null || cacheManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (cacheManager.getCache(RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST) != null) {
|
||||||
|
cacheManager.getCache(RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST).evict(deptId);
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
// 缓存失效失败不影响主流程
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,18 @@ import com.zt.plat.framework.datapermission.core.annotation.DataPermission;
|
|||||||
import com.zt.plat.framework.tenant.core.aop.TenantIgnore;
|
import com.zt.plat.framework.tenant.core.aop.TenantIgnore;
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dict.DictTypeDO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
|
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
|
||||||
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
||||||
import com.zt.plat.module.system.dal.mysql.userdept.UserDeptMapper;
|
import com.zt.plat.module.system.dal.mysql.userdept.UserDeptMapper;
|
||||||
import com.zt.plat.module.system.dal.redis.RedisKeyConstants;
|
import com.zt.plat.module.system.dal.redis.RedisKeyConstants;
|
||||||
import com.zt.plat.module.system.enums.dept.DeptSourceEnum;
|
import com.zt.plat.module.system.enums.dept.DeptSourceEnum;
|
||||||
|
import com.zt.plat.module.system.enums.DictTypeConstants;
|
||||||
|
import com.zt.plat.module.system.service.dict.DictDataService;
|
||||||
|
import com.zt.plat.module.system.service.dict.DictTypeService;
|
||||||
import org.apache.seata.spring.annotation.GlobalTransactional;
|
import org.apache.seata.spring.annotation.GlobalTransactional;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -52,6 +58,12 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
private UserDeptMapper userDeptMapper;
|
private UserDeptMapper userDeptMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private com.zt.plat.module.system.mq.producer.databus.DatabusChangeProducer databusChangeProducer;
|
private com.zt.plat.module.system.mq.producer.databus.DatabusChangeProducer databusChangeProducer;
|
||||||
|
@Resource
|
||||||
|
private DeptExternalCodeService deptExternalCodeService;
|
||||||
|
@Resource
|
||||||
|
private DictTypeService dictTypeService;
|
||||||
|
@Resource
|
||||||
|
private DictDataService dictDataService;
|
||||||
|
|
||||||
private static final String ROOT_CODE_PREFIX = "ZT";
|
private static final String ROOT_CODE_PREFIX = "ZT";
|
||||||
private static final int CODE_SEGMENT_LENGTH = 3;
|
private static final int CODE_SEGMENT_LENGTH = 3;
|
||||||
@@ -75,23 +87,10 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
// 校验部门名的唯一性
|
// 校验部门名的唯一性
|
||||||
validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
|
validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
|
||||||
// 生成并校验部门编码
|
// 生成并校验部门编码
|
||||||
boolean isIWorkSource = Objects.equals(createReqVO.getDeptSource(), DeptSourceEnum.IWORK.getSource());
|
Long effectiveParentId = normalizeParentId(createReqVO.getParentId());
|
||||||
if (isIWorkSource) {
|
String resolvedCode = generateDeptCode(effectiveParentId);
|
||||||
// iWork 来源直接使用提供的编码,不再生成
|
validateDeptCodeUnique(null, resolvedCode);
|
||||||
String providedCode = StrUtil.blankToDefault(createReqVO.getCode(), null);
|
createReqVO.setCode(resolvedCode);
|
||||||
createReqVO.setCode(providedCode);
|
|
||||||
} else {
|
|
||||||
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);
|
DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class);
|
||||||
@@ -101,6 +100,9 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
}
|
}
|
||||||
deptMapper.insert(dept);
|
deptMapper.insert(dept);
|
||||||
|
|
||||||
|
// 维护外部系统编码映射(若有传入)
|
||||||
|
upsertExternalCodeMapping(createReqVO, dept.getId());
|
||||||
|
|
||||||
// 发布部门创建事件
|
// 发布部门创建事件
|
||||||
databusChangeProducer.sendDeptCreatedMessage(dept);
|
databusChangeProducer.sendDeptCreatedMessage(dept);
|
||||||
|
|
||||||
@@ -121,37 +123,15 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
// 校验部门名的唯一性
|
// 校验部门名的唯一性
|
||||||
validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
|
validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
|
||||||
// 如果上级发生变化,需要重新生成编码并同步子级
|
// 如果上级发生变化,需要重新生成编码并同步子级
|
||||||
boolean isIWorkSource = Objects.equals(originalDept.getDeptSource(), DeptSourceEnum.IWORK.getSource());
|
|
||||||
Long newParentId = normalizeParentId(updateReqVO.getParentId());
|
Long newParentId = normalizeParentId(updateReqVO.getParentId());
|
||||||
Long oldParentId = normalizeParentId(originalDept.getParentId());
|
Long oldParentId = normalizeParentId(originalDept.getParentId());
|
||||||
boolean parentChanged = !Objects.equals(newParentId, oldParentId);
|
boolean parentChanged = !Objects.equals(newParentId, oldParentId);
|
||||||
if (isIWorkSource) {
|
String resolvedCode = originalDept.getCode();
|
||||||
// iWork 来源直接使用提供的编码,不再生成
|
if (parentChanged || StrUtil.isBlank(resolvedCode)) {
|
||||||
String providedCode = StrUtil.blankToDefault(updateReqVO.getCode(), null);
|
resolvedCode = generateDeptCode(newParentId);
|
||||||
updateReqVO.setCode(providedCode);
|
validateDeptCodeUnique(updateReqVO.getId(), resolvedCode);
|
||||||
} else {
|
|
||||||
if (parentChanged) {
|
|
||||||
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 {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
updateReqVO.setCode(resolvedCode);
|
||||||
|
|
||||||
// 更新部门
|
// 更新部门
|
||||||
DeptDO updateObj = BeanUtils.toBean(updateReqVO, DeptDO.class);
|
DeptDO updateObj = BeanUtils.toBean(updateReqVO, DeptDO.class);
|
||||||
@@ -166,6 +146,9 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
if (parentChanged) {
|
if (parentChanged) {
|
||||||
refreshChildCodesRecursively(updateObj.getId(), updateReqVO.getCode());
|
refreshChildCodesRecursively(updateObj.getId(), updateReqVO.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 维护外部系统编码映射(若有传入)
|
||||||
|
upsertExternalCodeMapping(updateReqVO, updateReqVO.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -183,6 +166,9 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
DeptDO dept = deptMapper.selectById(id);
|
DeptDO dept = deptMapper.selectById(id);
|
||||||
Long tenantId = (dept != null) ? dept.getTenantId() : null;
|
Long tenantId = (dept != null) ? dept.getTenantId() : null;
|
||||||
|
|
||||||
|
// 级联删除外部编码映射并清理缓存
|
||||||
|
deptExternalCodeService.deleteDeptExternalCodesByDeptId(id);
|
||||||
|
|
||||||
// 删除部门
|
// 删除部门
|
||||||
deptMapper.deleteById(id);
|
deptMapper.deleteById(id);
|
||||||
|
|
||||||
@@ -754,4 +740,65 @@ public class DeptServiceImpl implements DeptService {
|
|||||||
return dept;
|
return dept;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void upsertExternalCodeMapping(DeptSaveReqVO reqVO, Long deptId) {
|
||||||
|
if (reqVO == null || deptId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String systemCode = StrUtil.trimToNull(reqVO.getExternalSystemCode());
|
||||||
|
String externalCode = StrUtil.trimToNull(reqVO.getExternalDeptCode());
|
||||||
|
if (StrUtil.isBlank(systemCode) || StrUtil.isBlank(externalCode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 缺失的外部系统字典类型或数据会自动补齐
|
||||||
|
ensureExternalSystemDict(systemCode);
|
||||||
|
deptExternalCodeService.saveOrUpdateDeptExternalCode(
|
||||||
|
deptId,
|
||||||
|
systemCode,
|
||||||
|
externalCode,
|
||||||
|
reqVO.getExternalDeptName(),
|
||||||
|
CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确保外部系统字典存在(含字典类型与对应值),若缺失则自动创建
|
||||||
|
*/
|
||||||
|
private void ensureExternalSystemDict(String systemCode) {
|
||||||
|
String normalizedCode = StrUtil.trimToNull(systemCode);
|
||||||
|
if (normalizedCode == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DictTypeDO dictType = dictTypeService.getDictType(DictTypeConstants.DEPT_EXTERNAL_SYSTEM);
|
||||||
|
if (dictType == null) {
|
||||||
|
DictTypeSaveReqVO typeReq = new DictTypeSaveReqVO();
|
||||||
|
typeReq.setName("部门外部系统标识");
|
||||||
|
typeReq.setType(DictTypeConstants.DEPT_EXTERNAL_SYSTEM);
|
||||||
|
typeReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
typeReq.setRemark("外部组织同步自动创建");
|
||||||
|
dictTypeService.createDictType(typeReq);
|
||||||
|
} else if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) {
|
||||||
|
DictTypeSaveReqVO updateReq = new DictTypeSaveReqVO();
|
||||||
|
updateReq.setId(dictType.getId());
|
||||||
|
updateReq.setName(dictType.getName());
|
||||||
|
updateReq.setType(dictType.getType());
|
||||||
|
updateReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
updateReq.setRemark(dictType.getRemark());
|
||||||
|
dictTypeService.updateDictType(updateReq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dictDataService.getDictData(DictTypeConstants.DEPT_EXTERNAL_SYSTEM, normalizedCode) == null) {
|
||||||
|
DictDataSaveReqVO dataReq = new DictDataSaveReqVO();
|
||||||
|
dataReq.setDictType(DictTypeConstants.DEPT_EXTERNAL_SYSTEM);
|
||||||
|
dataReq.setLabel(normalizedCode);
|
||||||
|
dataReq.setValue(normalizedCode);
|
||||||
|
dataReq.setSort(0);
|
||||||
|
dataReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
dataReq.setRemark("外部组织同步自动创建");
|
||||||
|
dictDataService.createDictData(dataReq);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("[Dept] Ensure external system dict failed, systemCode={}", normalizedCode, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package com.zt.plat.module.system.service.dept;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.zt.plat.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.DeptExternalCodeSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.DeptExternalCodeMapper;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
||||||
|
import com.zt.plat.module.system.dal.redis.RedisKeyConstants;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.zt.plat.module.system.dal.redis.RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@Import({DeptExternalCodeServiceImpl.class, DeptExternalCodeServiceImplTest.CacheConfig.class})
|
||||||
|
class DeptExternalCodeServiceImplTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeptExternalCodeServiceImpl deptExternalCodeService;
|
||||||
|
@Resource
|
||||||
|
private DeptExternalCodeMapper deptExternalCodeMapper;
|
||||||
|
@Resource
|
||||||
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeptMapper deptMapper;
|
||||||
|
|
||||||
|
@TestConfiguration
|
||||||
|
@EnableCaching
|
||||||
|
static class CacheConfig {
|
||||||
|
@Bean
|
||||||
|
public CacheManager cacheManager() {
|
||||||
|
return new ConcurrentMapCacheManager(RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCacheEvictOnCreateAndUpdate() {
|
||||||
|
Long deptId = 100L;
|
||||||
|
DeptDO dept = new DeptDO();
|
||||||
|
dept.setId(deptId);
|
||||||
|
dept.setName("总部");
|
||||||
|
dept.setCode("ZT001");
|
||||||
|
dept.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
deptMapper.insert(dept);
|
||||||
|
|
||||||
|
// 预热缓存(空结果)
|
||||||
|
List<?> firstCall = deptExternalCodeService.getDeptExternalCodeListByDeptId(deptId);
|
||||||
|
assertTrue(firstCall.isEmpty());
|
||||||
|
assertNotNull(cacheManager.getCache(DEPT_EXTERNAL_CODE_LIST).get(deptId));
|
||||||
|
|
||||||
|
// 创建映射应触发缓存失效
|
||||||
|
DeptExternalCodeSaveReqVO createReq = new DeptExternalCodeSaveReqVO();
|
||||||
|
createReq.setDeptId(deptId);
|
||||||
|
createReq.setSystemCode("ERP");
|
||||||
|
createReq.setExternalDeptCode("ERP-001");
|
||||||
|
deptExternalCodeService.createDeptExternalCode(createReq);
|
||||||
|
|
||||||
|
List<?> refreshed = deptExternalCodeService.getDeptExternalCodeListByDeptId(deptId);
|
||||||
|
assertEquals(1, refreshed.size());
|
||||||
|
assertNotNull(cacheManager.getCache(DEPT_EXTERNAL_CODE_LIST).get(deptId));
|
||||||
|
|
||||||
|
// 更新映射也会清理缓存
|
||||||
|
DeptExternalCodeSaveReqVO updateReq = new DeptExternalCodeSaveReqVO();
|
||||||
|
Long id = deptExternalCodeMapper.selectListByDeptId(deptId).get(0).getId();
|
||||||
|
updateReq.setId(id);
|
||||||
|
updateReq.setDeptId(deptId);
|
||||||
|
updateReq.setSystemCode("ERP");
|
||||||
|
updateReq.setExternalDeptCode("ERP-002");
|
||||||
|
updateReq.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
deptExternalCodeService.updateDeptExternalCode(updateReq);
|
||||||
|
|
||||||
|
List<?> refreshedAfterUpdate = deptExternalCodeService.getDeptExternalCodeListByDeptId(deptId);
|
||||||
|
assertEquals(1, refreshedAfterUpdate.size());
|
||||||
|
assertEquals("ERP-002", deptExternalCodeMapper.selectById(id).getExternalDeptCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSaveOrUpdateDeptExternalCodeUpsert() {
|
||||||
|
Long deptId = 101L;
|
||||||
|
DeptDO dept = new DeptDO();
|
||||||
|
dept.setId(deptId);
|
||||||
|
dept.setName("事业部");
|
||||||
|
dept.setCode("ZT002");
|
||||||
|
dept.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
deptMapper.insert(dept);
|
||||||
|
|
||||||
|
Long firstId = deptExternalCodeService.saveOrUpdateDeptExternalCode(deptId, "OA", "OA-001", "OA-总部", null);
|
||||||
|
assertNotNull(firstId);
|
||||||
|
|
||||||
|
// upsert: 同一 system + dept 更新编码
|
||||||
|
Long secondId = deptExternalCodeService.saveOrUpdateDeptExternalCode(deptId, "OA", "OA-002", "OA-新编码", CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
assertEquals(firstId, secondId);
|
||||||
|
assertEquals("OA-002", deptExternalCodeMapper.selectById(firstId).getExternalDeptCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,11 +5,20 @@ import com.zt.plat.framework.common.util.object.ObjectUtils;
|
|||||||
import com.zt.plat.framework.test.core.ut.BaseDbUnitTest;
|
import com.zt.plat.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.DeptExternalCodeSaveReqVO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.DeptExternalCodeMapper;
|
||||||
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
||||||
|
import com.zt.plat.module.system.service.dept.DeptExternalCodeServiceImpl;
|
||||||
|
import com.zt.plat.module.system.dal.redis.RedisKeyConstants;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -27,13 +36,31 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
*
|
*
|
||||||
* @author niudehua
|
* @author niudehua
|
||||||
*/
|
*/
|
||||||
@Import(DeptServiceImpl.class)
|
@Import({DeptServiceImpl.class, DeptExternalCodeServiceImpl.class, DeptServiceImplTest.CacheConfig.class})
|
||||||
public class DeptServiceImplTest extends BaseDbUnitTest {
|
public class DeptServiceImplTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DeptServiceImpl deptService;
|
private DeptServiceImpl deptService;
|
||||||
@Resource
|
@Resource
|
||||||
private DeptMapper deptMapper;
|
private DeptMapper deptMapper;
|
||||||
|
@Resource
|
||||||
|
private DeptExternalCodeServiceImpl deptExternalCodeService;
|
||||||
|
@Resource
|
||||||
|
private DeptExternalCodeMapper deptExternalCodeMapper;
|
||||||
|
@Resource
|
||||||
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
|
@TestConfiguration
|
||||||
|
@EnableCaching
|
||||||
|
static class CacheConfig {
|
||||||
|
@Bean
|
||||||
|
public CacheManager cacheManager() {
|
||||||
|
return new ConcurrentMapCacheManager(
|
||||||
|
RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
|
||||||
|
RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Long createDept(Long parentId, String name, int sort) {
|
private Long createDept(Long parentId, String name, int sort) {
|
||||||
DeptSaveReqVO reqVO = new DeptSaveReqVO();
|
DeptSaveReqVO reqVO = new DeptSaveReqVO();
|
||||||
@@ -108,7 +135,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateDept_topLevelRespectCustomCode() {
|
public void testCreateDept_topLevelAutoCode_ignoreCustomInput() {
|
||||||
String customCode = "ROOT-001";
|
String customCode = "ROOT-001";
|
||||||
DeptSaveReqVO topLevelReq = new DeptSaveReqVO();
|
DeptSaveReqVO topLevelReq = new DeptSaveReqVO();
|
||||||
topLevelReq.setParentId(DeptDO.PARENT_ID_ROOT);
|
topLevelReq.setParentId(DeptDO.PARENT_ID_ROOT);
|
||||||
@@ -120,7 +147,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
|
|||||||
|
|
||||||
Long deptId = deptService.createDept(topLevelReq);
|
Long deptId = deptService.createDept(topLevelReq);
|
||||||
DeptDO created = deptMapper.selectById(deptId);
|
DeptDO created = deptMapper.selectById(deptId);
|
||||||
assertEquals(customCode, created.getCode());
|
assertEquals("ZT001", created.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -187,6 +214,29 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
|
|||||||
assertNull(deptMapper.selectById(id));
|
assertNull(deptMapper.selectById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteDept_cascadeExternalCodesAndEvictCache() {
|
||||||
|
Long deptId = createDept(DeptDO.PARENT_ID_ROOT, "总部", 1);
|
||||||
|
|
||||||
|
// 创建映射并预热缓存
|
||||||
|
DeptExternalCodeSaveReqVO createReq = new DeptExternalCodeSaveReqVO();
|
||||||
|
createReq.setDeptId(deptId);
|
||||||
|
createReq.setSystemCode("ERP");
|
||||||
|
createReq.setExternalDeptCode("ERP-001");
|
||||||
|
deptExternalCodeService.createDeptExternalCode(createReq);
|
||||||
|
deptExternalCodeService.getDeptExternalCodeListByDeptId(deptId);
|
||||||
|
assertNotNull(cacheManager.getCache(com.zt.plat.module.system.dal.redis.RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST)
|
||||||
|
.get(deptId));
|
||||||
|
|
||||||
|
// 删除部门
|
||||||
|
deptService.deleteDept(deptId);
|
||||||
|
|
||||||
|
// 校验映射被删除且缓存被清理
|
||||||
|
assertTrue(deptExternalCodeMapper.selectListByDeptId(deptId).isEmpty());
|
||||||
|
assertNull(cacheManager.getCache(com.zt.plat.module.system.dal.redis.RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST)
|
||||||
|
.get(deptId));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteDept_exitsChildren() {
|
public void testDeleteDept_exitsChildren() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
DELETE FROM "system_dept";
|
DELETE FROM "system_dept";
|
||||||
|
DELETE FROM "system_dept_external_code";
|
||||||
DELETE FROM "system_dict_data";
|
DELETE FROM "system_dict_data";
|
||||||
DELETE FROM "system_role";
|
DELETE FROM "system_role";
|
||||||
DELETE FROM "system_role_menu";
|
DELETE FROM "system_role_menu";
|
||||||
|
|||||||
@@ -34,6 +34,27 @@ CREATE TABLE IF NOT EXISTS "system_dept" (
|
|||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '部门表';
|
) COMMENT '部门表';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS "system_dept_external_code" (
|
||||||
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
|
"dept_id" bigint NOT NULL,
|
||||||
|
"system_code" varchar(64) NOT NULL,
|
||||||
|
"external_dept_code" varchar(128) NOT NULL,
|
||||||
|
"external_dept_name" varchar(255),
|
||||||
|
"status" tinyint DEFAULT 0 NOT NULL,
|
||||||
|
"remark" varchar(512),
|
||||||
|
"tenant_id" bigint DEFAULT 0,
|
||||||
|
"creator" varchar(64),
|
||||||
|
"create_time" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updater" varchar(64),
|
||||||
|
"update_time" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"deleted" tinyint DEFAULT 0 NOT NULL,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
) COMMENT '部门外部组织编码映射';
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS "uk_system_dept_external_code_ext" ON "system_dept_external_code" ("tenant_id", "system_code", "external_dept_code");
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS "uk_system_dept_external_code_dept" ON "system_dept_external_code" ("tenant_id", "system_code", "dept_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "idx_system_dept_external_code_dept" ON "system_dept_external_code" ("tenant_id", "dept_id");
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "system_dict_data" (
|
CREATE TABLE IF NOT EXISTS "system_dict_data" (
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"sort" int NOT NULL DEFAULT '0',
|
"sort" int NOT NULL DEFAULT '0',
|
||||||
|
|||||||
Reference in New Issue
Block a user