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/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 new file mode 100644 index 0000000..fd0a3c9 --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/enums/CheckInfoTypeEnum.java @@ -0,0 +1,37 @@ +package cn.axzo.orgmanax.dto.nodeuser.enums; + +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, "超级管理员", "【%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/req/BatchDeleteNodeUserCheckReq.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java new file mode 100644 index 0000000..ccb36b2 --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/req/BatchDeleteNodeUserCheckReq.java @@ -0,0 +1,36 @@ +package cn.axzo.orgmanax.dto.nodeuser.req; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.Set; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Data +public class BatchDeleteNodeUserCheckReq { + + /** + * personIds + */ + @NotNull(message = "personIds不可以为空!") + private Set personIds; + + private Long workspaceId; + + private Long ouId; + + /** + * 删除项目人员的时候传入 + * 节点ID + */ + private Long nodeId; + + /** + * 操作者ID + */ + private Long operatorId; +} 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/nodeuser/resp/BatchDeleteNodeUserCheckResp.java b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java new file mode 100644 index 0000000..44cab36 --- /dev/null +++ b/orgmanax-dto/src/main/java/cn/axzo/orgmanax/dto/nodeuser/resp/BatchDeleteNodeUserCheckResp.java @@ -0,0 +1,30 @@ +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; + +/** + * @author : zhanghonghao@axzo.cn + * @since : 2025/3/6 + */ +@Data +public class BatchDeleteNodeUserCheckResp { + + private Long personId; + + private List failInfos; + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class CheckFailInfo { + + private CheckInfoTypeEnum type; + + private Integer count; + } +} 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/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-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-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-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/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/controller/NodeUserCheckController.java b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/NodeUserCheckController.java new file mode 100644 index 0000000..cdcddc2 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/controller/NodeUserCheckController.java @@ -0,0 +1,34 @@ +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 cn.axzo.orgmanax.server.nodeuser.service.NodeUserCheckService; +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 NodeUserCheckController implements OrgNodeUserCheckApi { + + private final NodeUserCheckService nodeUserCheckService; + + @Override + public ApiResult> checkUnit(BatchDeleteNodeUserCheckReq req) { + return ApiResult.success(nodeUserCheckService.checkUnit(req)); + } + + @Override + public ApiResult> checkWorkspace(BatchDeleteNodeUserCheckReq req) { + 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/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/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..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 @@ -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,72 @@ 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()).identityType(req.getIdentityType()).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..689f1f4 --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/foundation/req/NodeUserDelete.java @@ -0,0 +1,40 @@ +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; + + /** + * 身份类型 按照项目删除的时候 传 + */ + private Integer identityType; + + 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/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..d8a563d --- /dev/null +++ b/orgmanax-server/src/main/java/cn/axzo/orgmanax/server/nodeuser/service/impl/NodeUserCheckServiceImpl.java @@ -0,0 +1,516 @@ +package cn.axzo.orgmanax.server.nodeuser.service.impl; + +import cn.axzo.apollo.workspace.api.v2.participating.req.ParticipatingUnitListReq; +import cn.axzo.apollo.workspace.api.v2.participating.resp.ParticipatingUnitResp; +import cn.axzo.foundation.exception.Axssert; +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.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.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; +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.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; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.function.Function; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NodeUserCheckServiceImpl implements NodeUserCheckService { + + private final WorkspaceGateway workspaceGateway; + + private final RoleUserGateway roleUserGateway; + + 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("${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); + Set teamLeader = Sets.newHashSet(); + organizationalNodeUserList.forEach(organizationalNodeUserVO -> { + if (IdentityTypeEnum.WORKER_LEADER.getCode().equals(organizationalNodeUserVO.getIdentityType()) || entTeamLeader.equals(organizationalNodeUserVO.getJob().getCode())) { + teamLeader.add(organizationalNodeUserVO.getPersonId()); + } + }); + if (CollUtil.isNotEmpty(teamLeader)) { + teamLeader.forEach(e -> { + BatchDeleteNodeUserCheckResp.CheckFailInfo checkFailInfo = new BatchDeleteNodeUserCheckResp.CheckFailInfo(); + checkFailInfo.setType(CheckInfoTypeEnum.TEAM_LEADER); + addFailInfo(failInfoMap, e, checkFailInfo); + }); + } + //判断当前人是否有操作权限 + if (NumberUtil.isPositiveNumber(req.getOperatorId())) { + + } + transformFailMap(failInfoMap, resultList); + 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) { + 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/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; + } +} 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"; + + +}