fix(aihr): validate candidate links
This commit is contained in:
+22
@@ -238,6 +238,9 @@ public class AihrInterviewService {
|
||||
if (current != null && !extPartyId.equals(current.extPartyId())) {
|
||||
throw new IllegalArgumentException("候选人已关联其他员工主体,请先由HR核对后处理");
|
||||
}
|
||||
if (current == null && !candidateExists(candidateId)) {
|
||||
throw new IllegalArgumentException("候选人不存在,请先创建或完成一次面试记录");
|
||||
}
|
||||
jdbcTemplate.update("""
|
||||
INSERT INTO aihr_candidate_employee_link
|
||||
(tenant_id, candidate_id, ext_party_id, status, linked_by, linked_time, create_time, update_time)
|
||||
@@ -248,6 +251,25 @@ public class AihrInterviewService {
|
||||
return candidateLink(candidateId);
|
||||
}
|
||||
|
||||
private boolean candidateExists(String candidateId) {
|
||||
if (candidates.containsKey(candidateId)
|
||||
|| sessions.values().stream().anyMatch(session -> candidateId.equals(session.candidate().id()))) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
ensureResultTable();
|
||||
Integer count = jdbcTemplate.queryForObject("""
|
||||
SELECT COUNT(*)
|
||||
FROM aihr_interview_result
|
||||
WHERE tenant_id = ? AND candidate_id = ?
|
||||
""", Integer.class, tenantId(), candidateId);
|
||||
return count != null && count > 0;
|
||||
} catch (DataAccessException e) {
|
||||
log.warn("resolve interview candidate failed(处理错误已隐藏)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private RecordResponse mapRecord(ResultSet rs, int rowNum) throws SQLException {
|
||||
var finishedTime = rs.getTimestamp("finished_time");
|
||||
Integer aiScore = rs.getInt("total_score");
|
||||
|
||||
+17
@@ -103,6 +103,23 @@ class AihrInterviewServiceTest {
|
||||
verify(jdbcTemplate).update(anyString(), eq("000000"), eq("candidate-3"), eq("employee-3"), eq("hr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("dev")
|
||||
void linkCandidateRejectsUnknownCandidate() {
|
||||
JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
|
||||
AihrInterviewService service = spy(new AihrInterviewService(new ObjectMapper(), null, jdbcTemplate));
|
||||
doReturn(null).when(service).candidateLink("candidate-unknown");
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), eq("000000"), eq("employee-5"))).thenReturn(1);
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), eq("000000"), eq("candidate-unknown"))).thenReturn(0);
|
||||
|
||||
IllegalArgumentException error = assertThrows(IllegalArgumentException.class, () -> service.linkCandidate(
|
||||
new CandidateLinkRequest("candidate-unknown", "employee-5"), "hr"
|
||||
));
|
||||
|
||||
assertEquals("候选人不存在,请先创建或完成一次面试记录", error.getMessage());
|
||||
verify(jdbcTemplate, never()).update(anyString(), eq("000000"), eq("candidate-unknown"), eq("employee-5"), eq("hr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("dev")
|
||||
void interviewRecordsAreScopedToCurrentTenant() {
|
||||
|
||||
@@ -177,3 +177,4 @@
|
||||
- 2026-07-14 BRD 4.4 每日三题资格补强:每日派题现在在组织快照存在 `hire_date` 列时按“入职日期至今不超过 3 个月”判断,边界按自然月且包含当天;旧 Demo 快照没有该列时继续使用“移动端训练记录少于 3 次”的兼容回退。正式试点仍需在外部组织同步落地并校验 `hire_date`,不能把回退口径当成正式新员工资格。
|
||||
- 2026-07-14 BRD G3 候选资料审核状态复核:候选人资料审核接口此前在空请求体时默认写回“待审核”,可能覆盖已有“已通过/已驳回”状态;现要求审核动作显式提交三态之一,空值和未知状态直接拒绝,避免后台误操作回退审核结论。
|
||||
- 2026-07-14 BRD 案例署名复核:案例库已有负责人字段,但此前上传、整理和入库记录都硬编码为“培训组”,无法追溯案例贡献者;现复用既有 `owner` 字段保存首次上传身份,整理和入库阶段保留原署名,手机号身份仅显示员工末四位,避免把原始手机号写入案例展示。
|
||||
- 2026-07-14 BRD 候选人关联完整性复核:候选人—员工关联接口此前只校验员工主体在职,允许给不存在的任意 `candidateId` 建立入职关联;现要求候选人必须来自内置候选档案、活动面试会话或当前租户已持久化面试记录,保留已有幂等关联和历史数据兼容。
|
||||
|
||||
@@ -515,6 +515,7 @@ contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java "media_oss_id"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java "storeSourceAudio"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java "currentCaseOwner"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java "候选人不存在,请先创建或完成一次面试记录"
|
||||
contains mobile-uni/src/pages/user/cases/index.vue "case-audio"
|
||||
contains frontend/src/views/knowledge/cases.vue "case-audio"
|
||||
contains backend/script/sql/aihr_practice_mysql8.sql "aihr_case_record"
|
||||
|
||||
Reference in New Issue
Block a user