fix: 人员数据治理迁移7
This commit is contained in:
+58
-9
@@ -4,13 +4,18 @@ import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import com.budwk.app.base.constant.RedisConstant;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.utils.PwdUtil;
|
||||
import com.budwk.app.sys.models.Sys_task;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.models.Sys_user_history;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.models.Sys_user_source;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||
import com.budwk.app.zhgh.personGovernance.apiConfig.model.*;
|
||||
@@ -60,6 +65,8 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
private PersonMemberMatchService personMemberMatchService;
|
||||
@Inject
|
||||
private SysDictService sysDictService;
|
||||
@Inject
|
||||
private SysRoleService sysRoleService;
|
||||
|
||||
/**
|
||||
* configId为保存的配置,triggerType为MANUAL/SCHEDULED;返回批次,FAILED时errorMessage为原因。
|
||||
@@ -373,7 +380,9 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
Map<String, NutMap> fields = new HashMap<>();
|
||||
columns.forEach(c -> fields.put(c.getString("columnName"), c));
|
||||
boolean unitTarget = "sys_unit".equalsIgnoreCase(config.getTargetTable());
|
||||
Assert.isTrue(fields.containsKey("id") && (unitTarget || fields.containsKey("pullTime")), "目标中间表必须包含id和pullTime字段");
|
||||
boolean userTarget = "sys_user".equalsIgnoreCase(config.getTargetTable());
|
||||
Assert.isTrue(fields.containsKey("id") && (unitTarget || userTarget || fields.containsKey("pullTime")),
|
||||
"目标中间表必须包含id和pullTime字段");
|
||||
if (unitTarget) {
|
||||
Assert.isTrue("HTTP_API".equals(config.getSourceType()) && "UPSERT".equals(config.getSyncMode())
|
||||
&& "id".equals(config.getIdentityField()), "单位API必须按来源单位id新增或更新");
|
||||
@@ -420,6 +429,10 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
columns.forEach(c -> types.put(c.getString("columnName"), c.getString("columnType")));
|
||||
String mode = syncMode(config);
|
||||
boolean unitTarget = "sys_unit".equalsIgnoreCase(config.getTargetTable());
|
||||
boolean userTarget = "sys_user".equalsIgnoreCase(config.getTargetTable());
|
||||
boolean preserveUserNulls = userTarget && "UPSERT".equals(mode);
|
||||
List<PersonApiFieldMapping> requiredUserMappings = preserveUserNulls
|
||||
? mappings.stream().filter(mapping -> Boolean.TRUE.equals(mapping.getRequired())).toList() : List.of();
|
||||
List<PersonApiSyncOptions.FieldRule> lengthRules = options.getRules().stream()
|
||||
.filter(rule -> rule.getLength() != null).toList();
|
||||
List<PersonApiSyncOptions.FieldRule> dictionaryRules = Boolean.TRUE.equals(options.getAutoCreateDict())
|
||||
@@ -450,7 +463,7 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
NutMap values = NutMap.NEW();
|
||||
for (PersonApiFieldMapping mapping : mappings) {
|
||||
Object value = personApiConfigService.readResponsePath(row, mapping.getSourceField());
|
||||
if (Boolean.TRUE.equals(mapping.getRequired())) {
|
||||
if (Boolean.TRUE.equals(mapping.getRequired()) && !(preserveUserNulls && value == null)) {
|
||||
Assert.isTrue(value != null && !Strings.isBlank(String.valueOf(value)), "必填来源字段为空:" + mapping.getSourceField());
|
||||
}
|
||||
try {
|
||||
@@ -468,7 +481,9 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
values.putIfAbsent("unitcode", values.get("id"));
|
||||
} else {
|
||||
values.put("id", R.UU32());
|
||||
values.put("pullTime", batch.getStartedAt());
|
||||
if (types.containsKey("pullTime")) {
|
||||
values.put("pullTime", batch.getStartedAt());
|
||||
}
|
||||
}
|
||||
valuesList.add(values);
|
||||
}
|
||||
@@ -486,7 +501,8 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
boolean protectSysUser = "SCHEDULED".equals(batch.getTriggerType())
|
||||
&& "sys_user".equalsIgnoreCase(config.getTargetTable());
|
||||
dao.run(connection -> writeChunk(connection, config, valuesList, mode, protectSysUser, counts,
|
||||
dictionaryRules, dictionaryValues, Strings.isNotBlank(options.getUnitConfigId()) ? unitIds : null));
|
||||
dictionaryRules, dictionaryValues, Strings.isNotBlank(options.getUnitConfigId()) ? unitIds : null,
|
||||
requiredUserMappings));
|
||||
batch.setNewCount(batch.getNewCount() + counts[0]);
|
||||
batch.setChangeCount(batch.getChangeCount() + counts[1]);
|
||||
batch.setSuccessCount(batch.getSuccessCount() + counts[0] + counts[1]);
|
||||
@@ -504,8 +520,10 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
private void writeChunk(Connection connection, PersonApiConfig config, List<NutMap> rows,
|
||||
String mode, boolean protectSysUser, int[] counts,
|
||||
List<PersonApiSyncOptions.FieldRule> dictionaryRules,
|
||||
Map<String, Set<String>> dictionaryValues, Set<String> unitIds) throws SQLException {
|
||||
Map<String, Set<String>> dictionaryValues, Set<String> unitIds,
|
||||
List<PersonApiFieldMapping> requiredUserMappings) throws SQLException {
|
||||
String table = quoteIdentifier(config.getTargetTable());
|
||||
boolean userTarget = "sys_user".equalsIgnoreCase(config.getTargetTable());
|
||||
Map<Integer, String> existing = new HashMap<>();
|
||||
Set<Integer> protectedRows = new HashSet<>();
|
||||
Map<Integer, Integer> representatives = new HashMap<>();
|
||||
@@ -607,11 +625,13 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
List<Sys_user_source> entities = inserts.values().stream()
|
||||
.map(row -> BeanUtil.toBean(row, Sys_user_source.class)).toList();
|
||||
dao.insert(entities);
|
||||
} else if (userTarget) {
|
||||
insertSystemUsers(connection, table, new ArrayList<>(inserts.values()), requiredUserMappings);
|
||||
} else {
|
||||
executeWriteBatch(connection, table, new ArrayList<>(inserts.values()), false);
|
||||
executeWriteBatch(connection, table, new ArrayList<>(inserts.values()), false, false);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) executeWriteBatch(connection, table, new ArrayList<>(updates.values()), true);
|
||||
if (!updates.isEmpty()) executeWriteBatch(connection, table, new ArrayList<>(updates.values()), true, userTarget);
|
||||
for (Collection<NutMap> written : List.of(inserts.values(), updates.values())) {
|
||||
for (NutMap row : written) {
|
||||
for (PersonApiSyncOptions.FieldRule rule : dictionaryRules) {
|
||||
@@ -642,6 +662,26 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
counts[1] = updates.size();
|
||||
}
|
||||
|
||||
private void insertSystemUsers(Connection connection, String table, List<NutMap> rows,
|
||||
List<PersonApiFieldMapping> requiredMappings) throws SQLException {
|
||||
Sys_role publicRole = sysRoleService.getByCode(RoleConstant.PUBLIC);
|
||||
List<Sys_user_role> roles = new ArrayList<>();
|
||||
for (NutMap row : rows) {
|
||||
String salt = R.UU32();
|
||||
row.put("salt", salt);
|
||||
row.put("password", PwdUtil.getPassword(PwdUtil.generate(12), salt));
|
||||
for (PersonApiFieldMapping mapping : requiredMappings) {
|
||||
Assert.notNull(row.get(mapping.getTargetField()), "必填来源字段为空:" + mapping.getSourceField());
|
||||
}
|
||||
Sys_user_role role = new Sys_user_role();
|
||||
role.setUserId(row.getString("id"));
|
||||
role.setRoleId(publicRole.getId());
|
||||
roles.add(role);
|
||||
}
|
||||
executeWriteBatch(connection, table, rows, false, false);
|
||||
dao.insert(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较更新前人员快照与本次映射值,返回 MemberChangeType 编码;空集合表示没有实际业务变化。
|
||||
* id、pullTime属于主键或同步批次字段,不参与人员变更判断。
|
||||
@@ -653,6 +693,7 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
for (Map.Entry<String, Object> entry : incomingValues.entrySet()) {
|
||||
String field = entry.getKey();
|
||||
if (List.of("id", "pullTime").contains(field)
|
||||
|| entry.getValue() == null
|
||||
|| valuesEqual(currentValues.get(field), entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
@@ -703,6 +744,10 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
}
|
||||
Sys_user_history history = new Sys_user_history();
|
||||
BeanUtil.copyProperties(user, history);
|
||||
if (changeTypes.contains(MemberChangeType.NEW.name())) {
|
||||
history.setPassword(null);
|
||||
history.setSalt(null);
|
||||
}
|
||||
history.setId(R.UU32());
|
||||
history.setChangeTime(new Date());
|
||||
history.setChangeOrigin(MemberChangeOrigin.SYSTEM.name());
|
||||
@@ -738,11 +783,15 @@ public class PersonGovernanceSyncServiceImpl implements PersonGovernanceSyncServ
|
||||
|
||||
/** JDBC executeBatch真正批量提交;更新只覆盖映射字段和pullTime,不覆盖目标主键及未映射字段。 */
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
private void executeWriteBatch(Connection connection, String table, List<NutMap> rows, boolean update) throws SQLException {
|
||||
private void executeWriteBatch(Connection connection, String table, List<NutMap> rows,
|
||||
boolean update, boolean preserveNulls) throws SQLException {
|
||||
List<String> fields = new ArrayList<>(rows.get(0).keySet());
|
||||
if (update) fields.remove("id");
|
||||
String sql = update
|
||||
? "UPDATE " + table + " SET " + fields.stream().map(f -> quoteIdentifier(f) + "=?")
|
||||
? "UPDATE " + table + " SET " + fields.stream().map(field -> {
|
||||
String column = quoteIdentifier(field);
|
||||
return column + (preserveNulls ? "=COALESCE(?," + column + ")" : "=?");
|
||||
})
|
||||
.collect(java.util.stream.Collectors.joining(",")) + " WHERE `id`=?"
|
||||
: "INSERT INTO " + table + " (" + fields.stream().map(this::quoteIdentifier)
|
||||
.collect(java.util.stream.Collectors.joining(",")) + ") VALUES ("
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.targetTable !== 'sys_unit'" label="自动同步单位" class="person-governance-system-member-match">
|
||||
<el-switch v-model="autoSyncUnit" :disabled="formLoading" @change="handleAutoSyncUnit"></el-switch>
|
||||
<el-select v-if="autoSyncUnit" v-model="syncOptions.unitConfigId" clearable filterable placeholder="请选择单位API配置">
|
||||
<el-select v-if="autoSyncUnit" v-model="syncOptions.unitConfigId" clearable filterable placeholder="请选择单位API配置" style="margin-left: 10px">
|
||||
<el-option v-for="item in unitConfigs" :key="item.id" :label="item.configName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -197,7 +197,7 @@
|
||||
<div v-if="form.targetTable !== 'sys_unit'" class="person-governance-mapping-toolbar-item">
|
||||
<label>自动同步单位</label>
|
||||
<el-switch v-model="autoSyncUnit" :disabled="formLoading" @change="handleAutoSyncUnit"></el-switch>
|
||||
<el-select v-if="autoSyncUnit" v-model="syncOptions.unitConfigId" clearable filterable placeholder="请选择单位API配置">
|
||||
<el-select v-if="autoSyncUnit" v-model="syncOptions.unitConfigId" clearable filterable placeholder="请选择单位API配置" style="margin-left: 10px">
|
||||
<el-option v-for="item in unitConfigs" :key="item.id" :label="item.configName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user