From 442d0ef53d2e793b809d3d24bafe800841cfd58f Mon Sep 17 00:00:00 2001 From: zhanghonghao Date: Thu, 6 Mar 2025 16:29:00 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(REQ-3714):=20=E5=BA=95=E5=BA=A7?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4node=5Fuser=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/nodeuser/req/ProcessNodeUserReq.java | 11 +- .../worker/req/ListOrgProjectWorkerReq.java | 43 +++++ .../repository/NodeUserUpsertRepository.java | 2 + .../impl/NodeUserUpsertRepositoryImpl.java | 16 +- .../repository/OrgUserUpsertRepository.java | 11 +- .../impl/OrgUserUpsertRepositoryImpl.java | 14 +- .../worker/dao/OrgProjectWorkerDao.java | 16 ++ .../worker/entity/OrgProjectWorker.java | 148 ++++++++++++++++++ .../worker/mapper/OrgProjectWorkerMapper.java | 10 ++ .../OrgProjectWorkerQueryRepository.java | 100 ++++++++++++ .../OrgProjectWorkerUpsertRepository.java | 13 ++ .../OrgProjectWorkerQueryRepositoryImpl.java | 40 +++++ .../OrgProjectWorkerUpsertRepositoryImpl.java | 28 ++++ ...OrganizationalNodeUserUpsertedPayload.java | 62 ++++++++ .../orgmanax/server/mq/enums/MQEventEnum.java | 65 ++++++++ .../producer/OrgUserChangedEventProducer.java | 71 +++++++++ .../foundation/NodeUserFoundationService.java | 13 +- .../impl/NodeUserFoundationServiceImpl.java | 89 ++++++++++- .../foundation/req/NodeUserDelete.java | 35 +++++ .../foundation/req/NodeUserUnitDelete.java | 34 ++++ .../req/NodeUserWorkspaceDelete.java | 34 ++++ .../impl/UnitDeleteNodeUserProcessor.java | 34 ++++ .../WorkspaceDeleteNodeUserProcessor.java | 32 ++++ .../foundation/OrgUserFoundationService.java | 11 ++ .../impl/OrgUserFoundationServiceImpl.java | 115 ++++++++++++++ .../req/OrgUserWithdrawOrQuitReq.java | 26 +++ .../OrgProjectWorkerFoundationService.java | 10 ++ ...OrgProjectWorkerFoundationServiceImpl.java | 52 ++++++ .../req/OrgProjectWorkerWithdrawReq.java | 20 +++ .../server/service/OperateLogService.java | 51 ++++++ 30 files changed, 1189 insertions(+), 17 deletions(-) create mode 100644 orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/project/worker/req/ListOrgProjectWorkerReq.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/dao/OrgProjectWorkerDao.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/entity/OrgProjectWorker.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/mapper/OrgProjectWorkerMapper.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerQueryRepository.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerUpsertRepository.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerQueryRepositoryImpl.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerUpsertRepositoryImpl.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/OrganizationalNodeUserUpsertedPayload.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/enums/MQEventEnum.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/producer/OrgUserChangedEventProducer.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserUnitDelete.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserWorkspaceDelete.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/UnitDeleteNodeUserProcessor.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/WorkspaceDeleteNodeUserProcessor.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/OrgUserFoundationService.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/impl/OrgUserFoundationServiceImpl.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/req/OrgUserWithdrawOrQuitReq.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/OrgProjectWorkerFoundationService.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/impl/OrgProjectWorkerFoundationServiceImpl.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/req/OrgProjectWorkerWithdrawReq.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/service/OperateLogService.java diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/ProcessNodeUserReq.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/ProcessNodeUserReq.java index 893820c..9f72966 100644 --- a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/ProcessNodeUserReq.java +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/ProcessNodeUserReq.java @@ -1,12 +1,7 @@ package cn.axzo.orgmanax.dto.nodeuser.req; import com.alibaba.fastjson.JSONObject; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import lombok.experimental.SuperBuilder; @NoArgsConstructor @@ -24,7 +19,9 @@ public class ProcessNodeUserReq { @Getter public enum Action { CREATE("创建", "createNodeUserProcessor"), - UPDATE("普通更新", "updateNodeUserProcessor"); + UPDATE("普通更新", "updateNodeUserProcessor"), + UNIT_DELETE("删除单位人员", "unitDeleteNodeUserProcessor"), + WORKSPACE_DELETE("删除项目人员", "workspaceDeleteNodeUserProcessor"); private final String desc; private final String processor; diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/project/worker/req/ListOrgProjectWorkerReq.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/project/worker/req/ListOrgProjectWorkerReq.java new file mode 100644 index 0000000..b3a434e --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/project/worker/req/ListOrgProjectWorkerReq.java @@ -0,0 +1,43 @@ +package cn.axzo.orgmanax.dto.project.worker.req; + +import cn.axzo.foundation.page.PageReqV2; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +@Data +@SuperBuilder +public class ListOrgProjectWorkerReq extends PageReqV2 { + + /** + * 工作台ID + */ + private Long workspaceId; + + /** + * 总包ID + */ + private Long entId; + + /** + * 所属单位id + */ + private Long organizationalUnitId; + + /** + * 工人personId + */ + private List workerPersonIds; + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/NodeUserUpsertRepository.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/NodeUserUpsertRepository.java index 9796e77..2e76d83 100644 --- a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/NodeUserUpsertRepository.java +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/NodeUserUpsertRepository.java @@ -18,6 +18,8 @@ public interface NodeUserUpsertRepository { OrganizationalNodeUser update(UpdateReq node); + void batchDelete(Set ids); + @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/impl/NodeUserUpsertRepositoryImpl.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/impl/NodeUserUpsertRepositoryImpl.java index 91ea35c..294eeff 100644 --- a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/impl/NodeUserUpsertRepositoryImpl.java +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/nodeuser/repository/impl/NodeUserUpsertRepositoryImpl.java @@ -5,11 +5,15 @@ import cn.axzo.orgmanax.infra.dao.nodeuser.dao.NodeUserDao; import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserUpsertRepository; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Date; +import java.util.Set; + @Service @RequiredArgsConstructor @Slf4j @@ -32,4 +36,14 @@ public class NodeUserUpsertRepositoryImpl implements NodeUserUpsertRepository { wrapper.update(req); return nodeUserDao.getById(req.getId()); } -} + + @Override + public void batchDelete(Set ids) { + Date date = new Date(); + nodeUserDao.lambdaUpdate().in(OrganizationalNodeUser::getId, ids) + .eq(OrganizationalNodeUser::getIsDelete, 0) + .setSql("is_delete = id, leave_at = CASE WHEN leave_at IS NULL THEN '" + DateUtil.formatDateTime(date) + "' ELSE leave_at END") + .update(); + } + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/OrgUserUpsertRepository.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/OrgUserUpsertRepository.java index b29379f..4bba255 100644 --- a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/OrgUserUpsertRepository.java +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/OrgUserUpsertRepository.java @@ -1,4 +1,13 @@ package cn.axzo.orgmanax.infra.dao.orguser.repository; +import cn.axzo.orgmanax.infra.dao.orguser.entity.OrgUser; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + public interface OrgUserUpsertRepository { -} + + @Transactional(rollbackFor = Throwable.class) + void batchUpdate(List orgUsers); + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/impl/OrgUserUpsertRepositoryImpl.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/impl/OrgUserUpsertRepositoryImpl.java index 8fdc804..7975b88 100644 --- a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/impl/OrgUserUpsertRepositoryImpl.java +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/orguser/repository/impl/OrgUserUpsertRepositoryImpl.java @@ -1,10 +1,22 @@ package cn.axzo.orgmanax.infra.dao.orguser.repository.impl; +import cn.axzo.orgmanax.infra.dao.orguser.dao.OrgUserDao; +import cn.axzo.orgmanax.infra.dao.orguser.entity.OrgUser; import cn.axzo.orgmanax.infra.dao.orguser.repository.OrgUserUpsertRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @Service @RequiredArgsConstructor public class OrgUserUpsertRepositoryImpl implements OrgUserUpsertRepository { -} + + private final OrgUserDao orgUserDao; + + @Override + public void batchUpdate(List orgUsers) { + orgUserDao.updateBatchById(orgUsers); + } + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/dao/OrgProjectWorkerDao.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/dao/OrgProjectWorkerDao.java new file mode 100644 index 0000000..abda69e --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/dao/OrgProjectWorkerDao.java @@ -0,0 +1,16 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.dao; + +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import cn.axzo.orgmanax.infra.dao.project.worker.mapper.OrgProjectWorkerMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Repository; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/1/8 + */ +@Repository +public class OrgProjectWorkerDao extends ServiceImpl { + + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/entity/OrgProjectWorker.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/entity/OrgProjectWorker.java new file mode 100644 index 0000000..48fbbd9 --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/entity/OrgProjectWorker.java @@ -0,0 +1,148 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.io.Serializable; +import java.util.Date; + +/** + * 项目内工人表实体类 + * + * @author chenliang@axzo.cn + * @since 2022-07-20 15:01:43 + */ +@TableName(value = "org_project_worker", autoResultMap = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class OrgProjectWorker implements Serializable { + + private static final long serialVersionUID = 260206461965825922L; + + + @TableField("id") + private Long id; + + /** + * 工作台ID + */ + @TableField("workspace_id") + private Long workspaceId; + + /** + * 总包ID + */ + @TableField("ent_id") + private Long entId; + + /** + * 所属单位id + */ + @TableField("organizational_unit_id") + private Long organizationalUnitId; + + /** + * 所属单位类型: 1:总包 4:专业分包 5:劳务分包 + */ + @TableField("organizational_unit_type") + private Integer organizationalUnitType; + + /** + * 项目内班组ID + */ + @TableField("project_team_id") + private Long projectTeamId; + + /** + * 工人personId + */ + @TableField("worker_person_id") + private Long workerPersonId; + + /** + * 工人身份ID + */ + @TableField("worker_identity_id") + private Long workerIdentityId; + + /** + * 状态:0、未激活 1、已激活 3已退场 + */ + @TableField("status") + private Integer status; + + /** + * 工种类别 + */ + @TableField("profession_category_name") + private String professionCategoryName; + + /** + * 入场时间 + */ + @TableField("join_at") + private Date joinAt; + + /** + * 离场时间 + */ + @TableField("resign_at") + private Date resignAt; + + /** + * 是否删除 0:未删除 其他:已删除 + */ + @TableField("is_delete") + private Long isDelete; + + /** + * 创建时间 + */ + @TableField("create_at") + private Date createAt; + + + @TableField("update_at") + private Date updateAt; + + /** + * 最后一次进工地的时间,进场打卡更新 + * 进场打卡更新, + */ + @TableField("last_check_in_time") + private Date lastCheckInTime; + + /** + * 最后一次出工地的时间,出场打卡更新 + */ + @TableField("last_check_out_time") + private Date lastCheckOutTime; + + /** + * 工人施工开始时间,工人所有任务单中最早开始时间 + */ + private Date constructionStartTime; + + /** + * 工人施工结束时间 + */ + private Date constructionEndTime; + /** + * 在岗、待岗 + */ + private Integer occupyStatus; + /** + * 推送未备案消息次数 + */ + @TableField("push_supervision_msg_count") + private Integer pushSupervisionMsgCount; + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/mapper/OrgProjectWorkerMapper.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/mapper/OrgProjectWorkerMapper.java new file mode 100644 index 0000000..cd829fb --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/mapper/OrgProjectWorkerMapper.java @@ -0,0 +1,10 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.mapper; + +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface OrgProjectWorkerMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerQueryRepository.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerQueryRepository.java new file mode 100644 index 0000000..0016707 --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerQueryRepository.java @@ -0,0 +1,100 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.repositrory; + +import cn.axzo.foundation.dao.support.wrapper.CriteriaField; +import cn.axzo.foundation.dao.support.wrapper.Operator; +import cn.axzo.foundation.page.PageReqV2; +import cn.axzo.foundation.page.PageResp; +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.google.common.base.Preconditions; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public interface OrgProjectWorkerQueryRepository { + + PageResp page(ListReq req); + + default List list(ListReq req) { + return page(req).getData(); + } + + default OrgProjectWorkerResp one(OneReq req) { + return oneOpt(req).orElse(null); + } + + default Optional oneOpt(OneReq req) { + req.check(); + ListReq page = BeanUtil.toBean(req, ListReq.class); + page.setPage(1); + page.setPageSize(1); + return page(page).getData().stream().findFirst(); + } + + @NoArgsConstructor + @AllArgsConstructor + @Data + @SuperBuilder + class OneReq { + private Long id; + private Set ids; + + public void check() { + Preconditions.checkArgument(id != null || CollUtil.isNotEmpty(ids), "参数异常"); + } + } + + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @AllArgsConstructor + @Data + @SuperBuilder + class ListReq extends PageReqV2 { + + /** + * 工作台ID + */ + @CriteriaField + private Long workspaceId; + + /** + * 所属单位id + */ + @CriteriaField + private Long organizationalUnitId; + + /** + * 状态 + */ + @CriteriaField + private Integer status; + + /** + * 工人personId + */ + @CriteriaField(field = "workerPersonId", operator = Operator.IN) + private List workerPersonIds; + + @CriteriaField(ignore = true) + private Boolean includeDeleted; + } + + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @AllArgsConstructor + @Data + @SuperBuilder + class OrgProjectWorkerResp extends OrgProjectWorker { + + // 按需扩展字段,占个位。避免报错 + private String todo; + } + +} diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerUpsertRepository.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerUpsertRepository.java new file mode 100644 index 0000000..66f23bb --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/OrgProjectWorkerUpsertRepository.java @@ -0,0 +1,13 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.repositrory; + +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface OrgProjectWorkerUpsertRepository { + + @Transactional(rollbackFor = Throwable.class) + void batchUpdate(List orgProjectWorkers); + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerQueryRepositoryImpl.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerQueryRepositoryImpl.java new file mode 100644 index 0000000..b381d3d --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerQueryRepositoryImpl.java @@ -0,0 +1,40 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.repositrory.impl; + +import cn.axzo.foundation.dao.support.converter.PageConverter; +import cn.axzo.foundation.dao.support.mysql.QueryWrapperHelper; +import cn.axzo.foundation.page.PageResp; +import cn.axzo.orgmanax.infra.dao.project.worker.dao.OrgProjectWorkerDao; +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import cn.axzo.orgmanax.infra.dao.project.worker.repositrory.OrgProjectWorkerQueryRepository; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.BooleanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class OrgProjectWorkerQueryRepositoryImpl implements OrgProjectWorkerQueryRepository { + + private final OrgProjectWorkerDao orgProjectWorkerDao; + + @Override + public PageResp page(ListReq req) { + IPage page = PageConverter.toMybatis(req, OrgProjectWorker.class); + QueryWrapper wrapper = QueryWrapperHelper.fromBean(req, OrgProjectWorker.class); + if (!BooleanUtil.isTrue(req.getIncludeDeleted())) { + wrapper.eq("is_delete", 0); + } + IPage results = orgProjectWorkerDao.page(page, wrapper) + .convert(e -> BeanUtil.toBean(e, OrgProjectWorkerQueryRepository.OrgProjectWorkerResp.class)); + return (PageResp) PageConverter.toResp(results); + } + +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerUpsertRepositoryImpl.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerUpsertRepositoryImpl.java new file mode 100644 index 0000000..beacbcb --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/dao/project/worker/repositrory/impl/OrgProjectWorkerUpsertRepositoryImpl.java @@ -0,0 +1,28 @@ +package cn.axzo.orgmanax.infra.dao.project.worker.repositrory.impl; + +import cn.axzo.orgmanax.infra.dao.project.worker.dao.OrgProjectWorkerDao; +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import cn.axzo.orgmanax.infra.dao.project.worker.repositrory.OrgProjectWorkerUpsertRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class OrgProjectWorkerUpsertRepositoryImpl implements OrgProjectWorkerUpsertRepository { + + private final OrgProjectWorkerDao orgProjectWorkerDao; + + @Override + public void batchUpdate(List orgProjectWorkers) { + orgProjectWorkerDao.updateBatchById(orgProjectWorkers); + } + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/OrganizationalNodeUserUpsertedPayload.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/OrganizationalNodeUserUpsertedPayload.java new file mode 100644 index 0000000..ce8897b --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/OrganizationalNodeUserUpsertedPayload.java @@ -0,0 +1,62 @@ +package cn.axzo.orgmanax.server.mq; + +import cn.axzo.foundation.event.support.Event; +import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; +import cn.axzo.orgmanax.server.mq.enums.MQEventEnum; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Preconditions; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.ObjectUtils; + +import java.io.Serializable; + +/** + * OrganizationalNodeUser 变更事件(新增/修改/删除) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrganizationalNodeUserUpsertedPayload implements Serializable { + + private OrganizationalNodeUser newValue; + private OrganizationalNodeUser oldValue; + private JSONObject ext; + + public Long getTopNodeId() { + return ObjectUtils.firstNonNull(oldValue, newValue).getTopNodeId(); + } + + public Long getPersonId() { + return ObjectUtils.firstNonNull(oldValue, newValue).getPersonId(); + } + + public Long getIdentityId() { + return ObjectUtils.firstNonNull(oldValue, newValue).getIdentityId(); + } + + public Integer getIdentityType() { + return ObjectUtils.firstNonNull(oldValue, newValue).getIdentityType(); + } + + public static Event from(OrganizationalNodeUser newValue, + OrganizationalNodeUser oldValue, + String operator, JSONObject ext) { + Preconditions.checkArgument(ObjectUtils.anyNotNull(newValue, oldValue)); + return Event.builder() + .shardingKey(ObjectUtils.firstNonNull(newValue, oldValue).getId() + "") + .targetId(ObjectUtils.firstNonNull(newValue, oldValue).getId() + "") + .targetType(MQEventEnum.NODE_USER_UPSERTED.getModel()) + .eventCode(new Event.EventCode(MQEventEnum.NODE_USER_UPSERTED.getModel(), MQEventEnum.NODE_USER_UPSERTED.getTag())) + .operatorId(operator) + .data(OrganizationalNodeUserUpsertedPayload.builder() + .newValue(newValue) + .oldValue(oldValue) + .ext(ext) + .build()) + .build(); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/enums/MQEventEnum.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/enums/MQEventEnum.java new file mode 100644 index 0000000..8162b29 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/enums/MQEventEnum.java @@ -0,0 +1,65 @@ +package cn.axzo.orgmanax.server.mq.enums; + +import cn.axzo.foundation.event.support.Event; +import lombok.Getter; + +@Getter +public enum MQEventEnum { + + NODE_CREATE("node", "node-create", "节点创建"), + NODE_UPDATE("node", "node-update", "节点修改"), + NODE_DELETE("node", "node-delete", "节点删除"), + + NODE_USER_CREATE("node-user", "node-user-create", "节点用户创建"), + NODE_USER_UPDATE("node-user", "node-user-update", "节点用户修改"), + NODE_USER_DELETE("node-user", "node-user-delete", "节点用户删除"), + NODE_USER_UPSERTED("node-user", "node-user-upserted", "节点用户更新"), + + NODE_USER_VERIFY("profile", "verify-success", "节点用户实名认证"), + + WORKSPACE_USER_CHANGED("workspace-user", "workspace-user-changed", "项目用户变更"), + + UNIT_CREATE("unit", "unit-create", "单位创建"), + UNIT_UPDATE("unit", "unit-update", "单位修改"), + // updated 事件会将 old,new发出来 + UNIT_UPDATED("unit", "unit-updated", "单位修改"), + UNIT_DELETE("unit", "unit-delete", "单位删除"), + + INDUSTRY_DICT_CHANGE("industry-dict", "industry-dict-change", "行业字典变更"), + + + COOPERATE_SHIP_CREATE_OR_UPDATE("cooperate-ship", "cooperate-ship-create-or-update", "创建或更新协作关系"), + COOPERATE_SHIP_RESIGN("cooperate-ship", "cooperate-ship-resign", "退场"), + PERSON_TAG_BATCH_UPDATED("person-tag", "person-tag-batch-upserted", "批量修改用户标签"), + PROJECT_WORKER_RESIGN("project-worker", "project-worker-resign", "工人退场"), + + ORG_USER_MOVEMENT("org-user", "org-user-movement", "用户组织异动"), + ORG_NODE_USER_CHANGED("org-user", "org-node-user-change", "用户人岗架异动"), + COOPERATE_SHIP_UPSERT("cooperate-ship", "cooperate-ship-upsert", "创建或更新协作关系"), + + SAAS_ROLE_UPSERT("saas-role", "saas-role-upsert", "更新角色信息"), + + /** + * 小组 + */ + PROJECT_GROUP_CHANGE_LEADER("group","project-group-chang-leader","项目小组更换小组长"), + + GROUP_CREATE("group","group-create","项目小组组创建"), + GROUP_DISSOLVE("group","group-dissolve","项目小组组解散") + + ; + private final String model; + private final String tag; + private final String desc; + private final Event.EventCode eventCode; + + MQEventEnum(String model, String tag, String desc) { + this.eventCode = Event.EventCode.builder() + .module(model) + .name(tag) + .build(); + this.model = model; + this.tag = tag; + this.desc = desc; + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/producer/OrgUserChangedEventProducer.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/producer/OrgUserChangedEventProducer.java new file mode 100644 index 0000000..648aeb3 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/mq/producer/OrgUserChangedEventProducer.java @@ -0,0 +1,71 @@ +package cn.axzo.orgmanax.server.mq.producer; + +import cn.axzo.foundation.event.support.Event; +import cn.axzo.foundation.event.support.producer.EventProducer; +import cn.axzo.orgmanax.dto.common.util.NumberUtil; +import cn.axzo.orgmanax.dto.orguser.event.OrgUserStatusChangedEvent; +import cn.axzo.orgmanax.server.mq.enums.MQEventEnum; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.extra.spring.SpringUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.Objects; + +/** + * @author luofu + * @version 1.0 + * @date 2024/10/31 + */ +@Slf4j +@Component +public class OrgUserChangedEventProducer implements InitializingBean { + + private static final String EVENT_INVALID = "the event is invalid. {}"; + + private static EventProducer eventProducer; + + public static void sendStatusEvent(OrgUserStatusChangedEvent event) { + if (isInvalid(event)) { + log.info(EVENT_INVALID, event); + return; + } + //生产消息 + eventProducer.send(map(event)); + } + + public static void batchSendStatusEvents(Collection events) { + if (CollUtil.isEmpty(events)) { + log.info("the events is empty."); + return; + } + events.forEach(OrgUserChangedEventProducer::sendStatusEvent); + } + + + public static boolean isInvalid(OrgUserStatusChangedEvent eventData) { + return Objects.isNull(eventData) + || NumberUtil.isNotPositiveNumber(eventData.getPersonId()) + || NumberUtil.isNotPositiveNumber(eventData.getOuId()) + || NumberUtil.isNotPositiveNumber(eventData.getWorkspaceId()) + || Objects.isNull(eventData.getStatusCode()) + || NumberUtil.isNotPositiveNumber(eventData.getTransferTimestamp()); + } + + private static Event map(OrgUserStatusChangedEvent event) { + MQEventEnum mqEvent = MQEventEnum.ORG_USER_MOVEMENT; + return Event.builder() + .shardingKey(String.valueOf(event.getPersonId())) + .targetType(mqEvent.getModel()) + .eventCode(mqEvent.getEventCode()) + .data(event) + .build(); + } + + @Override + public void afterPropertiesSet() throws Exception { + eventProducer = SpringUtil.getBean(EventProducer.class); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/NodeUserFoundationService.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/NodeUserFoundationService.java index 5ee1cc3..ee98c9e 100644 --- a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/NodeUserFoundationService.java +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/NodeUserFoundationService.java @@ -1,12 +1,10 @@ package cn.axzo.orgmanax.server.nodeuser.foundation; -import cn.axzo.orgmanax.dto.nodeuser.dto.NodeUserDTO; import cn.axzo.orgmanax.dto.nodeuser.req.SearchEntNodeUserReq; import cn.axzo.orgmanax.dto.nodeuser.resp.SearchEntNodeUserResp; import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; -import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserQueryRepository; -import cn.axzo.orgmanax.infra.dao.orgjob.entity.OrgJob; import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserCreate; +import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserDelete; import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserUpdate; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +30,15 @@ public interface NodeUserFoundationService { @Transactional(rollbackFor = Throwable.class) OrganizationalNodeUser update(NodeUserUpdate req); + /** + * 该接口为更新的收口接口,业务使用的时候,需要自行做业务判断 + * + * @param req + * @return + */ + @Transactional(rollbackFor = Throwable.class) + List delete(NodeUserDelete req); + /** * 根据岗位进行过滤 * @param nodeUsers diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java index 771752b..b147285 100644 --- a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java @@ -1,15 +1,19 @@ package cn.axzo.orgmanax.server.nodeuser.foundation.impl; +import cn.axzo.apollo.workspace.api.v2.workspace.req.WorkspaceDetailReq; +import cn.axzo.apollo.workspace.api.v2.workspace.resp.WorkspaceDetailResp; import cn.axzo.foundation.event.support.Event; import cn.axzo.foundation.event.support.producer.EventProducer; import cn.axzo.foundation.exception.Axssert; import cn.axzo.orgmanax.common.config.BizResultCode; +import cn.axzo.orgmanax.dto.common.util.NumberUtil; import cn.axzo.orgmanax.dto.nodeuser.enums.NodeUserTypeEnum; import cn.axzo.orgmanax.dto.nodeuser.req.SearchEntNodeUserReq; import cn.axzo.orgmanax.dto.nodeuser.resp.SearchEntNodeUserResp; import cn.axzo.orgmanax.infra.client.profile.PersonProfileGateway; import cn.axzo.orgmanax.infra.client.profile.dto.ProfileGetIdentityProfileLiteResp; import cn.axzo.orgmanax.infra.client.profile.dto.ProfilePersonResp; +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.node.entity.OrganizationalNode; @@ -20,21 +24,30 @@ import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserQueryRepository; import cn.axzo.orgmanax.infra.dao.nodeuser.repository.NodeUserUpsertRepository; import cn.axzo.orgmanax.infra.dao.orgjob.entity.OrgJob; import cn.axzo.orgmanax.infra.dao.orgjob.repository.OrgJobQueryRepository; +import cn.axzo.orgmanax.infra.dao.unit.repository.UnitQueryRepository; +import cn.axzo.orgmanax.server.mq.OrganizationalNodeUserUpsertedPayload; import cn.axzo.orgmanax.server.node.event.inner.NodeEventType; import cn.axzo.orgmanax.server.nodeuser.event.inner.payload.NodeUserUpsertedPayload; import cn.axzo.orgmanax.server.nodeuser.foundation.NodeUserFoundationService; import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserCreate; +import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserDelete; import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserUpdate; +import cn.axzo.orgmanax.server.orguser.foundation.OrgUserFoundationService; +import cn.axzo.orgmanax.server.orguser.foundation.req.OrgUserWithdrawOrQuitReq; +import cn.axzo.orgmanax.server.project.worker.foundation.OrgProjectWorkerFoundationService; +import cn.axzo.orgmanax.server.project.worker.foundation.req.OrgProjectWorkerWithdrawReq; +import cn.axzo.orgmanax.server.service.OperateLogService; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; +import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.stream.Collectors; /** * @author tanjie@axzo.cn @@ -52,7 +65,10 @@ public class NodeUserFoundationServiceImpl implements NodeUserFoundationService private final PersonProfileGateway profileGateway; private final OrganizationalNodeUserMapper organizationalNodeUserMapper; private final OrgJobQueryRepository orgJobQueryRepository; - + private final UnitQueryRepository unitQueryRepository; + private final WorkspaceGateway workspaceGateway; + private final OrgUserFoundationService orgUserFoundationService; + private final OrgProjectWorkerFoundationService orgProjectWorkerFoundationService; /** * 创建部门标准接口 @@ -142,6 +158,71 @@ public class NodeUserFoundationServiceImpl implements NodeUserFoundationService return nodeUserUpsertRepository.update(updateReq); } + @Override + public List delete(NodeUserDelete req) { + checkDeleteReq(req); + List list = nodeUserQueryRepository.list(NodeUserQueryRepository.ListReq.builder().organizationalUnitId(req.getOuId()) + .workspaceId(req.getWorkspaceId()).personIds(req.getPersonIds()).build()); + if (CollUtil.isEmpty(list)) { + return CollUtil.newArrayList(); + } + //批量删除node_user + nodeUserUpsertRepository.batchDelete(list.stream().map(NodeUserQueryRepository.NodeUserResp::getId).collect(Collectors.toSet())); + List nodeUserList = list.stream().map(e -> BeanUtil.toBean(e, OrganizationalNodeUser.class)).collect(Collectors.toList()); + nodeUserList.forEach(this::sendNodeUserDeleteMq); + + //处理orgUser退场或离职逻辑 + Map> quitMap = nodeUserList.stream().collect(Collectors.groupingBy(OrganizationalNodeUser::getTopNodeId, + Collectors.mapping(OrganizationalNodeUser::getPersonId, Collectors.toSet()))); + OrgUserWithdrawOrQuitReq quitReq = new OrgUserWithdrawOrQuitReq(); + quitReq.setUnitUpdate(req.isUnitDelete()); + quitReq.setWorkspaceId(req.getWorkspaceId()); + quitReq.setOuId(req.getOuId()); + if (req.isUnitDelete()) { + quitReq.setWorkspaceId(nodeUserList.get(0).getWorkspaceId()); + } + quitReq.setTopNodeIdAndPersonIds(quitMap); + orgUserFoundationService.batchWithdrawOrQuit(quitReq); + + //项目内工人退场 + OrgProjectWorkerWithdrawReq workerReq = new OrgProjectWorkerWithdrawReq(); + workerReq.setOuId(req.getOuId()); + workerReq.setWorkspaceId(req.getWorkspaceId()); + if (req.isUnitDelete()) { + workerReq.setWorkspaceId(nodeUserList.get(0).getWorkspaceId()); + } + workerReq.setPersonIds(req.getPersonIds()); + orgProjectWorkerFoundationService.batchWithdraw(workerReq); + return nodeUserList; + } + + private void sendNodeUserDeleteMq(OrganizationalNodeUser e) { + String summary = "部门人员删除"; + // 方便记录操作日志 + OperateLogService.OperateType operateType = OperateLogService.OperateType.DELETE; + OperateLogService.SaveParam saveParam = OperateLogService.SaveParam.builder() + .summary(summary) + .resourceType(OperateLogService.ResourceType.ORGANIZATIONAL_NODE_USER) + .resourceId(ObjectUtils.firstNonNull(e, null).getId()) + .operateType(operateType) + .apiCaller("orgmanax") + .build(); + eventProducer.send(OrganizationalNodeUserUpsertedPayload.from(null, e, "-1", + new JSONObject().fluentPut("operateLogSaveParam", saveParam))); + } + + private void checkDeleteReq(NodeUserDelete req) { + if (NumberUtil.isPositiveNumber(req.getOuId())) { + UnitQueryRepository.UnitResp one = unitQueryRepository.oneOpt(UnitQueryRepository.OneReq.builder().id(req.getOuId()).build()) + .orElseThrow(() -> BizResultCode.ENTITY_NOT_FOUND.toException("单位不存在{}", req.getOuId())); + } + if (NumberUtil.isPositiveNumber(req.getWorkspaceId())) { + WorkspaceDetailReq workspaceDetailReq = WorkspaceDetailReq.builder().id(req.getWorkspaceId()).build(); + WorkspaceDetailResp workspaceDetailResp = workspaceGateway.getDetail(workspaceDetailReq); + Axssert.checkNonNull(workspaceDetailResp, "项目不存在"); + } + } + @Override public void filterByJobs(Collection nodeUsers, Collection jobCodes) { List orgJobs = orgJobQueryRepository.list(OrgJobQueryRepository.ListReq.builder() diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java new file mode 100644 index 0000000..2af228e --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java @@ -0,0 +1,35 @@ +package cn.axzo.orgmanax.server.nodeuser.foundation.req; + +import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; +import cn.hutool.core.bean.BeanUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@SuperBuilder +public class NodeUserDelete { + + private Long ouId; + + private Long operatorId; + + private Long workspaceId; + + private List personIds; + + /** + * 是否企业删除 + */ + private boolean isUnitDelete; + + public OrganizationalNodeUser toEntity() { + return BeanUtil.toBean(this, OrganizationalNodeUser.class); + } + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserUnitDelete.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserUnitDelete.java new file mode 100644 index 0000000..d5e5863 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserUnitDelete.java @@ -0,0 +1,34 @@ +package cn.axzo.orgmanax.server.nodeuser.foundation.req; + +import cn.axzo.foundation.exception.Axssert; +import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; +import cn.hutool.core.bean.BeanUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@SuperBuilder +public class NodeUserUnitDelete { + + private Long ouId; + + private Long operatorId; + + private List personIds; + + public void check() { + Axssert.checkNonNull(operatorId, "操作人不能为空"); + Axssert.checkNonNull(ouId, "单位不能为空"); + Axssert.checkNonNull(personIds, "用户id列表不能都为空"); + } + + public OrganizationalNodeUser toEntity() { + return BeanUtil.toBean(this, OrganizationalNodeUser.class); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserWorkspaceDelete.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserWorkspaceDelete.java new file mode 100644 index 0000000..688f4f1 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserWorkspaceDelete.java @@ -0,0 +1,34 @@ +package cn.axzo.orgmanax.server.nodeuser.foundation.req; + +import cn.axzo.foundation.exception.Axssert; +import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; +import cn.hutool.core.bean.BeanUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@SuperBuilder +public class NodeUserWorkspaceDelete { + + private Long workspaceId; + + private Long operatorId; + + private List personIds; + + public void check() { + Axssert.checkNonNull(operatorId, "操作人不能为空"); + Axssert.checkNonNull(workspaceId, "项目不能为空"); + Axssert.checkNonNull(personIds, "用户id列表不能都为空"); + } + + public OrganizationalNodeUser toEntity() { + return BeanUtil.toBean(this, OrganizationalNodeUser.class); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/UnitDeleteNodeUserProcessor.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/UnitDeleteNodeUserProcessor.java new file mode 100644 index 0000000..6bbb603 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/UnitDeleteNodeUserProcessor.java @@ -0,0 +1,34 @@ +package cn.axzo.orgmanax.server.nodeuser.service.processor.impl; + +import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; +import cn.axzo.orgmanax.server.nodeuser.foundation.NodeUserFoundationService; +import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserDelete; +import cn.axzo.orgmanax.server.nodeuser.service.processor.NodeUserProcessor; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 删除单位人员 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class UnitDeleteNodeUserProcessor implements NodeUserProcessor { + + private final NodeUserFoundationService nodeUserFoundationService; + + @Override + public ProcessResult process(ProcessContext context) { + // 转成该处理器关注的参数对象 + NodeUserDelete nodeUserDelete = context.getParams().toJavaObject(NodeUserDelete.class); + nodeUserDelete.setUnitDelete(true); + List nodeUserList = nodeUserFoundationService.delete(nodeUserDelete); + + // 返回数据 + return ProcessResult.success((JSONObject) JSONObject.toJSON(nodeUserList)); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/WorkspaceDeleteNodeUserProcessor.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/WorkspaceDeleteNodeUserProcessor.java new file mode 100644 index 0000000..ddb0408 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/processor/impl/WorkspaceDeleteNodeUserProcessor.java @@ -0,0 +1,32 @@ +package cn.axzo.orgmanax.server.nodeuser.service.processor.impl; + +import cn.axzo.orgmanax.infra.dao.nodeuser.entity.OrganizationalNodeUser; +import cn.axzo.orgmanax.server.nodeuser.foundation.NodeUserFoundationService; +import cn.axzo.orgmanax.server.nodeuser.foundation.req.NodeUserDelete; +import cn.axzo.orgmanax.server.nodeuser.service.processor.NodeUserProcessor; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 删除项目人员 + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class WorkspaceDeleteNodeUserProcessor implements NodeUserProcessor { + private final NodeUserFoundationService nodeUserFoundationService; + + @Override + public ProcessResult process(ProcessContext context) { + // 转成该处理器关注的参数对象 + NodeUserDelete nodeUserDelete = context.getParams().toJavaObject(NodeUserDelete.class); + List nodeUserList = nodeUserFoundationService.delete(nodeUserDelete); + + // 返回数据 + return ProcessResult.success((JSONObject) JSONObject.toJSON(nodeUserList)); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/OrgUserFoundationService.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/OrgUserFoundationService.java new file mode 100644 index 0000000..f011c51 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/OrgUserFoundationService.java @@ -0,0 +1,11 @@ +package cn.axzo.orgmanax.server.orguser.foundation; + +import cn.axzo.orgmanax.server.orguser.foundation.req.OrgUserWithdrawOrQuitReq; +import org.springframework.transaction.annotation.Transactional; + +public interface OrgUserFoundationService { + + @Transactional(rollbackFor = Throwable.class) + void batchWithdrawOrQuit(OrgUserWithdrawOrQuitReq req); + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/impl/OrgUserFoundationServiceImpl.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/impl/OrgUserFoundationServiceImpl.java new file mode 100644 index 0000000..8e16d83 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/impl/OrgUserFoundationServiceImpl.java @@ -0,0 +1,115 @@ +package cn.axzo.orgmanax.server.orguser.foundation.impl; + +import cn.axzo.apollo.workspace.api.v2.workspace.req.WorkspaceDetailReq; +import cn.axzo.apollo.workspace.api.v2.workspace.resp.WorkspaceDetailResp; +import cn.axzo.orgmanax.dto.nodeuser.enums.OrgUserStatusEnum; +import cn.axzo.orgmanax.dto.orguser.dto.OrgUserDTO; +import cn.axzo.orgmanax.dto.orguser.event.OrgUserStatusChangedEvent; +import cn.axzo.orgmanax.dto.orguser.req.ListOrgUserReq; +import cn.axzo.orgmanax.infra.client.workspace.WorkspaceGateway; +import cn.axzo.orgmanax.infra.client.workspace.dto.Workspace; +import cn.axzo.orgmanax.infra.dao.orguser.entity.OrgUser; +import cn.axzo.orgmanax.infra.dao.orguser.repository.OrgUserQueryRepository; +import cn.axzo.orgmanax.infra.dao.orguser.repository.OrgUserUpsertRepository; +import cn.axzo.orgmanax.server.mq.producer.OrgUserChangedEventProducer; +import cn.axzo.orgmanax.server.orguser.foundation.OrgUserFoundationService; +import cn.axzo.orgmanax.server.orguser.foundation.req.OrgUserWithdrawOrQuitReq; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Pair; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class OrgUserFoundationServiceImpl implements OrgUserFoundationService { + + private final WorkspaceGateway workspaceGateway; + private final OrgUserQueryRepository orgUserQueryRepository; + private final OrgUserUpsertRepository orgUserUpsertRepository; + + @Override + public void batchWithdrawOrQuit(OrgUserWithdrawOrQuitReq req) { + OrgUserStatusEnum status; + if (req.isUnitUpdate()) { + WorkspaceDetailReq workspaceDetailReq = new WorkspaceDetailReq(); + workspaceDetailReq.setId(req.getWorkspaceId()); + WorkspaceDetailResp detail = workspaceGateway.getDetail(workspaceDetailReq); + status = Integer.valueOf(Workspace.WorkspaceTypeEnum.GENERAL_PROJECT.value).equals(detail.getWorkspaceType()) ? + OrgUserStatusEnum.WITHDRAW : OrgUserStatusEnum.QUIT; + } else { + status = OrgUserStatusEnum.WITHDRAW; + } + ListOrgUserReq listOrgUserReq = new ListOrgUserReq(); + listOrgUserReq.setOuId(req.getOuId()); + listOrgUserReq.setWorkspaceId(req.getWorkspaceId()); + Set personIds = req.getTopNodeIdAndPersonIds().values().stream().flatMap(Set::stream).collect(Collectors.toSet()); + listOrgUserReq.setPersonIds(personIds); + List list = orgUserQueryRepository.list(listOrgUserReq); + if (CollUtil.isEmpty(list)) { + return; + } + Pair operator = Pair.of(-1L, "系统"); + Date now = new Date(); + List orgUsers = list.stream().map(orgUserResp -> { + OrgUser orgUser = new OrgUser(); + orgUser.setId(orgUserResp.getId()); + orgUser.setOperatorId(operator.getKey()); + orgUser.setOperatorName(operator.getValue()); + orgUser.setTransferTime(now); + orgUser.setStatus(status.getCode()); + return orgUser; + }).collect(Collectors.toList()); + orgUserUpsertRepository.batchUpdate(orgUsers); + Map orgUserMap = orgUsers.stream().collect(Collectors.toMap(OrgUser::getPersonId, orgUser -> orgUser)); + for (Map.Entry> setEntry : req.getTopNodeIdAndPersonIds().entrySet()) { + Long topNodeId = setEntry.getKey(); + Set personIdSet = setEntry.getValue(); + List orgUserList = orgUserMap.entrySet().stream() + .filter(personIdOrgUserEntry -> personIdSet.contains(personIdOrgUserEntry.getKey())) + .map(Map.Entry::getValue).collect(Collectors.toList()); + List dtoList = CollUtil.map(orgUsers, this::toOrgUserDTO, true); + // 发送用户状态变更事件 + batchSendStatusEvents(dtoList, topNodeId); + } + } + + private void batchSendStatusEvents(Collection orgUsers, Long topNodeId) { + if (CollUtil.isEmpty(orgUsers)) { + return; + } + // 事务提交之后发送MQ + Function eventMapper = e -> toOrgUserStatusChangedEvent(e, topNodeId); + List events = CollUtil.map(orgUsers, eventMapper, true); + OrgUserChangedEventProducer.batchSendStatusEvents(events); + } + + public static OrgUserStatusChangedEvent toOrgUserStatusChangedEvent(OrgUserDTO orgUser, Long topNodeId) { + return OrgUserStatusChangedEvent.builder() + .personId(orgUser.getPersonId()) + .ouId(orgUser.getOuId()) + .workspaceId(orgUser.getWorkspaceId()) + .topNodeId(topNodeId) + .statusCode(orgUser.getStatus()) + .transferTimestamp(orgUser.getTransferTime().getTime()) + .operatorId(orgUser.getOperatorId()) + .build(); + } + + private OrgUserDTO toOrgUserDTO(OrgUser orgUser) { + OrgUserDTO dto = OrgUserDTO.builder().build(); + BeanUtils.copyProperties(orgUser, dto); + return dto; + } + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/req/OrgUserWithdrawOrQuitReq.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/req/OrgUserWithdrawOrQuitReq.java new file mode 100644 index 0000000..4745578 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/orguser/foundation/req/OrgUserWithdrawOrQuitReq.java @@ -0,0 +1,26 @@ +package cn.axzo.orgmanax.server.orguser.foundation.req; + +import lombok.Data; + +import java.util.Map; +import java.util.Set; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Data +public class OrgUserWithdrawOrQuitReq { + + private Long ouId; + + private Long workspaceId; + + private Map> topNodeIdAndPersonIds; + + /** + * 是否单位更新 + */ + private boolean isUnitUpdate; + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/OrgProjectWorkerFoundationService.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/OrgProjectWorkerFoundationService.java new file mode 100644 index 0000000..2291a9c --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/OrgProjectWorkerFoundationService.java @@ -0,0 +1,10 @@ +package cn.axzo.orgmanax.server.project.worker.foundation; + +import cn.axzo.orgmanax.server.project.worker.foundation.req.OrgProjectWorkerWithdrawReq; +import org.springframework.transaction.annotation.Transactional; + +public interface OrgProjectWorkerFoundationService { + + @Transactional(rollbackFor = Throwable.class) + void batchWithdraw(OrgProjectWorkerWithdrawReq req); +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/impl/OrgProjectWorkerFoundationServiceImpl.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/impl/OrgProjectWorkerFoundationServiceImpl.java new file mode 100644 index 0000000..ea60426 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/impl/OrgProjectWorkerFoundationServiceImpl.java @@ -0,0 +1,52 @@ +package cn.axzo.orgmanax.server.project.worker.foundation.impl; + +import cn.axzo.orgmanax.dto.project.worker.enums.ProjectWorkerStatusEnum; +import cn.axzo.orgmanax.infra.dao.project.worker.entity.OrgProjectWorker; +import cn.axzo.orgmanax.infra.dao.project.worker.repositrory.OrgProjectWorkerQueryRepository; +import cn.axzo.orgmanax.infra.dao.project.worker.repositrory.OrgProjectWorkerUpsertRepository; +import cn.axzo.orgmanax.server.project.worker.foundation.OrgProjectWorkerFoundationService; +import cn.axzo.orgmanax.server.project.worker.foundation.req.OrgProjectWorkerWithdrawReq; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class OrgProjectWorkerFoundationServiceImpl implements OrgProjectWorkerFoundationService { + + private final OrgProjectWorkerQueryRepository orgProjectWorkerQueryRepository; + private final OrgProjectWorkerUpsertRepository orgProjectWorkerUpsertRepository; + + @Override + public void batchWithdraw(OrgProjectWorkerWithdrawReq req) { + OrgProjectWorkerQueryRepository.ListReq listReq = new OrgProjectWorkerQueryRepository.ListReq(); + listReq.setOrganizationalUnitId(req.getOuId()); + listReq.setWorkspaceId(req.getWorkspaceId()); + listReq.setWorkerPersonIds(req.getPersonIds()); + listReq.setStatus(ProjectWorkerStatusEnum.ACTIVE.getValue()); + List projectWorkerResps = orgProjectWorkerQueryRepository.list(listReq); + if (CollUtil.isEmpty(projectWorkerResps)) { + return; + } + Date now = new Date(); + List orgProjectWorkers = projectWorkerResps.stream().map(e -> { + OrgProjectWorker orgProjectWorker = BeanUtil.toBean(e, OrgProjectWorker.class); + e.setStatus(ProjectWorkerStatusEnum.WITHDRAW.getValue()); + e.setResignAt(now); + e.setUpdateAt(now); + return orgProjectWorker; + }).collect(Collectors.toList()); + orgProjectWorkerUpsertRepository.batchUpdate(orgProjectWorkers); + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/req/OrgProjectWorkerWithdrawReq.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/req/OrgProjectWorkerWithdrawReq.java new file mode 100644 index 0000000..08a24e8 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/project/worker/foundation/req/OrgProjectWorkerWithdrawReq.java @@ -0,0 +1,20 @@ +package cn.axzo.orgmanax.server.project.worker.foundation.req; + +import lombok.Data; + +import java.util.List; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Data +public class OrgProjectWorkerWithdrawReq { + + private Long ouId; + + private Long workspaceId; + + private List personIds; + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/service/OperateLogService.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/service/OperateLogService.java new file mode 100644 index 0000000..f79411d --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/service/OperateLogService.java @@ -0,0 +1,51 @@ +package cn.axzo.orgmanax.server.service; + +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Preconditions; +import lombok.*; + +public interface OperateLogService { + /** + * 保存操作日志 + * + * @return + */ + void save(SaveParam param); + + @NoArgsConstructor + @Data + @Builder + @AllArgsConstructor + class SaveParam { + private static final Long UNKNOWN_OPERATOR_ID = -1L; + private Long operatorId; + private String operatorName; + private String apiCaller; + private Long resourceId; + private ResourceType resourceType; + private OperateType operateType; + private Object oldValue; + private Object newValue; + private String summary; + private JSONObject ext; + + public void check() { + Preconditions.checkArgument(resourceType != null && resourceId != null, "操作资源类型和资源id不能为空"); + } + } + + @Getter + @AllArgsConstructor(access = AccessLevel.PRIVATE) + enum ResourceType { + ORGANIZATIONAL_UNIT("organizational_unit", "单位"), + ORGANIZATIONAL_NODE("organizational_node", "部门"), + ORGANIZATIONAL_NODE_USER("organizational_node_user", "部门人员"), + SAAS_COOPERATE_SHIP("saas_cooperate_ship", "协同关系"); + private final String tableName; + private final String desc; + } + + enum OperateType { + ADD, UPDATE, DELETE; + } +} From 230b2fc6b253686f4b617f15a01c1d60a4024e4f Mon Sep 17 00:00:00 2001 From: zhanghonghao Date: Thu, 6 Mar 2025 19:04:16 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(REQ-3714):=20=E5=BA=95=E5=BA=A7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodeuser/feign/OrgNodeUserCheckApi.java | 41 +++++++++++++++++++ .../req/BatchDeleteNodeUserCheckReq.java | 30 ++++++++++++++ .../resp/BatchDeleteNodeUserCheckResp.java | 25 +++++++++++ .../OrgNodeUserCheckController.java | 32 +++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 orgmanax-api/src/main/java/cn/axzo/orgmanax/api/nodeuser/feign/OrgNodeUserCheckApi.java create mode 100644 orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java create mode 100644 orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java diff --git a/orgmanax-api/src/main/java/cn/axzo/orgmanax/api/nodeuser/feign/OrgNodeUserCheckApi.java b/orgmanax-api/src/main/java/cn/axzo/orgmanax/api/nodeuser/feign/OrgNodeUserCheckApi.java new file mode 100644 index 0000000..12901b8 --- /dev/null +++ b/orgmanax-api/src/main/java/cn/axzo/orgmanax/api/nodeuser/feign/OrgNodeUserCheckApi.java @@ -0,0 +1,41 @@ +package cn.axzo.orgmanax.api.nodeuser.feign; + +import cn.axzo.foundation.result.ApiResult; +import cn.axzo.orgmanax.dto.nodeuser.req.BatchDeleteNodeUserCheckReq; +import cn.axzo.orgmanax.dto.nodeuser.resp.BatchDeleteNodeUserCheckResp; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +/** + * 部门相关基础API + * + * @author tanjie@axzo.cn + * @date 2024/12/2 15:40 + */ +@FeignClient( + value = "orgmanax", + url = "${axzo.service.orgmanax:http://orgmanax:8080}") +public interface OrgNodeUserCheckApi { + + /** + * 根据条件聚合查询节点用户 + * + * @param req + * @return + */ + @PostMapping("/api/node-user/batchDelete/check/unit") + ApiResult> checkUnit(@RequestBody @Validated BatchDeleteNodeUserCheckReq req); + + /** + * 根据条件聚合查询节点用户 + * + * @param req + * @return + */ + @PostMapping("/api/node-user/batchDelete/check/workspace") + ApiResult> checkWorkspace(@RequestBody @Validated BatchDeleteNodeUserCheckReq req); +} diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java new file mode 100644 index 0000000..b155739 --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java @@ -0,0 +1,30 @@ +package cn.axzo.orgmanax.dto.nodeuser.req; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Data +public class BatchDeleteNodeUserCheckReq { + + /** + * personIds + */ + @NotNull(message = "personIds不可以为空!") + private List personIds; + + private Long workspaceId; + + private Long ouId; + + /** + * 删除项目人员的时候传入 + * 节点ID + */ + private Long nodeId; +} diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java new file mode 100644 index 0000000..5b0b3a4 --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java @@ -0,0 +1,25 @@ +package cn.axzo.orgmanax.dto.nodeuser.resp; + +import lombok.Data; + +import java.util.List; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Data +public class BatchDeleteNodeUserCheckResp { + + private Long personId; + + private List failInfos; + + @Data + public static class CheckFailInfo { + + private Integer type; + + private Integer count; + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java new file mode 100644 index 0000000..0b98c20 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java @@ -0,0 +1,32 @@ +package cn.axzo.orgmanax.server.nodeuser.controller; + +import cn.axzo.foundation.result.ApiResult; +import cn.axzo.orgmanax.api.nodeuser.feign.OrgNodeUserCheckApi; +import cn.axzo.orgmanax.dto.nodeuser.req.BatchDeleteNodeUserCheckReq; +import cn.axzo.orgmanax.dto.nodeuser.resp.BatchDeleteNodeUserCheckResp; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@RestController +@RequestMapping +@RequiredArgsConstructor +public class OrgNodeUserCheckController implements OrgNodeUserCheckApi { + + + @Override + public ApiResult> checkUnit(BatchDeleteNodeUserCheckReq req) { + return null; + } + + @Override + public ApiResult> checkWorkspace(BatchDeleteNodeUserCheckReq req) { + return null; + } +} \ No newline at end of file From 346d99646e50acba477c4fdc526e467b1c97e0b1 Mon Sep 17 00:00:00 2001 From: "honghao.zhang" Date: Fri, 7 Mar 2025 00:08:10 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat(REQ-3714):=20=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=8D=95=E4=BD=8D=E9=98=BB=E6=96=AD=E6=A0=A1=E9=AA=8C=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/nodeuser/enums/CheckInfoTypeEnum.java | 17 ++ .../req/BatchDeleteNodeUserCheckReq.java | 8 +- .../resp/BatchDeleteNodeUserCheckResp.java | 3 +- .../client/workspace/WorkspaceGateway.java | 13 ++ ...ller.java => NodeUserCheckController.java} | 8 +- .../impl/NodeUserFoundationServiceImpl.java | 5 +- .../foundation/req/NodeUserDelete.java | 5 + .../service/NodeUserCheckService.java | 13 ++ .../impl/NodeUserCheckServiceImpl.java | 190 ++++++++++++++++++ 9 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java rename orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/{OrgNodeUserCheckController.java => NodeUserCheckController.java} (71%) create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/NodeUserCheckService.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java new file mode 100644 index 0000000..a75c4b3 --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java @@ -0,0 +1,17 @@ +package cn.axzo.orgmanax.dto.nodeuser.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum CheckInfoTypeEnum { + + SUPER_ADMIN(1, "超级管理员"), + IN_PROJECT(2, "在项目中"), + TEAM_LEADER(3, "班组长"); + + private final Integer value; + private final String desc; +} diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java index b155739..ccb36b2 100644 --- a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java @@ -4,6 +4,7 @@ import lombok.Data; import javax.validation.constraints.NotNull; import java.util.List; +import java.util.Set; /** * @author : zhanghonghao@axzo.cn @@ -16,7 +17,7 @@ public class BatchDeleteNodeUserCheckReq { * personIds */ @NotNull(message = "personIds不可以为空!") - private List personIds; + private Set personIds; private Long workspaceId; @@ -27,4 +28,9 @@ public class BatchDeleteNodeUserCheckReq { * 节点ID */ private Long nodeId; + + /** + * 操作者ID + */ + private Long operatorId; } diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java index 5b0b3a4..a109440 100644 --- a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java @@ -1,5 +1,6 @@ package cn.axzo.orgmanax.dto.nodeuser.resp; +import cn.axzo.orgmanax.dto.nodeuser.enums.CheckInfoTypeEnum; import lombok.Data; import java.util.List; @@ -18,7 +19,7 @@ public class BatchDeleteNodeUserCheckResp { @Data public static class CheckFailInfo { - private Integer type; + private CheckInfoTypeEnum type; private Integer count; } diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/workspace/WorkspaceGateway.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/workspace/WorkspaceGateway.java index 5fa8f27..3ffa262 100644 --- a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/workspace/WorkspaceGateway.java +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/workspace/WorkspaceGateway.java @@ -1,5 +1,8 @@ package cn.axzo.orgmanax.infra.client.workspace; +import cn.axzo.apollo.workspace.api.v2.participating.feign.ParticipatingUnitV2Api; +import cn.axzo.apollo.workspace.api.v2.participating.req.ParticipatingUnitListReq; +import cn.axzo.apollo.workspace.api.v2.participating.resp.ParticipatingUnitResp; import cn.axzo.apollo.workspace.api.v2.workspace.feign.WorkspaceV2Api; import cn.axzo.apollo.workspace.api.v2.workspace.req.ListWorkspaceReq; import cn.axzo.apollo.workspace.api.v2.workspace.req.WorkspaceDetailReq; @@ -15,6 +18,7 @@ import org.springframework.stereotype.Component; import java.util.List; /** + * */ @RequiredArgsConstructor @Component @@ -23,8 +27,11 @@ public class WorkspaceGateway { private final WorkspaceV2Api workspaceV2Api; + private final ParticipatingUnitV2Api participatingUnitV2Api; + /** * 更新和新增 + * * @param request * @return */ @@ -34,6 +41,7 @@ public class WorkspaceGateway { /** * 获取详情 + * * @param request * @return */ @@ -43,10 +51,15 @@ public class WorkspaceGateway { /** * 获取详情 + * * @param request * @return */ public List list(ListWorkspaceReq request) { return RpcWrapper.wrapApiResult(() -> workspaceV2Api.listV2(request)); } + + public List listParticipatingUnits(ParticipatingUnitListReq unitListReq) { + return RpcWrapper.wrapApiResult(() -> participatingUnitV2Api.list(unitListReq)); + } } diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/NodeUserCheckController.java similarity index 71% rename from orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java rename to orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/NodeUserCheckController.java index 0b98c20..cdcddc2 100644 --- a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/OrgNodeUserCheckController.java +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/NodeUserCheckController.java @@ -4,6 +4,7 @@ import cn.axzo.foundation.result.ApiResult; import cn.axzo.orgmanax.api.nodeuser.feign.OrgNodeUserCheckApi; import cn.axzo.orgmanax.dto.nodeuser.req.BatchDeleteNodeUserCheckReq; import cn.axzo.orgmanax.dto.nodeuser.resp.BatchDeleteNodeUserCheckResp; +import cn.axzo.orgmanax.server.nodeuser.service.NodeUserCheckService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -17,16 +18,17 @@ import java.util.List; @RestController @RequestMapping @RequiredArgsConstructor -public class OrgNodeUserCheckController implements OrgNodeUserCheckApi { +public class NodeUserCheckController implements OrgNodeUserCheckApi { + private final NodeUserCheckService nodeUserCheckService; @Override public ApiResult> checkUnit(BatchDeleteNodeUserCheckReq req) { - return null; + return ApiResult.success(nodeUserCheckService.checkUnit(req)); } @Override public ApiResult> checkWorkspace(BatchDeleteNodeUserCheckReq req) { - return null; + return ApiResult.success(nodeUserCheckService.checkWorkspace(req)); } } \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java index b147285..1b5246d 100644 --- a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/impl/NodeUserFoundationServiceImpl.java @@ -161,8 +161,9 @@ public class NodeUserFoundationServiceImpl implements NodeUserFoundationService @Override public List delete(NodeUserDelete req) { checkDeleteReq(req); - List list = nodeUserQueryRepository.list(NodeUserQueryRepository.ListReq.builder().organizationalUnitId(req.getOuId()) - .workspaceId(req.getWorkspaceId()).personIds(req.getPersonIds()).build()); + List list = nodeUserQueryRepository.list( + NodeUserQueryRepository.ListReq.builder().organizationalUnitId(req.getOuId()) + .workspaceId(req.getWorkspaceId()).personIds(req.getPersonIds()).identityType(req.getIdentityType()).build()); if (CollUtil.isEmpty(list)) { return CollUtil.newArrayList(); } diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java index 2af228e..689f1f4 100644 --- a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java @@ -28,6 +28,11 @@ public class NodeUserDelete { */ private boolean isUnitDelete; + /** + * 身份类型 按照项目删除的时候 传 + */ + private Integer identityType; + public OrganizationalNodeUser toEntity() { return BeanUtil.toBean(this, OrganizationalNodeUser.class); } diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/NodeUserCheckService.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/NodeUserCheckService.java new file mode 100644 index 0000000..fcc1211 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/NodeUserCheckService.java @@ -0,0 +1,13 @@ +package cn.axzo.orgmanax.server.nodeuser.service; + +import cn.axzo.orgmanax.dto.nodeuser.req.BatchDeleteNodeUserCheckReq; +import cn.axzo.orgmanax.dto.nodeuser.resp.BatchDeleteNodeUserCheckResp; + +import java.util.List; + +public interface NodeUserCheckService { + + List checkUnit(BatchDeleteNodeUserCheckReq req); + + List checkWorkspace(BatchDeleteNodeUserCheckReq req); +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java new file mode 100644 index 0000000..9af7e32 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java @@ -0,0 +1,190 @@ +package cn.axzo.orgmanax.server.nodeuser.service.impl; + +import cn.axzo.apollo.workspace.api.v2.participating.feign.ParticipatingUnitV2Api; +import cn.axzo.apollo.workspace.api.v2.participating.req.ParticipatingUnitListReq; +import cn.axzo.apollo.workspace.api.v2.participating.resp.ParticipatingUnitResp; +import cn.axzo.basics.common.exception.ServiceException; +import cn.axzo.basics.common.util.NumberUtil; +import cn.axzo.foundation.exception.Axssert; +import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.orgmanax.dto.cooperateship.dto.OrgCooperateShipDTO; +import cn.axzo.orgmanax.dto.cooperateship.req.ListOrgCooperateShipReq; +import cn.axzo.orgmanax.dto.nodeuser.dto.NodeUserDTO; +import cn.axzo.orgmanax.dto.nodeuser.enums.CheckInfoTypeEnum; +import cn.axzo.orgmanax.dto.nodeuser.req.BatchDeleteNodeUserCheckReq; +import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq; +import cn.axzo.orgmanax.dto.nodeuser.resp.BatchDeleteNodeUserCheckResp; +import cn.axzo.orgmanax.infra.client.profile.PersonProfileGateway; +import cn.axzo.orgmanax.infra.client.profile.dto.model.PersonProfileDto; +import cn.axzo.orgmanax.infra.client.tyr.RoleUserGateway; +import cn.axzo.orgmanax.infra.client.workspace.WorkspaceGateway; +import cn.axzo.orgmanax.infra.client.workspace.dto.Workspace; +import cn.axzo.orgmanax.infra.dao.cooperateship.entity.SaasCooperateShip; +import cn.axzo.orgmanax.server.cooperateship.service.CooperateShipService; +import cn.axzo.orgmanax.server.nodeuser.service.NodeUserCheckService; +import cn.axzo.orgmanax.server.nodeuser.service.NodeUserService; +import cn.axzo.tyr.feign.enums.IdentityTypeEnum; +import cn.axzo.tyr.feign.enums.RoleTypeEnum; +import cn.axzo.tyr.feign.req.PageRoleUserReq; +import cn.axzo.tyr.feign.resp.RoleUserResp; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.BooleanUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NodeUserCheckServiceImpl implements NodeUserCheckService { + + private final WorkspaceGateway workspaceGateway; + + private final RoleUserGateway roleUserGateway; + + private final PersonProfileGateway profileGateway; + + private final CooperateShipService cooperateShipService; + + private final NodeUserService nodeUserService; + + // 企业内班组长岗位编码 + @Value("${entTeamLeader:entTeamLeader}") + private String entTeamLeader; + + // 班组管理员岗位编码 + @Value("${entTeamManager:entTeamManager}") + private String entTeamManager; + + // 企业内班组工人岗位编码 + @Value("${entWorker:entWorker}") + private String entWorker; + + + @Override + public List checkUnit(BatchDeleteNodeUserCheckReq req) { + List resultList = new ArrayList<>(); + Map> failInfoMap = new HashMap<>(); + Long ouId = req.getOuId(); + Long workspaceId = req.getWorkspaceId(); + Set personIds = req.getPersonIds(); + ParticipatingUnitListReq participatingUnitListReq = new ParticipatingUnitListReq(); + participatingUnitListReq.setLevels(ListUtil.of(Workspace.WorkspaceTypeEnum.GENERAL_ENT.value, Workspace.WorkspaceTypeEnum.GENERAL_PROJECT.value)); + participatingUnitListReq.setWorkspaceId(workspaceId); + participatingUnitListReq.setOrganizationUnitId(ouId); + List participatingUnitList = workspaceGateway.listParticipatingUnits(participatingUnitListReq); + Axssert.checkNotEmpty(participatingUnitList, "当前单位未参建任何项目,获取详细信息失败"); + Long topNodeId = participatingUnitList.get(0).getOrganizationNodeId(); + //1 单位联系人(超管)不能删除 + PageRoleUserReq param = new PageRoleUserReq(); + PageRoleUserReq.WorkspaceOuPair workspaceOuPair = new PageRoleUserReq.WorkspaceOuPair(); + workspaceOuPair.setWorkspaceId(workspaceId); + workspaceOuPair.setOuId(ouId); + param.setWorkspaceOuPairs(Collections.singletonList(workspaceOuPair)); + param.setRoleTypes(Collections.singleton(RoleTypeEnum.SUPER_ADMIN)); + List superAminInfoResult = roleUserGateway.pageAll(param); + superAminInfoResult.forEach(e -> { + if (personIds.contains(e.getPersonId())) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.SUPER_ADMIN); + addFailInfo(failInfoMap, e.getPersonId(), checkFailInfo); + } + }); + + ListOrgCooperateShipReq listOrgCooperateShipReq = new ListOrgCooperateShipReq(); + listOrgCooperateShipReq.setOuIds(Collections.singleton(ouId)); + listOrgCooperateShipReq.setStatuses(CollUtil.newHashSet(0, 1)); + List listPersonJoinedWorkspace = cooperateShipService.list(listOrgCooperateShipReq); + Set inProjectPersonIds = filterByPerson(listPersonJoinedWorkspace, personIds); + if (CollectionUtil.isNotEmpty(inProjectPersonIds)) { + inProjectPersonIds.forEach(e -> { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.IN_PROJECT); + addFailInfo(failInfoMap, e, checkFailInfo); + }); + } + + ListNodeUserReq nodeUserQueryVO = new ListNodeUserReq(); + nodeUserQueryVO.setPersonIds(personIds); + nodeUserQueryVO.setOrganizationalUnitId(ouId); + nodeUserQueryVO.setTopNodeIds(Collections.singletonList(topNodeId)); + nodeUserQueryVO.setNeeds(ListNodeUserReq.Needs.builder().job(true).build()); + //查询人所在的部门节点列表 + List organizationalNodeUserList = nodeUserService.list(nodeUserQueryVO); + AtomicBoolean isWorker = new AtomicBoolean(false); + AtomicBoolean isPractitioner = new AtomicBoolean(false); + List teamLeader = Lists.newArrayList(); + List workerOrgNodeIds = Lists.newArrayList(); + organizationalNodeUserList.forEach(organizationalNodeUserVO -> { + if (IdentityTypeEnum.WORKER_LEADER.getCode().equals(organizationalNodeUserVO.getIdentityType()) || + entTeamLeader.equals(organizationalNodeUserVO.getJob().getCode())) { + teamLeader.add(organizationalNodeUserVO.getPersonId()); + } + if (IdentityTypeEnum.WORKER.getCode().equals(organizationalNodeUserVO.getIdentityType()) || + entWorker.equals(organizationalNodeUserVO.getJob().getCode())) { + isWorker.set(true); + workerOrgNodeIds.add(organizationalNodeUserVO.getOrganizationalNodeId()); + } + if (IdentityTypeEnum.PRACTITIONER.getCode().equals(organizationalNodeUserVO.getIdentityType())) { + isPractitioner.set(true); + } + }); + if (CollUtil.isNotEmpty(teamLeader)) { + teamLeader.forEach(e -> { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.TEAM_LEADER); + addFailInfo(failInfoMap, e, checkFailInfo); + }); + } + if (CollUtil.isNotEmpty(failInfoMap)) { + failInfoMap.forEach((personId, checkFailInfos) -> { + BatchDeleteNodeUserCheckResp batchDeleteNodeUserCheckVO = new BatchDeleteNodeUserCheckResp(); + batchDeleteNodeUserCheckVO.setPersonId(personId); + batchDeleteNodeUserCheckVO.setFailInfos(checkFailInfos); + resultList.add(batchDeleteNodeUserCheckVO); + }); + } + return resultList; + } + + private Set filterByPerson(List result, Set personIds) { + if (CollUtil.isEmpty(personIds)) { + return personIds; + } + Set filterResult = new HashSet<>(); + List topNodeIds = result.stream() + .map(OrgCooperateShipDTO::getOrganizationalNodeId) + .distinct() + .collect(Collectors.toList()); + ListNodeUserReq nodeUserReq = new ListNodeUserReq(); + nodeUserReq.setTopNodeIds(topNodeIds); + nodeUserReq.setPersonIds(personIds); + List nodeUserDTOS = nodeUserService.list(nodeUserReq); + Map personNodeMap = nodeUserDTOS.stream().collect(Collectors.toMap(NodeUserDTO::getPersonId, NodeUserDTO::getTopNodeId)); + Set shipNodeIds = result.stream().map(OrgCooperateShipDTO::getOrganizationalNodeId).collect(Collectors.toSet()); + for (Map.Entry entry : personNodeMap.entrySet()) { + if (shipNodeIds.contains(entry.getValue())) { + filterResult.add(entry.getKey()); + } + } + return filterResult; + } + + private void addFailInfo(Map> failInfoMap, Long personId, BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo) { + failInfoMap.computeIfAbsent(personId, k -> new ArrayList<>()).add(checkFailInfo); + } + + @Override + public List checkWorkspace(BatchDeleteNodeUserCheckReq req) { + return new ArrayList<>(); + } +} From d911db51664fd9b367956fc303fb2a5121f45efb Mon Sep 17 00:00:00 2001 From: zhanghonghao Date: Fri, 7 Mar 2025 14:40:29 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat(REQ-3714):=20=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BA=BA=E5=91=98=E6=A3=80=E6=9F=A5=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../orgmanax/dto/node/dto/OrgNodeDTO.java | 17 + .../dto/nodeuser/enums/CheckInfoTypeEnum.java | 30 +- .../resp/BatchDeleteNodeUserCheckResp.java | 4 + .../client/karma/KarmaThirdApiClient.java | 10 + .../client/karma/ThirdCheckFailResp.java | 17 + .../sdk/karma/KarmaThirdApiClientImpl.java | 50 +++ .../nodeuser/dto/CheckUserOperateParam.java | 30 ++ .../impl/NodeUserCheckServiceImpl.java | 412 ++++++++++++++++-- .../util/constants/JobCodeConstants.java | 34 ++ 9 files changed, 556 insertions(+), 48 deletions(-) create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/KarmaThirdApiClient.java create mode 100644 orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/ThirdCheckFailResp.java create mode 100644 orgmanax-integration/src/main/java/cn/axzo/orgmanax/integration/sdk/karma/KarmaThirdApiClientImpl.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/dto/CheckUserOperateParam.java create mode 100644 orgmanax-server/src/main/java/cn/axzo/orgmanax/server/util/constants/JobCodeConstants.java diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/node/dto/OrgNodeDTO.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/node/dto/OrgNodeDTO.java index 81da898..af94bc4 100644 --- a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/node/dto/OrgNodeDTO.java +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/node/dto/OrgNodeDTO.java @@ -1,6 +1,8 @@ package cn.axzo.orgmanax.dto.node.dto; +import cn.axzo.foundation.result.ResultCode; import cn.axzo.orgmanax.dto.cooperateship.dto.OrgCooperateShipDTO; +import cn.axzo.orgmanax.dto.node.enums.NodeTypeEnum; import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Data; @@ -10,6 +12,7 @@ import lombok.experimental.SuperBuilder; import java.io.Serializable; import java.util.Date; import java.util.List; +import java.util.Objects; import java.util.Optional; @NoArgsConstructor @@ -154,4 +157,18 @@ public class OrgNodeDTO implements Serializable { } return (T) Optional.ofNullable(profile).map(p -> JSONObject.parseObject(p.toString(), clazz)).orElse(null); } + + /** + * 获取项目内小组节点配置信息 + * @return 是否合作小组,true 独立,false 非独立 + */ + public Boolean independentGroup() { + if (!Objects.equals(this.nodeType, NodeTypeEnum.PROJECT_GROUP.getValue())) { + throw ResultCode.INVALID_PARAMS.toException("小组节点类型错误"); + } + if (Objects.nonNull(this.profile) && !this.profile.isEmpty()) { + return this.profile.getBooleanValue("independentGroup"); + } + return null; + } } diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java index a75c4b3..fd0a3c9 100644 --- a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java @@ -4,14 +4,34 @@ import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + @Getter @AllArgsConstructor(access = AccessLevel.PRIVATE) public enum CheckInfoTypeEnum { - SUPER_ADMIN(1, "超级管理员"), - IN_PROJECT(2, "在项目中"), - TEAM_LEADER(3, "班组长"); - + SUPER_ADMIN(1, "超级管理员", "【%s】是超级管理员,无法删除!", 0), + IN_PROJECT(2, "在项目中", "【%s】,在项目中,无法删除!", 0), + TEAM_LEADER(3, "班组长", "【%s】,是班组长,无法删除!", 0), + PROJECT_GROUP_LEADER(4, "合作小组小组长", "【%s】,是项目组组长,无法删除!", 0), + NOT_IN_JURISDICTION(5, "不在管辖范围", "【%s】,不在你的管辖范围,无法删除!", 0), + ANY_ADMIN(6, "单位负责人", "【%s】是项目单位负责人,无法删除!", 0), + TASK_ORDER(7, "任务单", "当前人员有未完成的任务单:%d单。无法删除!", 2), + RECTIFY_ORDERS(8, "整改单", "当前人员有未完成的整改单:%d单。无法删除!", 6), + ACCEPTANCE_PROCESS(9, "验收流程", "当前人员有未完成的验收单:%d单。无法删除!", 7); private final Integer value; private final String desc; -} + private final String msg; + private final Integer thirdType; + + private static final Map thirdTypeMap = Arrays.stream(CheckInfoTypeEnum.values()) + .collect(Collectors.toMap(CheckInfoTypeEnum::getThirdType, Function.identity(), (key1, key2) -> key2)); + + public static CheckInfoTypeEnum getByThirdType(Integer type) { + return thirdTypeMap.get(type); + } + +} \ No newline at end of file diff --git a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java index a109440..44cab36 100644 --- a/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java @@ -1,7 +1,9 @@ package cn.axzo.orgmanax.dto.nodeuser.resp; import cn.axzo.orgmanax.dto.nodeuser.enums.CheckInfoTypeEnum; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.List; @@ -17,6 +19,8 @@ public class BatchDeleteNodeUserCheckResp { private List failInfos; @Data + @AllArgsConstructor + @NoArgsConstructor public static class CheckFailInfo { private CheckInfoTypeEnum type; diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/KarmaThirdApiClient.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/KarmaThirdApiClient.java new file mode 100644 index 0000000..9890002 --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/KarmaThirdApiClient.java @@ -0,0 +1,10 @@ +package cn.axzo.orgmanax.infra.client.karma; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface KarmaThirdApiClient { + + Map> getThirdCheckFail(Long workspaceId, Set personIds); +} \ No newline at end of file diff --git a/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/ThirdCheckFailResp.java b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/ThirdCheckFailResp.java new file mode 100644 index 0000000..78bc4a3 --- /dev/null +++ b/orgmanax-infra/src/main/java/cn/axzo/orgmanax/infra/client/karma/ThirdCheckFailResp.java @@ -0,0 +1,17 @@ +package cn.axzo.orgmanax.infra.client.karma; + +import cn.axzo.orgmanax.dto.nodeuser.enums.CheckInfoTypeEnum; +import lombok.Data; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/7 + */ +@Data +public class ThirdCheckFailResp { + + private CheckInfoTypeEnum type; + + private Integer count; + +} \ No newline at end of file diff --git a/orgmanax-integration/src/main/java/cn/axzo/orgmanax/integration/sdk/karma/KarmaThirdApiClientImpl.java b/orgmanax-integration/src/main/java/cn/axzo/orgmanax/integration/sdk/karma/KarmaThirdApiClientImpl.java new file mode 100644 index 0000000..e1910bb --- /dev/null +++ b/orgmanax-integration/src/main/java/cn/axzo/orgmanax/integration/sdk/karma/KarmaThirdApiClientImpl.java @@ -0,0 +1,50 @@ +package cn.axzo.orgmanax.integration.sdk.karma; + +import cn.axzo.karma.client.feign.team.ThirdApiCheckServiceApi; +import cn.axzo.karma.client.model.request.ThirdApiPersonNormalCheckReq; +import cn.axzo.karma.client.model.vo.OpFailVO; +import cn.axzo.orgmanax.dto.nodeuser.enums.CheckInfoTypeEnum; +import cn.axzo.orgmanax.infra.client.karma.KarmaThirdApiClient; +import cn.axzo.orgmanax.infra.client.karma.ThirdCheckFailResp; +import cn.axzo.orgmanax.integration.core.RpcWrapper; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/7 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class KarmaThirdApiClientImpl implements KarmaThirdApiClient { + + private final ThirdApiCheckServiceApi thirdApiCheckServiceApi; + + @Override + public Map> getThirdCheckFail(Long workspaceId, Set personIds) { + ThirdApiPersonNormalCheckReq checkReq = new ThirdApiPersonNormalCheckReq(); + checkReq.setWorkspaceId(workspaceId); + checkReq.setPersonIdList(new ArrayList<>(personIds)); + Map> checkMap = RpcWrapper.commonRes(() -> thirdApiCheckServiceApi.thirdApiNormalCheckPerson(checkReq)); + if (CollUtil.isEmpty(checkMap)) { + return Collections.emptyMap(); + } + Map> failInfoMap = new HashMap<>(); + checkMap.forEach((key, opFailVOs) -> { + List personList = opFailVOs.stream().map(opFailVO -> { + ThirdCheckFailResp thirdCheckFailResp = new ThirdCheckFailResp(); + thirdCheckFailResp.setType(CheckInfoTypeEnum.getByThirdType(opFailVO.getType())); + thirdCheckFailResp.setCount(opFailVO.getCount()); + return thirdCheckFailResp; + }).collect(Collectors.toList()); + failInfoMap.put(key, personList); + }); + return failInfoMap; + } +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/dto/CheckUserOperateParam.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/dto/CheckUserOperateParam.java new file mode 100644 index 0000000..3d1c95a --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/dto/CheckUserOperateParam.java @@ -0,0 +1,30 @@ +package cn.axzo.orgmanax.server.nodeuser.dto; + +import cn.axzo.foundation.result.ResultCode; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.ObjectUtils; + +import java.util.Set; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/7 + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +public class CheckUserOperateParam { + private Long operatorId; + private Set personIds; + private Long workspaceId; + + public void check() { + if (ObjectUtils.anyNull(personIds, workspaceId, operatorId)) { + throw ResultCode.INVALID_PARAMS.toException("参数异常,您暂无权限!"); + } + } +} diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java index 9af7e32..d8a563d 100644 --- a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java @@ -1,28 +1,33 @@ package cn.axzo.orgmanax.server.nodeuser.service.impl; -import cn.axzo.apollo.workspace.api.v2.participating.feign.ParticipatingUnitV2Api; import cn.axzo.apollo.workspace.api.v2.participating.req.ParticipatingUnitListReq; import cn.axzo.apollo.workspace.api.v2.participating.resp.ParticipatingUnitResp; -import cn.axzo.basics.common.exception.ServiceException; -import cn.axzo.basics.common.util.NumberUtil; import cn.axzo.foundation.exception.Axssert; -import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.foundation.result.ResultCode; +import cn.axzo.orgmanax.dto.common.IdentityType; +import cn.axzo.orgmanax.dto.common.util.NumberUtil; import cn.axzo.orgmanax.dto.cooperateship.dto.OrgCooperateShipDTO; +import cn.axzo.orgmanax.dto.cooperateship.enums.CooperateShipTypeEnum; import cn.axzo.orgmanax.dto.cooperateship.req.ListOrgCooperateShipReq; +import cn.axzo.orgmanax.dto.node.dto.OrgNodeDTO; +import cn.axzo.orgmanax.dto.node.enums.NodeTypeEnum; +import cn.axzo.orgmanax.dto.node.req.ListNodeReq; import cn.axzo.orgmanax.dto.nodeuser.dto.NodeUserDTO; import cn.axzo.orgmanax.dto.nodeuser.enums.CheckInfoTypeEnum; import cn.axzo.orgmanax.dto.nodeuser.req.BatchDeleteNodeUserCheckReq; import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq; import cn.axzo.orgmanax.dto.nodeuser.resp.BatchDeleteNodeUserCheckResp; -import cn.axzo.orgmanax.infra.client.profile.PersonProfileGateway; -import cn.axzo.orgmanax.infra.client.profile.dto.model.PersonProfileDto; +import cn.axzo.orgmanax.infra.client.karma.KarmaThirdApiClient; +import cn.axzo.orgmanax.infra.client.karma.ThirdCheckFailResp; import cn.axzo.orgmanax.infra.client.tyr.RoleUserGateway; import cn.axzo.orgmanax.infra.client.workspace.WorkspaceGateway; import cn.axzo.orgmanax.infra.client.workspace.dto.Workspace; -import cn.axzo.orgmanax.infra.dao.cooperateship.entity.SaasCooperateShip; import cn.axzo.orgmanax.server.cooperateship.service.CooperateShipService; +import cn.axzo.orgmanax.server.node.service.NodeService; +import cn.axzo.orgmanax.server.nodeuser.dto.CheckUserOperateParam; import cn.axzo.orgmanax.server.nodeuser.service.NodeUserCheckService; import cn.axzo.orgmanax.server.nodeuser.service.NodeUserService; +import cn.axzo.orgmanax.server.util.constants.JobCodeConstants; import cn.axzo.tyr.feign.enums.IdentityTypeEnum; import cn.axzo.tyr.feign.enums.RoleTypeEnum; import cn.axzo.tyr.feign.req.PageRoleUserReq; @@ -30,7 +35,9 @@ import cn.axzo.tyr.feign.resp.RoleUserResp; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import lombok.RequiredArgsConstructor; @@ -39,7 +46,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; +import java.util.function.ToIntFunction; import java.util.stream.Collectors; @Slf4j @@ -51,25 +59,32 @@ public class NodeUserCheckServiceImpl implements NodeUserCheckService { private final RoleUserGateway roleUserGateway; - private final PersonProfileGateway profileGateway; - private final CooperateShipService cooperateShipService; private final NodeUserService nodeUserService; + private final NodeService nodeService; + + private final KarmaThirdApiClient karmaThirdApiClient; + + // 单位类型默认角色关系,后面可以座位管理员的逻辑进行迭代 + @Value("#{${participateUnitDefaultRoleId:{}}}") + public Map participateUnitDefaultRoleId; + + /** + * 小组长角色分组编码 + */ + @Value("${projectTeamGPLeader:projectTeamGPLeader}") + private String projectTeamGPLeader; + // 企业内班组长岗位编码 @Value("${entTeamLeader:entTeamLeader}") private String entTeamLeader; - // 班组管理员岗位编码 - @Value("${entTeamManager:entTeamManager}") - private String entTeamManager; - // 企业内班组工人岗位编码 @Value("${entWorker:entWorker}") private String entWorker; - @Override public List checkUnit(BatchDeleteNodeUserCheckReq req) { List resultList = new ArrayList<>(); @@ -120,23 +135,11 @@ public class NodeUserCheckServiceImpl implements NodeUserCheckService { nodeUserQueryVO.setNeeds(ListNodeUserReq.Needs.builder().job(true).build()); //查询人所在的部门节点列表 List organizationalNodeUserList = nodeUserService.list(nodeUserQueryVO); - AtomicBoolean isWorker = new AtomicBoolean(false); - AtomicBoolean isPractitioner = new AtomicBoolean(false); - List teamLeader = Lists.newArrayList(); - List workerOrgNodeIds = Lists.newArrayList(); + Set teamLeader = Sets.newHashSet(); organizationalNodeUserList.forEach(organizationalNodeUserVO -> { - if (IdentityTypeEnum.WORKER_LEADER.getCode().equals(organizationalNodeUserVO.getIdentityType()) || - entTeamLeader.equals(organizationalNodeUserVO.getJob().getCode())) { + if (IdentityTypeEnum.WORKER_LEADER.getCode().equals(organizationalNodeUserVO.getIdentityType()) || entTeamLeader.equals(organizationalNodeUserVO.getJob().getCode())) { teamLeader.add(organizationalNodeUserVO.getPersonId()); } - if (IdentityTypeEnum.WORKER.getCode().equals(organizationalNodeUserVO.getIdentityType()) || - entWorker.equals(organizationalNodeUserVO.getJob().getCode())) { - isWorker.set(true); - workerOrgNodeIds.add(organizationalNodeUserVO.getOrganizationalNodeId()); - } - if (IdentityTypeEnum.PRACTITIONER.getCode().equals(organizationalNodeUserVO.getIdentityType())) { - isPractitioner.set(true); - } }); if (CollUtil.isNotEmpty(teamLeader)) { teamLeader.forEach(e -> { @@ -145,14 +148,11 @@ public class NodeUserCheckServiceImpl implements NodeUserCheckService { addFailInfo(failInfoMap, e, checkFailInfo); }); } - if (CollUtil.isNotEmpty(failInfoMap)) { - failInfoMap.forEach((personId, checkFailInfos) -> { - BatchDeleteNodeUserCheckResp batchDeleteNodeUserCheckVO = new BatchDeleteNodeUserCheckResp(); - batchDeleteNodeUserCheckVO.setPersonId(personId); - batchDeleteNodeUserCheckVO.setFailInfos(checkFailInfos); - resultList.add(batchDeleteNodeUserCheckVO); - }); + //判断当前人是否有操作权限 + if (NumberUtil.isPositiveNumber(req.getOperatorId())) { + } + transformFailMap(failInfoMap, resultList); return resultList; } @@ -161,10 +161,7 @@ public class NodeUserCheckServiceImpl implements NodeUserCheckService { return personIds; } Set filterResult = new HashSet<>(); - List topNodeIds = result.stream() - .map(OrgCooperateShipDTO::getOrganizationalNodeId) - .distinct() - .collect(Collectors.toList()); + List topNodeIds = result.stream().map(OrgCooperateShipDTO::getOrganizationalNodeId).distinct().collect(Collectors.toList()); ListNodeUserReq nodeUserReq = new ListNodeUserReq(); nodeUserReq.setTopNodeIds(topNodeIds); nodeUserReq.setPersonIds(personIds); @@ -185,6 +182,335 @@ public class NodeUserCheckServiceImpl implements NodeUserCheckService { @Override public List checkWorkspace(BatchDeleteNodeUserCheckReq req) { - return new ArrayList<>(); + Long personId = req.getOperatorId(); + List resultList = new ArrayList<>(); + Map> failInfoMap = new HashMap<>(); + ListOrgCooperateShipReq listOrgCooperateShipReq = new ListOrgCooperateShipReq(); + listOrgCooperateShipReq.setOuIds(Collections.singleton(req.getOuId())); + listOrgCooperateShipReq.setWorkspaceIds(Collections.singleton(req.getWorkspaceId())); + listOrgCooperateShipReq.setStatuses(CollUtil.newHashSet(0, 1)); + List cooperateShipRespList = cooperateShipService.list(listOrgCooperateShipReq); + Axssert.checkNotEmpty(cooperateShipRespList, "操作失败,获取协同组织失败"); + // 协同节点关联的顶级部门节点列表 + List nodeIds = cooperateShipRespList.stream().map(OrgCooperateShipDTO::getOrganizationalNodeId).distinct().collect(Collectors.toList()); + List nodePersonIds = Lists.newArrayList(req.getPersonIds()); + nodePersonIds.add(personId); + ListNodeUserReq query = ListNodeUserReq.builder() + .topNodeIds(nodeIds) + .personIds(nodePersonIds) + .findByAncestorNodeId(true) + .build(); + // 查询当前登录及待删除人员在当前项目中的参与记录(仅限当前登录单位) + List nodeUsers = nodeUserService.list(query); + // 校验当前入参 + checkPermission(nodeUsers, personId); + // 过滤当前操作人员 + nodeUsers = nodeUsers.stream() + .filter(e -> req.getPersonIds().contains(e.getPersonId())) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(nodeUsers)) { + req.getPersonIds().forEach(e -> { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.NOT_IN_JURISDICTION); + addFailInfo(failInfoMap, e, checkFailInfo); + }); + } + nodeUsers.stream().filter(e -> e.getIdentityType().equals(IdentityType.WORKER_LEADER.getCode())).findAny().ifPresent(e -> { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.TEAM_LEADER); + addFailInfo(failInfoMap, e.getPersonId(), checkFailInfo); + }); + + // 判断是否合作小组小组长,合作小组小组长不允许删除 + checkIndependentGroupLeader(nodeUsers, failInfoMap); + + // 判断是否拥有admin角色 判断是否是分包管理员 + List adminRoleIds = getSpecialRole(); + PageRoleUserReq roleUserParam = PageRoleUserReq.builder().build(); + PageRoleUserReq.WorkspaceOuPair workspaceOuPair = new PageRoleUserReq.WorkspaceOuPair(); + workspaceOuPair.setWorkspaceId(req.getWorkspaceId()); + workspaceOuPair.setOuId(req.getOuId()); + roleUserParam.setWorkspaceOuPairs(Collections.singletonList(workspaceOuPair)); + roleUserParam.setPersonIds(req.getPersonIds()); + roleUserParam.setNeedRole(true); + + List saasRoleUserInfo = roleUserGateway.pageAll(roleUserParam); + saasRoleUserInfo.forEach(e -> { + Optional roleTypeEnumOptional = RoleTypeEnum.fromValue(e.getRole().getRoleType()); + RoleTypeEnum roleTypeEnum = RoleTypeEnum.AUTO_OWN; + if (roleTypeEnumOptional.isPresent()) { + roleTypeEnum = roleTypeEnumOptional.get(); + } + boolean anyAdminRole = adminRoleIds.contains(e.getRoleId()) || roleTypeEnum.isAdmin(); + if (anyAdminRole) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.ANY_ADMIN); + addFailInfo(failInfoMap, e.getPersonId(), checkFailInfo); + } + }); + // 检查班组节点权限 + checkUserOperate(CheckUserOperateParam.builder() + .operatorId(req.getOperatorId()) + .personIds(req.getPersonIds()) + .workspaceId(req.getWorkspaceId()) + .build(), failInfoMap); + // 三方阻断校验 + thirdApiCheckPerson(req.getWorkspaceId(), req.getPersonIds(), failInfoMap); + transformFailMap(failInfoMap, resultList); + return resultList; } -} + + private static void transformFailMap(Map> failInfoMap, List resultList) { + if (CollUtil.isNotEmpty(failInfoMap)) { + failInfoMap.forEach((failPerson, checkFailInfos) -> { + // Use a LinkedHashMap to keep track of the last count for each type + Map lastCounts = new LinkedHashMap<>(); + for (BatchDeleteNodeUserCheckResp.CheckFailInfo info : checkFailInfos) { + lastCounts.put(info.getType(), info.getCount()); + } + + // Create a new list of CheckFailInfo objects with unique types and their last counts + List uniqueFailInfos = new ArrayList<>(); + for (Map.Entry entry : lastCounts.entrySet()) { + uniqueFailInfos.add(new BatchDeleteNodeUserCheckResp.CheckFailInfo(entry.getKey(), entry.getValue())); + } + BatchDeleteNodeUserCheckResp batchDeleteNodeUserCheckVO = new BatchDeleteNodeUserCheckResp(); + batchDeleteNodeUserCheckVO.setPersonId(failPerson); + batchDeleteNodeUserCheckVO.setFailInfos(uniqueFailInfos); + resultList.add(batchDeleteNodeUserCheckVO); + }); + } + } + + private void thirdApiCheckPerson(Long workspaceId, Set personIds, Map> failInfoMap) { + Map> thirdCheckFail = karmaThirdApiClient.getThirdCheckFail(workspaceId, personIds); + if (CollUtil.isEmpty(thirdCheckFail)) { + return; + } + thirdCheckFail.forEach((key, value) -> value.forEach(thirdCheckFailResp -> { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(thirdCheckFailResp.getType()); + checkFailInfo.setCount(thirdCheckFailResp.getCount()); + addFailInfo(failInfoMap, key, checkFailInfo); + })); + } + + private void checkIndependentGroupLeader(List nodeUsers, Map> failInfoMap) { + Set nodeIdList = nodeUsers.stream().map(NodeUserDTO::getOrganizationalNodeId).collect(Collectors.toSet()); + ListNodeReq nodeBatchQueryVO = new ListNodeReq(); + nodeBatchQueryVO.setIds(nodeIdList); + List nodeVOList = nodeService.list(nodeBatchQueryVO); + if (CollectionUtil.isEmpty(nodeVOList)) { + throw ResultCode.INVALID_PARAMS.toException("操作失败:获取部门节点信息失败"); + } + Map nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(OrgNodeDTO::getId, Function.identity())); + for (NodeUserDTO u : nodeUsers) { + if (projectTeamGPLeader.equals(u.getJob().getCode())) { + OrgNodeDTO nodeVO = nodeVOMap.getOrDefault(u.getOrganizationalNodeId(), null); + if (Objects.nonNull(nodeVO) && NodeTypeEnum.PROJECT_GROUP.getValue().equals(nodeVO.getNodeType()) + && Objects.nonNull(nodeVO.independentGroup()) && nodeVO.independentGroup()) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.PROJECT_GROUP_LEADER); + addFailInfo(failInfoMap, u.getPersonId(), checkFailInfo); + } + } + } + } + + private void checkPermission(List nodeUsers, Long personId) { + if (CollUtil.isEmpty(nodeUsers) + || nodeUsers.stream().noneMatch(e -> Objects.equals(e.getPersonId(), personId))) { + throw ResultCode.INVALID_PARAMS.toException("你已被移除当前项目"); + } + } + + private List getSpecialRole() { + if (participateUnitDefaultRoleId != null && !participateUnitDefaultRoleId.isEmpty()) { + return new ArrayList<>(participateUnitDefaultRoleId.values()); + } else { + return new ArrayList<>(); + } + } + + public void checkUserOperate(CheckUserOperateParam param, Map> failInfoMap) { + if (NumberUtil.isNotPositiveNumber(param.getOperatorId())) { + return; + } + param.check(); + List nodePersonIds = Lists.newArrayList(param.getPersonIds()); + nodePersonIds.add(param.getOperatorId()); + ListNodeUserReq nodeUserReq = ListNodeUserReq.builder() + .personIds(nodePersonIds) + .workspaceId(param.getWorkspaceId()) + .needs(ListNodeUserReq.Needs.builder().job(true).node(true).build()) + .build(); + List nodeUsers = nodeUserService.list(nodeUserReq); + NodeUserDTO operator = nodeUsers.stream().filter(nu -> Objects.equals(nu.getPersonId(), param.getOperatorId())) + .filter(nu -> StrUtil.isNotBlank(nu.getJob().getCode())) + .min(Comparator.comparingInt(NODE_USER_PRIORITY_RESOLVER)).orElse(null); + List targets = param.getPersonIds().stream() + .map(personId -> nodeUsers.stream() + .filter(nu -> Objects.equals(nu.getPersonId(), personId)) + .min(Comparator.comparingInt(NODE_USER_PRIORITY_RESOLVER)) + .orElse(null)) + .collect(Collectors.toList()); + + log.info("## checkUserOperate, param = {}, operator = {}, targets = {}, nodeUsers = {} " + , JSON.toJSONString(param), JSON.toJSONString(operator), JSON.toJSONString(targets), JSON.toJSONString(nodeUsers)); + if (operator == null) { + throw ResultCode.INVALID_PARAMS.toException("你已经被移出该企业/项目,请及时联系管理员;你可以退出登录或切换到其他企业/项目使用"); + } + if (CollUtil.isEmpty(targets)) { + throw ResultCode.INVALID_PARAMS.toException("操作对象已经被移出该企业/项目,请刷新页面重新操作"); + } + + // 如果只有工人身份,则直接提示无权限 + if (isProjectWorker(operator)) { + throw ResultCode.INVALID_PARAMS.toException("操作失败,您暂无权限!"); + } + if (param.getPersonIds().size() == 1 && param.getPersonIds().contains(param.getOperatorId())) { + return; + } + // 如果 操作人是 从业人员 直接返回 + if (isPractitioner(operator)) { + return; + } + // 操作人是 班组长或者带班长, 则被操作人,只能是 自己,或者自己班组 及 小组的工人 + if (isProjectTeamLeader(operator) || isProjectTeamManager(operator)) { + targets.forEach(target -> teamManagerCheck(target, operator, failInfoMap)); + } + if (isProjectGroupManager(operator)) { + targets.forEach(target -> groupManagerCheck(target, operator, nodeUsers, failInfoMap)); + } + } + + private void groupManagerCheck(NodeUserDTO target, NodeUserDTO operator, List nodeUsers, Map> failInfoMap) { + if (isPractitioner(target)) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.ANY_ADMIN); + addFailInfo(failInfoMap, target.getPersonId(), checkFailInfo); + return; + } + // 工人必须仅在自己小组 + boolean isSameGroup = nodeUsers.stream() + .filter(nu -> Objects.equals(nu.getPersonId(), target.getPersonId())) + .anyMatch(nu -> Objects.equals(nu.getOrganizationalNodeId(), operator.getOrganizationalNodeId())); + if (!isSameGroup) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.NOT_IN_JURISDICTION); + addFailInfo(failInfoMap, target.getPersonId(), checkFailInfo); + } + } + + private void teamManagerCheck(NodeUserDTO target, NodeUserDTO operator, Map> failInfoMap) { + if (isPractitioner(target)) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.ANY_ADMIN); + addFailInfo(failInfoMap, target.getPersonId(), checkFailInfo); + return; + } + boolean isSameTeam = Objects.equals(target.getOrganizationalNodeId(), operator.getOrganizationalNodeId()); + if (isSameTeam) { + return; + } + // 否则,自己下级小组,也可以。 + boolean isGroup = target.getNode() != null + && Objects.equals(target.getNode().getNodeType(), NodeTypeEnum.PROJECT_GROUP.getCode()); + if (!isGroup) { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.NOT_IN_JURISDICTION); + addFailInfo(failInfoMap, target.getPersonId(), checkFailInfo); + return; + } + Long belongProjectTeamNodeId = resolveProjectTeamNodeId(target.getOrganizationalNodeId()); + if (Objects.equals(belongProjectTeamNodeId, operator.getOrganizationalNodeId())) { + return; + } + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.NOT_IN_JURISDICTION); + addFailInfo(failInfoMap, target.getPersonId(), checkFailInfo); + } + + private boolean isPractitioner(NodeUserDTO nodeUser) { + if (nodeUser == null) { + return false; + } + return Objects.equals(nodeUser.getIdentityType(), IdentityType.PRACTITIONER.getCode()); + } + + private boolean isProjectWorker(NodeUserDTO nodeUser) { + if (nodeUser == null) { + return false; + } + return Objects.equals(nodeUser.getJob().getCode(), JobCodeConstants.PROJECT_TEAM_WORKER); + } + + private boolean isProjectTeamLeader(NodeUserDTO nodeUser) { + if (nodeUser == null) { + return false; + } + return Objects.equals(nodeUser.getJob().getCode(), JobCodeConstants.PROJ_TEAM_LEADER); + } + + private boolean isProjectTeamManager(NodeUserDTO nodeUser) { + if (nodeUser == null) { + return false; + } + return Objects.equals(nodeUser.getJob().getCode(), JobCodeConstants.PROJ_TEAM_MANAGER); + } + + private boolean isProjectGroupManager(NodeUserDTO nodeUser) { + if (nodeUser == null) { + return false; + } + return Objects.equals(nodeUser.getJob().getCode(), JobCodeConstants.PROJECT_TEAM_GROUP_LEADER); + } + + private static final ToIntFunction NODE_USER_PRIORITY_RESOLVER = nodeUser -> { + if (nodeUser == null) { + return 9999; + } + if (Objects.equals(nodeUser.getIdentityType(), IdentityType.PRACTITIONER.getCode())) { + return 20; + } + if (StrUtil.isBlank(nodeUser.getJob().getCode())) { + return 9999; + } + switch (nodeUser.getJob().getCode()) { + case JobCodeConstants.PROJECT_TEAM_WORKER: + // 工人 + return 100; + case JobCodeConstants.PROJECT_TEAM_GROUP_LEADER: + // 小组长 + return 90; + case JobCodeConstants.PROJ_TEAM_MANAGER: + // 带班长 + return 80; + case JobCodeConstants.PROJ_TEAM_LEADER: + // 班组长 + return 70; + case JobCodeConstants.ENT_TEAM_WORK: + // 平台工人 + return 60; + case JobCodeConstants.ENT_TEAM_MANAGER: + // 平台班组管理员 + return 50; + case JobCodeConstants.ENT_TEAM_LEADER: + // 平台班组长 + return 40; + default: + return 20; + } + }; + + private Long resolveProjectTeamNodeId(Long nodeId) { + ListOrgCooperateShipReq saasCooperateShipQueryReq = ListOrgCooperateShipReq.builder() + .organizationNodeIds(ImmutableSet.of(nodeId)) + .includeAncestors(true) + .build(); + List nodes = cooperateShipService.list(saasCooperateShipQueryReq); + return nodes.stream().filter(n -> Objects.equals(n.getCooperateType(), CooperateShipTypeEnum.PROJ_TEAM.getCode())).findFirst() + .map(OrgCooperateShipDTO::getOrganizationalNodeId).orElse(0L); + } + +} \ No newline at end of file diff --git a/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/util/constants/JobCodeConstants.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/util/constants/JobCodeConstants.java new file mode 100644 index 0000000..d1d15b3 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/util/constants/JobCodeConstants.java @@ -0,0 +1,34 @@ +package cn.axzo.orgmanax.server.util.constants; + +/** + * 岗位编码常量 + * + * @version V1.0 + * @author: ZhanSiHu + * @date: 2024/1/25 14:03 + */ +public class JobCodeConstants { + /** 企业内班组长 **/ + public static final String ENT_TEAM_LEADER = "entTeamLeader"; + /** 企业内班组管理员 **/ + public static final String ENT_TEAM_MANAGER = "entTeamManager"; + /** 企业内工人 **/ + public static final String ENT_TEAM_WORK = "entWorker"; + + /** 项目内班组 班组长 **/ + public static final String PROJ_TEAM_LEADER = "projTeamLeader"; + + /** + * 项目 - 带班长 + */ + public static final String PROJ_TEAM_MANAGER = "projectTeamManager"; + /** + * 项目 - 小组长 + */ + public static final String PROJECT_TEAM_GROUP_LEADER = "projectTeamGPLeader"; + + + public static final String PROJECT_TEAM_WORKER = "projWorker"; + + +}