Merge remote-tracking branch 'origin/feature/REQ-3282' into feature/REQ-3282

This commit is contained in:
zhanghongbo 2024-12-25 11:01:48 +08:00
commit b393b75ae2
9 changed files with 80 additions and 75 deletions

View File

@ -116,6 +116,11 @@ public class OrgNodeDTO implements Serializable {
*/
private List<OrgNodeDTO> descendantNodes;
/**
* 子节点
*/
private List<OrgNodeDTO> childrenNodes;
/**
* 协同关系信息
*/

View File

@ -31,7 +31,7 @@ public class ListNodeReq extends PageReqV2 {
/**
* 节点名称查询模糊
*/
private Set<String> nodeName;
private String nodeName;
/**
* 指定部门类型
@ -71,22 +71,11 @@ public class ListNodeReq extends PageReqV2 {
@Builder.Default
private Boolean includeChildren = false;
/**
* 是否查询节点用户
*/
private Boolean isSelectNodeUser;
/**
* 是否查询删除的
*/
private Boolean includeDelete;
/**
* 数据权限缓存数据key
*/
private String dataPermissionCacheKey;
/**
* 只返回topNode
*/

View File

@ -21,17 +21,17 @@ import java.util.*;
*/
public interface NodeQueryRepository {
PageResp<NodeResp> page(ListReq req);
PageResp<OrganizationalNode> page(ListReq req);
default List<NodeResp> list(ListReq req) {
default List<OrganizationalNode> list(ListReq req) {
return page(req).getData();
}
default NodeResp one(OneReq req) {
default OrganizationalNode one(OneReq req) {
return oneOpt(req).orElse(null);
}
default Optional<NodeResp> oneOpt(OneReq req) {
default Optional<OrganizationalNode> oneOpt(OneReq req) {
req.check();
ListReq page = BeanUtil.toBean(req, ListReq.class);
page.setPage(1);
@ -52,26 +52,6 @@ public interface NodeQueryRepository {
}
}
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Data
@SuperBuilder
class NodeResp extends OrganizationalNode {
/**
* 查询参数指定 needParent = true才会返回
*
* @see ListNodeReq#getNeedParent()
*/
private NodeResp parentNode;
/**
* 项目ID
*/
private Long workspaceId;
}
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@ -90,9 +70,22 @@ public interface NodeQueryRepository {
* 组织单位ids
*/
@Builder.Default
@CriteriaField(field = "ouId", operator = Operator.IN)
@CriteriaField(field = "organizationalUnitId", operator = Operator.IN)
private Collection<Long> ouIds = Collections.emptySet();
/**
* 节点名称
*/
@CriteriaField(field = "nodeName", operator = Operator.SW)
private String nodeName;
/**
* 节点名称
*/
@Builder.Default
@CriteriaField(field = "nodeName", operator = Operator.IN)
private Collection<String> nodeNames = Collections.emptySet();
/**
* 指定部门类型
*/

View File

@ -6,6 +6,7 @@ import cn.axzo.foundation.page.PageResp;
import cn.axzo.orgmanax.infra.dao.node.dao.NodeDao;
import cn.axzo.orgmanax.infra.dao.node.entity.OrganizationalNode;
import cn.axzo.orgmanax.infra.dao.node.repository.NodeQueryRepository;
import cn.axzo.orgmanax.infra.dao.orgjob.repository.OrgJobQueryRepository;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
@ -34,7 +35,7 @@ public class NodeQueryRepositoryImpl implements NodeQueryRepository {
private final NodeDao nodeDao;
@Override
public PageResp<NodeResp> page(ListReq req) {
public PageResp<OrganizationalNode> page(ListReq req) {
IPage<OrganizationalNode> page = PageConverter.toMybatis(req, OrganizationalNode.class);
QueryWrapper<OrganizationalNode> wrapper = QueryWrapperHelper.fromBean(req, OrganizationalNode.class);
@ -52,29 +53,17 @@ public class NodeQueryRepositoryImpl implements NodeQueryRepository {
});
}
IPage<NodeResp> results = nodeDao.page(page, wrapper)
.convert(e -> BeanUtil.toBean(e, NodeResp.class));
PageResp<NodeResp> resp = PageConverter.toResp(results);
List<NodeResp> records = resp.getData();
if (wrapper.isEmptyOfWhere()) {
return PageResp.<OrganizationalNode>builder().build();
}
IPage<OrganizationalNode> results = nodeDao.page(page, wrapper);
PageResp<OrganizationalNode> resp = PageConverter.toResp(results);
List<OrganizationalNode> records = resp.getData();
if (CollUtil.isEmpty(records)) {
return resp;
}
return resp;
}
private void assembleParentNode(ListReq req, List<NodeResp> records) {
// if (!BooleanUtil.isTrue(req.getIncludeAncestors())) {
// return;
// }
// Map<Long, NodeResp> nodesById = records.stream().collect(Collectors.toMap(NodeResp::getId, Function.identity()));
// // assemble parentNode
// Set<Long> parentNodeIds = records.stream().map(OrganizationalNode::getParentId).collect(Collectors.toSet());
// Set<Long> needQueryDbParentNodeIds = Sets.difference(nodesById.keySet(), parentNodeIds);
// Stream<NodeResp> queryDbParentNodes = needQueryDbParentNodeIds.isEmpty() ? Stream.of()
// : nodeDao.listByIds(needQueryDbParentNodeIds).stream().map(e -> BeanUtil.toBean(e, NodeResp.class));
// Map<Long, NodeResp> parentNodeByParentId = Stream.concat(records.stream().filter(s -> parentNodeIds.contains(s.getId())), queryDbParentNodes)
// .collect(Collectors.toMap(OrganizationalNode::getId, Function.identity()));
// records.forEach(r -> r.setParentNode(parentNodeByParentId.get(r.getParentId())));
}
}

View File

@ -14,6 +14,7 @@ import cn.axzo.orgmanax.infra.client.workspace.WorkspaceGateway;
import cn.axzo.orgmanax.infra.dao.cooperateship.entity.SaasCooperateShip;
import cn.axzo.orgmanax.infra.dao.cooperateship.repository.CooperateShipQueryRepository;
import cn.axzo.orgmanax.infra.dao.cooperateship.repository.CooperateShipUpsertRepository;
import cn.axzo.orgmanax.infra.dao.node.entity.OrganizationalNode;
import cn.axzo.orgmanax.infra.dao.node.repository.NodeQueryRepository;
import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserQueryRepository;
import cn.axzo.orgmanax.infra.dao.unit.repository.UnitQueryRepository;
@ -59,7 +60,7 @@ public class CooperateShipServiceImpl implements CooperateShipService {
@Override
public SaasCooperateShip create(CreateReq req) {
// node check
NodeQueryRepository.NodeResp node = nodeQueryRepository.oneOpt(NodeQueryRepository.OneReq.builder().id(req.getOrganizationalNodeId()).build())
OrganizationalNode node = nodeQueryRepository.oneOpt(NodeQueryRepository.OneReq.builder().id(req.getOrganizationalNodeId()).build())
.orElseThrow(() -> BizResultCode.ENTITY_NOT_FOUND.toException("部门不存在{}", req.getOrganizationalNodeId()));
Axssert.check(node.isTopNode(), BizResultCode.INVALID_PARAM, "只有顶级节点才能添加协同关系");
// workspace check

View File

@ -73,7 +73,7 @@ public class NodeFoundationServiceImpl implements NodeFoundationService {
.topNodeId(savedNode.getTopNodeId())
.path(savedNode.getPath())
.build());
NodeQueryRepository.NodeResp saved = nodeQueryRepository.one(NodeQueryRepository.OneReq.builder().id(organizationalNode.getId()).build());
OrganizationalNode saved = nodeQueryRepository.one(NodeQueryRepository.OneReq.builder().id(organizationalNode.getId()).build());
// 发送数据变更基础MQ
eventProducer.send(Event.builder()

View File

@ -10,6 +10,7 @@ import cn.axzo.orgmanax.dto.nodeuser.dto.NodeUserDTO;
import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq;
import cn.axzo.orgmanax.infra.dao.cooperateship.entity.SaasCooperateShip;
import cn.axzo.orgmanax.infra.dao.cooperateship.repository.CooperateShipQueryRepository;
import cn.axzo.orgmanax.infra.dao.node.entity.OrganizationalNode;
import cn.axzo.orgmanax.infra.dao.node.repository.NodeQueryRepository;
import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser;
import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserQueryRepository;
@ -57,7 +58,7 @@ public class NodeServiceImpl implements NodeService {
Axssert.notNull(req.getAction(), BizResultCode.INVALID_PARAM, "执行行为不能为空");
Axssert.notNull(req.getOperatorId(), BizResultCode.INVALID_PARAM, "操作人不能为空");
// 如果指定了id校验部门是否存在并加载出node以便后续使用
NodeQueryRepository.NodeResp current = req.getId() == null ? null
OrganizationalNode current = req.getId() == null ? null
: nodeQueryRepository.oneOpt(NodeQueryRepository.OneReq.builder().id(req.getId()).build())
.orElseThrow(() -> BizResultCode.ENTITY_NOT_FOUND.toException("要操作的部门不存在,{}", req.getId()));
@ -83,6 +84,9 @@ public class NodeServiceImpl implements NodeService {
.pageSize(req.getPageSize())
.ids(req.getIds())
.ouIds(req.getOuIds())
.topNodeIds(req.getTopNodeIds())
.nodeName(req.getNodeName())
.nodeNames(req.getNodeNames())
.includeOrgNodeTypes(req.getIncludeOrgNodeTypes())
.excludeOrgNodeTypes(req.getExcludeOrgNodeTypes())
.includeDelete(req.getIncludeDelete())
@ -130,7 +134,7 @@ public class NodeServiceImpl implements NodeService {
}
// 查询组织节点
PageResp<NodeQueryRepository.NodeResp> page = nodeQueryRepository.page(reqListBuilder.build());
PageResp<OrganizationalNode> page = nodeQueryRepository.page(reqListBuilder.build());
if (CollUtil.isEmpty(page.getData())) {
return emptyPageResp;
}
@ -141,14 +145,14 @@ public class NodeServiceImpl implements NodeService {
// 是否查询父级节点
if (BooleanUtil.isTrue(req.getIncludeParent())) {
Set<Long> parentIds = nodeFoundationService.extractParentIds(page.getData());
List<NodeQueryRepository.NodeResp> parentNodes = nodeQueryRepository.list(NodeQueryRepository.ListReq.builder().ids(parentIds).build());
List<OrganizationalNode> parentNodes = nodeQueryRepository.list(NodeQueryRepository.ListReq.builder().ids(parentIds).build());
assembleParentNodes(records, parentNodes);
}
// 是否查询祖父节点
if (BooleanUtil.isTrue(req.getIncludeAncestors())) {
Set<Long> ancestorIds = nodeFoundationService.extractAncestorIds(page.getData());
List<NodeQueryRepository.NodeResp> parentNodes = nodeQueryRepository.list(NodeQueryRepository.ListReq.builder().ids(ancestorIds).build());
List<OrganizationalNode> parentNodes = nodeQueryRepository.list(NodeQueryRepository.ListReq.builder().ids(ancestorIds).build());
if (CollUtil.isNotEmpty(parentNodes)) {
assembleParentNodes(records, parentNodes);
assembleAncestorNodes(records, parentNodes);
@ -158,18 +162,20 @@ public class NodeServiceImpl implements NodeService {
// 是否查询子孙节点
if (BooleanUtil.isTrue(req.getIncludeDescendants())) {
Set<String> paths = nodeFoundationService.extractPaths(page.getData(), ",");
List<NodeQueryRepository.NodeResp> descendantsNodes = nodeQueryRepository.list(
List<OrganizationalNode> descendantsNodes = nodeQueryRepository.list(
NodeQueryRepository.ListReq.builder()
.pathsRight(paths).build());
assembleChildrenNodes(records, descendantsNodes);
assembleDescendantNodes(records, descendantsNodes);
}
// 是否查询子节点
if (BooleanUtil.isTrue(req.getIncludeChildren())) {
Set<Long> ids = nodeFoundationService.extract(page.getData(), NodeQueryRepository.NodeResp::getId);
List<NodeQueryRepository.NodeResp> childrenNodes = nodeQueryRepository.list(
Set<Long> ids = nodeFoundationService.extract(page.getData(), OrganizationalNode::getId);
List<OrganizationalNode> childrenNodes = nodeQueryRepository.list(
NodeQueryRepository.ListReq.builder()
.parentIds(ids).build());
assembleChildrenNodes(records, childrenNodes);
}
return new PageResp<>(page.getTotal(), page.getSize(), page.getCurrent(), records);
@ -181,11 +187,11 @@ public class NodeServiceImpl implements NodeService {
* @param nodes
* @param ancestorNodes
*/
public void assembleAncestorNodes(List<OrgNodeDTO> nodes, List<NodeQueryRepository.NodeResp> ancestorNodes) {
public void assembleAncestorNodes(List<OrgNodeDTO> nodes, List<OrganizationalNode> ancestorNodes) {
if (CollUtil.isEmpty(nodes) || CollUtil.isEmpty(ancestorNodes)) {
return;
}
Map<Long, NodeQueryRepository.NodeResp> parentNodeMap = ancestorNodes.stream().collect(Collectors.toMap(NodeQueryRepository.NodeResp::getId, Function.identity()));
Map<Long, OrganizationalNode> parentNodeMap = ancestorNodes.stream().collect(Collectors.toMap(OrganizationalNode::getId, Function.identity()));
nodes.forEach(e -> {
String[] parentIds = e.getPath().split(",");
e.setAncestorNodes(Arrays.stream(parentIds)
@ -203,17 +209,17 @@ public class NodeServiceImpl implements NodeService {
* @param nodes
* @param parentNodes
*/
public void assembleParentNodes(List<OrgNodeDTO> nodes, List<NodeQueryRepository.NodeResp> parentNodes) {
public void assembleParentNodes(List<OrgNodeDTO> nodes, List<OrganizationalNode> parentNodes) {
if (CollUtil.isEmpty(nodes) || CollUtil.isEmpty(parentNodes)) {
return;
}
Map<Long, NodeQueryRepository.NodeResp> parentNodeMap = parentNodes.stream().collect(Collectors.toMap(NodeQueryRepository.NodeResp::getId, Function.identity()));
Map<Long, OrganizationalNode> parentNodeMap = parentNodes.stream().collect(Collectors.toMap(OrganizationalNode::getId, Function.identity()));
nodes.forEach(e -> {
Long parentId = e.getParentId();
if (Objects.isNull(parentId) || parentId == 0) {
return;
}
NodeQueryRepository.NodeResp nodeResp = parentNodeMap.get(parentId);
OrganizationalNode nodeResp = parentNodeMap.get(parentId);
e.setParentNode(BeanUtil.copyProperties(nodeResp, OrgNodeDTO.class));
});
}
@ -224,7 +230,7 @@ public class NodeServiceImpl implements NodeService {
* @param nodes
* @param descendantNodes
*/
public void assembleDescendantNodes(List<OrgNodeDTO> nodes, List<NodeQueryRepository.NodeResp> descendantNodes) {
public void assembleDescendantNodes(List<OrgNodeDTO> nodes, List<OrganizationalNode> descendantNodes) {
if (CollUtil.isEmpty(nodes) || CollUtil.isEmpty(descendantNodes)) {
return;
}
@ -236,4 +242,24 @@ public class NodeServiceImpl implements NodeService {
.collect(Collectors.toList()));
});
}
/**
* 聚合祖父节点
*
* @param nodes
* @param childrenNodes
*/
public void assembleChildrenNodes(List<OrgNodeDTO> nodes, List<OrganizationalNode> childrenNodes) {
if (CollUtil.isEmpty(nodes) || CollUtil.isEmpty(childrenNodes)) {
return;
}
Map<Long, List<OrgNodeDTO>> childrenNodeMap = childrenNodes
.stream()
.map(t -> BeanUtil.copyProperties(t, OrgNodeDTO.class))
.collect(Collectors.groupingBy(OrgNodeDTO::getParentId));
nodes.forEach(e -> {
List<OrgNodeDTO> orgNodeDTOS = childrenNodeMap.get(e.getId());
e.setChildrenNodes(CollUtil.emptyIfNull(orgNodeDTOS));
});
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.orgmanax.server.node.service.processor;
import cn.axzo.orgmanax.dto.node.req.ProcessNodeReq;
import cn.axzo.orgmanax.infra.dao.node.entity.OrganizationalNode;
import cn.axzo.orgmanax.infra.dao.node.repository.NodeQueryRepository;
import com.alibaba.fastjson.JSONObject;
import lombok.AccessLevel;
@ -23,7 +24,7 @@ public interface NodeProcessor {
@NoArgsConstructor
@AllArgsConstructor
class ProcessContext {
NodeQueryRepository.NodeResp node;
OrganizationalNode node;
ProcessNodeReq.Action action;
JSONObject params;

View File

@ -11,6 +11,7 @@ import cn.axzo.orgmanax.infra.client.profile.dto.ProfileIdentityResp;
import cn.axzo.orgmanax.infra.client.profile.dto.ProfilePersonResp;
import cn.axzo.orgmanax.infra.dao.cooperateship.entity.SaasCooperateShip;
import cn.axzo.orgmanax.infra.dao.cooperateship.repository.CooperateShipQueryRepository;
import cn.axzo.orgmanax.infra.dao.node.entity.OrganizationalNode;
import cn.axzo.orgmanax.infra.dao.node.repository.NodeQueryRepository;
import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser;
import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserQueryRepository;
@ -60,7 +61,7 @@ public class NodeUserFoundationServiceImpl implements NodeUserFoundationService
param.check();
// 部门是否存在
NodeQueryRepository.NodeResp node = nodeQueryRepository.oneOpt(NodeQueryRepository.OneReq.builder().id(param.getNodeId()).build())
OrganizationalNode node = nodeQueryRepository.oneOpt(NodeQueryRepository.OneReq.builder().id(param.getNodeId()).build())
.orElseThrow(() -> BizResultCode.ENTITY_NOT_FOUND.toException("部门不存在{}", param.getNodeId()));
// 人是否存在
@ -141,7 +142,7 @@ public class NodeUserFoundationServiceImpl implements NodeUserFoundationService
nodeUsers.removeIf(e -> !jobIds.contains(e.getOrganizationalJobId()));
}
private Long resolveWorkspaceId(NodeQueryRepository.NodeResp node) {
private Long resolveWorkspaceId(OrganizationalNode node) {
if (Objects.equals(node.getNodeType(), NodeUserTypeEnum.TEAM.getValue())) {
return 0L;
}