Merge remote-tracking branch 'base-version/main' into dev
This commit is contained in:
@@ -14,6 +14,9 @@ public class AdminUserRespDTO implements VO {
|
||||
@Schema(description = "用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "zhangsan")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
|
||||
private String nickname;
|
||||
|
||||
|
||||
@@ -114,17 +114,23 @@ public class IWorkIntegrationController {
|
||||
// ----------------- 同步到本地 -----------------
|
||||
|
||||
@PostMapping("/hr/full-sync")
|
||||
@Operation(summary = "手动触发 iWork 组织/人员全量同步")
|
||||
@Operation(summary = "手动触发 iWork 组织/人员同步")
|
||||
public CommonResult<IWorkFullSyncRespVO> fullSync(@Valid @RequestBody IWorkFullSyncReqVO reqVO) {
|
||||
return success(syncService.fullSync(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/hr/departments/full-sync")
|
||||
@Operation(summary = "手动触发 iWork 部门全量同步")
|
||||
@Operation(summary = "手动触发 iWork 部门同步")
|
||||
public CommonResult<IWorkFullSyncRespVO> fullSyncDepartments(@Valid @RequestBody IWorkFullSyncReqVO reqVO) {
|
||||
return success(syncService.fullSyncDepartments(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/hr/subcompanies/full-sync")
|
||||
@Operation(summary = "手动触发 iWork 分部同步")
|
||||
public CommonResult<IWorkFullSyncRespVO> fullSyncSubcompanies(@Valid @RequestBody IWorkFullSyncReqVO reqVO) {
|
||||
return success(syncService.fullSyncSubcompanies(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/hr/job-titles/full-sync")
|
||||
@Operation(summary = "手动触发 iWork 岗位全量同步")
|
||||
public CommonResult<IWorkFullSyncRespVO> fullSyncJobTitles(@Valid @RequestBody IWorkFullSyncReqVO reqVO) {
|
||||
|
||||
@@ -159,13 +159,9 @@ public class IWorkHrDepartmentPageRespVO {
|
||||
private String supsubcomname;
|
||||
|
||||
@Schema(description = "父部门 ID")
|
||||
@JsonProperty("parentdeptid")
|
||||
@JsonProperty("supdepid")
|
||||
@JsonDeserialize(using = LenientIntegerDeserializer.class)
|
||||
private Integer parentdeptid;
|
||||
|
||||
@Schema(description = "父部门名称")
|
||||
@JsonProperty("parentdeptname")
|
||||
private String parentdeptname;
|
||||
private Integer supdepid;
|
||||
|
||||
@Schema(description = "层级路径")
|
||||
@JsonProperty("alllevel")
|
||||
|
||||
@@ -5,11 +5,10 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.zt.plat.module.system.service.integration.iwork.jackson.LenientIntegerDeserializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import com.zt.plat.module.system.service.integration.iwork.jackson.LenientIntegerDeserializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -50,9 +49,10 @@ public class IWorkHrSubcompanyPageRespVO {
|
||||
@Schema(description = "分部信息")
|
||||
public static class Subcompany {
|
||||
|
||||
@Schema(description = "分部唯一 ID")
|
||||
@JsonProperty("subcompanyid1")
|
||||
private Integer subcompanyid1;
|
||||
@Schema(description = "部门 ID(iWork 主键)")
|
||||
@JsonProperty("id")
|
||||
@JsonDeserialize(using = LenientIntegerDeserializer.class)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "分部编码")
|
||||
@JsonProperty("subcompanycode")
|
||||
|
||||
@@ -74,16 +74,23 @@ public class DeptServiceImpl implements DeptService {
|
||||
// 校验部门名的唯一性
|
||||
validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
|
||||
// 生成并校验部门编码
|
||||
Long effectiveParentId = normalizeParentId(createReqVO.getParentId());
|
||||
boolean isTopLevel = Objects.equals(effectiveParentId, DeptDO.PARENT_ID_ROOT);
|
||||
String resolvedCode;
|
||||
if (isTopLevel) {
|
||||
resolvedCode = resolveTopLevelCode(null, createReqVO.getCode());
|
||||
boolean isIWorkSource = Objects.equals(createReqVO.getDeptSource(), DeptSourceEnum.IWORK.getSource());
|
||||
if (isIWorkSource) {
|
||||
// iWork 来源直接使用提供的编码,不再生成
|
||||
String providedCode = StrUtil.blankToDefault(createReqVO.getCode(), null);
|
||||
createReqVO.setCode(providedCode);
|
||||
} else {
|
||||
resolvedCode = generateDeptCode(effectiveParentId);
|
||||
validateDeptCodeUnique(null, resolvedCode);
|
||||
Long effectiveParentId = normalizeParentId(createReqVO.getParentId());
|
||||
boolean isTopLevel = Objects.equals(effectiveParentId, DeptDO.PARENT_ID_ROOT);
|
||||
String resolvedCode;
|
||||
if (isTopLevel) {
|
||||
resolvedCode = resolveTopLevelCode(null, createReqVO.getCode());
|
||||
} else {
|
||||
resolvedCode = generateDeptCode(effectiveParentId);
|
||||
validateDeptCodeUnique(null, resolvedCode);
|
||||
}
|
||||
createReqVO.setCode(resolvedCode);
|
||||
}
|
||||
createReqVO.setCode(resolvedCode);
|
||||
|
||||
// 插入部门
|
||||
DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class);
|
||||
@@ -110,28 +117,35 @@ public class DeptServiceImpl implements DeptService {
|
||||
// 校验部门名的唯一性
|
||||
validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
|
||||
// 如果上级发生变化,需要重新生成编码并同步子级
|
||||
boolean isIWorkSource = Objects.equals(originalDept.getDeptSource(), DeptSourceEnum.IWORK.getSource());
|
||||
Long newParentId = normalizeParentId(updateReqVO.getParentId());
|
||||
Long oldParentId = normalizeParentId(originalDept.getParentId());
|
||||
boolean parentChanged = !Objects.equals(newParentId, oldParentId);
|
||||
if (parentChanged) {
|
||||
String newCode;
|
||||
if (Objects.equals(newParentId, DeptDO.PARENT_ID_ROOT)) {
|
||||
newCode = resolveTopLevelCode(updateReqVO.getId(), updateReqVO.getCode());
|
||||
} else {
|
||||
newCode = generateDeptCode(updateReqVO.getParentId());
|
||||
validateDeptCodeUnique(updateReqVO.getId(), newCode);
|
||||
}
|
||||
updateReqVO.setCode(newCode);
|
||||
if (isIWorkSource) {
|
||||
// iWork 来源直接使用提供的编码,不再生成
|
||||
String providedCode = StrUtil.blankToDefault(updateReqVO.getCode(), null);
|
||||
updateReqVO.setCode(providedCode);
|
||||
} else {
|
||||
if (Objects.equals(newParentId, DeptDO.PARENT_ID_ROOT)) {
|
||||
String requestedCode = updateReqVO.getCode();
|
||||
if (StrUtil.isNotBlank(requestedCode) && !StrUtil.equals(requestedCode.trim(), originalDept.getCode())) {
|
||||
updateReqVO.setCode(resolveTopLevelCode(updateReqVO.getId(), requestedCode));
|
||||
if (parentChanged) {
|
||||
String newCode;
|
||||
if (Objects.equals(newParentId, DeptDO.PARENT_ID_ROOT)) {
|
||||
newCode = resolveTopLevelCode(updateReqVO.getId(), updateReqVO.getCode());
|
||||
} else {
|
||||
newCode = generateDeptCode(updateReqVO.getParentId());
|
||||
validateDeptCodeUnique(updateReqVO.getId(), newCode);
|
||||
}
|
||||
updateReqVO.setCode(newCode);
|
||||
} else {
|
||||
if (Objects.equals(newParentId, DeptDO.PARENT_ID_ROOT)) {
|
||||
String requestedCode = updateReqVO.getCode();
|
||||
if (StrUtil.isNotBlank(requestedCode) && !StrUtil.equals(requestedCode.trim(), originalDept.getCode())) {
|
||||
updateReqVO.setCode(resolveTopLevelCode(updateReqVO.getId(), requestedCode));
|
||||
} else {
|
||||
updateReqVO.setCode(originalDept.getCode());
|
||||
}
|
||||
} else {
|
||||
updateReqVO.setCode(originalDept.getCode());
|
||||
}
|
||||
} else {
|
||||
updateReqVO.setCode(originalDept.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,15 @@ public interface IWorkSyncService {
|
||||
IWorkFullSyncRespVO fullSync(IWorkFullSyncReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 仅同步部门(会自动包含依赖的分部)
|
||||
* 仅同步部门
|
||||
*/
|
||||
IWorkFullSyncRespVO fullSyncDepartments(IWorkFullSyncReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 仅同步分部
|
||||
*/
|
||||
IWorkFullSyncRespVO fullSyncSubcompanies(IWorkFullSyncReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 仅同步岗位
|
||||
*/
|
||||
|
||||
@@ -28,14 +28,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
@@ -72,12 +65,12 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
||||
while (iterator.hasNext()) {
|
||||
IWorkHrSubcompanyPageRespVO.Subcompany sub = iterator.next();
|
||||
if (shouldSkipByCanceled(sub.getCanceled(), options)) {
|
||||
logSkip("分部", sub.getSubcompanyid1(), "iWork 标记为失效且当前不同步失效记录");
|
||||
logSkip("分部", sub.getId(), "iWork 标记为失效且当前不同步失效记录");
|
||||
result.increaseSkipped();
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
Integer externalId = sub.getSubcompanyid1();
|
||||
Integer externalId = sub.getId();
|
||||
if (externalId == null) {
|
||||
log.warn("[iWork] 分部缺少标识,跳过:{}", sub.getSubcompanyname());
|
||||
result.increaseFailed();
|
||||
@@ -95,7 +88,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
||||
options);
|
||||
applyDeptOutcome(result, outcome, "分部", sub.getSubcompanyname());
|
||||
} catch (Exception ex) {
|
||||
log.error("[iWork] 同步分部失败: id={} name={}", sub.getSubcompanyid1(), sub.getSubcompanyname(), ex);
|
||||
log.error("[iWork] 同步分部失败: id={} name={}", sub.getId(), sub.getSubcompanyname(), ex);
|
||||
result.increaseFailed();
|
||||
result.withMessage("同步分部失败: " + ex.getMessage());
|
||||
}
|
||||
@@ -108,7 +101,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
||||
}
|
||||
if (!queue.isEmpty()) {
|
||||
for (IWorkHrSubcompanyPageRespVO.Subcompany remaining : queue) {
|
||||
log.warn("[iWork] 分部因父级缺失未同步: id={} name={}", remaining.getSubcompanyid1(), remaining.getSubcompanyname());
|
||||
log.warn("[iWork] 分部因父级缺失未同步: id={} name={}", remaining.getId(), remaining.getSubcompanyname());
|
||||
result.increaseFailed();
|
||||
}
|
||||
}
|
||||
@@ -397,7 +390,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
||||
DeptSaveReqVO req = new DeptSaveReqVO();
|
||||
req.setId(deptId);
|
||||
req.setName(limitLength(StrUtil.blankToDefault(data.getSubcompanyname(), "未命名分部"), 30));
|
||||
req.setShortName(limitLength(data.getSubcompanyname(), 20));
|
||||
// req.setShortName(limitLength(data.getSubcompanyname(), 20));
|
||||
req.setCode(trimToNull(data.getSubcompanycode()));
|
||||
req.setParentId(parentId == null ? DeptDO.PARENT_ID_ROOT : parentId);
|
||||
req.setSort(defaultSort(data.getShoworder()));
|
||||
@@ -415,7 +408,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
||||
DeptSaveReqVO req = new DeptSaveReqVO();
|
||||
req.setId(deptId);
|
||||
req.setName(limitLength(StrUtil.blankToDefault(data.getDepartmentname(), "未命名部门"), 30));
|
||||
req.setShortName(limitLength(StrUtil.blankToDefault(data.getDepartmentmark(), data.getDepartmentname()), 20));
|
||||
// req.setShortName(limitLength(StrUtil.blankToDefault(data.getDepartmentmark(), data.getDepartmentname()), 20));
|
||||
req.setCode(trimToNull(data.getDepartmentcode()));
|
||||
req.setParentId(parentId == null ? DeptDO.PARENT_ID_ROOT : parentId);
|
||||
req.setSort(defaultSort(data.getShoworder()));
|
||||
@@ -472,8 +465,8 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
||||
}
|
||||
|
||||
private ParentHolder resolveDepartmentParent(IWorkHrDepartmentPageRespVO.Department dept) {
|
||||
Long parentDeptId = toLong(dept.getParentdeptid());
|
||||
if (parentDeptId != null) {
|
||||
Long parentDeptId = toLong(dept.getSupdepid());
|
||||
if (parentDeptId != null && parentDeptId > 0) {
|
||||
return new ParentHolder(parentDeptId);
|
||||
}
|
||||
Long subcompanyId = toLong(dept.getSubcompanyid1());
|
||||
|
||||
@@ -37,6 +37,11 @@ public class IWorkSyncServiceImpl implements IWorkSyncService {
|
||||
return runFullSync(reqVO, EnumSet.of(IWorkSyncEntityTypeEnum.DEPARTMENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorkFullSyncRespVO fullSyncSubcompanies(IWorkFullSyncReqVO reqVO) {
|
||||
return runFullSync(reqVO, EnumSet.of(IWorkSyncEntityTypeEnum.SUBCOMPANY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorkFullSyncRespVO fullSyncJobTitles(IWorkFullSyncReqVO reqVO) {
|
||||
return runFullSync(reqVO, EnumSet.of(IWorkSyncEntityTypeEnum.JOB_TITLE));
|
||||
@@ -56,6 +61,7 @@ public class IWorkSyncServiceImpl implements IWorkSyncService {
|
||||
boolean syncUsers = scopes.contains(IWorkSyncEntityTypeEnum.USER);
|
||||
boolean syncDepartments = scopes.contains(IWorkSyncEntityTypeEnum.DEPARTMENT);
|
||||
boolean syncSubcompanies = scopes.contains(IWorkSyncEntityTypeEnum.SUBCOMPANY);
|
||||
boolean syncJobTitle = scopes.contains(IWorkSyncEntityTypeEnum.JOB_TITLE);
|
||||
int processedPages = 0;
|
||||
IWorkSyncProcessor.SyncOptions options = buildFullSyncOptions(reqVO);
|
||||
if (syncSubcompanies) {
|
||||
@@ -64,7 +70,7 @@ public class IWorkSyncServiceImpl implements IWorkSyncService {
|
||||
if (syncDepartments) {
|
||||
processedPages += executeDepartmentFullSync(reqVO, options, respVO.getDepartmentStat(), batchStats);
|
||||
}
|
||||
if (scopes.contains(IWorkSyncEntityTypeEnum.JOB_TITLE)) {
|
||||
if (syncJobTitle) {
|
||||
processedPages += executeJobTitleFullSync(reqVO, options, respVO.getJobTitleStat(), batchStats);
|
||||
}
|
||||
if (syncUsers) {
|
||||
|
||||
Reference in New Issue
Block a user