🐛 修复OA公司与部门主键撞号导致下级部门挂错父级
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+63
-18
@@ -1039,7 +1039,7 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
boolean isCompany = this.isOaCompany(dept);
|
||||
boolean parentExists = isCompany
|
||||
? companyByOaId.containsKey(parentOaId)
|
||||
: departmentByOaId.containsKey(parentOaId) || companyByOaId.containsKey(parentOaId);
|
||||
: this.resolveOaDepartmentParent(dept, parentOaId, companyByOaId, departmentByOaId) != null;
|
||||
// 全量数据整理后仍找不到上级:公司、部门一律删除,不改挂保留
|
||||
if (!parentExists) {
|
||||
deleteIds.add(dept.getId());
|
||||
@@ -1063,7 +1063,7 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
}
|
||||
Dept parent = this.isOaCompany(dept)
|
||||
? companyByOaId.get(parentOaId)
|
||||
: Optional.ofNullable(departmentByOaId.get(parentOaId)).orElse(companyByOaId.get(parentOaId));
|
||||
: this.resolveOaDepartmentParent(dept, parentOaId, companyByOaId, departmentByOaId);
|
||||
if (parent != null && deleteIds.contains(parent.getId())) {
|
||||
deleteIds.add(dept.getId());
|
||||
oaCascadeChanged = true;
|
||||
@@ -1175,7 +1175,10 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 OA 上级主键解析本系统父级
|
||||
* 根据 OA 上级主键解析本系统父级。
|
||||
* <p>
|
||||
* OA 公司与部门主键同属数字空间(如公司 id=19「运输事业部」与部门 id=19「投资发展部」),
|
||||
* 解析部门上级时必须按「同属公司」消歧,禁止跨公司误挂。
|
||||
*/
|
||||
private OaParentLink resolveOaParentLink(Dept dept, Map<String, Dept> companyByOaId, Map<String, Dept> departmentByOaId) {
|
||||
String parentOaId = dept.getOaSupSubComId();
|
||||
@@ -1202,21 +1205,7 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
log.warn("部门缺少上级OA主键,跳过层级重建 oaId={} deptId={}", dept.getOaId(), dept.getId());
|
||||
return null;
|
||||
}
|
||||
boolean parentIsDepartment = StringUtil.isNotBlank(dept.getParentCode())
|
||||
&& dept.getParentCode().startsWith(OAConvertConstant.DEPARTMENT_OA_PREFIX);
|
||||
boolean parentIsCompany = StringUtil.isNotBlank(dept.getParentCode())
|
||||
&& dept.getParentCode().startsWith(OAConvertConstant.COMPANY_OA_PREFIX);
|
||||
Dept parent;
|
||||
if (parentIsDepartment) {
|
||||
parent = departmentByOaId.get(parentOaId);
|
||||
} else if (parentIsCompany) {
|
||||
parent = companyByOaId.get(parentOaId);
|
||||
} else {
|
||||
parent = departmentByOaId.get(parentOaId);
|
||||
if (parent == null) {
|
||||
parent = companyByOaId.get(parentOaId);
|
||||
}
|
||||
}
|
||||
Dept parent = this.resolveOaDepartmentParent(dept, parentOaId, companyByOaId, departmentByOaId);
|
||||
if (parent == null || parent.getId() == null || Objects.equals(parent.getId(), dept.getId())) {
|
||||
log.warn("未找到上级组织,跳过层级重建 oaId={} oaSupSubComId={} deptId={}",
|
||||
dept.getOaId(), parentOaId, dept.getId());
|
||||
@@ -1227,6 +1216,62 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
return new OaParentLink(parent.getId(), this.resolveParentCode(parent, prefix, parentOaId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析部门的 OA 上级:优先同公司下的上级部门,其次所属/同号公司;避免公司与部门 oaId 撞号误挂。
|
||||
*/
|
||||
private Dept resolveOaDepartmentParent(Dept dept, String parentOaId,
|
||||
Map<String, Dept> companyByOaId, Map<String, Dept> departmentByOaId) {
|
||||
Dept belongCompany = this.findBelongCompany(dept, companyByOaId);
|
||||
// 根部门:oaSupSubComId 存的是所属公司 OA 主键
|
||||
if (belongCompany != null && StringUtil.equals(parentOaId, belongCompany.getOaId())) {
|
||||
return belongCompany;
|
||||
}
|
||||
Dept parentDept = departmentByOaId.get(parentOaId);
|
||||
if (parentDept != null && this.isSameOaCompanyTree(dept, parentDept, companyByOaId)) {
|
||||
return parentDept;
|
||||
}
|
||||
return companyByOaId.get(parentOaId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按所属公司编码或 OA 主键定位本地公司
|
||||
*/
|
||||
private Dept findBelongCompany(Dept dept, Map<String, Dept> companyByOaId) {
|
||||
if (dept == null || companyByOaId == null || companyByOaId.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (StringUtil.isNotBlank(dept.getBelongCompanyCode())) {
|
||||
for (Dept company : companyByOaId.values()) {
|
||||
if (company != null && StringUtil.equals(company.getDeptCode(), dept.getBelongCompanyCode())) {
|
||||
return company;
|
||||
}
|
||||
}
|
||||
Dept byOaId = companyByOaId.get(dept.getBelongCompanyCode());
|
||||
if (byOaId != null) {
|
||||
return byOaId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个组织是否同属一家 OA 公司(用于部门 oaId 与公司 oaId 撞号消歧)
|
||||
*/
|
||||
private boolean isSameOaCompanyTree(Dept left, Dept right, Map<String, Dept> companyByOaId) {
|
||||
if (left == null || right == null) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtil.isNotBlank(left.getBelongCompanyCode()) && StringUtil.isNotBlank(right.getBelongCompanyCode())) {
|
||||
return StringUtil.equals(left.getBelongCompanyCode(), right.getBelongCompanyCode());
|
||||
}
|
||||
Dept leftCompany = this.findBelongCompany(left, companyByOaId);
|
||||
Dept rightCompany = this.isOaCompany(right) ? right : this.findBelongCompany(right, companyByOaId);
|
||||
if (leftCompany == null || rightCompany == null || leftCompany.getId() == null || rightCompany.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(leftCompany.getId(), rightCompany.getId());
|
||||
}
|
||||
|
||||
private String resolveParentCode(Dept parent, String prefix, String parentOaId) {
|
||||
if (StringUtil.isNotBlank(parent.getDeptCode())) {
|
||||
return parent.getDeptCode();
|
||||
|
||||
+25
-3
@@ -468,10 +468,11 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
boolean companyPageFinished = Boolean.TRUE.equals(pageVO.getFinished());
|
||||
if (companyPageFinished) {
|
||||
if (companyIndex + 1 < companyOaIds.size()) {
|
||||
// 当前公司部门已拉完,进入下一公司(整体未结束,不重建层级)
|
||||
// 当前公司部门已拉完:先按 OA 主键校正父子挂载,再进入下一公司
|
||||
pageVO.setCompanyFinished(true);
|
||||
pageVO.setNextCompanyOaId(companyOaIds.get(companyIndex + 1));
|
||||
pageVO.setFinished(false);
|
||||
deptService.rebuildOaHierarchy();
|
||||
} else {
|
||||
// 全部公司轮询完成:清理白名单外组织、重建层级、清理无法挂载数据并刷新祖级列表
|
||||
pageVO.setCompanyFinished(true);
|
||||
@@ -805,9 +806,11 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
}
|
||||
String parentOaId = dept.getOaSupSubComId();
|
||||
Dept belongCompany = companyByOaId.values().stream()
|
||||
.filter(company -> StringUtils.equals(company.getDeptCode(), dept.getBelongCompanyCode()))
|
||||
.filter(company -> StringUtils.equals(company.getDeptCode(), dept.getBelongCompanyCode())
|
||||
|| StringUtils.equals(company.getOaId(), dept.getBelongCompanyCode()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
// 根部门:oaSupSubComId 即所属公司 OA 主键,必须挂公司(OA 公司/部门主键会撞号)
|
||||
if (belongCompany != null && (OAConstant.ROOT_COMPANY_ID.equals(parentOaId)
|
||||
|| StringUtils.equals(parentOaId, belongCompany.getOaId()))) {
|
||||
dept.setParentCode(belongCompany.getDeptCode());
|
||||
@@ -818,9 +821,19 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
if (parentDept == null) {
|
||||
parentDept = existingByOaId.get(parentOaId);
|
||||
}
|
||||
// 跨公司同号部门不可作为上级(例如总部部门 id=19 与公司 id=19)
|
||||
if (parentDept != null && StringUtils.isNotBlank(dept.getBelongCompanyCode())
|
||||
&& StringUtils.isNotBlank(parentDept.getBelongCompanyCode())
|
||||
&& !StringUtils.equals(dept.getBelongCompanyCode(), parentDept.getBelongCompanyCode())) {
|
||||
parentDept = null;
|
||||
}
|
||||
Dept parentCompany = StringUtils.isNotBlank(parentOaId) ? companyByOaId.get(parentOaId) : null;
|
||||
if (parentDept != null && StringUtils.isNotBlank(parentDept.getDeptCode())) {
|
||||
dept.setParentCode(parentDept.getDeptCode());
|
||||
dept.setParentId(parentDept.getId());
|
||||
} else if (parentCompany != null && StringUtils.isNotBlank(parentCompany.getDeptCode())) {
|
||||
dept.setParentCode(parentCompany.getDeptCode());
|
||||
dept.setParentId(parentCompany.getId());
|
||||
} else if (belongCompany != null) {
|
||||
// 上级部门尚未就绪时先挂所属公司,分批结束后按 OA 主键重建
|
||||
dept.setParentCode(belongCompany.getDeptCode());
|
||||
@@ -1034,7 +1047,7 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
|
||||
/**
|
||||
* oaModified 一致则跳过更新;任一侧为空无法确认一致,执行更新以补齐字段。
|
||||
* 组织编码已按新规则重算且与库中不一致时,即使 modified 相同也要更新。
|
||||
* 组织编码已按新规则重算、或父子挂载与库中不一致时,即使 modified 相同也要更新。
|
||||
*/
|
||||
private boolean shouldSkipOaUpdate(Dept existing, Dept incoming) {
|
||||
if (existing == null) {
|
||||
@@ -1044,6 +1057,15 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
&& !StringUtils.equals(existing.getDeptCode(), incoming.getDeptCode())) {
|
||||
return false;
|
||||
}
|
||||
if (incoming != null && incoming.getParentId() != null
|
||||
&& !Objects.equals(existing.getParentId(), incoming.getParentId())) {
|
||||
return false;
|
||||
}
|
||||
if (incoming != null && StringUtils.isNotBlank(incoming.getParentCode())
|
||||
&& !StringUtils.equals(StringUtils.trimToEmpty(existing.getParentCode()),
|
||||
StringUtils.trimToEmpty(incoming.getParentCode()))) {
|
||||
return false;
|
||||
}
|
||||
String localModified = StringUtils.trimToEmpty(existing.getOaModified());
|
||||
String remoteModified = StringUtils.trimToEmpty(incoming == null ? null : incoming.getOaModified());
|
||||
if (localModified.isEmpty() || remoteModified.isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user