修改TMS用户同步只增量同步用户数据
This commit is contained in:
@@ -40,6 +40,9 @@ public class OrgSyncService
|
||||
/** 写库人标记 */
|
||||
public static final String SYNC_MARKER = "oracle-sync";
|
||||
|
||||
/** TMS 用户增量同步写库人标记 */
|
||||
public static final String USER_SYNC_MARKER = "tms-user-sync";
|
||||
|
||||
/** 新用户默认密码(BCrypt,明文 123456) */
|
||||
private static final String DEFAULT_PASSWORD =
|
||||
"$2a$10$gAOzrNJaYLM2m85.9ykkLO0IPvQktxqee8RVpAu1e3.J0Ujiv4Z0G";
|
||||
@@ -101,6 +104,194 @@ public class OrgSyncService
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* TMS 用户增量同步(按钮「TMS同步用户」)。
|
||||
* 规则:
|
||||
* 1) 不变动组织机构(sys_dept)、不同步角色/岗位(sys_role、sys_user_role、sys_user_post);
|
||||
* 2) 只同步用户:已存在的用户一律保持不变,仅新增系统中不存在的用户;
|
||||
* 3) 匹配优先级:先按工号(EMPLOYEE_CODE = sys_user.user_name)匹配,
|
||||
* 再按姓名(EMPLOYEE_NAME = sys_user.nick_name)+ 所在机构匹配;
|
||||
* 4) 新用户部门:按 TMS 部门名称匹配现有机构(优先“威狮国际”直属部门),
|
||||
* 机构匹配不到的统一挂到根部门“威狮国际”(dept_id=200);
|
||||
* 5) 新用户 user_id 自增、默认密码 123456、不分配角色。
|
||||
*/
|
||||
public Map<String, Object> syncUsersOnly()
|
||||
{
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
List<Map<String, Object>> deptRows = oracleOrgReader.readAllDept();
|
||||
List<Map<String, Object>> empRows = oracleOrgReader.readAllEmployee();
|
||||
|
||||
// TMS 部门编码 -> 部门名称(TAB_DEPT 中 DEPT_NAME 即机构名)
|
||||
Map<String, String> tmsDeptNameByCode = new HashMap<String, String>();
|
||||
for (Map<String, Object> row : deptRows)
|
||||
{
|
||||
String code = clean(str(row, "DEPT_CODE"));
|
||||
String name = clean(str(row, "DEPT_NAME"));
|
||||
if (code != null && name != null && !tmsDeptNameByCode.containsKey(code))
|
||||
{
|
||||
tmsDeptNameByCode.put(code, name);
|
||||
}
|
||||
}
|
||||
|
||||
// 现有机构:部门名称 -> deptId(重名时优先“威狮国际”直属部门)
|
||||
List<SysDept> bmsDepts = orgSyncWriter.readSyncDepts();
|
||||
Map<String, Long> bmsDeptIdByName = new HashMap<String, Long>();
|
||||
for (SysDept d : bmsDepts)
|
||||
{
|
||||
String name = clean(d.getDeptName());
|
||||
if (name == null || d.getDeptId() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Long exist = bmsDeptIdByName.get(name);
|
||||
if (exist == null
|
||||
|| (d.getParentId() != null && d.getParentId().longValue() == ROOT_DEPT_ID
|
||||
&& exist.longValue() != ROOT_DEPT_ID))
|
||||
{
|
||||
bmsDeptIdByName.put(name, d.getDeptId());
|
||||
}
|
||||
}
|
||||
|
||||
// 现有用户匹配索引:工号(小写);姓名 + 机构
|
||||
List<SysUser> bmsUsers = orgSyncWriter.readSyncUsers();
|
||||
Map<String, SysUser> userByLoginName = new HashMap<String, SysUser>();
|
||||
Map<String, SysUser> userByNameDept = new HashMap<String, SysUser>();
|
||||
for (SysUser u : bmsUsers)
|
||||
{
|
||||
if (u == null || u.getUserId() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (clean(u.getUserName()) != null
|
||||
&& !userByLoginName.containsKey(u.getUserName().trim().toLowerCase()))
|
||||
{
|
||||
userByLoginName.put(u.getUserName().trim().toLowerCase(), u);
|
||||
}
|
||||
if (clean(u.getNickName()) != null && u.getDeptId() != null)
|
||||
{
|
||||
String key = nameDeptKey(u.getDeptId(), u.getNickName());
|
||||
if (!userByNameDept.containsKey(key))
|
||||
{
|
||||
userByNameDept.put(key, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<SysUser> toInsert = new ArrayList<SysUser>();
|
||||
Set<String> batchLoginNames = new HashSet<String>();
|
||||
long matchedByCode = 0;
|
||||
long matchedByName = 0;
|
||||
long orgFallback = 0;
|
||||
long skipped = 0;
|
||||
|
||||
for (Map<String, Object> row : empRows)
|
||||
{
|
||||
String code = clean(str(row, "EMPLOYEE_CODE"));
|
||||
String name = clean(str(row, "EMPLOYEE_NAME"));
|
||||
if (code == null && name == null)
|
||||
{
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
if (code != null && BUILTIN_ADMIN.equalsIgnoreCase(code))
|
||||
{
|
||||
// 不动 BMS 内置超级管理员
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 按机构匹配部门:TMS DEPT_CODE -> TMS 部门名称 -> 现有 sys_dept;匹配不到挂威狮国际
|
||||
Long targetDeptId = ROOT_DEPT_ID;
|
||||
String deptCode = clean(str(row, "DEPT_CODE"));
|
||||
if (deptCode != null)
|
||||
{
|
||||
String tmsDeptName = tmsDeptNameByCode.get(deptCode);
|
||||
if (tmsDeptName != null)
|
||||
{
|
||||
Long matched = bmsDeptIdByName.get(tmsDeptName);
|
||||
if (matched != null)
|
||||
{
|
||||
targetDeptId = matched;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean underRoot = targetDeptId == ROOT_DEPT_ID;
|
||||
|
||||
// 1) 优先工号匹配
|
||||
if (code != null && userByLoginName.containsKey(code.toLowerCase()))
|
||||
{
|
||||
matchedByCode++;
|
||||
continue;
|
||||
}
|
||||
// 2) 再按姓名 + 所在机构匹配
|
||||
if (name != null && userByNameDept.containsKey(nameDeptKey(targetDeptId, name)))
|
||||
{
|
||||
matchedByName++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3) 不存在 -> 新增(工号是登录账号,缺失无法建号)
|
||||
if (code == null)
|
||||
{
|
||||
log.warn("TMS 用户同步跳过:姓名={} 缺少工号(EMPLOYEE_CODE),无法创建登录账号", name);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
if (!batchLoginNames.add(code.toLowerCase()))
|
||||
{
|
||||
log.warn("TMS 用户同步跳过:工号 {}({}) 在 TMS 数据中重复", code, name);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
if (underRoot)
|
||||
{
|
||||
orgFallback++;
|
||||
}
|
||||
|
||||
SysUser u = new SysUser();
|
||||
u.setDeptId(targetDeptId);
|
||||
u.setUserName(code);
|
||||
u.setNickName(name != null ? truncate(name, 30) : code);
|
||||
u.setPassword(DEFAULT_PASSWORD);
|
||||
u.setStatus("1".equals(clean(str(row, "BL_OPEN"))) ? "0" : "1");
|
||||
u.setSex(mapSex(clean(str(row, "SEX"))));
|
||||
u.setEmail(cleanEmail(str(row, "EMAIL")));
|
||||
u.setPhonenumber(cleanPhone(str(row, "MOBILE_PHONE")));
|
||||
u.setRemark(truncate(clean(str(row, "REMARK")), 500));
|
||||
Object createDate = row.get("CREATE_DATE");
|
||||
u.setCreateTime(createDate instanceof Date ? (Date) createDate : new Date());
|
||||
u.setCreateBy(USER_SYNC_MARKER);
|
||||
toInsert.add(u);
|
||||
}
|
||||
|
||||
orgSyncWriter.insertNewUsers(toInsert);
|
||||
|
||||
long cost = System.currentTimeMillis() - t0;
|
||||
String summary = String.format(
|
||||
"TMS 用户同步完成:读取 TMS 员工 %d 人,已存在保持不变 %d 人(工号匹配 %d / 姓名+机构匹配 %d),新增 %d 人(其中机构未匹配挂“%s”%d 人),跳过 %d 条,耗时 %dms。新用户默认密码 123456,未分配角色。",
|
||||
empRows.size(), matchedByCode + matchedByName, matchedByCode, matchedByName,
|
||||
toInsert.size(), ROOT_DEPT_NAME, orgFallback, skipped, cost);
|
||||
log.info(summary);
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
result.put("total", empRows.size());
|
||||
result.put("existCount", matchedByCode + matchedByName);
|
||||
result.put("matchedByCode", matchedByCode);
|
||||
result.put("matchedByName", matchedByName);
|
||||
result.put("insertCount", toInsert.size());
|
||||
result.put("orgFallbackCount", orgFallback);
|
||||
result.put("skipCount", skipped);
|
||||
result.put("costMs", cost);
|
||||
result.put("summary", summary);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String nameDeptKey(Long deptId, String name)
|
||||
{
|
||||
return deptId + "|" + name.trim();
|
||||
}
|
||||
|
||||
private List<SysDept> buildDepts(List<Map<String, Object>> rows)
|
||||
{
|
||||
List<SysDept> list = new ArrayList<>();
|
||||
|
||||
@@ -59,4 +59,26 @@ public class OrgSyncWriter
|
||||
// 6. 超级管理员挂到根部门
|
||||
writerMapper.updateUserDept(1L, adminDeptId);
|
||||
}
|
||||
|
||||
/** TMS 用户增量同步:读取现有全部未删除部门 */
|
||||
public List<SysDept> readSyncDepts()
|
||||
{
|
||||
return writerMapper.selectSyncDepts();
|
||||
}
|
||||
|
||||
/** TMS 用户增量同步:读取现有全部未删除用户(仅匹配字段) */
|
||||
public List<SysUser> readSyncUsers()
|
||||
{
|
||||
return writerMapper.selectSyncUsers();
|
||||
}
|
||||
|
||||
/** TMS 用户增量同步:仅新增用户(user_id 自增,不触碰部门/角色/岗位),单事务 */
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void insertNewUsers(List<SysUser> users)
|
||||
{
|
||||
for (int i = 0; i < users.size(); i += USER_BATCH)
|
||||
{
|
||||
writerMapper.batchInsertUserAutoId(users.subList(i, Math.min(i + USER_BATCH, users.size())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -43,4 +43,13 @@ public interface SysOrgSyncWriterMapper
|
||||
|
||||
/** 将指定用户挂到根部门 */
|
||||
int updateUserDept(@Param("userId") Long userId, @Param("deptId") Long deptId);
|
||||
|
||||
/** 查询全部未删除部门(TMS 用户增量同步:按部门名称匹配机构) */
|
||||
List<SysDept> selectSyncDepts();
|
||||
|
||||
/** 查询全部未删除用户的匹配字段(TMS 用户增量同步:工号/姓名+机构匹配) */
|
||||
List<SysUser> selectSyncUsers();
|
||||
|
||||
/** 批量新增用户(user_id 自增,不指定 ID,不写角色/岗位) */
|
||||
int batchInsertUserAutoId(@Param("list") List<SysUser> list);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bms.system.orgsync.mapper.SysOrgSyncWriterMapper">
|
||||
|
||||
<!-- 全局未开启下划线转驼峰,TMS 用户增量同步查询使用显式映射 -->
|
||||
<resultMap id="syncDeptResult" type="com.bms.common.core.domain.entity.SysDept">
|
||||
<id property="deptId" column="dept_id"/>
|
||||
<result property="parentId" column="parent_id"/>
|
||||
<result property="deptName" column="dept_name"/>
|
||||
<result property="status" column="status"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="syncUserResult" type="com.bms.common.core.domain.entity.SysUser">
|
||||
<id property="userId" column="user_id"/>
|
||||
<result property="deptId" column="dept_id"/>
|
||||
<result property="userName" column="user_name"/>
|
||||
<result property="nickName" column="nick_name"/>
|
||||
</resultMap>
|
||||
|
||||
<delete id="deleteAllRoleDept">
|
||||
delete from sys_role_dept
|
||||
</delete>
|
||||
@@ -62,4 +77,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<update id="updateUserDept">
|
||||
update sys_user set dept_id = #{deptId} where user_id = #{userId}
|
||||
</update>
|
||||
|
||||
<select id="selectSyncDepts" resultMap="syncDeptResult">
|
||||
select dept_id, parent_id, dept_name, status
|
||||
from sys_dept
|
||||
where del_flag = '0'
|
||||
</select>
|
||||
|
||||
<select id="selectSyncUsers" resultMap="syncUserResult">
|
||||
select user_id, dept_id, user_name, nick_name
|
||||
from sys_user
|
||||
where del_flag = '0'
|
||||
</select>
|
||||
|
||||
<insert id="batchInsertUserAutoId" parameterType="java.util.List">
|
||||
insert into sys_user(dept_id, user_name, nick_name, user_type, email, phonenumber, sex,
|
||||
password, status, del_flag, create_by, create_time, remark)
|
||||
values
|
||||
<foreach collection="list" item="u" separator=",">
|
||||
(#{u.deptId}, #{u.userName}, #{u.nickName}, '00', #{u.email}, #{u.phonenumber},
|
||||
#{u.sex}, #{u.password}, #{u.status}, '0', #{u.createBy},
|
||||
<choose><when test="u.createTime != null">#{u.createTime}</when><otherwise>sysdate()</otherwise></choose>,
|
||||
#{u.remark})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user