From 0d89472b71cfb7aafd89b5f412d88ff7caba1e51 Mon Sep 17 00:00:00 2001 From: zhaokai Date: Thu, 18 Jun 2026 14:21:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(sync):=20=E4=BC=98=E5=8C=96=E4=BA=BA?= =?UTF-8?q?=E8=B5=84=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E5=A2=9E=E5=8A=A0=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- start/src/main/resources/sdk-prod.yml | 3 + .../user/plan/HumanCorpDepartmentSyncJob.java | 42 ++ .../user/plan/HumanCorpUserChangeSyncJob.java | 40 ++ .../human/user/plan/HumanCorpUserSyncJob.java | 41 ++ .../human/user/plan/HumanDeptSyncJob.java | 6 +- .../plan/HumanUserDeptCompareSyncJob.java | 4 +- .../human/user/plan/HumanUserSyncJob.java | 5 +- .../user/web/HumanResourceCorpController.java | 82 +++ .../human/user/web/HumanUserController.java | 19 +- .../human/user/command/HumanDeptSyncExe.java | 291 +++++++- .../user/command/HumanResourceCorpAddExe.java | 40 ++ .../command/HumanResourceCorpRemoveExe.java | 39 + .../command/HumanResourceCorpUpdateExe.java | 34 + .../human/user/command/HumanUserSyncExe.java | 669 +++++++++++++++++- .../HumanResourceCorpCoConvertor.java | 24 + .../query/HumanResourceCorpQueryExe.java | 42 ++ .../user/config/HumanResourcesConfig.java | 26 + .../human/user/service/AsyncSyncService.java | 14 +- .../service/HumanResourceCorpServiceImpl.java | 59 ++ .../user/api/HumanResourceCorpServiceI.java | 27 + .../user/dto/HumanResourceCorpAddCmd.java | 56 ++ .../user/dto/HumanResourceCorpPageQry.java | 28 + .../user/dto/HumanResourceCorpUpdateCmd.java | 55 ++ .../dto/clientobject/HumanResourceCorpCO.java | 85 +++ .../domain/enums/UserEmploymentFlagEnum.java | 52 ++ .../gateway/HumanResourceCorpGateway.java | 30 + .../human/user/domain/model/DeptEntity.java | 51 ++ .../user/domain/model/HumanResourceCorpE.java | 61 ++ .../human/user/domain/utils/SignUtil.java | 263 +++++++ .../HumanResourceCorpGatewayImpl.java | 50 ++ .../dataobject/HumanResourceCorpDO.java | 54 ++ .../mapper/HumanResourceCorpMapper.java | 17 + .../HumanResourceCorpRepository.java | 21 + .../impl/HumanResourceCorpRepositoryImpl.java | 51 ++ .../src/main/resources/TableCreationDDL.sql | 29 + .../mapper/HumanResourceCorpMapper.xml | 7 + 36 files changed, 2369 insertions(+), 48 deletions(-) create mode 100644 web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpDepartmentSyncJob.java create mode 100644 web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserChangeSyncJob.java create mode 100644 web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserSyncJob.java create mode 100644 web-adapter/src/main/java/com/zcloud/human/user/web/HumanResourceCorpController.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpAddExe.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpRemoveExe.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpUpdateExe.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/command/convertor/HumanResourceCorpCoConvertor.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/command/query/HumanResourceCorpQueryExe.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/config/HumanResourcesConfig.java create mode 100644 web-app/src/main/java/com/zcloud/human/user/service/HumanResourceCorpServiceImpl.java create mode 100644 web-client/src/main/java/com/zcloud/human/user/api/HumanResourceCorpServiceI.java create mode 100644 web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpAddCmd.java create mode 100644 web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpPageQry.java create mode 100644 web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpUpdateCmd.java create mode 100644 web-client/src/main/java/com/zcloud/human/user/dto/clientobject/HumanResourceCorpCO.java create mode 100644 web-domain/src/main/java/com/zcloud/human/user/domain/enums/UserEmploymentFlagEnum.java create mode 100644 web-domain/src/main/java/com/zcloud/human/user/domain/gateway/HumanResourceCorpGateway.java create mode 100644 web-domain/src/main/java/com/zcloud/human/user/domain/model/DeptEntity.java create mode 100644 web-domain/src/main/java/com/zcloud/human/user/domain/model/HumanResourceCorpE.java create mode 100644 web-domain/src/main/java/com/zcloud/human/user/domain/utils/SignUtil.java create mode 100644 web-infrastructure/src/main/java/com/zcloud/human/user/gatewayimpl/HumanResourceCorpGatewayImpl.java create mode 100644 web-infrastructure/src/main/java/com/zcloud/human/user/persistence/dataobject/HumanResourceCorpDO.java create mode 100644 web-infrastructure/src/main/java/com/zcloud/human/user/persistence/mapper/HumanResourceCorpMapper.java create mode 100644 web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/HumanResourceCorpRepository.java create mode 100644 web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/impl/HumanResourceCorpRepositoryImpl.java create mode 100644 web-infrastructure/src/main/resources/mapper/HumanResourceCorpMapper.xml diff --git a/start/src/main/resources/sdk-prod.yml b/start/src/main/resources/sdk-prod.yml index da6198e..3352eeb 100644 --- a/start/src/main/resources/sdk-prod.yml +++ b/start/src/main/resources/sdk-prod.yml @@ -36,3 +36,6 @@ archives: queueCapacity: 60 namePrefix: async-task- keepAliveSeconds: 60 +humanresources: + appKey: A5EF205479D2DFB5E621E159AA8FF34B + appSecret: 53130AAAAC791D5B7AFD6D89C51853510190C903405242C49B83DECBBA0ADA5E \ No newline at end of file diff --git a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpDepartmentSyncJob.java b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpDepartmentSyncJob.java new file mode 100644 index 0000000..e1d4767 --- /dev/null +++ b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpDepartmentSyncJob.java @@ -0,0 +1,42 @@ +package com.zcloud.human.user.plan; + +import com.jjb.saas.framework.job.Job; +import com.jjb.saas.framework.job.annotation.JobRegister; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import com.zcloud.human.user.command.HumanDeptSyncExe; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 人资部门数据同步定时任务 + * + */ +@RequiredArgsConstructor +@Component +@Slf4j +public class HumanCorpDepartmentSyncJob implements Job { + + private final HumanDeptSyncExe humanDeptSyncExe; + + @Override +// @JobRegister(cron = "0 30 0 * * ?", jobDesc = "人资部门数据同步任务开始",triggerStatus = 1) + @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资部门全量数据同步任务开始",triggerStatus = 1) + @XxlJob("com.zcloud.human.user.plan.HumanCorpDepartmentSyncJob") + public ReturnT execute(String param) { + XxlJobHelper.log("============人资部门数据同步任务开始=========="); + + try { + param = "test"; + String result = humanDeptSyncExe.CorpDepartmentSync(param); + XxlJobHelper.log("同步结果:{}", result); + XxlJobHelper.log("============人资部门数据同步任务结束=========="); + return new ReturnT<>(ReturnT.SUCCESS_CODE, result); + } catch (Exception e) { + XxlJobHelper.log("同步任务执行失败:{}", e.getMessage()); + return new ReturnT<>(ReturnT.FAIL_CODE, "同步任务执行失败:" + e.getMessage()); + } + } +} diff --git a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserChangeSyncJob.java b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserChangeSyncJob.java new file mode 100644 index 0000000..e3ff83a --- /dev/null +++ b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserChangeSyncJob.java @@ -0,0 +1,40 @@ +package com.zcloud.human.user.plan; + +import com.jjb.saas.framework.job.Job; +import com.jjb.saas.framework.job.annotation.JobRegister; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import com.zcloud.human.user.command.HumanUserSyncExe; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 人资人员数据同步定时任务 + */ +@RequiredArgsConstructor +@Component +@Slf4j +public class HumanCorpUserChangeSyncJob implements Job { + + private final HumanUserSyncExe humanUserSyncExe; + + @Override +// @JobRegister(cron = "0 30 0 * * ?", jobDesc = "人资部门数据同步任务开始",triggerStatus = 1) + @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资用户变更数据同步任务开始",triggerStatus = 1) + @XxlJob("com.zcloud.human.user.plan.HumanCorpUserChangeSyncJob") + public ReturnT execute(String param) { + XxlJobHelper.log("============人资人员变更数据同步任务开始=========="); + + try { + String result = humanUserSyncExe.CorpUserChangeSync(param); + XxlJobHelper.log("同步结果:{}", result); + XxlJobHelper.log("============人资人员变更数据同步任务结束=========="); + return new ReturnT<>(ReturnT.SUCCESS_CODE, result); + } catch (Exception e) { + XxlJobHelper.log("人资人员变更数据同步任务执行失败:{}", e.getMessage()); + return new ReturnT<>(ReturnT.FAIL_CODE, "人资人员变更数据同步任务执行失败:" + e.getMessage()); + } + } +} diff --git a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserSyncJob.java b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserSyncJob.java new file mode 100644 index 0000000..03f2e0d --- /dev/null +++ b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanCorpUserSyncJob.java @@ -0,0 +1,41 @@ +package com.zcloud.human.user.plan; + +import com.jjb.saas.framework.job.Job; +import com.jjb.saas.framework.job.annotation.JobRegister; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import com.zcloud.human.user.command.HumanUserSyncExe; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 人资人员数据同步定时任务 + */ +@RequiredArgsConstructor +@Component +@Slf4j +public class HumanCorpUserSyncJob implements Job { + + private final HumanUserSyncExe humanUserSyncExe; + + @Override +// @JobRegister(cron = "0 30 0 * * ?", jobDesc = "人资部门数据同步任务开始",triggerStatus = 1) + @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资用户全量同步任务开始new",triggerStatus = 1) + @XxlJob("com.zcloud.human.user.plan.HumanCorpUserSyncJob") + public ReturnT execute(String param) { + XxlJobHelper.log("============人资人员数据同步任务开始=========="); + + try { + param = "test"; + String result = humanUserSyncExe.CorpUserSync(param); + XxlJobHelper.log("同步结果:{}", result); + XxlJobHelper.log("============人资人员数据同步任务结束=========="); + return new ReturnT<>(ReturnT.SUCCESS_CODE, result); + } catch (Exception e) { + XxlJobHelper.log("同步任务执行失败:{}", e.getMessage()); + return new ReturnT<>(ReturnT.FAIL_CODE, "同步任务执行失败:" + e.getMessage()); + } + } +} diff --git a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanDeptSyncJob.java b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanDeptSyncJob.java index bae2d5d..48a96c6 100644 --- a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanDeptSyncJob.java +++ b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanDeptSyncJob.java @@ -11,7 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** - * 人资部门数据同步定时任务 + * 人资部门数据同步定时任务,暂时没用,因为是直接往数据库落数据 * * @author zhaolei * @Date 2026-06-02 @@ -25,8 +25,8 @@ public class HumanDeptSyncJob implements Job { @Override // @JobRegister(cron = "0 30 0 * * ?", jobDesc = "人资部门数据同步任务开始",triggerStatus = 1) - @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资部门数据同步任务开始",triggerStatus = 1) - @XxlJob("com.zcloud.human.user.plan.HumanDeptSyncJob") +// @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资部门数据同步任务开始",triggerStatus = 1) +// @XxlJob("com.zcloud.human.user.plan.HumanDeptSyncJob") public ReturnT execute(String param) { XxlJobHelper.log("============人资部门数据同步任务开始=========="); diff --git a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserDeptCompareSyncJob.java b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserDeptCompareSyncJob.java index 97fdaa3..176d785 100644 --- a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserDeptCompareSyncJob.java +++ b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserDeptCompareSyncJob.java @@ -35,8 +35,8 @@ public class HumanUserDeptCompareSyncJob implements Job { @Override // @JobRegister(cron = "0 30 0 * * ?", jobDesc = "人资用户部门对比同步任务开始",triggerStatus = 1) - @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资用户部门对比同步任务开始",triggerStatus = 1) - @XxlJob("com.zcloud.human.user.plan.HumanUserDeptCompareSyncJob") +// @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资用户部门对比同步任务开始",triggerStatus = 1) +// @XxlJob("com.zcloud.human.user.plan.HumanUserDeptCompareSyncJob") public ReturnT execute(String param) { XxlJobHelper.log("============人资用户部门对比同步任务开始=========="); diff --git a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserSyncJob.java b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserSyncJob.java index e7678b3..4d61b0a 100644 --- a/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserSyncJob.java +++ b/web-adapter/src/main/java/com/zcloud/human/user/plan/HumanUserSyncJob.java @@ -28,12 +28,13 @@ public class HumanUserSyncJob implements Job { @Override // @JobRegister(cron = "0 30 0 * * ?", jobDesc = "人资人员数据同步任务开始",triggerStatus = 1) - @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资人员数据同步任务开始",triggerStatus = 1) - @XxlJob("com.zcloud.human.user.plan.HumanUserSyncJob") +// @JobRegister(cron = "0 30 0 1 1 ?", jobDesc = "人资人员数据同步任务开始",triggerStatus = 1) +// @XxlJob("com.zcloud.human.user.plan.HumanUserSyncJob") public ReturnT execute(String param) { XxlJobHelper.log("============人资人员数据同步任务开始=========="); try { + param = "test"; String result = humanUserSyncExe.execute(param); XxlJobHelper.log("同步结果:{}", result); XxlJobHelper.log("============人资人员数据同步任务结束=========="); diff --git a/web-adapter/src/main/java/com/zcloud/human/user/web/HumanResourceCorpController.java b/web-adapter/src/main/java/com/zcloud/human/user/web/HumanResourceCorpController.java new file mode 100644 index 0000000..1cf6612 --- /dev/null +++ b/web-adapter/src/main/java/com/zcloud/human/user/web/HumanResourceCorpController.java @@ -0,0 +1,82 @@ +package com.zcloud.human.user.web; + + +import com.alibaba.cola.dto.MultiResponse; +import com.alibaba.cola.dto.PageResponse; +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.dto.SingleResponse; +import com.jjb.saas.framework.auth.model.SSOUser; +import com.jjb.saas.framework.auth.utils.AuthContext; +import com.zcloud.human.user.api.HumanResourceCorpServiceI; +import com.zcloud.human.user.dto.HumanResourceCorpAddCmd; +import com.zcloud.human.user.dto.HumanResourceCorpPageQry; +import com.zcloud.human.user.dto.HumanResourceCorpUpdateCmd; +import com.zcloud.human.user.dto.clientobject.HumanResourceCorpCO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; + +/** + * web-adapter + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Api(tags = "人资企业部门信息") +@RequestMapping("/${application.gateway}/humanResourceCorp") +@RestController +@AllArgsConstructor +public class HumanResourceCorpController { + private final HumanResourceCorpServiceI humanResourceCorpService; + + @ApiOperation("新增") + @PostMapping("/save") + public SingleResponse add(@Validated @RequestBody HumanResourceCorpAddCmd cmd) { + SSOUser ssoUser = AuthContext.getCurrentUser(); + return humanResourceCorpService.add(cmd); + } + + @ApiOperation("分页") + @PostMapping("/list") + public PageResponse page(@RequestBody HumanResourceCorpPageQry qry) { + return humanResourceCorpService.listPage(qry); + } + + @ApiOperation("所有数据") + @GetMapping("/listAll") + public MultiResponse listAll() { + return MultiResponse.of(new ArrayList()); + } + + @ApiOperation("详情") + @GetMapping("/{id}") + public SingleResponse getInfoById(@PathVariable("id") Long id) { + return SingleResponse.of(new HumanResourceCorpCO()); + } + + @ApiOperation("删除") + @DeleteMapping("/{id}") + public Response remove(@PathVariable("id") Long id) { + humanResourceCorpService.remove(id); + return SingleResponse.buildSuccess(); + } + + @ApiOperation("删除多个") + @DeleteMapping("/ids") + public Response removeBatch(@RequestParam Long[] ids) { + humanResourceCorpService.removeBatch(ids); + return SingleResponse.buildSuccess(); + } + + @ApiOperation("修改") + @PutMapping("/edit") + public SingleResponse edit(@Validated @RequestBody HumanResourceCorpUpdateCmd humanResourceCorpUpdateCmd) { + humanResourceCorpService.edit(humanResourceCorpUpdateCmd); + return SingleResponse.buildSuccess(); + } +} + diff --git a/web-adapter/src/main/java/com/zcloud/human/user/web/HumanUserController.java b/web-adapter/src/main/java/com/zcloud/human/user/web/HumanUserController.java index 7e39497..eeca5b8 100644 --- a/web-adapter/src/main/java/com/zcloud/human/user/web/HumanUserController.java +++ b/web-adapter/src/main/java/com/zcloud/human/user/web/HumanUserController.java @@ -32,13 +32,20 @@ public class HumanUserController { @PostMapping("/asyncSyncHumanUser") public SingleResponse asyncSyncHumanUser() { log.info("开始同步用户信息"); - asyncSyncService.asyncSyncHumanUser("manual"); + asyncSyncService.asyncSyncHumanUser("test"); return SingleResponse.of("用户同步任务已提交,请查看日志了解进度"); } + @ApiOperation("同步用户信息-手动调用定时任务") + @PostMapping("/asyncSyncUserChange") + public SingleResponse asyncSyncUserChange() { + log.info("开始同步用户变更信息"); + asyncSyncService.asyncSyncUserChange("test"); + return SingleResponse.of("同步用户变更已提交,请查看日志了解进度"); + } - /** + /* *//** * 异步同步人资部门信息 - */ + *//* @ApiOperation("同步部门信息-手动调用定时任务") @PostMapping("/asyncSyncHumanDept") public SingleResponse asyncSyncHumanDept() { @@ -47,15 +54,15 @@ public class HumanUserController { return SingleResponse.of("部门同步任务已提交,请查看日志了解进度"); } - /** + *//** * 异步部门对比同步 - */ + *//* @ApiOperation("部门对比-手动调用定时任务") @PostMapping("/asyncSyncDeptCompare") public SingleResponse asyncSyncDeptCompare() { log.info("开始部门对比同步"); asyncSyncService.asyncSyncDeptCompare("manual"); return SingleResponse.of("部门对比同步任务已提交,请查看日志了解进度"); - } + }*/ } diff --git a/web-app/src/main/java/com/zcloud/human/user/command/HumanDeptSyncExe.java b/web-app/src/main/java/com/zcloud/human/user/command/HumanDeptSyncExe.java index 4cda046..ff39735 100644 --- a/web-app/src/main/java/com/zcloud/human/user/command/HumanDeptSyncExe.java +++ b/web-app/src/main/java/com/zcloud/human/user/command/HumanDeptSyncExe.java @@ -2,23 +2,35 @@ package com.zcloud.human.user.command; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONConfig; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.alibaba.cloud.commons.lang.StringUtils; import com.alibaba.cola.dto.MultiResponse; import com.alibaba.cola.dto.SingleResponse; +import com.zcloud.gbscommon.utils.Tools; import com.zcloud.gbscommon.zcloudcorp.face.ZcloudCorpFacade; import com.zcloud.gbscommon.zcloudcorp.response.ZcloudCorpInfoCO; import com.zcloud.gbscommon.zclouddepartment.face.ZcloudDepartmentFacade; import com.zcloud.gbscommon.zclouddepartment.request.ZcloudDepartmentAddCmd; import com.zcloud.gbscommon.zclouddepartment.response.ZcloudDepartmentInfoCo; +import com.zcloud.human.user.config.HumanResourcesConfig; +import com.zcloud.human.user.domain.utils.SignUtil; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; +import com.zcloud.human.user.persistence.repository.HumanResourceCorpRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * 人资部门数据同步执行器 @@ -49,12 +61,36 @@ public class HumanDeptSyncExe { */ private static final String USER_INFO_URL = "http://192.168.10.56:8090"; + /** + * 人资企业部门接口地址。 + */ + private static final String HUMAN_RESOURCE_DEPT_URL = "https://192.168.195.249:28001/idatashare/api/remoteCall/v1/1057031106228944896"; + + /** + * 人资企业部门接口标识。 + */ + private static final String HUMAN_RESOURCE_DEPT_API_ID = "1057031106228944896"; + + /** + * 人资企业部门接口分页大小。 + */ + private static final int HUMAN_RESOURCE_DEPT_PAGE_SIZE = 1000; + + /** + * 人资企业部门测试数据标记。 + */ + private static final String HUMAN_RESOURCE_DEPT_TEST_FLAG = "test"; + @DubboReference private ZcloudDepartmentFacade zcloudDepartmentFacade; @DubboReference private ZcloudCorpFacade zcloudCorpFacade; + private final HumanResourceCorpRepository humanResourceCorpRepository; + private final HumanResourcesConfig humanResourcesConfig; + + private final JSONConfig jsonConfig = JSONConfig.create().setIgnoreNullValue(true); /** * 执行同步 * @@ -70,6 +106,11 @@ public class HumanDeptSyncExe { log.warn("本系统不存在公司:{},终止同步", SYSTEM_CORP_NAME); return "同步终止:本系统不存在公司" + SYSTEM_CORP_NAME; } + Long gbsRootDeptId = findGbsRootDeptId(corpId); + if (gbsRootDeptId == null) { + log.warn("本系统公司:{} 下没有根部门,终止同步", SYSTEM_CORP_NAME); + return "同步终止:本系统公司" + SYSTEM_CORP_NAME + "下没有根部门"; + } String result = ""; if("manual".equals(param)){ @@ -83,11 +124,6 @@ public class HumanDeptSyncExe { return "同步终止:未找到公司" + SYSTEM_CORP_NAME + "的部门数据"; } - Long gbsRootDeptId = findGbsRootDeptId(corpId); - if (gbsRootDeptId == null) { - log.warn("本系统公司:{} 下没有根部门,终止同步", SYSTEM_CORP_NAME); - return "同步终止:本系统公司" + SYSTEM_CORP_NAME + "下没有根部门"; - } JSONArray children = rootDept.getJSONArray("children"); if (children == null || children.isEmpty()) { @@ -393,4 +429,249 @@ public class HumanDeptSyncExe { "\t}]\n" + "}"; } + + @Transactional(rollbackFor = Exception.class) + public String CorpDepartmentSync(String param) { + log.info("============开始同步人资企业部门本地数据=========="); + JSONArray sourceRows = pullAllCorpDepartmentRows(param); + if (sourceRows.isEmpty()) { + log.info("未获取到人资企业部门数据"); + return "同步完成:未获取到人资企业部门数据"; + } + + List corpList = buildHumanResourceCorpList(sourceRows); + if (corpList.isEmpty()) { + log.info("未解析到有效的人资企业部门数据"); + return "同步完成:未解析到有效的人资企业部门数据"; + } + + humanResourceCorpRepository.replaceAll(corpList); + String message = String.format("同步完成:拉取 %d 条原始部门数据,落库 %d 条本地记录", sourceRows.size(), corpList.size()); + log.info(message); + log.info("============结束同步人资企业部门本地数据=========="); + return message; + } + + private JSONArray pullAllCorpDepartmentRows(String param) { + if (useTestCorpDepartmentData(param)) { + log.info("人资企业部门同步使用测试JSON数据,param={}", param); + return getTestCorpDepartmentRows(); + } + + JSONArray allRows = new JSONArray(); + int pageNum = 1; + while (true) { + JSONArray pageRows = pullCorpDepartmentPage(pageNum); + if (pageRows.isEmpty()) { + break; + } + allRows.addAll(pageRows); + log.info("人资企业部门接口第 {} 页返回 {} 条数据", pageNum, pageRows.size()); + if (pageRows.size() < HUMAN_RESOURCE_DEPT_PAGE_SIZE) { + break; + } + pageNum++; + } + return allRows; + } + + private boolean useTestCorpDepartmentData(String param) { + return param != null && HUMAN_RESOURCE_DEPT_TEST_FLAG.equalsIgnoreCase(param.trim()); + } + + private JSONArray pullCorpDepartmentPage(int pageNum) { + SignUtil signUtil = buildSignUtil(pageNum); + JSONObject requestBody = buildCorpDepartmentRequest(signUtil); + log.info("开始调用人资企业部门接口,第 {} 页", pageNum); + String body = HttpRequest.post(HUMAN_RESOURCE_DEPT_URL) + .timeout(30000) + .header("Content-Type", "application/json") + .body(requestBody.toString()) + .execute() + .body(); + if (StringUtils.isEmpty(body)) { + log.warn("人资企业部门接口第 {} 页返回空响应", pageNum); + return new JSONArray(); + } + + JSONObject returnJson = JSONUtil.parseObj(body, jsonConfig); + Object bo = returnJson.get("bo"); + if (bo == null) { + log.warn("人资企业部门接口第 {} 页未返回 bo 节点,响应:{}", pageNum, body); + return new JSONArray(); + } + + JSONObject boJson = JSONUtil.parseObj(bo); + Object rows = boJson.get("rows"); + if (rows == null) { + return new JSONArray(); + } + return JSONUtil.parseArray(rows); + } + + private SignUtil buildSignUtil(int pageNum) { + SignUtil signUtil = new SignUtil(); + signUtil.setAppKey(getAppKey()); + signUtil.setAppSecret(getAppSecret()); + signUtil.setEnvType("online"); + signUtil.setPageNum(pageNum); + signUtil.setPageSize(HUMAN_RESOURCE_DEPT_PAGE_SIZE); + signUtil.setNonce(RandomStringUtils.randomAlphanumeric(5)); + signUtil.setTimeStamp(System.currentTimeMillis()); + signUtil.setParamMap(new HashMap<>()); + signUtil.setOrderByList(new ArrayList<>()); + signUtil.buildSignatureParam(); + return signUtil; + } + + private JSONObject buildCorpDepartmentRequest(SignUtil signUtil) { + String signature = SignUtil.getSignature(signUtil.getSignatureParam()); + return new JSONObject() + .set("appKey", getAppKey()) + .set("timeStamp", signUtil.getTimeStamp()) + .set("nonce", signUtil.getNonce()) + .set("signature", signature) + .set("signatureParam", null) + .set("apiid", HUMAN_RESOURCE_DEPT_API_ID) + .set("pageNum", signUtil.getPageNum()) + .set("pageSize", signUtil.getPageSize()) + .set("paramMap", signUtil.getParamMap()) + .set("orderByList", signUtil.getOrderByList()) + .set("hasTotal", "Y") + .set("envType", signUtil.getEnvType()) + .set("empNo", "10262589") + .set("invokeLogId", null) + .set("versionType", "published") + .set("sdkType", "JAVA") + .set("sdkVersion", "1.0.13") + .set("accessIp", null); + } + + private List buildHumanResourceCorpList(JSONArray sourceRows) { + List corpList = new ArrayList<>(); + Set deptCodeSet = new LinkedHashSet<>(); + collectHumanResourceCorp(sourceRows, corpList, deptCodeSet); + return corpList; + } + + private void collectHumanResourceCorp(JSONArray jsonArray, List corpList, Set deptCodeSet) { + for (Object item : jsonArray) { + collectHumanResourceCorp(JSONUtil.parseObj(item), corpList, deptCodeSet); + } + } + + private void collectHumanResourceCorp(JSONObject jsonObject, List corpList, Set deptCodeSet) { + if (jsonObject == null) { + return; + } + + String deptCode = jsonObject.getStr("dept_code"); + if (StringUtils.isNotEmpty(deptCode) && deptCodeSet.add(deptCode)) { + corpList.add(buildHumanResourceCorpDO(jsonObject)); + } + + JSONArray children = jsonObject.getJSONArray("children"); + if (children == null || children.isEmpty()) { + return; + } + collectHumanResourceCorp(children, corpList, deptCodeSet); + } + + private HumanResourceCorpDO buildHumanResourceCorpDO(JSONObject jsonObject) { + HumanResourceCorpDO corpDO = new HumanResourceCorpDO(); + corpDO.setHumanResourceCorpId(Tools.get32UUID()); + corpDO.setCorpinfoId(resolveCorpinfoId(jsonObject)); + corpDO.setCorporationCode(jsonObject.getStr("corporation_code")); + corpDO.setCorporationName(jsonObject.getStr("corporation_name")); + corpDO.setDeptName(jsonObject.getStr("dept_name")); + corpDO.setDeptCode(jsonObject.getStr("dept_code")); + corpDO.setDeptLevel(jsonObject.getStr("dept_level")); + corpDO.setDeptCodePath(jsonObject.getStr("dept_code_path")); + corpDO.setSuperiorOrganizationCode(jsonObject.getStr("superior_organization_code")); + return corpDO; + } + + private String resolveCorpinfoId(JSONObject jsonObject) { + String corporationCode = jsonObject.getStr("corporation_code"); + if (StringUtils.isNotEmpty(corporationCode)) { + return corporationCode; + } + return jsonObject.getStr("dept_code"); + } + + private JSONArray getTestCorpDepartmentRows() { + return JSONUtil.parseArray("[\n" + + " {\n" + + " \"corporation_code\": \"7f304de353c358egcfg267f023db8f25\",\n" + + " \"corporation_name\": \"河港集团\",\n" + + " \"dept_name\": \"子公司\",\n" + + " \"dept_code\": \"28bd895f27934aa7a9acf665d73ead8d\",\n" + + " \"dept_level\": \"1\",\n" + + " \"dept_code_path\": \"7f304de353c358egcfg267f023db8f25-28bd895f27934aa7a9acf665d73ead8d\",\n" + + " \"superior_organization_code\": \"7f304de353c358egcfg267f023db8f25\",\n" + + " \"children\": [\n" + + " {\n" + + " \"corporation_code\": \"fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"corporation_name\": \"曹妃甸矿石储运\",\n" + + " \"dept_name\": \"曹妃甸矿石储运\",\n" + + " \"dept_code\": \"fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"dept_level\": \"2\",\n" + + " \"dept_code_path\": \"7f304de353c358egcfg267f023db8f25-28bd895f27934aa7a9acf665d73ead8d-fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"superior_organization_code\": \"28bd895f27934aa7a9acf665d73ead8d\",\n" + + " \"children\": [\n" + + " {\n" + + " \"corporation_code\": \"fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"corporation_name\": \"曹妃甸矿石储运\",\n" + + " \"dept_name\": \"机关\",\n" + + " \"dept_code\": \"f96c45159b994489adf79a4ab92ac5cc\",\n" + + " \"dept_level\": \"3\",\n" + + " \"dept_code_path\": \"7f304de353c358egcfg267f023db8f25-28bd895f27934aa7a9acf665d73ead8d-fa91e56b6d0a47ee8e9d42a75cd97ed4-f96c45159b994489adf79a4ab92ac5cc\",\n" + + " \"superior_organization_code\": \"fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"children\": [\n" + + " {\n" + + " \"corporation_code\": \"fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"corporation_name\": \"曹妃甸矿石储运\",\n" + + " \"dept_name\": \"综合办公室\",\n" + + " \"dept_code\": \"9ba0f0faada74c18afb81d38e9fb6d24\",\n" + + " \"dept_level\": \"4\",\n" + + " \"dept_code_path\": \"7f304de353c358egcfg267f023db8f25-28bd895f27934aa7a9acf665d73ead8d-fa91e56b6d0a47ee8e9d42a75cd97ed4-f96c45159b994489adf79a4ab92ac5cc-9ba0f0faada74c18afb81d38e9fb6d24\",\n" + + " \"superior_organization_code\": \"f96c45159b994489adf79a4ab92ac5cc\",\n" + + " \"children\": []\n" + + " },\n" + + " {\n" + + " \"corporation_code\": \"fa91e56b6d0a47ee8e9d42a75cd97ed4\",\n" + + " \"corporation_name\": \"曹妃甸矿石储运\",\n" + + " \"dept_name\": \"财务部\",\n" + + " \"dept_code\": \"3ad24f7af17e4b149b693641e5d29ed3\",\n" + + " \"dept_level\": \"4\",\n" + + " \"dept_code_path\": \"7f304de353c358egcfg267f023db8f25-28bd895f27934aa7a9acf665d73ead8d-fa91e56b6d0a47ee8e9d42a75cd97ed4-f96c45159b994489adf79a4ab92ac5cc-3ad24f7af17e4b149b693641e5d29ed3\",\n" + + " \"superior_organization_code\": \"f96c45159b994489adf79a4ab92ac5cc\",\n" + + " \"children\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"corporation_code\": \"06414841dcf64b5e82673f561bef2b63\",\n" + + " \"corporation_name\": \"东方石油\",\n" + + " \"dept_name\": \"东方石油\",\n" + + " \"dept_code\": \"06414841dcf64b5e82673f561bef2b63\",\n" + + " \"dept_level\": \"2\",\n" + + " \"dept_code_path\": \"7f304de353c358egcfg267f023db8f25-28bd895f27934aa7a9acf665d73ead8d-06414841dcf64b5e82673f561bef2b63\",\n" + + " \"superior_organization_code\": \"28bd895f27934aa7a9acf665d73ead8d\",\n" + + " \"children\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "]"); + } + + private String getAppKey() { + return humanResourcesConfig.getAppKey(); + } + + private String getAppSecret() { + return humanResourcesConfig.getAppSecret(); + } } diff --git a/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpAddExe.java b/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpAddExe.java new file mode 100644 index 0000000..b0bc761 --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpAddExe.java @@ -0,0 +1,40 @@ +package com.zcloud.human.user.command; + +import com.alibaba.cola.exception.BizException; +import com.zcloud.human.user.domain.gateway.HumanResourceCorpGateway; +import com.zcloud.human.user.domain.model.HumanResourceCorpE; +import com.zcloud.human.user.dto.HumanResourceCorpAddCmd; +import lombok.AllArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + + +/** + * web-app + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Component +@AllArgsConstructor +public class HumanResourceCorpAddExe { + private final HumanResourceCorpGateway humanResourceCorpGateway; + + @Transactional(rollbackFor = Exception.class) + public boolean execute(HumanResourceCorpAddCmd cmd) { + HumanResourceCorpE humanResourceCorpE = new HumanResourceCorpE(); + BeanUtils.copyProperties(cmd, humanResourceCorpE); + boolean res = false; + try { + res = humanResourceCorpGateway.add(humanResourceCorpE); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (!res) { + throw new BizException("保存失败"); + } + return true; + } +} + diff --git a/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpRemoveExe.java b/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpRemoveExe.java new file mode 100644 index 0000000..ac74e3f --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpRemoveExe.java @@ -0,0 +1,39 @@ +package com.zcloud.human.user.command; + +import com.alibaba.cola.exception.BizException; +import com.zcloud.human.user.domain.gateway.HumanResourceCorpGateway; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + + +/** + * web-app + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Component +@AllArgsConstructor +public class HumanResourceCorpRemoveExe { + private final HumanResourceCorpGateway humanResourceCorpGateway; + + @Transactional(rollbackFor = Exception.class) + public boolean execute(Long id) { + boolean res = humanResourceCorpGateway.deletedHumanResourceCorpById(id); + if (!res) { + throw new BizException("删除失败"); + } + return true; + } + + @Transactional(rollbackFor = Exception.class) + public boolean execute(Long[] ids) { + boolean res = humanResourceCorpGateway.deletedHumanResourceCorpByIds(ids); + if (!res) { + throw new BizException("删除失败"); + } + return true; + } +} + diff --git a/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpUpdateExe.java b/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpUpdateExe.java new file mode 100644 index 0000000..ce50e99 --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/command/HumanResourceCorpUpdateExe.java @@ -0,0 +1,34 @@ +package com.zcloud.human.user.command; + +import com.alibaba.cola.exception.BizException; +import com.zcloud.human.user.domain.gateway.HumanResourceCorpGateway; +import com.zcloud.human.user.domain.model.HumanResourceCorpE; +import com.zcloud.human.user.dto.HumanResourceCorpUpdateCmd; +import lombok.AllArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + + +/** + * web-app + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Component +@AllArgsConstructor +public class HumanResourceCorpUpdateExe { + private final HumanResourceCorpGateway humanResourceCorpGateway; + + @Transactional(rollbackFor = Exception.class) + public void execute(HumanResourceCorpUpdateCmd humanResourceCorpUpdateCmd) { + HumanResourceCorpE humanResourceCorpE = new HumanResourceCorpE(); + BeanUtils.copyProperties(humanResourceCorpUpdateCmd, humanResourceCorpE); + boolean res = humanResourceCorpGateway.update(humanResourceCorpE); + if (!res) { + throw new BizException("修改失败"); + } + } +} + diff --git a/web-app/src/main/java/com/zcloud/human/user/command/HumanUserSyncExe.java b/web-app/src/main/java/com/zcloud/human/user/command/HumanUserSyncExe.java index bd2ed95..0f21ab7 100644 --- a/web-app/src/main/java/com/zcloud/human/user/command/HumanUserSyncExe.java +++ b/web-app/src/main/java/com/zcloud/human/user/command/HumanUserSyncExe.java @@ -2,38 +2,49 @@ package com.zcloud.human.user.command; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONConfig; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.alibaba.cloud.commons.lang.StringUtils; import com.alibaba.cola.dto.MultiResponse; +import com.alibaba.cola.dto.PageResponse; import com.alibaba.cola.dto.SingleResponse; +import com.alibaba.fastjson.JSON; import com.jjb.saas.system.client.role.facade.RoleFacade; import com.jjb.saas.system.client.role.response.RoleCO; import com.jjb.saas.system.client.user.facade.UserFacade; import com.jjb.saas.system.client.user.request.RoleDeptAddCmd; -import com.jjb.saas.system.client.user.request.UserAddCmd; -import com.jjb.saas.system.client.user.response.UserCO; +import com.jjb.saas.system.client.user.response.UserDetailCO; +import com.jjb.saas.system.client.user.response.UserRoleDeptCO; import com.zcloud.gbscommon.zcloudcorp.face.ZcloudCorpFacade; import com.zcloud.gbscommon.zcloudcorp.response.ZcloudCorpInfoCO; import com.zcloud.gbscommon.zclouddepartment.face.ZcloudDepartmentFacade; +import com.zcloud.gbscommon.zclouddepartment.request.ZcloudDepartmentPageQry; import com.zcloud.gbscommon.zclouddepartment.response.ZcloudDepartmentInfoCo; import com.zcloud.gbscommon.zclouduser.facade.ZcloudUserFacade; import com.zcloud.gbscommon.zclouduser.request.ZcloudUserAddCmd; +import com.zcloud.gbscommon.zclouduser.request.ZcloudUserInfoQry; +import com.zcloud.gbscommon.zclouduser.request.ZcloudUserUpdateCmd; +import com.zcloud.gbscommon.zclouduser.response.ZcloudUserCo; +import com.zcloud.human.user.config.HumanResourcesConfig; +import com.zcloud.human.user.domain.enums.UserEmploymentFlagEnum; import com.zcloud.human.user.domain.gateway.HumanUserGateway; import com.zcloud.human.user.domain.gateway.HumanUserRecordGateway; import com.zcloud.human.user.domain.model.HumanUserE; import com.zcloud.human.user.domain.model.HumanUserRecordE; +import com.zcloud.human.user.domain.utils.SignUtil; +import com.zcloud.human.user.persistence.dataobject.HumanUserDO; +import com.zcloud.human.user.persistence.repository.HumanUserRepository; +import jodd.util.Base64; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 人资人员数据同步执行器 @@ -51,7 +62,8 @@ public class HumanUserSyncExe { /** * 本系统公司名称,用于查询本系统企业ID和部门。 */ - private static final String SYSTEM_CORP_NAME = "秦皇岛港股份有限公司"; +// private static final String SYSTEM_CORP_NAME = "秦皇岛港股份有限公司"; + private static final String SYSTEM_CORP_NAME = "卓云企业"; /** * 第三方数据中要查找的目标企业名称,用于过滤人员数据。 @@ -63,8 +75,36 @@ public class HumanUserSyncExe { */ private static final String USER_INFO_URL = "http://192.168.10.56:8090"; - @DubboReference - private UserFacade userFacade; + /** + * 人资人员接口地址。 + */ + private static final String HUMAN_RESOURCE_USER_URL = "https://192.168.195.249:28001/idatashare/api/remoteCall/v1/1057412621613957120"; + + /** + * 人资人员接口标识。 + */ + private static final String HUMAN_RESOURCE_USER_API_ID = "1057412621613957120"; + + /** + * 人资人员接口分页大小。 + */ + private static final int HUMAN_RESOURCE_USER_PAGE_SIZE = 50; + + /** + * 人资人员测试数据标记。 + */ + private static final String HUMAN_RESOURCE_USER_TEST_FLAG = "test"; + + /** + * 人资人员变更接口地址。 + */ + private static final String HUMAN_RESOURCE_USER_CHANGE_URL = "https://192.168.195.249:28001/idatashare/api/remoteCall/v1/1057031732824408064"; + + /** + * 人资人员变更接口标识。 + */ + private static final String HUMAN_RESOURCE_USER_CHANGE_API_ID = "1057031732824408064"; + @DubboReference private RoleFacade roleFacade; @@ -77,9 +117,16 @@ public class HumanUserSyncExe { @DubboReference private ZcloudCorpFacade zcloudCorpFacade; + @DubboReference + private ZcloudDepartmentFacade zcloudDepartmentFacade; private final HumanUserGateway humanUserGateway; + private final HumanUserRepository humanUserRepository; + private final HumanUserRecordGateway humanUserRecordGateway; + private final HumanResourcesConfig humanResourcesConfig; + + private final JSONConfig jsonConfig = JSONConfig.create().setIgnoreNullValue(true); /** * 执行同步 @@ -91,7 +138,7 @@ public class HumanUserSyncExe { public String execute(String param) { log.info("============获取人资全量人员信息开始=========="); - Long corpId = getTargetCorpId(); + Long corpId = getTargetCorpId(SYSTEM_CORP_NAME); if (corpId == null) { log.warn("本系统不存在公司:{},终止同步", SYSTEM_CORP_NAME); return "同步终止:本系统不存在公司" + SYSTEM_CORP_NAME; @@ -104,7 +151,7 @@ public class HumanUserSyncExe { } String result = ""; - if("manual".equals(param)){ + if("test".equals(param)){ result = getSimulationData(); }else{ result = getUserInfo(); @@ -150,20 +197,20 @@ public class HumanUserSyncExe { // TODO 岗位留白 if (StringUtils.isEmpty(employeeName) || StringUtils.isEmpty(corporationName) || StringUtils.isEmpty(deptName)) { - log.warn("跳过无效人员数据:公司、部门或姓名为空,原始数据:{}", jsonObject); + log.info("跳过无效人员数据:公司、部门或姓名为空,原始数据:{}", jsonObject); skipCount++; continue; } - if (!TARGET_CORP_NAME.equals(corporationName)) { - log.debug("跳过非目标公司人员:{},公司:{}", employeeName, corporationName); + if (!SYSTEM_CORP_NAME.equals(corporationName)) { + log.info("跳过非目标公司人员:{},公司:{}", employeeName, corporationName); skipCount++; continue; } Long deptId = deptNameIdMap.get(deptName); if (deptId == null) { - log.warn("跳过人员:{},本系统公司:{} 下不存在部门:{}", employeeName, SYSTEM_CORP_NAME, deptName); + log.info("跳过人员:{},本系统公司:{} 下不存在部门:{}", employeeName, SYSTEM_CORP_NAME, deptName); skipCount++; continue; } @@ -194,13 +241,15 @@ public class HumanUserSyncExe { continue; } // 步骤3:判断统一用户管理(user表)是否存在该人员 - Long existingUserId = isUserExists(deptId, employeeName); +// Long existingUserId = isUserExists(deptId, Base64.encodeToString(idCardNumber), null); + Long existingUserId = null; + log.info("统一用户管理已存在人员:{},用户ID:{}", employeeName, existingUserId); if (existingUserId != null) { // 人员不存在于human_user表,保存新人资用户 HumanUserE newHumanUser = buildHumanUser(jsonObject); newHumanUser.setUserId(existingUserId); humanUserGateway.add(newHumanUser); - log.debug("保存人资用户表:{},身份证号:{}", employeeName, idCardNumber); + log.info("保存人资用户表:{},身份证号:{}", employeeName, idCardNumber); // 统一用户已存在,保存变动记录(关联已存在的用户ID) log.info("统一用户管理已存在人员:{},用户ID:{},保存变动记录", employeeName, existingUserId); HumanUserRecordE record = buildHumanUserRecord(jsonObject, existingUserId); @@ -214,7 +263,7 @@ public class HumanUserSyncExe { HumanUserE newHumanUser = buildHumanUser(jsonObject); newHumanUser.setUserId(newUserId); humanUserGateway.add(newHumanUser); - log.debug("新增统一用户管理账号成功:{},身份证号:{},用户ID:{}", employeeName, idCardNumber, newUserId); + log.info("新增统一用户管理账号成功:{},身份证号:{},用户ID:{}", employeeName, idCardNumber, newUserId); // 保存变动记录(关联新创建的用户ID) HumanUserRecordE record = buildHumanUserRecord(jsonObject, newUserId); humanUserRecordGateway.add(record); @@ -284,13 +333,13 @@ public class HumanUserSyncExe { /** * 获取公司ID。 */ - private Long getTargetCorpId() { + private Long getTargetCorpId(String corpName) { MultiResponse response = zcloudCorpFacade.getCorpList(); if (response == null || !response.isSuccess() || response.getData() == null) { return null; } return response.getData().stream() - .filter(corp -> SYSTEM_CORP_NAME.equals(corp.getCorpName())) + .filter(corp -> corpName.equals(corp.getCorpName())) .map(ZcloudCorpInfoCO::getId) .findFirst() .orElse(null); @@ -303,14 +352,18 @@ public class HumanUserSyncExe { * @return 部门名称与ID的映射 */ private Map getTargetCorpDeptNameIdMap(Long corpId) { - MultiResponse response = deptFacade.getDeptList(); - if (response == null || !response.isSuccess() || response.getData() == null) { + ZcloudDepartmentPageQry qry = new ZcloudDepartmentPageQry(); + qry.setEqCorpInfoId(corpId); + qry.setEqParentId(corpId); + qry.setPageSize(10000); + PageResponse zcloudDepartmentInfoCoPageResponse = zcloudDepartmentFacade.pageByParentId(qry); + if (zcloudDepartmentInfoCoPageResponse == null || !zcloudDepartmentInfoCoPageResponse.isSuccess() || zcloudDepartmentInfoCoPageResponse.getData() == null) { log.warn("获取部门列表失败"); return Collections.emptyMap(); } Map result = new HashMap<>(); - for (ZcloudDepartmentInfoCo dept : response.getData()) { + for (ZcloudDepartmentInfoCo dept : zcloudDepartmentInfoCoPageResponse.getData()) { if (corpId.equals(dept.getCorpinfoId())) { result.put(dept.getName(), dept.getId()); log.debug("找到企业[{}]下的部门:{} (ID: {})", corpId, dept.getName(), dept.getId()); @@ -324,18 +377,20 @@ public class HumanUserSyncExe { /** * 根据部门ID和人员姓名判断人员是否已经存在,并返回人员ID。 * - * @param deptId 部门ID - * @param employeeName 人员姓名 + * @param phoneNumber * @return 人员ID,如果不存在返回null */ - private Long isUserExists(Long deptId, String employeeName) { - MultiResponse response = userFacade.listByOrgId(deptId); + private Long isUserExists(String idCardNumber, String phoneNumber) { + ZcloudUserInfoQry qry = new ZcloudUserInfoQry(); + qry.setUserIdCard(idCardNumber); + qry.setPhone(phoneNumber); + MultiResponse response = zcloudUserFacade.listUserByInfo(qry); if (response == null || !response.isSuccess() || response.getData() == null) { return null; } return response.getData().stream() - .filter(user -> employeeName.equals(user.getName())) - .map(UserCO::getId) + .filter(user -> idCardNumber.equals(user.getUserIdCard())) + .map(ZcloudUserCo::getId) .findFirst() .orElse(null); } @@ -423,6 +478,7 @@ public class HumanUserSyncExe { humanUserE.initFromJson(jsonObject); humanUserE.setCreateTime(LocalDateTime.now()); humanUserE.setUpdateTime(LocalDateTime.now()); + humanUserE.setDeleteEnum("FALSE"); return humanUserE; } @@ -437,6 +493,8 @@ public class HumanUserSyncExe { HumanUserRecordE recordE = new HumanUserRecordE(); recordE.initFromJson(jsonObject); recordE.setUserId(userId); + recordE.setCreateTime(LocalDateTime.now()); + recordE.setUpdateTime(LocalDateTime.now()); return recordE; } @@ -484,4 +542,557 @@ public class HumanUserSyncExe { "\t}\n" + "]"; } + + @Transactional(rollbackFor = Exception.class) + public String CorpUserSync(String param) { + log.info("============开始同步人资人员本地数据=========="); + JSONArray sourceRows = pullAllCorpUserRows(param); + if (sourceRows.isEmpty()) { + log.info("未获取到人资人员数据"); + return "同步完成:未获取到人资人员数据"; + } + + int[] saveResult = saveCorpUserRows(sourceRows); + String message = String.format("同步完成:拉取 %d 条原始人员数据,新增 %d 条,更新 %d 条,跳过 %d 条", + sourceRows.size(), saveResult[0], saveResult[1], saveResult[2]); + log.info(message); + log.info("============结束同步人资人员本地数据=========="); + return message; + } + + private JSONArray pullAllCorpUserRows(String param) { + if (useTestCorpUserData(param)) { + log.info("人资人员同步使用测试JSON数据,param={}", param); + return getTestCorpUserRows(); + } + + JSONArray allRows = new JSONArray(); + int pageNum = 1; + while (true) { + JSONArray pageRows = pullCorpUserPage(pageNum); + if (pageRows.isEmpty()) { + break; + } + allRows.addAll(pageRows); + log.info("人资人员接口第 {} 页返回 {} 条数据", pageNum, pageRows.size()); + if (pageRows.size() < HUMAN_RESOURCE_USER_PAGE_SIZE) { + break; + } + pageNum++; + } + return allRows; + } + + private boolean useTestCorpUserData(String param) { + return param != null && HUMAN_RESOURCE_USER_TEST_FLAG.equalsIgnoreCase(param.trim()); + } + + private JSONArray pullCorpUserPage(int pageNum) { + SignUtil signUtil = buildUserSignUtil(pageNum); + JSONObject requestBody = buildCorpUserRequest(signUtil); + log.info("开始调用人资人员接口,第 {} 页", pageNum); + String body = HttpRequest.post(HUMAN_RESOURCE_USER_URL) + .timeout(30000) + .header("Content-Type", "application/json") + .body(requestBody.toString()) + .execute() + .body(); + if (StringUtils.isEmpty(body)) { + log.warn("人资人员接口第 {} 页返回空响应", pageNum); + return new JSONArray(); + } + + JSONObject returnJson = JSONUtil.parseObj(body, jsonConfig); + String code = returnJson.getStr("code"); + if (StringUtils.isNotEmpty(code) && !"0000".equals(code)) { + log.warn("人资人员接口第 {} 页返回失败,code={},响应={}", pageNum, code, body); + return new JSONArray(); + } + + Object bo = returnJson.get("bo"); + if (bo == null) { + log.warn("人资人员接口第 {} 页未返回 bo 节点,响应:{}", pageNum, body); + return new JSONArray(); + } + + JSONObject boJson = JSONUtil.parseObj(bo); + Object rows = boJson.get("rows"); + if (rows == null) { + return new JSONArray(); + } + return JSONUtil.parseArray(rows); + } + + private SignUtil buildUserSignUtil(int pageNum) { + SignUtil signUtil = new SignUtil(); + signUtil.setAppKey(getAppKey()); + signUtil.setAppSecret(getAppSecret()); + signUtil.setEnvType("online"); + signUtil.setPageNum(pageNum); + signUtil.setPageSize(HUMAN_RESOURCE_USER_PAGE_SIZE); + signUtil.setNonce(RandomStringUtils.randomAlphanumeric(5)); + signUtil.setTimeStamp(System.currentTimeMillis()); + signUtil.setParamMap(new HashMap<>()); + List orderByList = new ArrayList<>(); + orderByList.add("id_card_number,DESC"); + signUtil.setOrderByList(orderByList); + signUtil.buildSignatureParam(); + return signUtil; + } + + private JSONObject buildCorpUserRequest(SignUtil signUtil) { + String signature = SignUtil.getSignature(signUtil.getSignatureParam()); + return new JSONObject() + .set("appKey", getAppKey()) + .set("timeStamp", signUtil.getTimeStamp()) + .set("nonce", signUtil.getNonce()) + .set("signature", signature) + .set("signatureParam", null) + .set("apiid", HUMAN_RESOURCE_USER_API_ID) + .set("pageNum", signUtil.getPageNum()) + .set("pageSize", signUtil.getPageSize()) + .set("paramMap", signUtil.getParamMap()) + .set("orderByList", signUtil.getOrderByList()) + .set("hasTotal", "Y") + .set("envType", signUtil.getEnvType()) + .set("empNo", "10262589") + .set("versionType", "published") + .set("invokeLogId", null) + .set("sdkType", "JAVA") + .set("sdkVersion", "1.0.13") + .set("accessIp", null); + } + + private int[] saveCorpUserRows(JSONArray sourceRows) { + int addCount = 0; + int updateCount = 0; + int skipCount = 0; + for (Object item : sourceRows) { + JSONObject jsonObject = JSONUtil.parseObj(item); + String employeeName = jsonObject.getStr("employee_name"); + String corporationName = jsonObject.getStr("corporation_name"); + String deptName = jsonObject.getStr("dept_name"); + String idCardNumber = jsonObject.getStr("id_card_number"); + String phoneNumber = jsonObject.getStr("phone_number"); + + if (StringUtils.isEmpty(employeeName) || StringUtils.isEmpty(corporationName) + || StringUtils.isEmpty(deptName) || StringUtils.isEmpty(idCardNumber)) { + log.warn("跳过无效人资人员数据:姓名、企业、部门或身份证号为空,原始数据:{}", jsonObject); + skipCount++; + continue; + } + + HumanUserE existingHumanUser = humanUserGateway.getByIdCardNumber(idCardNumber); + if (existingHumanUser == null) { +// Long existingUserId = isUserExists( Base64.encodeToString(idCardNumber),phoneNumber); + HumanUserE newHumanUser = buildHumanUser(jsonObject); +// newHumanUser.setUserId(existingUserId); + humanUserGateway.add(newHumanUser); + addCount++; + continue; + } + + mergeHumanUser(existingHumanUser, jsonObject); + humanUserGateway.update(existingHumanUser); + updateCount++; + } + return new int[]{addCount, updateCount, skipCount}; + } + + private void mergeHumanUser(HumanUserE existingHumanUser, JSONObject jsonObject) { + HumanUserE latestHumanUser = buildHumanUser(jsonObject); + latestHumanUser.setId(existingHumanUser.getId()); + latestHumanUser.setUserId(existingHumanUser.getUserId()); + latestHumanUser.setHumanUserId(existingHumanUser.getHumanUserId()); + latestHumanUser.setIsConfirm(existingHumanUser.getIsConfirm()); + latestHumanUser.setConfirmStatus(existingHumanUser.getConfirmStatus()); + latestHumanUser.setCreateId(existingHumanUser.getCreateId()); + latestHumanUser.setCreateName(existingHumanUser.getCreateName()); + latestHumanUser.setCreateTime(existingHumanUser.getCreateTime()); + latestHumanUser.setUpdateId(existingHumanUser.getUpdateId()); + latestHumanUser.setUpdateName(existingHumanUser.getUpdateName()); + latestHumanUser.setVersion(existingHumanUser.getVersion()); + latestHumanUser.setDeleteEnum(existingHumanUser.getDeleteEnum()); + latestHumanUser.setTenantId(existingHumanUser.getTenantId()); + latestHumanUser.setOrgId(existingHumanUser.getOrgId()); + latestHumanUser.setEnv(existingHumanUser.getEnv()); + latestHumanUser.setRemarks(existingHumanUser.getRemarks()); + latestHumanUser.setUpdateTime(LocalDateTime.now()); + + existingHumanUser.setEmployeeName(latestHumanUser.getEmployeeName()); + existingHumanUser.setEmployeeGender(latestHumanUser.getEmployeeGender()); + existingHumanUser.setEmployeeAge(latestHumanUser.getEmployeeAge()); + existingHumanUser.setEntryTime(latestHumanUser.getEntryTime()); + existingHumanUser.setEmployeeStatus(latestHumanUser.getEmployeeStatus()); + existingHumanUser.setJobName(latestHumanUser.getJobName()); + existingHumanUser.setJobLevel(latestHumanUser.getJobLevel()); + existingHumanUser.setDeptName(latestHumanUser.getDeptName()); + existingHumanUser.setDeptCode(latestHumanUser.getDeptCode()); + existingHumanUser.setPositionName(latestHumanUser.getPositionName()); + existingHumanUser.setPhoneNumber(latestHumanUser.getPhoneNumber()); + existingHumanUser.setIdCardNumber(latestHumanUser.getIdCardNumber()); + existingHumanUser.setEmployeeImagesCode(latestHumanUser.getEmployeeImagesCode()); + existingHumanUser.setEmployeeImages(latestHumanUser.getEmployeeImages()); + existingHumanUser.setCorporationCode(latestHumanUser.getCorporationCode()); + existingHumanUser.setCorporationName(latestHumanUser.getCorporationName()); + existingHumanUser.setUpdateTime(latestHumanUser.getUpdateTime()); + } + + private JSONArray getTestCorpUserRows() { + return JSONUtil.parseArray("[\n" + + " {\n" + + " \"dept_code\": \"132588b1871341acb51c5638a735dbe7\",\n" + + " \"corporation_code\": \"28f4eed3300b431c958bea4d93e49434\",\n" + + " \"entry_time\": \"2011-07-05 00:00:00\",\n" + + " \"employee_gender\": \"男\",\n" + + " \"position_name\": \"\t测试组长\",\n" + + " \"dept_name\": \"测试部\",\n" + + " \"employee_images_code\": \"a101bf6d844b43b9b85aeba419ff0458\",\n" + + " \"employee_name\": \"马兆华\",\n" + + " \"corporation_name\": \"卓云企业\",\n" + + " \"employee_images\": \"\",\n" + + " \"employee_age\": 45,\n" + + " \"job_name\": \"工艺技术员\",\n" + + " \"phone_number\": \"18700000009\",\n" + + " \"employee_status\": \"在职\",\n" + + " \"job_level\": \"M8\",\n" + + " \"id_card_number\": \"654201197901154618\"\n" + + " }\n" + + "]"); + } + + @Transactional(rollbackFor = Exception.class) + public String CorpUserChangeSync(String param) { + log.info("开始同步人资人员变更数据"); + JSONArray sourceRows = pullAllCorpUserChangeRows(param); + if (sourceRows.isEmpty()) { + log.info("未获取到人资人员变更数据"); + return "同步完成:未获取到人资人员变更数据"; + } + log.info("拉取到 {} 条人员变更数据", sourceRows.size()); + + int[] syncResult = saveCorpUserChangeRows(sourceRows); + String message = String.format( + "同步完成:拉取 %d 条人员变更数据,新增变更记录 %d 条,更新本地人员 %d 条,更新统一用户 %d 条,跳过 %d 条,失败 %d 条", + sourceRows.size(), syncResult[0], syncResult[1], syncResult[2], syncResult[3], syncResult[4]); + log.info(message); + log.info("结束同步人资人员变更数据"); + return message; + } + + private JSONArray pullAllCorpUserChangeRows(String param) { + if (useTestCorpUserData(param)) { + log.info("人资人员变更同步使用测试JSON数据,param={}", param); + return getTestCorpUserChangeRows(); + } + return pullCorpUserChangeRows(); + } + + private JSONArray pullCorpUserChangeRows() { + SignUtil signUtil = buildUserChangeSignUtil(); + JSONObject requestBody = buildCorpUserChangeRequest(signUtil); + log.info("开始调用人资人员变更接口"); + String body = HttpRequest.post(HUMAN_RESOURCE_USER_CHANGE_URL) + .timeout(30000) + .header("Content-Type", "application/json") + .body(requestBody.toString()) + .execute() + .body(); + if (StringUtils.isEmpty(body)) { + log.warn("人资人员变更接口返回空响应"); + return new JSONArray(); + } + return extractRemoteRows(body, "人资人员变更接口"); + } + + private SignUtil buildUserChangeSignUtil() { + SignUtil signUtil = new SignUtil(); + signUtil.setAppKey(getAppKey()); + signUtil.setAppSecret(getAppSecret()); + signUtil.setEnvType("online"); + signUtil.setNonce(RandomStringUtils.randomAlphanumeric(5)); + signUtil.setTimeStamp(System.currentTimeMillis()); + signUtil.setParamMap(new HashMap<>()); + signUtil.setOrderByList(new ArrayList<>()); + signUtil.buildSignatureParam(); + return signUtil; + } + + private JSONObject buildCorpUserChangeRequest(SignUtil signUtil) { + String signature = SignUtil.getSignature(signUtil.getSignatureParam()); + return new JSONObject() + .set("appKey", getAppKey()) + .set("timeStamp", signUtil.getTimeStamp()) + .set("nonce", signUtil.getNonce()) + .set("signature", signature) + .set("signatureParam", null) + .set("apiid", HUMAN_RESOURCE_USER_CHANGE_API_ID) + .set("paramMap", signUtil.getParamMap()) + .set("orderByList", signUtil.getOrderByList()) + .set("envType", signUtil.getEnvType()) + .set("empNo", "10262589") + .set("invokeLogId", null) + .set("versionType", "published") + .set("sdkType", "JAVA") + .set("sdkVersion", "1.0.13") + .set("accessIp", null); + } + + private JSONArray extractRemoteRows(String body, String scene) { + JSONObject returnJson = JSONUtil.parseObj(body, jsonConfig); + String code = returnJson.getStr("code"); + if (StringUtils.isNotEmpty(code) && !"0000".equals(code)) { + log.warn("{}返回失败,code={},响应={}", scene, code, body); + return new JSONArray(); + } + + JSONArray rootRows = getArray(returnJson, "rows", "list", "records"); + if (rootRows != null) { + return rootRows; + } + + Object bo = returnJson.get("bo"); + if (bo != null) { + if (bo instanceof JSONArray) { + return JSONUtil.parseArray(bo); + } + JSONObject boJson = JSONUtil.parseObj(bo); + JSONArray boRows = getArray(boJson, "rows", "list", "records"); + if (boRows != null) { + return boRows; + } + JSONObject dataObject = boJson.getJSONObject("data"); + if (dataObject != null) { + JSONArray dataRows = getArray(dataObject, "rows", "list", "records"); + if (dataRows != null) { + return dataRows; + } + } + } + + JSONArray parsedRows = parseUserArray(body); + if (!parsedRows.isEmpty()) { + return parsedRows; + } + + log.warn("{}未解析到人员数据,响应={}", scene, body); + return new JSONArray(); + } + + private int[] saveCorpUserChangeRows(JSONArray sourceRows) { + int recordCount = 0; + int localUpdateCount = 0; + int userUpdateCount = 0; + int skipCount = 0; + int failCount = 0; + log.info("开始循环对比人员变更数据,{}",JSONUtil.toJsonStr(sourceRows)); + for (Object item : sourceRows) { + try { + JSONObject jsonObject = JSONUtil.parseObj(item); + String employeeName = jsonObject.getStr("employee_name"); + String idCardNumber = jsonObject.getStr("id_card_number"); + String corporationName = jsonObject.getStr("corporation_name"); + if (StringUtils.isEmpty(employeeName) || StringUtils.isEmpty(idCardNumber)) { + log.info("跳过无效人员变更数据:姓名或身份证号为空,原始数据:{}", jsonObject); + skipCount++; + continue; + } + + HumanUserE existingHumanUser = humanUserGateway.getByIdCardNumber(idCardNumber); + if (existingHumanUser == null) { + log.info("跳过人员变更数据:本地未找到身份证号为 {} 的人员,原始数据:{}", idCardNumber, jsonObject); + skipCount++; + continue; + } + Long corpId = getTargetCorpId(corporationName); + log.info("目标企业ID:{}", corpId); + Map deptNameIdMap = corpId == null ? Collections.emptyMap() : getTargetCorpDeptNameIdMap(corpId); + + + log.info("开始处理本地用户信息,{}",JSONUtil.toJsonStr(existingHumanUser)); + HumanUserRecordE record = buildHumanUserRecord(jsonObject, existingHumanUser.getUserId()); + humanUserRecordGateway.add(record); + recordCount++; + + mergeHumanUser(existingHumanUser, jsonObject); + humanUserGateway.update(existingHumanUser); + localUpdateCount++; + + String deptName = jsonObject.getStr("dept_name"); + Long deptId = StringUtils.isEmpty(deptName) || deptNameIdMap == null ? null : deptNameIdMap.get(deptName); + if (existingHumanUser.getUserId() != null) { + log.info("开始统一用户更新,userId={}",existingHumanUser.getUserId() ); + if (updateBasicInfodUser(existingHumanUser, deptId,corpId)) { + userUpdateCount++; + } else { + log.warn("统一用户更新未成功,userId={},身份证号={}", existingHumanUser.getUserId(), idCardNumber); + } + } + } catch (Exception e) { + log.error("处理人员变更数据失败,原始数据:{}", item, e); + failCount++; + } + } + + return new int[]{recordCount, localUpdateCount, userUpdateCount, skipCount, failCount}; + } + + private boolean updateBasicInfodUser(HumanUserE humanUser, Long deptId, Long corpId) { + if (humanUser.getUserId() == null) { + return false; + } + +// SingleResponse detailResponse = userFacade.getDetail(humanUser.getUserId()); + String phoneNumber = StringUtils.isNotEmpty(humanUser.getPhoneNumber()) ? humanUser.getPhoneNumber() : null; + String idCardNumber = StringUtils.isNotEmpty(humanUser.getIdCardNumber()) ? Base64.encodeToString(humanUser.getIdCardNumber()) :null; + Long existingUserId = isUserExists(idCardNumber,phoneNumber); + SingleResponse infoByUserId = zcloudUserFacade.getInfoByUserId(existingUserId); + if (infoByUserId == null || !infoByUserId.isSuccess() || infoByUserId.getData() == null) { + log.warn("获取统一用户详情失败,userId={}", humanUser.getUserId()); + return false; + } + + ZcloudUserCo detail = infoByUserId.getData(); + String employeeName = StringUtils.isNotEmpty(humanUser.getEmployeeName()) ? humanUser.getEmployeeName() : detail.getName(); + + String postName = StringUtils.isNotEmpty(humanUser.getPositionName()) ? humanUser.getPositionName() : humanUser.getJobName(); + ZcloudUserUpdateCmd cmd = new ZcloudUserUpdateCmd(); + + cmd.setId(existingUserId); + cmd.setName(employeeName); + cmd.setPhone(phoneNumber); + cmd.setUserIdCard(idCardNumber); + if (corpId != null) { + cmd.setCorpinfoId(corpId); + } + if (deptId != null) { + cmd.setDepartmentId(deptId); + } + if (StringUtils.isNotEmpty(postName)) { + cmd.setPostName(postName); + } + cmd.setRzFlag(1); + UserEmploymentFlagEnum byDesc = UserEmploymentFlagEnum.getByDesc(humanUser.getEmployeeStatus()); + cmd.setEmploymentFlag(byDesc==null?null:byDesc.getCode()); + log.info("调用统一用户请求:{}",JSONUtil.toJsonStr(cmd)); + SingleResponse updateResponse = zcloudUserFacade.updateHumanUser(cmd); + log.info("统一用户更新结果:{}",JSONUtil.toJsonStr(updateResponse)); + return updateResponse != null && updateResponse.isSuccess(); + } + + private List buildRoleDeptAddCmds(List roleDepts, Long deptId) { + List result = new ArrayList<>(); + if (roleDepts != null) { + for (UserRoleDeptCO roleDept : roleDepts) { + if (roleDept == null || roleDept.getRoleId() == null) { + continue; + } + RoleDeptAddCmd roleDeptAddCmd = new RoleDeptAddCmd(); + roleDeptAddCmd.setRoleId(roleDept.getRoleId()); + roleDeptAddCmd.setDeptId(deptId != null ? deptId : roleDept.getDeptId()); + result.add(roleDeptAddCmd); + } + } + + if (!result.isEmpty() || deptId == null) { + return result; + } + + Long defaultRoleId = getDefaultRoleId(); + if (defaultRoleId == null) { + return result; + } + + RoleDeptAddCmd defaultRoleDept = new RoleDeptAddCmd(); + defaultRoleDept.setRoleId(defaultRoleId); + defaultRoleDept.setDeptId(deptId); + result.add(defaultRoleDept); + return result; + } + + private String resolveSexEnum(String employeeGender, String fallbackSexEnum) { + if (StringUtils.isEmpty(employeeGender)) { + return fallbackSexEnum; + } + String gender = employeeGender.trim(); + if ((gender.length() == 1 && gender.charAt(0) == 30007) + || "1".equals(gender) || "MALE".equalsIgnoreCase(gender)) { + return "MALE"; + } + if ((gender.length() == 1 && gender.charAt(0) == 22899) + || "2".equals(gender) || "FEMALE".equalsIgnoreCase(gender)) { + return "FEMALE"; + } + return fallbackSexEnum; + } + + private Long parseLongValue(String value) { + if (StringUtils.isEmpty(value)) { + return null; + } + try { + return Long.valueOf(value); + } catch (NumberFormatException e) { + log.warn("文件ID不是有效的数字,value={}", value); + return null; + } + } + + private JSONArray getTestCorpUserChangeRows() { + + HumanUserDO byId = humanUserRepository.getById(1); + + String remark = byId.getRemarks(); + return JSONUtil.parseArray(remark); + + + /* JSONArray array = new JSONArray(); + + JSONObject first = new JSONObject(); + first.set("dept_code", "132588b1871341acb51c5638a735dbe7"); + first.set("corporation_code", "28f4eed3300b431c958bea4d93e49434"); + first.set("entry_time", "2011-07-05 00:00:00"); + first.set("employee_gender", "MALE"); + first.set("position_name", "开发岗位"); + first.set("dept_name", "开发部门"); + first.set("employee_images_code", "a101bf6d844b43b9b85aeba419ff0458"); + first.set("employee_name", "TEST_USER_B"); + first.set("corporation_name", "zhk分公司"); + first.set("employee_images", ""); + first.set("employee_age", 45); + first.set("job_name", "TEST_JOB_A"); + first.set("phone_number", "18700000009"); + first.set("employee_status", "在职"); + first.set("job_level", "M9"); + first.set("id_card_number", "654201197901154618"); + array.add(first); +*//* + JSONObject second = new JSONObject(); + second.set("dept_code", "3cb898c954b947e3acfb8161d23103f7"); + second.set("corporation_code", "5a472a9d94f84832bc83b93133832f55"); + second.set("entry_time", "2024-11-01 00:00:00"); + second.set("employee_gender", "FEMALE"); + second.set("position_name", "TEST_POSITION_B"); + second.set("dept_name", "TEST_DEPT_B"); + second.set("employee_images_code", "de475a7601a9450fb4a1109f70d1f3be"); + second.set("employee_name", "TEST_USER_B"); + second.set("corporation_name", "TEST_CORP_B"); + second.set("employee_images", ""); + second.set("employee_age", 54); + second.set("job_name", "TEST_JOB_B"); + second.set("phone_number", "16603390000"); + second.set("employee_status", "劳务派遣"); + second.set("id_card_number", "E64056788"); + array.add(second);*//* + + return array;*/ + } + + private String getAppKey() { + return humanResourcesConfig.getAppKey(); + } + + private String getAppSecret() { + return humanResourcesConfig.getAppSecret(); + } } diff --git a/web-app/src/main/java/com/zcloud/human/user/command/convertor/HumanResourceCorpCoConvertor.java b/web-app/src/main/java/com/zcloud/human/user/command/convertor/HumanResourceCorpCoConvertor.java new file mode 100644 index 0000000..da7093a --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/command/convertor/HumanResourceCorpCoConvertor.java @@ -0,0 +1,24 @@ +package com.zcloud.human.user.command.convertor; + +import com.zcloud.human.user.dto.clientobject.HumanResourceCorpCO; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; +import org.mapstruct.Mapper; + +import java.util.List; + + +/** + * web-app + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Mapper(componentModel = "spring") +public interface HumanResourceCorpCoConvertor { + /** + * @param humanResourceCorpDOs + * @return + */ + List converDOsToCOs(List humanResourceCorpDOs); +} + diff --git a/web-app/src/main/java/com/zcloud/human/user/command/query/HumanResourceCorpQueryExe.java b/web-app/src/main/java/com/zcloud/human/user/command/query/HumanResourceCorpQueryExe.java new file mode 100644 index 0000000..49505cd --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/command/query/HumanResourceCorpQueryExe.java @@ -0,0 +1,42 @@ +package com.zcloud.human.user.command.query; + +import com.alibaba.cola.dto.PageResponse; +import com.zcloud.gbscommon.utils.PageQueryHelper; +import com.zcloud.human.user.command.convertor.HumanResourceCorpCoConvertor; +import com.zcloud.human.user.dto.HumanResourceCorpPageQry; +import com.zcloud.human.user.dto.clientobject.HumanResourceCorpCO; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; +import com.zcloud.human.user.persistence.repository.HumanResourceCorpRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + + +/** + * web-app + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Component +@AllArgsConstructor +public class HumanResourceCorpQueryExe { + private final HumanResourceCorpRepository humanResourceCorpRepository; + private final HumanResourceCorpCoConvertor humanResourceCorpCoConvertor; + + /** + * 分页 + * + * @param humanResourceCorpPageQry + * @return + */ + public PageResponse execute(HumanResourceCorpPageQry humanResourceCorpPageQry) { + Map params = PageQueryHelper.toHashMap(humanResourceCorpPageQry); + PageResponse pageResponse = humanResourceCorpRepository.listPage(params); + List examCenterCOS = humanResourceCorpCoConvertor.converDOsToCOs(pageResponse.getData()); + return PageResponse.of(examCenterCOS, pageResponse.getTotalCount(), pageResponse.getPageSize(), pageResponse.getPageIndex()); + } +} + diff --git a/web-app/src/main/java/com/zcloud/human/user/config/HumanResourcesConfig.java b/web-app/src/main/java/com/zcloud/human/user/config/HumanResourcesConfig.java new file mode 100644 index 0000000..4b62a18 --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/config/HumanResourcesConfig.java @@ -0,0 +1,26 @@ +package com.zcloud.human.user.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 人资接口配置。 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "humanresources") +public class HumanResourcesConfig { + + /** + * 人资接口应用标识。 + */ + private String appKey; + + /** + * 人资接口应用密钥。 + */ + private String appSecret; +} diff --git a/web-app/src/main/java/com/zcloud/human/user/service/AsyncSyncService.java b/web-app/src/main/java/com/zcloud/human/user/service/AsyncSyncService.java index ada7d4c..eadfbd2 100644 --- a/web-app/src/main/java/com/zcloud/human/user/service/AsyncSyncService.java +++ b/web-app/src/main/java/com/zcloud/human/user/service/AsyncSyncService.java @@ -21,12 +21,22 @@ public class AsyncSyncService { public void asyncSyncHumanUser(String param) { log.info("开始异步同步人资人员信息"); try { - String result = humanUserSyncExe.execute(param); + String result = humanUserSyncExe.CorpUserSync(param); log.info("异步同步人资人员信息完成:{}", result); } catch (Exception e) { log.error("异步同步人资人员信息失败:{}", e.getMessage(), e); } } + public void asyncSyncUserChange(String test) { + log.info("开始异步同步人资人员变更信息"); + try { + String result = humanUserSyncExe.CorpUserChangeSync(test); + log.info("异步同步人资人员信息完成:{}", result); + } catch (Exception e) { + log.error("异步同步人资人员信息失败:{}", e.getMessage(), e); + } + } + @Async("syncTaskExecutor") public void asyncSyncHumanDept(String param) { @@ -49,4 +59,6 @@ public class AsyncSyncService { log.error("异步同步人资部门对比失败:{}", e.getMessage(), e); } } + + } diff --git a/web-app/src/main/java/com/zcloud/human/user/service/HumanResourceCorpServiceImpl.java b/web-app/src/main/java/com/zcloud/human/user/service/HumanResourceCorpServiceImpl.java new file mode 100644 index 0000000..0d35665 --- /dev/null +++ b/web-app/src/main/java/com/zcloud/human/user/service/HumanResourceCorpServiceImpl.java @@ -0,0 +1,59 @@ +package com.zcloud.human.user.service; + +import com.alibaba.cola.dto.PageResponse; +import com.alibaba.cola.dto.SingleResponse; +import com.zcloud.human.user.api.HumanResourceCorpServiceI; +import com.zcloud.human.user.command.HumanResourceCorpAddExe; +import com.zcloud.human.user.command.HumanResourceCorpRemoveExe; +import com.zcloud.human.user.command.HumanResourceCorpUpdateExe; +import com.zcloud.human.user.command.query.HumanResourceCorpQueryExe; +import com.zcloud.human.user.dto.HumanResourceCorpAddCmd; +import com.zcloud.human.user.dto.HumanResourceCorpPageQry; +import com.zcloud.human.user.dto.HumanResourceCorpUpdateCmd; +import com.zcloud.human.user.dto.clientobject.HumanResourceCorpCO; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * web-app + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Service +@AllArgsConstructor +public class HumanResourceCorpServiceImpl implements HumanResourceCorpServiceI { + private final HumanResourceCorpAddExe humanResourceCorpAddExe; + private final HumanResourceCorpUpdateExe humanResourceCorpUpdateExe; + private final HumanResourceCorpRemoveExe humanResourceCorpRemoveExe; + private final HumanResourceCorpQueryExe humanResourceCorpQueryExe; + + @Override + public PageResponse listPage(HumanResourceCorpPageQry qry) { + + return humanResourceCorpQueryExe.execute(qry); + } + + @Override + public SingleResponse add(HumanResourceCorpAddCmd cmd) { + + humanResourceCorpAddExe.execute(cmd); + return SingleResponse.buildSuccess(); + } + + @Override + public void edit(HumanResourceCorpUpdateCmd humanResourceCorpUpdateCmd) { + humanResourceCorpUpdateExe.execute(humanResourceCorpUpdateCmd); + } + + @Override + public void remove(Long id) { + humanResourceCorpRemoveExe.execute(id); + } + + @Override + public void removeBatch(Long[] ids) { + humanResourceCorpRemoveExe.execute(ids); + } +} + diff --git a/web-client/src/main/java/com/zcloud/human/user/api/HumanResourceCorpServiceI.java b/web-client/src/main/java/com/zcloud/human/user/api/HumanResourceCorpServiceI.java new file mode 100644 index 0000000..00b8d8d --- /dev/null +++ b/web-client/src/main/java/com/zcloud/human/user/api/HumanResourceCorpServiceI.java @@ -0,0 +1,27 @@ +package com.zcloud.human.user.api; + +import com.alibaba.cola.dto.PageResponse; +import com.alibaba.cola.dto.SingleResponse; +import com.zcloud.human.user.dto.HumanResourceCorpAddCmd; +import com.zcloud.human.user.dto.HumanResourceCorpPageQry; +import com.zcloud.human.user.dto.HumanResourceCorpUpdateCmd; +import com.zcloud.human.user.dto.clientobject.HumanResourceCorpCO; + +/** + * web-client + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +public interface HumanResourceCorpServiceI { + PageResponse listPage(HumanResourceCorpPageQry qry); + + SingleResponse add(HumanResourceCorpAddCmd cmd); + + void edit(HumanResourceCorpUpdateCmd cmd); + + void remove(Long id); + + void removeBatch(Long[] ids); +} + diff --git a/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpAddCmd.java b/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpAddCmd.java new file mode 100644 index 0000000..96ff207 --- /dev/null +++ b/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpAddCmd.java @@ -0,0 +1,56 @@ +package com.zcloud.human.user.dto; + +import com.alibaba.cola.dto.Command; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; + +/** + * web-client + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HumanResourceCorpAddCmd extends Command { + @ApiModelProperty(value = "企业id", name = "corpinfoId", required = true) + @NotEmpty(message = "企业id不能为空") + private String corpinfoId; + + @ApiModelProperty(value = "企业编码", name = "corporationCode", required = true) + @NotEmpty(message = "企业编码不能为空") + private String corporationCode; + + @ApiModelProperty(value = "企业名称", name = "corporationName", required = true) + @NotEmpty(message = "企业名称不能为空") + private String corporationName; + + @ApiModelProperty(value = "部门名称", name = "deptName", required = true) + @NotEmpty(message = "部门名称不能为空") + private String deptName; + + @ApiModelProperty(value = "部门编码", name = "deptCode", required = true) + @NotEmpty(message = "部门编码不能为空") + private String deptCode; + + @ApiModelProperty(value = "部门级别", name = "deptLevel", required = true) + @NotEmpty(message = "部门级别不能为空") + private String deptLevel; + + @ApiModelProperty(value = "部门路径", name = "deptCodePath", required = true) + @NotEmpty(message = "部门路径不能为空") + private String deptCodePath; + + @ApiModelProperty(value = "父级部门编码", name = "superiorOrganizationCode", required = true) + @NotEmpty(message = "父级部门编码不能为空") + private String superiorOrganizationCode; + +} + diff --git a/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpPageQry.java b/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpPageQry.java new file mode 100644 index 0000000..7509fe1 --- /dev/null +++ b/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpPageQry.java @@ -0,0 +1,28 @@ +package com.zcloud.human.user.dto; + +import com.alibaba.cola.dto.PageQuery; +import lombok.Data; + + +/** + * web-client + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Data +public class HumanResourceCorpPageQry extends PageQuery { + + /** + * 查询条件操作前缀,支持以下几种数据库查询操作: + * - `like`: 模糊匹配查询,对应SQL的LIKE操作符 + * - `eq`: 等值查询,对应SQL的=操作符 + * - `gt`: 大于比较查询 + * - `lt`: 小于比较查询 + * - `ge`: 大于等于比较查询 + * - `le`: 小于等于比较查询 + * - `ne`: 不等比较查询,对应SQL的!=操作符 + */ + private String likeHumanResourceCorpId; +} + diff --git a/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpUpdateCmd.java b/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpUpdateCmd.java new file mode 100644 index 0000000..d6bf091 --- /dev/null +++ b/web-client/src/main/java/com/zcloud/human/user/dto/HumanResourceCorpUpdateCmd.java @@ -0,0 +1,55 @@ +package com.zcloud.human.user.dto; + +import com.alibaba.cola.dto.Command; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * web-client + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HumanResourceCorpUpdateCmd extends Command { + @ApiModelProperty(value = "主键", name = "id", required = true) + @NotNull(message = "主键不能为空") + private Long id; + @ApiModelProperty(value = "业务主键id", name = "humanResourceCorpId", required = true) + @NotEmpty(message = "业务主键id不能为空") + private String humanResourceCorpId; + @ApiModelProperty(value = "企业id", name = "corpinfoId", required = true) + @NotEmpty(message = "企业id不能为空") + private String corpinfoId; + @ApiModelProperty(value = "企业编码", name = "corporationCode", required = true) + @NotEmpty(message = "企业编码不能为空") + private String corporationCode; + @ApiModelProperty(value = "企业名称", name = "corporationName", required = true) + @NotEmpty(message = "企业名称不能为空") + private String corporationName; + @ApiModelProperty(value = "部门名称", name = "deptName", required = true) + @NotEmpty(message = "部门名称不能为空") + private String deptName; + @ApiModelProperty(value = "部门编码", name = "deptCode", required = true) + @NotEmpty(message = "部门编码不能为空") + private String deptCode; + @ApiModelProperty(value = "部门级别", name = "deptLevel", required = true) + @NotEmpty(message = "部门级别不能为空") + private String deptLevel; + @ApiModelProperty(value = "部门路径", name = "deptCodePath", required = true) + @NotEmpty(message = "部门路径不能为空") + private String deptCodePath; + @ApiModelProperty(value = "父级部门编码", name = "superiorOrganizationCode", required = true) + @NotEmpty(message = "父级部门编码不能为空") + private String superiorOrganizationCode; +} + diff --git a/web-client/src/main/java/com/zcloud/human/user/dto/clientobject/HumanResourceCorpCO.java b/web-client/src/main/java/com/zcloud/human/user/dto/clientobject/HumanResourceCorpCO.java new file mode 100644 index 0000000..06e88ec --- /dev/null +++ b/web-client/src/main/java/com/zcloud/human/user/dto/clientobject/HumanResourceCorpCO.java @@ -0,0 +1,85 @@ +package com.zcloud.human.user.dto.clientobject; + +import com.alibaba.cola.dto.ClientObject; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + + +/** + * web-client + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Data +public class HumanResourceCorpCO extends ClientObject { + //主键 + @ApiModelProperty(value = "主键") + private Long id; + //业务主键id + @ApiModelProperty(value = "业务主键id") + private String humanResourceCorpId; + //企业id + @ApiModelProperty(value = "企业id") + private String corpinfoId; + //企业编码 + @ApiModelProperty(value = "企业编码") + private String corporationCode; + //企业名称 + @ApiModelProperty(value = "企业名称") + private String corporationName; + //部门名称 + @ApiModelProperty(value = "部门名称") + private String deptName; + //部门编码 + @ApiModelProperty(value = "部门编码") + private String deptCode; + //部门级别 + @ApiModelProperty(value = "部门级别") + private String deptLevel; + //部门路径 + @ApiModelProperty(value = "部门路径") + private String deptCodePath; + //父级部门编码 + @ApiModelProperty(value = "父级部门编码") + private String superiorOrganizationCode; + //乐观锁 + @ApiModelProperty(value = "乐观锁") + private Integer version; + //创建人 + @ApiModelProperty(value = "创建人") + private Long createId; + //创建人姓名 + @ApiModelProperty(value = "创建人姓名") + private String createName; + //创建时间 + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + //更新人 + @ApiModelProperty(value = "更新人") + private Long updateId; + //修改人名称 + @ApiModelProperty(value = "修改人名称") + private String updateName; + //更新时间 + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + //描述 + @ApiModelProperty(value = "描述") + private String remarks; + //是否删除 + @ApiModelProperty(value = "是否删除") + private String deleteEnum; + //租户ID + @ApiModelProperty(value = "租户ID") + private Long tenantId; + //机构ID + @ApiModelProperty(value = "机构ID") + private Long orgId; + //环境 + @ApiModelProperty(value = "环境") + private String env; +} + diff --git a/web-domain/src/main/java/com/zcloud/human/user/domain/enums/UserEmploymentFlagEnum.java b/web-domain/src/main/java/com/zcloud/human/user/domain/enums/UserEmploymentFlagEnum.java new file mode 100644 index 0000000..5ade25e --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/human/user/domain/enums/UserEmploymentFlagEnum.java @@ -0,0 +1,52 @@ +package com.zcloud.human.user.domain.enums; + +import lombok.Getter; + +/** + * 入入职状态,0-离职, 1-在职, 2-信息变更中, 3-未入职, 4-实习生, 5-实习结束, 6-退休, 7-劳务派遣, 8-劳务派遣结束, 11-入职待审核, 10-离职待审核', + * + */ +@Getter +public enum UserEmploymentFlagEnum { + /** + * 枚举值 + */ + RESIGNATION(0, "离职"), + ON(1, "在职"), + INFO_CHANGE(2, "信息变更中"), + NOT_ON(3, "未入职"), + INTERN(4, "实习生"), + INTERNSHIP_ENDED(5, "实习结束"), + RETIREMENT(6, "退休"), + LABOR_DISPATCH(7, "劳务派遣"), + END_OF_LABOR_DISPATCH(8, "劳务派遣结束"), + ENTRY_AUDIT(11, "入职待审核"), + RESIGNATION_AUDIT(10, "离职待审核"), + ; + private final Integer code; + private final String desc; + + UserEmploymentFlagEnum(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + //根据code获取枚举值 + public static UserEmploymentFlagEnum getByCode(Integer code) { + for (UserEmploymentFlagEnum item : values()) { + if (item.getCode().equals(code)) { + return item; + } + } + return null; + } + + //根据枚举获取code + public static UserEmploymentFlagEnum getByDesc(String desc) { + for (UserEmploymentFlagEnum item : values()) { + if (item.getDesc().equals(desc)) { + return item; + } + } + return null; + } +} diff --git a/web-domain/src/main/java/com/zcloud/human/user/domain/gateway/HumanResourceCorpGateway.java b/web-domain/src/main/java/com/zcloud/human/user/domain/gateway/HumanResourceCorpGateway.java new file mode 100644 index 0000000..6da665f --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/human/user/domain/gateway/HumanResourceCorpGateway.java @@ -0,0 +1,30 @@ +package com.zcloud.human.user.domain.gateway; + +import com.zcloud.human.user.domain.model.HumanResourceCorpE; + +/** + * web-domain + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +public interface HumanResourceCorpGateway { + + /** + * 新增 + */ + Boolean add(HumanResourceCorpE humanResourceCorpE); + + /** + * 修改 + */ + Boolean update(HumanResourceCorpE humanResourceCorpE); + + /** + * 删除 + */ + Boolean deletedHumanResourceCorpById(Long id); + + Boolean deletedHumanResourceCorpByIds(Long[] id); +} + diff --git a/web-domain/src/main/java/com/zcloud/human/user/domain/model/DeptEntity.java b/web-domain/src/main/java/com/zcloud/human/user/domain/model/DeptEntity.java new file mode 100644 index 0000000..bca7af7 --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/human/user/domain/model/DeptEntity.java @@ -0,0 +1,51 @@ +package com.zcloud.human.user.domain.model; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import lombok.Data; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Data +public class DeptEntity { + private static Set processedDeptCodes = new HashSet<>(); + private String corporation_code; + private String corporation_name; + private String dept_name; + private String dept_code; + private String dept_level; + private String dept_code_path; + private String superior_organization_code; + private List children; + + public static List getList(Object x) { + List list = JSONObject.parseObject(JSONObject.toJSONString(x), new TypeReference>() { + }); + List parent = list.stream() + .filter(n -> "1".equals(n.getDept_level())) + .collect(Collectors.toList()); + for (DeptEntity m : parent) { + getList(m, list); + } + return parent; + } + + private static void getList(DeptEntity parent, List list) { + if (processedDeptCodes.contains(parent.getDept_code())) { + return; // 避免重复处理 + } + processedDeptCodes.add(parent.getDept_code()); + + List child = list.stream() + .filter(n -> parent.getDept_code().trim().equals(n.getSuperior_organization_code().trim())) + .collect(Collectors.toList()); + parent.setChildren(child); + for (DeptEntity m : child) { + getList(m, list); + } + } + +} diff --git a/web-domain/src/main/java/com/zcloud/human/user/domain/model/HumanResourceCorpE.java b/web-domain/src/main/java/com/zcloud/human/user/domain/model/HumanResourceCorpE.java new file mode 100644 index 0000000..930215b --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/human/user/domain/model/HumanResourceCorpE.java @@ -0,0 +1,61 @@ +package com.zcloud.human.user.domain.model; + +import com.jjb.saas.framework.domain.model.BaseE; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * web-domain + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Data +public class HumanResourceCorpE extends BaseE { + //主键 + private Long id; + //业务主键id + private String humanResourceCorpId; + //企业id + private String corpinfoId; + //企业编码 + private String corporationCode; + //企业名称 + private String corporationName; + //部门名称 + private String deptName; + //部门编码 + private String deptCode; + //部门级别 + private String deptLevel; + //部门路径 + private String deptCodePath; + //父级部门编码 + private String superiorOrganizationCode; + //乐观锁 + private Integer version; + //创建人 + private Long createId; + //创建人姓名 + private String createName; + //创建时间 + private LocalDateTime createTime; + //更新人 + private Long updateId; + //修改人名称 + private String updateName; + //更新时间 + private LocalDateTime updateTime; + //描述 + private String remarks; + //是否删除 + private String deleteEnum; + //租户ID + private Long tenantId; + //机构ID + private Long orgId; + //环境 + private String env; +} + diff --git a/web-domain/src/main/java/com/zcloud/human/user/domain/utils/SignUtil.java b/web-domain/src/main/java/com/zcloud/human/user/domain/utils/SignUtil.java new file mode 100644 index 0000000..b504c69 --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/human/user/domain/utils/SignUtil.java @@ -0,0 +1,263 @@ +package com.zcloud.human.user.domain.utils; + +import cn.hutool.core.util.StrUtil; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.util.CollectionUtils; + +import java.security.MessageDigest; +import java.util.*; + +/** + * 对接人资系统签名工具类 + */ +public class SignUtil { + private String appKey; + private String appSecret; + private Integer pageNum; + private Integer pageSize; + private Map paramMap; + private List orderByList; + private Long timeStamp; + private String nonce; + private String envType; + private Map signatureParam; + + public static void main(String[] args) { + SignUtil signUtil = new SignUtil(); + signUtil.setAppKey("7401C9849D1BF3CAF796E146C7AE05AE"); + + signUtil.setAppSecret("29E60A33FC846468AFCCFD2576FA28120317AB8259E3D1EF9BD236422618613C"); + signUtil.setPageNum(1); + signUtil.setPageSize(1000); + Map paramMap = new HashMap<>(); + //paramMap.put("status", "1"); + signUtil.setParamMap(paramMap); + List orderByList = new ArrayList<>(); + //orderByList.add("version,DESC"); + signUtil.setOrderByList(orderByList); + signUtil.setEnvType("online"); + signUtil.setTimeStamp(System.currentTimeMillis()); + signUtil.setNonce(RandomStringUtils.randomAlphanumeric(5)); + signUtil.buildSignatureParam(); + String signature = getSignature(signUtil.getSignatureParam()); + System.out.println(signUtil.getTimeStamp()); + System.out.println(signUtil.getNonce()); + System.out.println(signature); + } + + /** + * 生成签名算法,生成规则:参数+时间戳+唯一编码+AppKey+AppSecret 升序拼 + * 接后通过 SHA-256 加密的得到 + **/ + public static String getSignature(Map map) { + if (CollectionUtils.isEmpty(map)) { + return ""; + } + Set> set = map.entrySet(); + StringBuffer sb = new StringBuffer(); + for (Iterator> it = set.iterator(); + it.hasNext(); ) { + Map.Entry me = it.next(); + sb.append(me.getKey()).append(me.getValue()); + } + String signString = sb.toString(); + if (StrUtil.isNotBlank(signString)) { + return ShaUtils.encryptBySha256(signString).toUpperCase(); + } + return ""; + } + + public void buildSignatureParam() { + Map argsMap = new TreeMap<>(); + argsMap.put(SignatureParamName.APP_KEY.getParamName(), + this.getAppKey()); + argsMap.put(SignatureParamName.APP_SECRET.getParamName(), + this.getAppSecret()); + argsMap.put(SignatureParamName.PAGE_NUM.getParamName(), + this.getPageNum()); + argsMap.put(SignatureParamName.PAGE_SIZE.getParamName(), + this.getPageSize()); + argsMap.put(SignatureParamName.PARAM_MAP.getParamName(), + this.getParamMap()); + argsMap.put(SignatureParamName.ORDER_BY_LIST.getParamName(), + this.getOrderByList()); + argsMap.put(SignatureParamName.TIME_STAMP.getParamName(), + this.getTimeStamp()); + argsMap.put(SignatureParamName.NONCE.getParamName(), + this.getNonce()); + argsMap.put(SignatureParamName.ENV_TYPE.getParamName(), + this.getEnvType()); + this.signatureParam = argsMap; + } + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } + + public String getAppSecret() { + return appSecret; + } + + public void setAppSecret(String appSecret) { + this.appSecret = appSecret; + } + + public Long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(Long timeStamp) { + this.timeStamp = timeStamp; + } + + public String getNonce() { + return nonce; + } + + public void setNonce(String nonce) { + this.nonce = nonce; + } + + public Integer getPageNum() { + return pageNum; + } + + public void setPageNum(Integer pageNum) { + this.pageNum = pageNum; + } + + public Integer getPageSize() { + return pageSize; + } + + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + public Map getParamMap() { + return paramMap; + } + + public void setParamMap(Map paramMap) { + this.paramMap = paramMap; + } + + public List getOrderByList() { + return orderByList; + } + + public void setOrderByList(List orderByList) { + this.orderByList = orderByList; + } + + public String getEnvType() { + return envType; + } + + public void setEnvType(String envType) { + this.envType = envType; + } + + public Map getSignatureParam() { + return signatureParam; + } + + public void setSignatureParam(Map signatureParam) { + this.signatureParam = signatureParam; + } + + public enum SignatureParamName { + /** + * appKey + */ + APP_KEY("appKey"), + /** + * pageNum + */ + PAGE_NUM("pageNum"), + /** + * pageSize + */ + PAGE_SIZE("pageSize"), + /** + * appSecret + */ + APP_SECRET("appSecret"), + /** + * paramMap + */ + PARAM_MAP("paramMap"), + /** + * orderByList + */ + ORDER_BY_LIST("orderByList"), + /** + * timeStamp + */ + TIME_STAMP("timeStamp"), + /** + * nonce + */ + NONCE("nonce"), + /** + * envType + */ + ENV_TYPE("envType"); + private String paramName; + + SignatureParamName(String paramName) { + this.paramName = paramName; + } + + public String getParamName() { + return paramName; + } + } +} + +class ShaUtils { + private final static String CHAR_SET_UTF8 = "UTF-8"; + private final static String ALGORITHM_SHA256 = "SHA-256"; + + /** + * 加密 大小写敏感 + **/ + public static String encryptBySha256(String str) { + return encrypt(str, CHAR_SET_UTF8, ALGORITHM_SHA256); + } + + public static String encrypt(String str, String charset, String + algorithm) { + if (StrUtil.isBlank(str)) {// throw new + throw new RuntimeException(); + } + try { + MessageDigest messageDigest = + MessageDigest.getInstance(algorithm); + messageDigest.update(str.getBytes(charset)); + return byte2Hex(messageDigest.digest()); + } catch (Exception e) {// throw new + throw new RuntimeException(); + } + } + + /** + * SHA-256 将 byte 转为 16 进制 + **/ + private static String byte2Hex(byte[] bytes) { + StringBuffer stringBuffer = new StringBuffer(); + String temp; + for (int i = 0; i < bytes.length; i++) { + temp = Integer.toHexString(bytes[i] & 0xFF); + if (temp.length() == 1) { + stringBuffer.append("0"); + } + stringBuffer.append(temp); + } + return stringBuffer.toString(); + } +} diff --git a/web-infrastructure/src/main/java/com/zcloud/human/user/gatewayimpl/HumanResourceCorpGatewayImpl.java b/web-infrastructure/src/main/java/com/zcloud/human/user/gatewayimpl/HumanResourceCorpGatewayImpl.java new file mode 100644 index 0000000..bd5faec --- /dev/null +++ b/web-infrastructure/src/main/java/com/zcloud/human/user/gatewayimpl/HumanResourceCorpGatewayImpl.java @@ -0,0 +1,50 @@ +package com.zcloud.human.user.gatewayimpl; + +import com.zcloud.human.user.domain.gateway.HumanResourceCorpGateway; +import com.zcloud.human.user.domain.model.HumanResourceCorpE; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; +import com.zcloud.human.user.persistence.repository.HumanResourceCorpRepository; +import lombok.AllArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.Collections; + +/** + * web-infrastructure + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Service +@AllArgsConstructor +public class HumanResourceCorpGatewayImpl implements HumanResourceCorpGateway { + private final HumanResourceCorpRepository humanResourceCorpRepository; + + @Override + public Boolean add(HumanResourceCorpE humanResourceCorpE) { + HumanResourceCorpDO d = new HumanResourceCorpDO(); + BeanUtils.copyProperties(humanResourceCorpE, d); + humanResourceCorpRepository.save(d); + return true; + } + + @Override + public Boolean update(HumanResourceCorpE humanResourceCorpE) { + HumanResourceCorpDO d = new HumanResourceCorpDO(); + BeanUtils.copyProperties(humanResourceCorpE, d); + humanResourceCorpRepository.updateById(d); + return true; + } + + @Override + public Boolean deletedHumanResourceCorpById(Long id) { + return humanResourceCorpRepository.removeById(id); + } + + @Override + public Boolean deletedHumanResourceCorpByIds(Long[] ids) { + return humanResourceCorpRepository.removeByIds(Collections.singletonList(ids)); + } +} + diff --git a/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/dataobject/HumanResourceCorpDO.java b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/dataobject/HumanResourceCorpDO.java new file mode 100644 index 0000000..95afd11 --- /dev/null +++ b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/dataobject/HumanResourceCorpDO.java @@ -0,0 +1,54 @@ +package com.zcloud.human.user.persistence.dataobject; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.jjb.saas.framework.repository.basedo.BaseDO; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * web-infrastructure + * + * @Author zhaokai + * @Date 2026-06-16 09:00:22 + */ +@Data +@TableName("human_resource_corp") +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class HumanResourceCorpDO extends BaseDO { + //业务主键id + @ApiModelProperty(value = "业务主键id") + private String humanResourceCorpId; + //企业id + @ApiModelProperty(value = "企业id") + private String corpinfoId; + //企业编码 + @ApiModelProperty(value = "企业编码") + private String corporationCode; + //企业名称 + @ApiModelProperty(value = "企业名称") + private String corporationName; + //部门名称 + @ApiModelProperty(value = "部门名称") + private String deptName; + //部门编码 + @ApiModelProperty(value = "部门编码") + private String deptCode; + //部门级别 + @ApiModelProperty(value = "部门级别") + private String deptLevel; + //部门路径 + @ApiModelProperty(value = "部门路径") + private String deptCodePath; + //父级部门编码 + @ApiModelProperty(value = "父级部门编码") + private String superiorOrganizationCode; + + public HumanResourceCorpDO(String humanResourceCorpId) { + this.humanResourceCorpId = humanResourceCorpId; + } + +} + diff --git a/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/mapper/HumanResourceCorpMapper.java b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/mapper/HumanResourceCorpMapper.java new file mode 100644 index 0000000..4fd0de5 --- /dev/null +++ b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/mapper/HumanResourceCorpMapper.java @@ -0,0 +1,17 @@ +package com.zcloud.human.user.persistence.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * web-infrastructure + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Mapper +public interface HumanResourceCorpMapper extends BaseMapper { + +} + diff --git a/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/HumanResourceCorpRepository.java b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/HumanResourceCorpRepository.java new file mode 100644 index 0000000..38ed5ac --- /dev/null +++ b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/HumanResourceCorpRepository.java @@ -0,0 +1,21 @@ +package com.zcloud.human.user.persistence.repository; + +import com.alibaba.cola.dto.PageResponse; +import com.jjb.saas.framework.repository.repo.BaseRepository; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; + +import java.util.List; +import java.util.Map; + +/** + * web-infrastructure + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +public interface HumanResourceCorpRepository extends BaseRepository { + PageResponse listPage(Map params); + + void replaceAll(List corpList); +} + diff --git a/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/impl/HumanResourceCorpRepositoryImpl.java b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/impl/HumanResourceCorpRepositoryImpl.java new file mode 100644 index 0000000..286ace3 --- /dev/null +++ b/web-infrastructure/src/main/java/com/zcloud/human/user/persistence/repository/impl/HumanResourceCorpRepositoryImpl.java @@ -0,0 +1,51 @@ +package com.zcloud.human.user.persistence.repository.impl; + +import com.alibaba.cola.dto.PageResponse; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.jjb.saas.framework.repository.common.PageHelper; +import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl; +import com.zcloud.gbscommon.utils.PageQueryHelper; +import com.zcloud.gbscommon.utils.Query; +import com.zcloud.human.user.persistence.dataobject.HumanResourceCorpDO; +import com.zcloud.human.user.persistence.mapper.HumanResourceCorpMapper; +import com.zcloud.human.user.persistence.repository.HumanResourceCorpRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + * web-infrastructure + * + * @Author zhaokai + * @Date 2026-06-16 09:00:23 + */ +@Service +@RequiredArgsConstructor +public class HumanResourceCorpRepositoryImpl extends BaseRepositoryImpl implements HumanResourceCorpRepository { + private final HumanResourceCorpMapper humanResourceCorpMapper; + + @Override + public PageResponse listPage(Map params) { + IPage iPage = new Query().getPage(params); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper = PageQueryHelper.createPageQueryWrapper(queryWrapper, params); + queryWrapper.orderByDesc("create_time"); + IPage result = humanResourceCorpMapper.selectPage(iPage, queryWrapper); + return PageHelper.pageToResponse(result, result.getRecords()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void replaceAll(List corpList) { + humanResourceCorpMapper.delete(new QueryWrapper<>()); + if (corpList == null || corpList.isEmpty()) { + return; + } + saveBatch(corpList, 500); + } +} + diff --git a/web-infrastructure/src/main/resources/TableCreationDDL.sql b/web-infrastructure/src/main/resources/TableCreationDDL.sql index f7ef213..a928828 100644 --- a/web-infrastructure/src/main/resources/TableCreationDDL.sql +++ b/web-infrastructure/src/main/resources/TableCreationDDL.sql @@ -71,3 +71,32 @@ CREATE TABLE `human_user_record` ( `env` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='人资每日变动记录'; + + +CREATE TABLE `human_resource_corp` ( + `id` bigint NOT NULL COMMENT '主键', + `human_resource_corp_id` varchar(35) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '业务主键id', + `corpinfo_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业id', + `corporation_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业编码', + `corporation_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业名称', + `dept_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '部门名称', + `dept_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '部门编码', + `dept_level` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '部门级别', + `dept_code_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '部门路径', + `superior_organization_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级部门编码', + `version` int DEFAULT NULL COMMENT '乐观锁', + `create_id` bigint DEFAULT NULL COMMENT '创建人', + `create_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人姓名', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_id` bigint DEFAULT NULL COMMENT '更新人', + `update_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '修改人名称', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `remarks` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '描述', + `delete_enum` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '是否删除', + `tenant_id` bigint DEFAULT NULL COMMENT '租户ID', + `org_id` bigint DEFAULT NULL COMMENT '机构ID', + `env` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_human_resource_corp_dept_code` (`dept_code`) USING BTREE, + KEY `idx_human_resource_corp_corporation_code` (`corporation_code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='人资企业部门本地缓存表'; diff --git a/web-infrastructure/src/main/resources/mapper/HumanResourceCorpMapper.xml b/web-infrastructure/src/main/resources/mapper/HumanResourceCorpMapper.xml new file mode 100644 index 0000000..94f1532 --- /dev/null +++ b/web-infrastructure/src/main/resources/mapper/HumanResourceCorpMapper.xml @@ -0,0 +1,7 @@ + + + + + +