fix(aihr): restore org snapshot anomaly counts
This commit is contained in:
+4
-4
@@ -187,10 +187,10 @@ public class AihrOrgSyncService {
|
|||||||
select count(*) from aihr_org_snapshot
|
select count(*) from aihr_org_snapshot
|
||||||
""" + where + """
|
""" + where + """
|
||||||
and (
|
and (
|
||||||
person_name like '%?%'
|
instr(coalesce(person_name, ''), '?') > 0
|
||||||
or project_name like '%?%'
|
or instr(coalesce(project_name, ''), '?') > 0
|
||||||
or dept_name like '%?%'
|
or instr(coalesce(dept_name, ''), '?') > 0
|
||||||
or position_name like '%?%'
|
or instr(coalesce(position_name, ''), '?') > 0
|
||||||
)
|
)
|
||||||
""", args);
|
""", args);
|
||||||
List<Object> rowArgs = new ArrayList<>(args);
|
List<Object> rowArgs = new ArrayList<>(args);
|
||||||
|
|||||||
+44
@@ -6,11 +6,13 @@ import org.dromara.aihr.domain.AihrOrgSyncDto.SyncRequest;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.Tag;
|
import org.junit.jupiter.api.Tag;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@@ -54,6 +56,21 @@ public class AihrOrgSyncServiceTest {
|
|||||||
assertFalse(AihrOrgSyncService.hasUnusablePhoneCandidate(mapper.readTree("{\"name\":\"张三\"}")));
|
assertFalse(AihrOrgSyncService.hasUnusablePhoneCandidate(mapper.readTree("{\"name\":\"张三\"}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void snapshotSuspectTextQuerySearchesLiteralQuestionMarks() {
|
||||||
|
SnapshotJdbcTemplate jdbcTemplate = new SnapshotJdbcTemplate();
|
||||||
|
AihrOrgSyncService service = new AihrOrgSyncService(new ObjectMapper(), jdbcTemplate, mock(TransactionTemplate.class));
|
||||||
|
|
||||||
|
service.snapshot(null, null, null, null, 1, 20, null);
|
||||||
|
|
||||||
|
String suspectQuery = jdbcTemplate.queries.stream()
|
||||||
|
.filter(sql -> sql.contains("coalesce(person_name"))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
assertTrue(suspectQuery.contains("instr(coalesce(person_name, ''), '?') > 0"));
|
||||||
|
assertFalse(suspectQuery.contains("like '%?%'"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dryRunNeverTouchesSnapshotSchemaWhenExternalFetchFails() {
|
public void dryRunNeverTouchesSnapshotSchemaWhenExternalFetchFails() {
|
||||||
JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
|
JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
|
||||||
@@ -110,4 +127,31 @@ public class AihrOrgSyncServiceTest {
|
|||||||
server.stop(0);
|
server.stop(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class SnapshotJdbcTemplate extends JdbcTemplate {
|
||||||
|
private final List<String> queries = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T queryForObject(String sql, Class<T> requiredType) {
|
||||||
|
queries.add(sql);
|
||||||
|
return requiredType.cast(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) {
|
||||||
|
queries.add(sql);
|
||||||
|
return requiredType.cast(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) {
|
||||||
|
queries.add(sql);
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String sql) {
|
||||||
|
// Schema setup is irrelevant for this query contract test.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,12 @@
|
|||||||
4. 在业务提供一期视频样片及字段口径后,继续扩案例详情数据契约;当前原始音频回放已完成,但不替代视频、学习点和主管点评。
|
4. 在业务提供一期视频样片及字段口径后,继续扩案例详情数据契约;当前原始音频回放已完成,但不替代视频、学习点和主管点评。
|
||||||
5. 用正式试点窗口跑 BRD L1/M5,而不是继续增加视觉页面。
|
5. 用正式试点窗口跑 BRD L1/M5,而不是继续增加视觉页面。
|
||||||
|
|
||||||
|
## 2026-07-14 增量:组织快照异常统计修复
|
||||||
|
|
||||||
|
- 发现 `AihrOrgSyncService.snapshot()` 的疑似乱码统计把问号写成 `like '%?%'`,问号位于 SQL 字符串字面量内,未形成有效的参数或字符匹配,导致管理端组织快照的异常计数可能恒为 0。
|
||||||
|
- 已改为 MySQL `instr(coalesce(field, ''), '?') > 0`,继续沿用当前租户和筛选条件,并补回归测试与 `demo-check` marker;本地 `ry-vue` 直接查询得到 `3473` 条快照、`8` 条疑似异常文本,与修复后的统计口径一致。
|
||||||
|
- 该修复只恢复异常计数的真实性,不代表外部组织快照已经具备完整手机号映射;正式主管身份和项目范围仍需真实组织同步数据。
|
||||||
|
|
||||||
## 5. 每批完成定义
|
## 5. 每批完成定义
|
||||||
|
|
||||||
- 有明确 BRD 条款、代码路径和数据证据。
|
- 有明确 BRD 条款、代码路径和数据证据。
|
||||||
|
|||||||
@@ -455,6 +455,7 @@ contains mobile-uni/src/pages/supervisor/review/index.vue "人工贡献分"
|
|||||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java "/practice/reviews/{id}/reviewed"
|
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java "/practice/reviews/{id}/reviewed"
|
||||||
contains mobile-uni/src/pages/supervisor/review/index.vue "标记已复盘"
|
contains mobile-uni/src/pages/supervisor/review/index.vue "标记已复盘"
|
||||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "source = 'retry'"
|
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "source = 'retry'"
|
||||||
|
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java "instr(coalesce(person_name, '')"
|
||||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "maskSensitiveText"
|
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "maskSensitiveText"
|
||||||
contains mobile-uni/src/services/practice.ts "/api/aihr/mobile/practice/assignments"
|
contains mobile-uni/src/services/practice.ts "/api/aihr/mobile/practice/assignments"
|
||||||
contains frontend/src/api/aihr/case.ts "/api/knowledge/case/upload"
|
contains frontend/src/api/aihr/case.ts "/api/knowledge/case/upload"
|
||||||
|
|||||||
Reference in New Issue
Block a user