[#]修改部门推送消息逻辑
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
package com.zt.plat.module.system.api.dept.dto;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公司部门推送消息 Response DTO
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Schema(description = "RPC 服务 - 部门推送消息 Response DTO")
|
||||||
|
@Data
|
||||||
|
public class DeptMsgRespDTO {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本系统部门 ID
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统标识
|
||||||
|
*/
|
||||||
|
private String systemCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统组织编码
|
||||||
|
*/
|
||||||
|
private String externalDeptCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统组织名称
|
||||||
|
*/
|
||||||
|
private String externalDeptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射状态
|
||||||
|
* 枚举 {@link CommonStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否发送消息
|
||||||
|
*/
|
||||||
|
private Integer isSendMsg;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,23 +2,27 @@ package com.zt.plat.module.system.api.esp;
|
|||||||
|
|
||||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
import com.zt.plat.module.system.api.dept.dto.*;
|
import com.zt.plat.module.system.api.dept.dto.*;
|
||||||
import com.zt.plat.module.system.api.esp.dto.EspDto;
|
|
||||||
import com.zt.plat.module.system.enums.ApiConstants;
|
import com.zt.plat.module.system.enums.ApiConstants;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@FeignClient(name = ApiConstants.NAME)
|
@FeignClient(name = ApiConstants.NAME)
|
||||||
@Tag(name = "RPC 服务 - 部门")
|
@Tag(name = "RPC 服务 - 部门推送消息")
|
||||||
public interface EspApi {
|
public interface EspApi {
|
||||||
|
|
||||||
String PREFIX = ApiConstants.PREFIX + "/dept";
|
String PREFIX = ApiConstants.PREFIX + "/dept-esp";
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/create")
|
||||||
|
@Operation(summary = "新增部门")
|
||||||
|
CommonResult<Long> createDept(@RequestBody DeptSaveReqDTO createReqVO);
|
||||||
|
|
||||||
|
|
||||||
@PostMapping(PREFIX + "/pushMsg")
|
@PostMapping(PREFIX + "/pushMsg")
|
||||||
@Operation(summary = "推送消息")
|
@Operation(summary = "查询部门消息")
|
||||||
CommonResult<List<EspDto>> pushMsg(@RequestBody DeptSaveReqDTO syncReqDTO);
|
CommonResult<List<DeptMsgRespDTO>> selectDepMsg(@RequestBody DeptSaveReqDTO syncReqDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ public class ApiConstants {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务名
|
* 服务名
|
||||||
*
|
|
||||||
* 注意,需要保证和 spring.application.name 保持一致
|
* 注意,需要保证和 spring.application.name 保持一致
|
||||||
*/
|
*/
|
||||||
public static final String NAME = "system-server";
|
public static final String NAME = "system-server";
|
||||||
|
|||||||
@@ -206,6 +206,8 @@ public interface ErrorCodeConstants {
|
|||||||
// ========== 用户与部门关系 1-002-029-000 ==========
|
// ========== 用户与部门关系 1-002-029-000 ==========
|
||||||
ErrorCode USER_DEPT_NOT_EXISTS = new ErrorCode(1_002_029_000, "用户与部门关系不存在");
|
ErrorCode USER_DEPT_NOT_EXISTS = new ErrorCode(1_002_029_000, "用户与部门关系不存在");
|
||||||
|
|
||||||
|
ErrorCode USER_DEPT_SAVE_EXISTS = new ErrorCode(1_002_029_001, "插入用户部门失败");
|
||||||
|
|
||||||
// ========== 系统序列号分段明细 1-002-030-000 ==========
|
// ========== 系统序列号分段明细 1-002-030-000 ==========
|
||||||
ErrorCode SEQUENCE_DETAIL_NOT_EXISTS = new ErrorCode(1_002_030_000, "系统序列号分段明细不存在");
|
ErrorCode SEQUENCE_DETAIL_NOT_EXISTS = new ErrorCode(1_002_030_000, "系统序列号分段明细不存在");
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,17 @@ package com.zt.plat.module.system.api.esp;
|
|||||||
|
|
||||||
import com.zt.plat.framework.common.exception.enums.GlobalErrorCodeConstants;
|
import com.zt.plat.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
import com.zt.plat.framework.common.util.object.ObjectUtils;
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.api.dept.dto.DeptMsgRespDTO;
|
||||||
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
|
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
|
||||||
import com.zt.plat.module.system.api.esp.dto.EspDto;
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
import com.zt.plat.module.system.service.dept.IEspService;
|
import com.zt.plat.module.system.service.dept.IEspService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@Validated
|
@Validated
|
||||||
@@ -18,16 +20,26 @@ public class EspApiImpl implements EspApi {
|
|||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IEspService deptService;
|
private IEspService espService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<List<EspDto>> pushMsg(DeptSaveReqDTO syncReqDTO)
|
public CommonResult<Long> createDept(DeptSaveReqDTO createReqVO) {
|
||||||
|
DeptSaveReqVO reqVO = BeanUtils.toBean(createReqVO, DeptSaveReqVO.class);
|
||||||
|
Long deptId = espService.createDept(reqVO);
|
||||||
|
return success(deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<DeptMsgRespDTO>> selectDepMsg(DeptSaveReqDTO syncReqDTO)
|
||||||
{
|
{
|
||||||
if(Objects.isNull(syncReqDTO) || null == syncReqDTO.getId())
|
if(Objects.isNull(syncReqDTO) || null == syncReqDTO.getId())
|
||||||
{
|
{
|
||||||
return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
|
return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
|
||||||
"ID不能为空");
|
"ID不能为空");
|
||||||
}
|
}
|
||||||
return CommonResult.success(deptService.pushMsg(syncReqDTO));
|
return espService.selectDepMsg(syncReqDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,14 +74,15 @@ public class DeptDO extends TenantBaseDO {
|
|||||||
* 枚举 {@link CommonStatusEnum}
|
* 枚举 {@link CommonStatusEnum}
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
/**
|
|
||||||
* 是否公司
|
|
||||||
*/
|
|
||||||
private Boolean isCompany;
|
|
||||||
/**
|
/**
|
||||||
* 是否集团
|
* 是否集团
|
||||||
*/
|
*/
|
||||||
private Boolean isGroup;
|
private Boolean isGroup;
|
||||||
|
/**
|
||||||
|
* 是否公司
|
||||||
|
*/
|
||||||
|
private Boolean isCompany;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门来源类型
|
* 部门来源类型
|
||||||
|
|||||||
@@ -1,26 +1,37 @@
|
|||||||
package com.zt.plat.module.system.service.dept;
|
package com.zt.plat.module.system.service.dept;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.zt.plat.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
import com.zt.plat.framework.common.pojo.PageResult;
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
import com.zt.plat.framework.common.util.object.BeanUtils;
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.api.dept.dto.DeptMsgRespDTO;
|
||||||
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
|
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
|
||||||
import com.zt.plat.module.system.api.esp.dto.EspDto;
|
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspPageReqVO;
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspPageReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspSaveRespVo;
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspSaveRespVo;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
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.DeptPushMsgDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptPushMsgDO;
|
||||||
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.dept.EspMapper;
|
import com.zt.plat.module.system.dal.mysql.dept.EspMapper;
|
||||||
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 jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.seata.common.result.Result;
|
import org.apache.seata.spring.annotation.GlobalTransactional;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
@@ -33,13 +44,31 @@ import static com.zt.plat.module.system.enums.ErrorCodeConstants.*;
|
|||||||
@Validated
|
@Validated
|
||||||
public class EspServiceImpl implements IEspService {
|
public class EspServiceImpl implements IEspService {
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeptExternalCodeService deptExternalCodeService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private EspMapper espMapper;
|
private EspMapper espMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DeptMapper deptMapper;
|
private DeptMapper deptMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CacheManager cacheManager;
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private com.zt.plat.module.system.mq.producer.databus.DatabusChangeProducer databusChangeProducer;
|
||||||
|
|
||||||
|
private static final String ROOT_CODE_PREFIX = "ZT";
|
||||||
|
private static final String EXTERNAL_CODE_PREFIX = "CU";
|
||||||
|
private static final int CODE_SEGMENT_LENGTH = 3;
|
||||||
|
private static final int MAX_SEQUENCE = 999;
|
||||||
|
private static final int BATCH_SIZE = 1000;
|
||||||
|
private static final Comparator<DeptDO> DEPT_COMPARATOR = Comparator
|
||||||
|
.comparing(DeptDO::getSort, Comparator.nullsLast(Comparator.naturalOrder()))
|
||||||
|
.thenComparing(DeptDO::getId, Comparator.nullsLast(Comparator.naturalOrder()));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST, key = "#createReqVO.deptId", beforeInvocation = false)
|
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_EXTERNAL_CODE_LIST, key = "#createReqVO.deptId", beforeInvocation = false)
|
||||||
public Long createDeptPushMsg(EspSaveRespVo createReqVO) {
|
public Long createDeptPushMsg(EspSaveRespVo createReqVO) {
|
||||||
@@ -103,12 +132,243 @@ public class EspServiceImpl implements IEspService {
|
|||||||
return espMapper.selectListByDeptId(deptId);
|
return espMapper.selectListByDeptId(deptId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<EspDto> pushMsg(DeptSaveReqDTO syncReqDTO) {
|
|
||||||
|
|
||||||
return BeanUtils.toBean(espMapper.selectpushMsg(syncReqDTO), EspDto.class);
|
@Override
|
||||||
|
@GlobalTransactional(rollbackFor = Exception.class)
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
|
||||||
|
public Long createDept(DeptSaveReqVO createReqVO) {
|
||||||
|
// 允许上级组织为空,视为顶级组织
|
||||||
|
createReqVO.setParentId(normalizeParentId(createReqVO.getParentId()));
|
||||||
|
// 创建时默认有效
|
||||||
|
createReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
// 默认部门来源:未指定时视为外部部门
|
||||||
|
if (createReqVO.getDeptSource() == null) {
|
||||||
|
createReqVO.setDeptSource(DeptSourceEnum.EXTERNAL.getSource());
|
||||||
|
}
|
||||||
|
// 校验父部门的有效性
|
||||||
|
validateParentDept(null, createReqVO.getParentId());
|
||||||
|
// 校验部门名的唯一性
|
||||||
|
validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
|
||||||
|
// 生成并校验部门编码(所有来源统一走生成逻辑,iWork 不再豁免)
|
||||||
|
if (Boolean.TRUE.equals(createReqVO.getDelayCodeGeneration())) {
|
||||||
|
createReqVO.setCode(null);
|
||||||
|
} else {
|
||||||
|
String resolvedCode = generateDeptCode(createReqVO.getParentId(), createReqVO.getDeptSource());
|
||||||
|
validateDeptCodeUnique(null, resolvedCode);
|
||||||
|
createReqVO.setCode(resolvedCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入部门
|
||||||
|
DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class);
|
||||||
|
// 设置部门来源(前置已默认化,此处兜底)
|
||||||
|
if (dept.getDeptSource() == null) {
|
||||||
|
dept.setDeptSource(DeptSourceEnum.EXTERNAL.getSource());
|
||||||
|
}
|
||||||
|
int insert = deptMapper.insert(dept);
|
||||||
|
if (insert == 0) {
|
||||||
|
throw exception(USER_DEPT_SAVE_EXISTS);
|
||||||
|
}
|
||||||
|
// 外部编码映射
|
||||||
|
upsertExternalMappingIfPresent(dept.getId(), createReqVO);
|
||||||
|
// 发布部门创建事件
|
||||||
|
databusChangeProducer.sendDeptCreatedMessage(dept);
|
||||||
|
//推送消息
|
||||||
|
DeptSaveReqDTO deptSaveReqDTO = new DeptSaveReqDTO();
|
||||||
|
BeanUtils.copyProperties(dept,deptSaveReqDTO);
|
||||||
|
return dept.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<DeptMsgRespDTO>> selectDepMsg(DeptSaveReqDTO syncReqDTO) {
|
||||||
|
if (syncReqDTO == null) {
|
||||||
|
return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<DeptPushMsgDO> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
if(syncReqDTO.getId() != null){
|
||||||
|
wrapper.eq(DeptPushMsgDO::getId, syncReqDTO.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DeptPushMsgDO> list = espMapper.selectList(wrapper);
|
||||||
|
if (CollectionUtils.isEmpty(list)){
|
||||||
|
return CommonResult.error(GlobalErrorCodeConstants.NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<DeptMsgRespDTO> lists = new ArrayList<>(list.size());
|
||||||
|
for (DeptPushMsgDO deptPushMsgDO : list){
|
||||||
|
DeptMsgRespDTO deptMsgRespDTO = new DeptMsgRespDTO();
|
||||||
|
BeanUtils.copyProperties(deptPushMsgDO, deptMsgRespDTO);
|
||||||
|
lists.add(deptMsgRespDTO);
|
||||||
|
}
|
||||||
|
return CommonResult.success(lists);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long normalizeParentId(Long parentId) {
|
||||||
|
return parentId == null ? DeptDO.PARENT_ID_ROOT : parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateParentDept(Long id, Long parentId) {
|
||||||
|
if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 1. 不能设置自己为父部门
|
||||||
|
if (Objects.equals(id, parentId)) {
|
||||||
|
throw exception(DEPT_PARENT_ERROR);
|
||||||
|
}
|
||||||
|
// 2. 父部门不存在
|
||||||
|
DeptDO parentDept = deptMapper.selectById(parentId);
|
||||||
|
if (parentDept == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String generateDeptCode(Long parentId, Integer deptSource) {
|
||||||
|
Long effectiveParentId = normalizeParentId(parentId);
|
||||||
|
String prefix = resolveCodePrefix(effectiveParentId, deptSource);
|
||||||
|
int nextSequence = determineNextSequence(effectiveParentId, prefix);
|
||||||
|
assertSequenceRange(nextSequence);
|
||||||
|
return prefix + formatSequence(nextSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateDeptNameUnique(Long id, Long parentId, String name) {
|
||||||
|
Long effectiveParentId = normalizeParentId(parentId);
|
||||||
|
if (Objects.equals(effectiveParentId, DeptDO.PARENT_ID_ROOT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DeptDO dept = deptMapper.selectByParentIdAndName(effectiveParentId, name);
|
||||||
|
if (dept == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果 id 为空,说明不用比较是否为相同 id 的部门
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(DEPT_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
|
if (ObjectUtil.notEqual(dept.getId(), id)) {
|
||||||
|
throw exception(DEPT_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateDeptCodeUnique(Long id, String code) {
|
||||||
|
if (StrUtil.isBlank(code)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DeptDO dept = deptMapper.selectByCode(code);
|
||||||
|
if (dept == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果 id 为空,说明不用比较是否为相同 id 的部门
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(DEPT_CODE_DUPLICATE);
|
||||||
|
}
|
||||||
|
if (ObjectUtil.notEqual(dept.getId(), id)) {
|
||||||
|
throw exception(DEPT_CODE_DUPLICATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void upsertExternalMappingIfPresent(Long deptId, DeptSaveReqVO reqVO) {
|
||||||
|
String systemCode = StrUtil.trimToNull(reqVO.getExternalSystemCode());
|
||||||
|
String externalCode = StrUtil.trimToNull(reqVO.getExternalDeptCode());
|
||||||
|
if (StrUtil.hasEmpty(systemCode, externalCode) || deptId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String externalName = StrUtil.trimToNull(reqVO.getExternalDeptName());
|
||||||
|
deptExternalCodeService.saveOrUpdateDeptExternalCode(deptId, systemCode, externalCode, externalName, reqVO.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String resolveCodePrefix(Long parentId, Integer deptSource) {
|
||||||
|
boolean isExternal = Objects.equals(deptSource, DeptSourceEnum.EXTERNAL.getSource());
|
||||||
|
if (DeptDO.PARENT_ID_ROOT.equals(parentId)) {
|
||||||
|
return isExternal ? EXTERNAL_CODE_PREFIX : ROOT_CODE_PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeptDO parentDept = deptMapper.selectById(parentId);
|
||||||
|
if (parentDept == null || StrUtil.isBlank(parentDept.getCode())) {
|
||||||
|
return isExternal ? EXTERNAL_CODE_PREFIX : ROOT_CODE_PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
String parentCode = parentDept.getCode();
|
||||||
|
if (isExternal) {
|
||||||
|
if (parentCode.startsWith(EXTERNAL_CODE_PREFIX)) {
|
||||||
|
return parentCode;
|
||||||
|
}
|
||||||
|
if (parentCode.startsWith(ROOT_CODE_PREFIX)) {
|
||||||
|
return EXTERNAL_CODE_PREFIX + parentCode.substring(ROOT_CODE_PREFIX.length());
|
||||||
|
}
|
||||||
|
return EXTERNAL_CODE_PREFIX;
|
||||||
|
}
|
||||||
|
return parentCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int determineNextSequence(Long parentId, String prefix) {
|
||||||
|
DeptDO lastChild = deptMapper.selectLastChildByCode(parentId, prefix);
|
||||||
|
Integer sequence = parseSequence(lastChild != null ? lastChild.getCode() : null, prefix);
|
||||||
|
if (sequence != null) {
|
||||||
|
return sequence + 1;
|
||||||
|
}
|
||||||
|
return deptMapper.selectListByParentId(parentId, null).stream()
|
||||||
|
.map(DeptDO::getCode)
|
||||||
|
.map(code -> parseSequence(code, prefix))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.max(Integer::compareTo)
|
||||||
|
.map(val -> val + 1)
|
||||||
|
.orElse(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void assertSequenceRange(int sequence) {
|
||||||
|
if (sequence > MAX_SEQUENCE) {
|
||||||
|
throw exception(DEPT_CODE_OUT_OF_RANGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatSequence(int sequence) {
|
||||||
|
return StrUtil.padPre(String.valueOf(sequence), CODE_SEGMENT_LENGTH, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer parseSequence(String code, String prefix) {
|
||||||
|
if (StrUtil.isBlank(code) || StrUtil.isBlank(prefix) || !code.startsWith(prefix)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String suffix = code.substring(prefix.length());
|
||||||
|
if (suffix.length() != CODE_SEGMENT_LENGTH || !StrUtil.isNumeric(suffix)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Integer.parseInt(suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private DeptPushMsgDO validateExists(Long id) {
|
private DeptPushMsgDO validateExists(Long id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw exception(DEPT_EXTERNAL_RELATION_NOT_EXISTS);
|
throw exception(DEPT_EXTERNAL_RELATION_NOT_EXISTS);
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.zt.plat.module.system.service.dept;
|
package com.zt.plat.module.system.service.dept;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
import com.zt.plat.framework.common.pojo.PageResult;
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.module.system.api.dept.dto.DeptMsgRespDTO;
|
||||||
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
|
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
|
||||||
import com.zt.plat.module.system.api.esp.dto.EspDto;
|
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspPageReqVO;
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspPageReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspSaveRespVo;
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspSaveRespVo;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.dept.DeptPushMsgDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptPushMsgDO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门推送消息 Service 接口
|
* 部门推送消息 Service 接口
|
||||||
*/
|
*/
|
||||||
@@ -47,11 +48,18 @@ public interface IEspService {
|
|||||||
*/
|
*/
|
||||||
List<DeptPushMsgDO> getPushMsgByDeptId(Long deptId);
|
List<DeptPushMsgDO> getPushMsgByDeptId(Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建部门
|
||||||
|
* @param reqVO 部门信息
|
||||||
|
* @return 部门编号
|
||||||
|
*/
|
||||||
|
Long createDept(DeptSaveReqVO reqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 推送部门数据到外部系统
|
* 推送部门数据到外部系统
|
||||||
* @param syncReqDTO 同步请求
|
* @param syncReqDTO 同步请求
|
||||||
*/
|
*/
|
||||||
List<EspDto> pushMsg(DeptSaveReqDTO syncReqDTO);
|
CommonResult<List<DeptMsgRespDTO>> selectDepMsg(DeptSaveReqDTO syncReqDTO);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user