feat(aihr): report org sync quality in precheck
This commit is contained in:
+2
@@ -27,6 +27,8 @@ public final class AihrOrgSyncDto {
|
||||
int employeeCount,
|
||||
int syncedCount,
|
||||
int skippedCount,
|
||||
int phoneLinked,
|
||||
int suspectText,
|
||||
List<String> warnings
|
||||
) {
|
||||
}
|
||||
|
||||
+39
-2
@@ -93,6 +93,14 @@ public class AihrOrgSyncService {
|
||||
rows.add(row);
|
||||
}
|
||||
}
|
||||
int phoneLinked = (int) rows.stream().filter(row -> !row.personPhone().isBlank()).count();
|
||||
int suspectText = (int) rows.stream().filter(AihrOrgSyncService::hasSuspectText).count();
|
||||
if (!rows.isEmpty() && phoneLinked < rows.size()) {
|
||||
warnings.add("外部员工快照手机号覆盖 " + phoneLinked + "/" + rows.size() + ",移动端正式登录仅可映射已带手机号人员");
|
||||
}
|
||||
if (suspectText > 0) {
|
||||
warnings.add("外部员工快照存在 " + suspectText + " 条疑似乱码字段,请检查开放接口编码或导入链路");
|
||||
}
|
||||
if (!dryRun && replaceExisting && rows.isEmpty()) {
|
||||
throw new IllegalArgumentException("外部员工快照为空,已阻止覆盖本地组织人员快照");
|
||||
}
|
||||
@@ -109,6 +117,8 @@ public class AihrOrgSyncService {
|
||||
employeeItems.size(),
|
||||
dryRun ? 0 : rows.size(),
|
||||
skipped,
|
||||
phoneLinked,
|
||||
suspectText,
|
||||
List.copyOf(warnings)
|
||||
);
|
||||
}
|
||||
@@ -515,8 +525,35 @@ public class AihrOrgSyncService {
|
||||
}
|
||||
|
||||
private static String phone(JsonNode employee) {
|
||||
return text(employee, "phone", "mobile", "mobile_phone", "mobilePhone", "contact_phone",
|
||||
"contactPhone", "phonenumber", "telephone", "tel");
|
||||
String[] fields = {"phone", "phone_number", "phoneNumber", "mobile", "mobile_phone",
|
||||
"mobilePhone", "mobile_tel", "mobileTel", "cellphone", "cellPhone", "contact_phone",
|
||||
"contactPhone", "contact_mobile", "contactMobile", "phonenumber", "telephone", "tel", "手机号", "手机", "联系电话"};
|
||||
for (String field : fields) {
|
||||
String normalized = normalizeMobilePhone(text(employee, field));
|
||||
if (!normalized.isBlank()) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static String normalizeMobilePhone(String value) {
|
||||
String digits = clean(value).replaceAll("\\D", "");
|
||||
if (digits.length() == 13 && digits.startsWith("86")) {
|
||||
digits = digits.substring(2);
|
||||
}
|
||||
return digits.matches("1[3-9]\\d{9}") ? digits : "";
|
||||
}
|
||||
|
||||
private static boolean hasSuspectText(OrgRow row) {
|
||||
return hasQuestionMark(row.projectName())
|
||||
|| hasQuestionMark(row.deptName())
|
||||
|| hasQuestionMark(row.personName())
|
||||
|| hasQuestionMark(row.positionName());
|
||||
}
|
||||
|
||||
private static boolean hasQuestionMark(String value) {
|
||||
return clean(value).contains("?");
|
||||
}
|
||||
|
||||
private static String text(JsonNode node, String... fields) {
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package org.dromara.aihr.service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@Tag("dev")
|
||||
public class AihrOrgSyncServiceTest {
|
||||
|
||||
@Test
|
||||
public void normalizeMobilePhoneOnlyKeepsUsableMobileNumber() {
|
||||
assertEquals("13900001111", AihrOrgSyncService.normalizeMobilePhone("+86 139-0000-1111"));
|
||||
assertEquals("", AihrOrgSyncService.normalizeMobilePhone("139****1111"));
|
||||
assertEquals("", AihrOrgSyncService.normalizeMobilePhone("025-88888888"));
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,5 @@
|
||||
- 优先复用已有 `/api/aihr/mobile/practice/*` 与 `/api/train/practice/*` 接口。
|
||||
- 组织人员快照在 `组织与权限` 页分页展示;业务页只取下拉候选,真实复盘范围由接口参数落到后端过滤。
|
||||
- `组织与权限` 页暴露手机号覆盖数和疑似乱码数,只做质量提示,不展示手机号明细。
|
||||
- 组织同步预检同步返回手机号覆盖数和疑似乱码数;手机号只统计可用于移动端登录的 11 位手机号。
|
||||
- 规则配置中心先做运营口径展示;需要真实持久化时再补 `incentive_rule` 等表。
|
||||
|
||||
@@ -113,6 +113,8 @@ export type OrgSyncResponse = {
|
||||
employeeCount: number;
|
||||
syncedCount: number;
|
||||
skippedCount: number;
|
||||
phoneLinked: number;
|
||||
suspectText: number;
|
||||
warnings: string[];
|
||||
};
|
||||
|
||||
|
||||
@@ -153,6 +153,9 @@
|
||||
<div>
|
||||
<span>写入/跳过</span><strong>{{ syncResult.syncedCount }} / {{ syncResult.skippedCount }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>手机号/疑似乱码</span><strong>{{ syncResult.phoneLinked }} / {{ syncResult.suspectText }}</strong>
|
||||
</div>
|
||||
<p v-if="syncResult.warnings?.length">{{ syncResult.warnings.join(';') }}</p>
|
||||
<p v-else>同步接口已返回结果。</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user