🔀 合并 websoft/dev,解决待回单状态与汇票可选冲突
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+4
@@ -43,6 +43,7 @@ import org.springblade.core.excel.util.ExcelUtil;
|
||||
import org.springblade.core.mp.support.Condition;
|
||||
import org.springblade.core.mp.support.Query;
|
||||
import org.springblade.core.secure.annotation.PreAuth;
|
||||
import org.springblade.core.secure.constant.AuthConstant;
|
||||
import org.springblade.core.tenant.annotation.NonDS;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
@@ -117,6 +118,9 @@ public class RegionController extends BladeController {
|
||||
/**
|
||||
* 懒加载列表
|
||||
*/
|
||||
// 引用数据下拉:小程序司机认证表单的住址选择也调用本接口。小程序用户不绑定系统角色,
|
||||
// 落到类上的 menu=region 校验会抛 401,前端随即清登录态把用户踢回登录页。
|
||||
@PreAuth(AuthConstant.PERMIT_ALL)
|
||||
@GetMapping("/lazy-tree")
|
||||
@Parameters({
|
||||
@Parameter(name = "code", description = "区划编号", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
||||
|
||||
+13
@@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.tenant.annotation.NonDS;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.system.pojo.dto.MpUserEnsureDTO;
|
||||
import org.springblade.system.pojo.entity.MpUser;
|
||||
import org.springblade.system.pojo.entity.MpUserInfo;
|
||||
import org.springblade.system.pojo.vo.MpUserDataScopeVO;
|
||||
@@ -73,6 +74,18 @@ public class MpUserClient implements IMpUserClient {
|
||||
return R.data(mpUserService.getByAccount(tenantId, account));
|
||||
}
|
||||
|
||||
@Override
|
||||
@GetMapping(USER_BY_OPENID)
|
||||
public R<MpUser> userByOpenid(String tenantId, String openid) {
|
||||
return R.data(mpUserService.getByOpenid(tenantId, openid));
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostMapping(ENSURE_USER)
|
||||
public R<MpUser> ensureUser(@RequestBody MpUserEnsureDTO param) {
|
||||
return R.data(mpUserService.ensureUser(param));
|
||||
}
|
||||
|
||||
@Override
|
||||
@GetMapping(USER_INFO_BY_ID)
|
||||
public R<MpUserInfo> userInfoById(Long userId) {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
bud.user_id
|
||||
from
|
||||
blade_user_dept bud
|
||||
left join blade_dept bd on bd.dept_code = bud.dept_code
|
||||
left join blade_dept bd on bd.id = bud.dept_id and bd.is_deleted = 0
|
||||
where
|
||||
bd.id is not null
|
||||
and bud.is_deleted = 0
|
||||
|
||||
+13
@@ -24,6 +24,7 @@ package org.springblade.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springblade.core.mp.base.BaseService;
|
||||
import org.springblade.system.pojo.dto.MpUserEnsureDTO;
|
||||
import org.springblade.system.pojo.entity.MpUser;
|
||||
import org.springblade.system.pojo.entity.MpUserInfo;
|
||||
import org.springblade.system.pojo.vo.MpUserDataScopeVO;
|
||||
@@ -48,6 +49,18 @@ public interface IMpUserService extends BaseService<MpUser> {
|
||||
*/
|
||||
MpUser getByAccount(String tenantId, String account);
|
||||
|
||||
/**
|
||||
* 按租户 + 微信小程序 openid 查询
|
||||
*/
|
||||
MpUser getByOpenid(String tenantId, String openid);
|
||||
|
||||
/**
|
||||
* 查找或创建小程序用户(登录路径专用)
|
||||
* <p>
|
||||
* 与 {@link #submit} 的提交式语义相反:手机号已存在时直接返回已有账号,且不改其身份。
|
||||
*/
|
||||
MpUser ensureUser(MpUserEnsureDTO param);
|
||||
|
||||
/**
|
||||
* 按主键组装登录信息
|
||||
*/
|
||||
|
||||
+108
@@ -24,7 +24,9 @@ package org.springblade.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.common.utils.PasswordRuleUtil;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||
@@ -34,10 +36,12 @@ import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springblade.core.tool.utils.DigestUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springblade.system.cache.MpUserCache;
|
||||
import org.springblade.system.cache.SysCache;
|
||||
import org.springblade.system.mapper.MpUserDataScopeMapper;
|
||||
import org.springblade.system.mapper.MpUserMapper;
|
||||
import org.springblade.system.pojo.dto.MpUserEnsureDTO;
|
||||
import org.springblade.system.pojo.entity.MpUser;
|
||||
import org.springblade.system.pojo.entity.MpUserDataScope;
|
||||
import org.springblade.system.pojo.entity.MpUserInfo;
|
||||
@@ -58,6 +62,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> implements IMpUserService {
|
||||
@@ -73,6 +78,16 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
|
||||
/** 数据层级范围:仅本级 */
|
||||
private static final int DATA_LEVEL_CURRENT_ONLY = 2;
|
||||
|
||||
/**
|
||||
* 兜底租户:与 blade_mp_user.tenant_id 的建表默认值一致
|
||||
*/
|
||||
private static final String DEFAULT_TENANT_ID = "000000";
|
||||
|
||||
/**
|
||||
* 登录请求携带租户的请求头名
|
||||
*/
|
||||
private static final String TENANT_HEADER = "Tenant-Id";
|
||||
|
||||
private final MpUserDataScopeMapper mpUserDataScopeMapper;
|
||||
|
||||
@Override
|
||||
@@ -99,6 +114,92 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MpUser getByOpenid(String tenantId, String openid) {
|
||||
if (Func.isBlank(tenantId) || Func.isBlank(openid)) {
|
||||
return null;
|
||||
}
|
||||
return getOne(Wrappers.<MpUser>lambdaQuery()
|
||||
.eq(MpUser::getTenantId, tenantId)
|
||||
.eq(MpUser::getOpenid, openid)
|
||||
.orderByDesc(MpUser::getCreateTime)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MpUser ensureUser(MpUserEnsureDTO param) {
|
||||
if (param == null) {
|
||||
throw new ServiceException("小程序用户参数不能为空");
|
||||
}
|
||||
String tenantId = resolveEnsureTenantId(param.getTenantId());
|
||||
String phone = trimToNull(param.getPhone());
|
||||
if (Func.isBlank(phone)) {
|
||||
throw new ServiceException("手机号不能为空");
|
||||
}
|
||||
// 先查后插:命中即返回,不新建也不改身份。租户为空时唯一键对 NULL 不去重,
|
||||
// 故 resolveEnsureTenantId 已在写库前把租户兜到非空。
|
||||
MpUser existed = getByPhone(tenantId, phone);
|
||||
if (existed != null && Func.isNotEmpty(existed.getId())) {
|
||||
return existed;
|
||||
}
|
||||
MpUser user = new MpUser();
|
||||
user.setTenantId(tenantId);
|
||||
user.setPhone(phone);
|
||||
user.setAccount(phone);
|
||||
user.setIdentities(MpUserIdentity.DRIVER.getCode());
|
||||
user.setOpenid(trimToNull(param.getOpenid()));
|
||||
user.setStatus(1);
|
||||
prepare(user);
|
||||
validate(user);
|
||||
// 登录路径不设密码,password 保持为空
|
||||
user.setPassword(null);
|
||||
try {
|
||||
save(user);
|
||||
} catch (Exception exception) {
|
||||
// 并发建号撞 (tenant_id, phone) 唯一键:重读一次并返回已有账号
|
||||
MpUser concurrent = getByPhone(tenantId, phone);
|
||||
if (concurrent != null && Func.isNotEmpty(concurrent.getId())) {
|
||||
return concurrent;
|
||||
}
|
||||
log.warn("小程序用户建号失败,租户={} 手机号={}", tenantId, phone, exception);
|
||||
throw new ServiceException("创建小程序用户失败");
|
||||
}
|
||||
if (Func.isEmpty(user.getId())) {
|
||||
throw new ServiceException("创建小程序用户失败");
|
||||
}
|
||||
MpUserCache.clear();
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录路径的租户解析:Tenant-Id 头 → 入参 tenantId → 默认租户
|
||||
* <p>
|
||||
* 请求头与入参不一致时以请求头为准。写库前必须得到非空值:唯一键 (tenant_id, phone)
|
||||
* 对 NULL 不去重,租户为 NULL 会为同一手机号造出重复账号。
|
||||
*/
|
||||
private String resolveEnsureTenantId(String tenantId) {
|
||||
String resolved = requestHeaderTenantId();
|
||||
if (resolved == null) {
|
||||
resolved = trimToNull(tenantId);
|
||||
}
|
||||
if (resolved == null) {
|
||||
resolved = DEFAULT_TENANT_ID;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前请求头里的租户;无请求上下文时返回 null
|
||||
*/
|
||||
private String requestHeaderTenantId() {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
return trimToNull(request.getHeader(TENANT_HEADER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MpUserInfo userInfo(Long userId) {
|
||||
if (Func.isEmpty(userId)) {
|
||||
@@ -324,6 +425,13 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
|
||||
if (!tenantId.equals(user.getTenantId())) {
|
||||
throw new ServiceException("租户不匹配,无法绑定 openid");
|
||||
}
|
||||
// 目标账号已有另一个非空 openid 时不覆盖:一个微信换绑由管理员处理,
|
||||
// 登录路径直接放弃本次绑定
|
||||
if (Func.isNotBlank(user.getOpenid()) && !user.getOpenid().equals(openid)) {
|
||||
log.warn("小程序用户已绑定其他 openid,跳过绑定:租户={} 账号={} 已有openid={} 本次openid={}",
|
||||
tenantId, userId, user.getOpenid(), openid);
|
||||
return false;
|
||||
}
|
||||
MpUser byOpenId = getOne(Wrappers.<MpUser>lambdaQuery()
|
||||
.eq(MpUser::getTenantId, tenantId)
|
||||
.eq(MpUser::getOpenid, openid)
|
||||
|
||||
+18
-6
@@ -277,6 +277,11 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
}, 10000, ComposeLogUtil.getLastLog()::info).accept(oaPersons::addAll);
|
||||
OaUserListSyncHelper.OaOrgIndex orgIndex = oaUserListSyncHelper.syncOrgsFromPersons(oaPersons);
|
||||
OaUserListSyncHelper.PersonSyncCount personSyncCount = oaUserListSyncHelper.handlePerson(oaPersons, orgIndex);
|
||||
if (startTime == null) {
|
||||
oaUserListSyncHelper.removeOaUsersAbsentFrom(
|
||||
oaUserListSyncHelper.extractOaLoginIds(oaPersons),
|
||||
oaUserListSyncHelper.extractWorkcodes(oaPersons));
|
||||
}
|
||||
CacheUtil.clear(USER_CACHE);
|
||||
CacheUtil.clear(SYS_CACHE);
|
||||
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
||||
@@ -295,9 +300,10 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
private OaPersonSyncPageVO syncPersonFromOaPage(int current, int size, boolean incremental, String modifiedSince) {
|
||||
int pageNo = current < 1 ? 1 : current;
|
||||
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
||||
// 全量同步首页开启原始数据收集,结束后按父级 id 写入 JSON
|
||||
// 全量同步首页开启原始数据收集,并开始累积登录名,最后一页再删除本地多余人员
|
||||
if (!incremental && pageNo == 1) {
|
||||
oaSyncRawDumpHelper.beginFullDump();
|
||||
oaUserListSyncHelper.beginFullSyncReconcile();
|
||||
}
|
||||
IncrementalStart incrementalStart = resolvePersonIncrementalStart(incremental, modifiedSince);
|
||||
OAPersonSearch personSearch = buildPersonSearch(incrementalStart.getStartTime());
|
||||
@@ -314,9 +320,17 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
long totalSize = responseData.getTotalSize() == null ? 0L : responseData.getTotalSize();
|
||||
if (!incremental) {
|
||||
oaSyncRawDumpHelper.collectPersons(oaPersons);
|
||||
oaUserListSyncHelper.collectFullSyncPersons(oaPersons);
|
||||
}
|
||||
OaUserListSyncHelper.OaOrgIndex orgIndex = oaUserListSyncHelper.syncOrgsFromPersons(oaPersons);
|
||||
OaUserListSyncHelper.PersonSyncCount personSyncCount = oaUserListSyncHelper.handlePerson(oaPersons, orgIndex);
|
||||
boolean finished = oaPersons.isEmpty()
|
||||
|| oaPersons.size() < pageSize
|
||||
|| (long) pageNo * pageSize >= totalSize;
|
||||
int removedCount = personSyncCount.getRemovedCount();
|
||||
if (!incremental && finished) {
|
||||
removedCount += oaUserListSyncHelper.finishFullSyncReconcile();
|
||||
}
|
||||
CacheUtil.clear(USER_CACHE);
|
||||
CacheUtil.clear(SYS_CACHE);
|
||||
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
||||
@@ -327,17 +341,15 @@ public class OASyncServiceImpl implements IOASyncService {
|
||||
pageVO.setFetchedCount(oaPersons.size());
|
||||
pageVO.setSyncedCount(personSyncCount.getSyncedCount());
|
||||
pageVO.setSkippedCount(personSyncCount.getSkippedCount());
|
||||
pageVO.setRemovedCount(removedCount);
|
||||
pageVO.setModifiedSince(incrementalStart.getModifiedSince());
|
||||
boolean finished = oaPersons.isEmpty()
|
||||
|| oaPersons.size() < pageSize
|
||||
|| (long) pageNo * pageSize >= totalSize;
|
||||
pageVO.setFinished(finished);
|
||||
if (!incremental && finished) {
|
||||
pageVO.setDumpFilePath(oaSyncRawDumpHelper.finishFullDump());
|
||||
}
|
||||
ComposeLogUtil.getLastLog().info("OA人员分页同步完成 mode={} {}/{},成功{},跳过{}",
|
||||
ComposeLogUtil.getLastLog().info("OA人员分页同步完成 mode={} {}/{},成功{},跳过{},删除{}",
|
||||
incremental ? "incremental" : "full", pageNo, totalSize,
|
||||
personSyncCount.getSyncedCount(), personSyncCount.getSkippedCount());
|
||||
personSyncCount.getSyncedCount(), personSyncCount.getSkippedCount(), removedCount);
|
||||
return pageVO;
|
||||
}
|
||||
|
||||
|
||||
+434
-46
@@ -30,6 +30,7 @@ import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springblade.common.constant.CommonConstant;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.DigestUtil;
|
||||
@@ -55,10 +56,12 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springblade.common.constant.CommonConstant.DEFAULT_PARAM_PASSWORD;
|
||||
@@ -76,6 +79,22 @@ public class OaUserListSyncHelper {
|
||||
|
||||
private static final int MAX_DEPT_ID_LENGTH = 2000;
|
||||
|
||||
private static final int OA_LOGIN_ID_BATCH_SIZE = 500;
|
||||
|
||||
/**
|
||||
* OA 人员状态:5 离职。离职人员不入库,已有 is_oa=2 账号直接删除。
|
||||
*/
|
||||
private static final String OA_PERSON_STATUS_RESIGNED = "5";
|
||||
|
||||
/**
|
||||
* 全量同步跨页累积的 OA 登录名。分页接口每页独立事务,删除必须等最后一页再执行。
|
||||
*/
|
||||
private final Set<String> fullSyncLoginIds = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private final Set<String> fullSyncWorkcodes = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private volatile boolean fullSyncCollecting;
|
||||
|
||||
private final IDeptService deptService;
|
||||
private final IUserService userService;
|
||||
private final UserConvert userConvert;
|
||||
@@ -390,48 +409,325 @@ public class OaUserListSyncHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步人员并绑定到三级部门
|
||||
* 全量同步从第一页开始收集 OA 登录名,最后一页再删除本地多余的 is_oa=2 人员。
|
||||
*/
|
||||
public synchronized void beginFullSyncReconcile() {
|
||||
this.fullSyncLoginIds.clear();
|
||||
this.fullSyncWorkcodes.clear();
|
||||
this.fullSyncCollecting = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 累积本页 OA 人员登录名,供全量同步结束后比对删除。
|
||||
*
|
||||
* @param oaPersons 本页 OA 人员
|
||||
*/
|
||||
public synchronized void collectFullSyncPersons(List<OAPersonResponse> oaPersons) {
|
||||
if (!this.fullSyncCollecting || CollectionUtil.isEmpty(oaPersons)) {
|
||||
return;
|
||||
}
|
||||
this.fullSyncLoginIds.addAll(this.extractOaLoginIds(oaPersons));
|
||||
this.fullSyncWorkcodes.addAll(this.extractWorkcodes(oaPersons));
|
||||
}
|
||||
|
||||
/**
|
||||
* 全量同步结束后,删除登录名不在本次 OA 数据中的 is_oa=2 人员。
|
||||
*
|
||||
* @return 删除人数;未开始收集或登录名集合为空时返回 0,避免误删全部 OA 人员
|
||||
*/
|
||||
public synchronized int finishFullSyncReconcile() {
|
||||
if (!this.fullSyncCollecting) {
|
||||
return 0;
|
||||
}
|
||||
this.fullSyncCollecting = false;
|
||||
Set<String> oaLoginIds = new LinkedHashSet<>(this.fullSyncLoginIds);
|
||||
Set<String> workcodes = new LinkedHashSet<>(this.fullSyncWorkcodes);
|
||||
this.fullSyncLoginIds.clear();
|
||||
this.fullSyncWorkcodes.clear();
|
||||
return this.removeOaUsersAbsentFrom(oaLoginIds, workcodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取仍在职的 OA 人员登录名。离职人员不计入,全量同步结束时会删掉对应本地账号。
|
||||
*
|
||||
* @param oaPersons OA人员
|
||||
* @return 去重后的登录名
|
||||
*/
|
||||
public Set<String> extractOaLoginIds(List<OAPersonResponse> oaPersons) {
|
||||
Set<String> oaLoginIds = new LinkedHashSet<>();
|
||||
if (CollectionUtil.isEmpty(oaPersons)) {
|
||||
return oaLoginIds;
|
||||
}
|
||||
for (OAPersonResponse oaPerson : oaPersons) {
|
||||
String oaLoginId = this.resolveOaLoginId(oaPerson);
|
||||
if (oaLoginId != null && !this.isOaResigned(oaPerson)) {
|
||||
oaLoginIds.add(oaLoginId);
|
||||
}
|
||||
}
|
||||
return oaLoginIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取仍在职人员的工号。没有登录名时靠工号保留本地账号。
|
||||
*
|
||||
* @param oaPersons OA人员
|
||||
* @return 去重后的工号
|
||||
*/
|
||||
public Set<String> extractWorkcodes(List<OAPersonResponse> oaPersons) {
|
||||
Set<String> workcodes = new LinkedHashSet<>();
|
||||
if (CollectionUtil.isEmpty(oaPersons)) {
|
||||
return workcodes;
|
||||
}
|
||||
for (OAPersonResponse oaPerson : oaPersons) {
|
||||
String workcode = this.resolveWorkcode(oaPerson);
|
||||
if (workcode != null && !this.isOaResigned(oaPerson)) {
|
||||
workcodes.add(workcode);
|
||||
}
|
||||
}
|
||||
return workcodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当前租户中 is_oa=2、且既不在本次登录名里、也不是无登录名工号人员的账号。
|
||||
* 登录名和工号都没收集到时不删除。当前登录账号即使不在同步数据中也保留。
|
||||
*
|
||||
* @param oaLoginIds 本次全量同步出现过的 OA 登录名
|
||||
* @param workcodes 本次全量同步出现过的工号
|
||||
* @return 删除人数
|
||||
*/
|
||||
public int removeOaUsersAbsentFrom(Set<String> oaLoginIds, Set<String> workcodes) {
|
||||
boolean noLoginIds = CollectionUtil.isEmpty(oaLoginIds);
|
||||
boolean noWorkcodes = CollectionUtil.isEmpty(workcodes);
|
||||
if (noLoginIds && noWorkcodes) {
|
||||
ComposeLogUtil.getLastLog().warn("全量同步未收集到OA登录名和工号,跳过删除本地 is_oa=2 人员");
|
||||
return 0;
|
||||
}
|
||||
Set<String> loginIdSet = noLoginIds ? Set.of() : oaLoginIds;
|
||||
Set<String> workcodeSet = noWorkcodes ? Set.of() : workcodes;
|
||||
String tenantId = this.resolveTenantId();
|
||||
List<User> oaUsers = this.userService.list(Wrappers.<User>lambdaQuery()
|
||||
.select(User::getId, User::getOaLoginId, User::getCode)
|
||||
.eq(User::getTenantId, tenantId)
|
||||
.eq(User::getIsOa, CommonConstant.YES));
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
List<Long> removeIds = new ArrayList<>();
|
||||
for (User oaUser : oaUsers) {
|
||||
if (oaUser.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
if (currentUserId != null && currentUserId > 0 && currentUserId.equals(oaUser.getId())) {
|
||||
ComposeLogUtil.getLastLog().warn("全量同步跳过删除当前登录账号 userId={}", oaUser.getId());
|
||||
continue;
|
||||
}
|
||||
String oaLoginId = StringUtils.trimToNull(oaUser.getOaLoginId());
|
||||
String workcode = StringUtils.trimToNull(oaUser.getCode());
|
||||
boolean keptByLoginId = oaLoginId != null && loginIdSet.contains(oaLoginId);
|
||||
boolean keptByWorkcode = oaLoginId == null && workcode != null && workcodeSet.contains(workcode);
|
||||
if (!keptByLoginId && !keptByWorkcode) {
|
||||
removeIds.add(oaUser.getId());
|
||||
}
|
||||
}
|
||||
if (removeIds.isEmpty()) {
|
||||
ComposeLogUtil.getLastLog().info("全量同步无需删除 is_oa=2 人员");
|
||||
return 0;
|
||||
}
|
||||
return this.deleteOaUsers(removeIds, "全量同步删除不在OA数据中的 is_oa=2 人员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 按 OA 登录名删除已有 is_oa=2 人员。用于离职人员,全量和增量同步都会执行。
|
||||
*
|
||||
* @param tenantId 租户
|
||||
* @param oaLoginIds 离职人员登录名
|
||||
* @return 删除人数
|
||||
*/
|
||||
private int removeOaUsersByLoginIds(String tenantId, Collection<String> oaLoginIds) {
|
||||
if (CollectionUtil.isEmpty(oaLoginIds)) {
|
||||
return 0;
|
||||
}
|
||||
List<String> oaLoginIdList = oaLoginIds.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (oaLoginIdList.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
List<Long> removeIds = new ArrayList<>();
|
||||
for (int fromIndex = 0; fromIndex < oaLoginIdList.size(); fromIndex += OA_LOGIN_ID_BATCH_SIZE) {
|
||||
List<String> oaLoginIdBatch = oaLoginIdList.subList(fromIndex, Math.min(fromIndex + OA_LOGIN_ID_BATCH_SIZE, oaLoginIdList.size()));
|
||||
this.userService.list(Wrappers.<User>lambdaQuery()
|
||||
.select(User::getId, User::getOaLoginId)
|
||||
.eq(User::getTenantId, tenantId)
|
||||
.eq(User::getIsOa, CommonConstant.YES)
|
||||
.in(User::getOaLoginId, oaLoginIdBatch))
|
||||
.forEach(oaUser -> {
|
||||
if (oaUser.getId() == null) {
|
||||
return;
|
||||
}
|
||||
if (currentUserId != null && currentUserId > 0 && currentUserId.equals(oaUser.getId())) {
|
||||
ComposeLogUtil.getLastLog().warn("同步跳过删除当前登录账号 userId={}", oaUser.getId());
|
||||
return;
|
||||
}
|
||||
removeIds.add(oaUser.getId());
|
||||
});
|
||||
}
|
||||
return this.deleteOaUsers(removeIds, "同步删除OA离职人员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除没有登录名、且工号属于离职人员的 is_oa=2 账号。
|
||||
*
|
||||
* @param tenantId 租户
|
||||
* @param workcodes 离职人员工号
|
||||
* @return 删除人数
|
||||
*/
|
||||
private int removeOaUsersByBlankLoginWorkcodes(String tenantId, Collection<String> workcodes) {
|
||||
if (CollectionUtil.isEmpty(workcodes)) {
|
||||
return 0;
|
||||
}
|
||||
List<String> workcodeList = workcodes.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (workcodeList.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
List<Long> removeIds = new ArrayList<>();
|
||||
for (int fromIndex = 0; fromIndex < workcodeList.size(); fromIndex += OA_LOGIN_ID_BATCH_SIZE) {
|
||||
List<String> workcodeBatch = workcodeList.subList(fromIndex, Math.min(fromIndex + OA_LOGIN_ID_BATCH_SIZE, workcodeList.size()));
|
||||
this.userService.list(Wrappers.<User>lambdaQuery()
|
||||
.select(User::getId, User::getOaLoginId, User::getCode)
|
||||
.eq(User::getTenantId, tenantId)
|
||||
.eq(User::getIsOa, CommonConstant.YES)
|
||||
.in(User::getCode, workcodeBatch)
|
||||
.and(wrapper -> wrapper.isNull(User::getOaLoginId).or().eq(User::getOaLoginId, "")))
|
||||
.forEach(oaUser -> {
|
||||
if (oaUser.getId() == null) {
|
||||
return;
|
||||
}
|
||||
if (currentUserId != null && currentUserId > 0 && currentUserId.equals(oaUser.getId())) {
|
||||
ComposeLogUtil.getLastLog().warn("同步跳过删除当前登录账号 userId={}", oaUser.getId());
|
||||
return;
|
||||
}
|
||||
removeIds.add(oaUser.getId());
|
||||
});
|
||||
}
|
||||
return this.deleteOaUsers(removeIds, "同步删除无登录名的OA离职人员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 逻辑删除用户及其部门关系。
|
||||
*
|
||||
* @param removeIds 用户 id
|
||||
* @param logMessage 日志说明
|
||||
* @return 删除人数
|
||||
*/
|
||||
private int deleteOaUsers(List<Long> removeIds, String logMessage) {
|
||||
if (CollectionUtil.isEmpty(removeIds)) {
|
||||
return 0;
|
||||
}
|
||||
for (int fromIndex = 0; fromIndex < removeIds.size(); fromIndex += OA_LOGIN_ID_BATCH_SIZE) {
|
||||
List<Long> removeIdBatch = removeIds.subList(fromIndex, Math.min(fromIndex + OA_LOGIN_ID_BATCH_SIZE, removeIds.size()));
|
||||
this.userService.deleteLogic(removeIdBatch);
|
||||
this.userDeptService.remove(Wrappers.<UserDept>lambdaQuery().in(UserDept::getUserId, removeIdBatch));
|
||||
}
|
||||
ComposeLogUtil.getLastLog().info("{}:{}", logMessage, removeIds.size());
|
||||
return removeIds.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* OA 状态 5 表示离职。
|
||||
*/
|
||||
private boolean isOaResigned(OAPersonResponse oaPerson) {
|
||||
return oaPerson != null && OA_PERSON_STATUS_RESIGNED.equals(StringUtils.trimToEmpty(oaPerson.getStatus()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步人员并绑定到三级部门。有登录名按登录名更新,没有登录名但有工号则按工号更新且不回填登录名。离职人员直接删除。
|
||||
*
|
||||
* @param oaPersons OA人员
|
||||
* @param orgIndex 组织索引
|
||||
* @return 本批同步成功与跳过数量
|
||||
* @return 本批同步成功、跳过与删除数量
|
||||
*/
|
||||
public PersonSyncCount handlePerson(List<OAPersonResponse> oaPersons, OaOrgIndex orgIndex) {
|
||||
if (CollectionUtil.isEmpty(oaPersons)) {
|
||||
return new PersonSyncCount(0, 0);
|
||||
return new PersonSyncCount(0, 0, 0);
|
||||
}
|
||||
Map<String, OAPersonResponse> uniquePersonMap = new LinkedHashMap<>();
|
||||
Set<String> resignedLoginIds = new LinkedHashSet<>();
|
||||
Set<String> resignedWorkcodes = new LinkedHashSet<>();
|
||||
int skippedCount = 0;
|
||||
for (OAPersonResponse oaPerson : oaPersons) {
|
||||
String oaLoginId = resolveOaLoginId(oaPerson);
|
||||
if (StringUtils.isBlank(oaLoginId)) {
|
||||
String syncKey = this.resolveSyncKey(oaPerson);
|
||||
if (syncKey == null) {
|
||||
skippedCount++;
|
||||
continue;
|
||||
}
|
||||
uniquePersonMap.put(oaLoginId, oaPerson);
|
||||
}
|
||||
if (uniquePersonMap.isEmpty()) {
|
||||
ComposeLogUtil.getLastLog().warn("OA人员均缺少登录名,跳过人员同步");
|
||||
return new PersonSyncCount(0, skippedCount);
|
||||
String oaLoginId = this.resolveOaLoginId(oaPerson);
|
||||
String workcode = this.resolveWorkcode(oaPerson);
|
||||
if (this.isOaResigned(oaPerson)) {
|
||||
uniquePersonMap.remove(syncKey);
|
||||
if (oaLoginId != null) {
|
||||
resignedLoginIds.add(oaLoginId);
|
||||
} else if (workcode != null) {
|
||||
resignedWorkcodes.add(workcode);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (oaLoginId != null) {
|
||||
resignedLoginIds.remove(oaLoginId);
|
||||
} else if (workcode != null) {
|
||||
resignedWorkcodes.remove(workcode);
|
||||
}
|
||||
uniquePersonMap.put(syncKey, oaPerson);
|
||||
}
|
||||
String tenantId = resolveTenantId();
|
||||
int removedCount = this.removeOaUsersByLoginIds(tenantId, resignedLoginIds)
|
||||
+ this.removeOaUsersByBlankLoginWorkcodes(tenantId, resignedWorkcodes);
|
||||
if (uniquePersonMap.isEmpty()) {
|
||||
if (resignedLoginIds.isEmpty() && resignedWorkcodes.isEmpty()) {
|
||||
ComposeLogUtil.getLastLog().warn("OA人员均缺少登录名和工号,跳过人员同步");
|
||||
}
|
||||
return new PersonSyncCount(0, skippedCount, removedCount);
|
||||
}
|
||||
String defaultPassword = DigestUtil.encrypt(ParamCache.getValue(DEFAULT_PARAM_PASSWORD));
|
||||
List<User> users = uniquePersonMap.entrySet().stream()
|
||||
.map(entry -> {
|
||||
User user = userConvert.person2user(entry.getValue(), defaultPassword);
|
||||
user.setTenantId(tenantId);
|
||||
user.setOaLoginId(entry.getKey());
|
||||
user.setAccount(entry.getKey());
|
||||
return user;
|
||||
})
|
||||
.toList();
|
||||
Map<String, User> existingByOaLoginId = this.loadUsersByOaLoginId(tenantId, uniquePersonMap.keySet());
|
||||
Set<String> oaLoginIds = new LinkedHashSet<>();
|
||||
Set<String> workcodes = new LinkedHashSet<>();
|
||||
for (OAPersonResponse oaPerson : uniquePersonMap.values()) {
|
||||
String oaLoginId = this.resolveOaLoginId(oaPerson);
|
||||
if (oaLoginId != null) {
|
||||
oaLoginIds.add(oaLoginId);
|
||||
continue;
|
||||
}
|
||||
String workcode = this.resolveWorkcode(oaPerson);
|
||||
if (workcode != null) {
|
||||
workcodes.add(workcode);
|
||||
}
|
||||
}
|
||||
Map<String, User> existingByOaLoginId = this.loadUsersByOaLoginId(tenantId, oaLoginIds);
|
||||
Map<String, User> existingByWorkcode = this.loadUsersByBlankLoginWorkcode(tenantId, workcodes);
|
||||
List<User> users = new ArrayList<>();
|
||||
Map<String, Long> userMap = new HashMap<>();
|
||||
Set<Long> existsUserIds = new HashSet<>();
|
||||
users.forEach(user -> {
|
||||
User existingUser = existingByOaLoginId.get(user.getOaLoginId());
|
||||
for (Map.Entry<String, OAPersonResponse> entry : uniquePersonMap.entrySet()) {
|
||||
OAPersonResponse oaPerson = entry.getValue();
|
||||
String oaLoginId = this.resolveOaLoginId(oaPerson);
|
||||
String workcode = this.resolveWorkcode(oaPerson);
|
||||
User user = this.userConvert.person2user(oaPerson, defaultPassword);
|
||||
user.setTenantId(tenantId);
|
||||
User existingUser = oaLoginId != null ? existingByOaLoginId.get(oaLoginId) : existingByWorkcode.get(workcode);
|
||||
if (oaLoginId != null) {
|
||||
user.setOaLoginId(oaLoginId);
|
||||
user.setAccount(oaLoginId);
|
||||
} else {
|
||||
user.setOaLoginId(null);
|
||||
user.setAccount(existingUser == null ? workcode : null);
|
||||
}
|
||||
if (existingUser != null) {
|
||||
user.setId(existingUser.getId());
|
||||
// 全局更新策略为 not_null,置空后不会回写密码和登录名
|
||||
user.setPassword(null);
|
||||
existsUserIds.add(existingUser.getId());
|
||||
} else {
|
||||
@@ -442,9 +738,10 @@ public class OaUserListSyncHelper {
|
||||
user.setDataLevelRange(1);
|
||||
user.setIncludeNewCustomer(0);
|
||||
}
|
||||
userService.encryptPhone(user);
|
||||
userMap.put(user.getOaLoginId(), user.getId());
|
||||
});
|
||||
this.userService.encryptPhone(user);
|
||||
users.add(user);
|
||||
userMap.put(entry.getKey(), user.getId());
|
||||
}
|
||||
|
||||
List<User> addUsers = users.stream()
|
||||
.filter(user -> !existsUserIds.contains(user.getId()))
|
||||
@@ -460,33 +757,58 @@ public class OaUserListSyncHelper {
|
||||
ComposeLogUtil.getLastLog().info("批量修改用户:{}", updateUsers.size());
|
||||
userService.updateBatchById(updateUsers);
|
||||
}
|
||||
ComposeLogUtil.getLastLog().info("缺少OA登录名已跳过的人员:{}", skippedCount);
|
||||
ComposeLogUtil.getLastLog().info("缺少登录名和工号已跳过的人员:{}", skippedCount);
|
||||
int syncedCount = addUsers.size() + updateUsers.size();
|
||||
if (userMap.isEmpty()) {
|
||||
return new PersonSyncCount(0, skippedCount);
|
||||
return new PersonSyncCount(0, skippedCount, removedCount);
|
||||
}
|
||||
|
||||
Map<String, Long> userDeptMap = userDeptService.list(Wrappers.<UserDept>lambdaQuery()
|
||||
.in(UserDept::getUserId, userMap.values())
|
||||
).stream()
|
||||
List<UserDept> existingUserDeptList = userDeptService.list(Wrappers.<UserDept>lambdaQuery()
|
||||
.in(UserDept::getUserId, userMap.values()));
|
||||
Map<String, Long> userDeptMap = existingUserDeptList.stream()
|
||||
.collect(Collectors.toMap(this::getUserDeptKey, UserDept::getId, (first, second) -> second));
|
||||
Set<Long> existsUserDeptIds = new HashSet<>(userDeptMap.values());
|
||||
List<UserDept> userDeptList = oaPersons.stream()
|
||||
Map<String, UserDept> currentUserDeptMap = new LinkedHashMap<>();
|
||||
oaPersons.stream()
|
||||
.filter(oaPerson -> {
|
||||
String oaLoginId = resolveOaLoginId(oaPerson);
|
||||
return StringUtils.isNotBlank(oaLoginId) && userMap.containsKey(oaLoginId);
|
||||
String syncKey = this.resolveSyncKey(oaPerson);
|
||||
return syncKey != null && userMap.containsKey(syncKey) && !this.isOaResigned(oaPerson);
|
||||
})
|
||||
.map(oaPerson -> this.buildUserDept(oaPerson, userMap, orgIndex))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(userDept -> {
|
||||
String userDeptKey = getUserDeptKey(userDept);
|
||||
if (userDeptMap.containsKey(userDeptKey)) {
|
||||
userDept.setId(userDeptMap.get(userDeptKey));
|
||||
} else {
|
||||
UserDept duplicated = currentUserDeptMap.get(userDeptKey);
|
||||
userDept.setId(duplicated == null
|
||||
? DefaultIdentifierGenerator.getInstance().nextId(null)
|
||||
: duplicated.getId());
|
||||
}
|
||||
currentUserDeptMap.put(userDeptKey, userDept);
|
||||
});
|
||||
List<UserDept> userDeptList = new ArrayList<>(currentUserDeptMap.values());
|
||||
Set<Long> currentUserDeptIds = userDeptList.stream()
|
||||
.map(UserDept::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Set<Long> reboundUserIds = userDeptList.stream()
|
||||
.map(UserDept::getUserId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
List<Long> staleUserDeptIds = existingUserDeptList.stream()
|
||||
.filter(userDept -> userDept.getId() != null && reboundUserIds.contains(userDept.getUserId()))
|
||||
.map(UserDept::getId)
|
||||
.filter(userDeptId -> !currentUserDeptIds.contains(userDeptId))
|
||||
.toList();
|
||||
userDeptList.forEach(userDept -> {
|
||||
String userDeptKey = getUserDeptKey(userDept);
|
||||
if (userDeptMap.containsKey(userDeptKey)) {
|
||||
userDept.setId(userDeptMap.get(userDeptKey));
|
||||
} else {
|
||||
userDept.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
|
||||
if (CollectionUtil.isNotEmpty(staleUserDeptIds)) {
|
||||
ComposeLogUtil.getLastLog().info("移除不再属于当前OA部门的人员关系:{}", staleUserDeptIds.size());
|
||||
for (int fromIndex = 0; fromIndex < staleUserDeptIds.size(); fromIndex += OA_LOGIN_ID_BATCH_SIZE) {
|
||||
List<Long> staleIdBatch = staleUserDeptIds.subList(fromIndex, Math.min(fromIndex + OA_LOGIN_ID_BATCH_SIZE, staleUserDeptIds.size()));
|
||||
userDeptService.removeByIds(staleIdBatch);
|
||||
}
|
||||
});
|
||||
}
|
||||
List<UserDept> addList = userDeptList.stream()
|
||||
.filter(userDept -> !existsUserDeptIds.contains(userDept.getId()))
|
||||
.toList();
|
||||
@@ -540,11 +862,11 @@ public class OaUserListSyncHelper {
|
||||
if (CollectionUtil.isNotEmpty(updateUserParams)) {
|
||||
userService.updateBatchById(updateUserParams);
|
||||
}
|
||||
return new PersonSyncCount(syncedCount, skippedCount);
|
||||
return new PersonSyncCount(syncedCount, skippedCount, removedCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按 OA 登录名加载已有用户。同一登录名有多条时保留较早的一条,后续同步都更新这一条。
|
||||
* 按 OA 登录名加载已有 is_oa=2 用户。同一登录名有多条时保留较早的一条,后续同步都更新这一条。
|
||||
*/
|
||||
private Map<String, User> loadUsersByOaLoginId(String tenantId, Collection<String> oaLoginIds) {
|
||||
Map<String, User> existingByOaLoginId = new HashMap<>();
|
||||
@@ -555,11 +877,11 @@ public class OaUserListSyncHelper {
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
int batchSize = 500;
|
||||
for (int fromIndex = 0; fromIndex < oaLoginIdList.size(); fromIndex += batchSize) {
|
||||
List<String> oaLoginIdBatch = oaLoginIdList.subList(fromIndex, Math.min(fromIndex + batchSize, oaLoginIdList.size()));
|
||||
for (int fromIndex = 0; fromIndex < oaLoginIdList.size(); fromIndex += OA_LOGIN_ID_BATCH_SIZE) {
|
||||
List<String> oaLoginIdBatch = oaLoginIdList.subList(fromIndex, Math.min(fromIndex + OA_LOGIN_ID_BATCH_SIZE, oaLoginIdList.size()));
|
||||
userService.list(Wrappers.<User>lambdaQuery()
|
||||
.eq(User::getTenantId, tenantId)
|
||||
.eq(User::getIsOa, CommonConstant.YES)
|
||||
.in(User::getOaLoginId, oaLoginIdBatch))
|
||||
.forEach(user -> {
|
||||
String oaLoginId = StringUtils.trimToNull(user.getOaLoginId());
|
||||
@@ -584,6 +906,39 @@ public class OaUserListSyncHelper {
|
||||
return existingByOaLoginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按工号加载没有登录名的 is_oa=2 用户。同一工号有多条时保留较早的一条。
|
||||
*/
|
||||
private Map<String, User> loadUsersByBlankLoginWorkcode(String tenantId, Collection<String> workcodes) {
|
||||
Map<String, User> existingByWorkcode = new HashMap<>();
|
||||
if (CollectionUtil.isEmpty(workcodes)) {
|
||||
return existingByWorkcode;
|
||||
}
|
||||
List<String> workcodeList = workcodes.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
for (int fromIndex = 0; fromIndex < workcodeList.size(); fromIndex += OA_LOGIN_ID_BATCH_SIZE) {
|
||||
List<String> workcodeBatch = workcodeList.subList(fromIndex, Math.min(fromIndex + OA_LOGIN_ID_BATCH_SIZE, workcodeList.size()));
|
||||
this.userService.list(Wrappers.<User>lambdaQuery()
|
||||
.eq(User::getTenantId, tenantId)
|
||||
.eq(User::getIsOa, CommonConstant.YES)
|
||||
.in(User::getCode, workcodeBatch)
|
||||
.and(wrapper -> wrapper.isNull(User::getOaLoginId).or().eq(User::getOaLoginId, "")))
|
||||
.forEach(user -> {
|
||||
String workcode = StringUtils.trimToNull(user.getCode());
|
||||
if (workcode == null) {
|
||||
return;
|
||||
}
|
||||
User previous = existingByWorkcode.get(workcode);
|
||||
if (previous == null || (user.getId() != null && previous.getId() != null && user.getId() < previous.getId())) {
|
||||
existingByWorkcode.put(workcode, user);
|
||||
}
|
||||
});
|
||||
}
|
||||
return existingByWorkcode;
|
||||
}
|
||||
|
||||
private String resolveOaLoginId(OAPersonResponse oaPerson) {
|
||||
if (oaPerson == null) {
|
||||
return null;
|
||||
@@ -591,6 +946,28 @@ public class OaUserListSyncHelper {
|
||||
return StringUtils.trimToNull(oaPerson.getLoginid());
|
||||
}
|
||||
|
||||
private String resolveWorkcode(OAPersonResponse oaPerson) {
|
||||
if (oaPerson == null) {
|
||||
return null;
|
||||
}
|
||||
return StringUtils.trimToNull(oaPerson.getWorkcode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 有登录名用登录名,没有登录名但有工号用工号。两者都没有则不同步。
|
||||
*/
|
||||
private String resolveSyncKey(OAPersonResponse oaPerson) {
|
||||
String oaLoginId = this.resolveOaLoginId(oaPerson);
|
||||
if (oaLoginId != null) {
|
||||
return "L:" + oaLoginId;
|
||||
}
|
||||
String workcode = this.resolveWorkcode(oaPerson);
|
||||
if (workcode != null) {
|
||||
return "W:" + workcode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isPersonBypassCode(String deptCode, DeptCategory deptCategory) {
|
||||
if (StringUtils.isBlank(deptCode)) {
|
||||
return true;
|
||||
@@ -635,6 +1012,11 @@ public class OaUserListSyncHelper {
|
||||
return null;
|
||||
}
|
||||
UserDept userDept = userConvert.person2userDept(oaPerson, userMap);
|
||||
String syncKey = this.resolveSyncKey(oaPerson);
|
||||
userDept.setUserId(syncKey == null ? null : userMap.get(syncKey));
|
||||
if (StringUtils.isBlank(this.resolveOaLoginId(oaPerson))) {
|
||||
userDept.setOaLoginId(null);
|
||||
}
|
||||
if (userDept.getUserId() == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -684,10 +1066,12 @@ public class OaUserListSyncHelper {
|
||||
public static class PersonSyncCount {
|
||||
private final int syncedCount;
|
||||
private final int skippedCount;
|
||||
private final int removedCount;
|
||||
|
||||
public PersonSyncCount(int syncedCount, int skippedCount) {
|
||||
public PersonSyncCount(int syncedCount, int skippedCount, int removedCount) {
|
||||
this.syncedCount = syncedCount;
|
||||
this.skippedCount = skippedCount;
|
||||
this.removedCount = removedCount;
|
||||
}
|
||||
|
||||
public int getSyncedCount() {
|
||||
@@ -697,6 +1081,10 @@ public class OaUserListSyncHelper {
|
||||
public int getSkippedCount() {
|
||||
return skippedCount;
|
||||
}
|
||||
|
||||
public int getRemovedCount() {
|
||||
return removedCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user