fix(aihr): scope case records to tenant
This commit is contained in:
+18
-10
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.aihr.domain.AihrCaseDto.CurateRequest;
|
||||
import org.dromara.aihr.domain.AihrCaseDto.CurateResponse;
|
||||
import org.dromara.aihr.domain.AihrCaseDto.DetailResponse;
|
||||
@@ -118,11 +119,12 @@ public class AihrCaseService {
|
||||
String sql = """
|
||||
SELECT case_id, title, type, status, update_time, owner, summary
|
||||
FROM aihr_case_record
|
||||
WHERE tenant_id = '000000'
|
||||
WHERE tenant_id = ?
|
||||
""" + projectWhere + """
|
||||
ORDER BY update_time DESC, id DESC
|
||||
LIMIT ?
|
||||
""";
|
||||
args.add(0, tenantId());
|
||||
return jdbcTemplate.query(sql, (rs, rowNum) -> new RecordResponse(
|
||||
firstNonBlank(rs.getString("case_id"), ""),
|
||||
firstNonBlank(rs.getString("title"), "现场案例"),
|
||||
@@ -150,8 +152,9 @@ public class AihrCaseService {
|
||||
String sql = """
|
||||
SELECT case_id, file_name, title, type, status, update_time, owner, transcript, summary, media_url, media_oss_id
|
||||
FROM aihr_case_record
|
||||
WHERE tenant_id = '000000' AND case_id = ?
|
||||
WHERE tenant_id = ? AND case_id = ?
|
||||
""" + projectWhere + " LIMIT 1";
|
||||
args.add(0, tenantId());
|
||||
return jdbcTemplate.query(sql, (rs, rowNum) -> {
|
||||
Long mediaOssId = rs.getObject("media_oss_id", Long.class);
|
||||
return new DetailResponse(
|
||||
@@ -179,13 +182,13 @@ public class AihrCaseService {
|
||||
return jdbcTemplate.query("""
|
||||
SELECT DISTINCT project_ext_org_id
|
||||
FROM aihr_org_snapshot
|
||||
WHERE tenant_id = '000000'
|
||||
WHERE tenant_id = ?
|
||||
AND employment_status = 'active'
|
||||
AND project_ext_org_id IS NOT NULL
|
||||
AND project_ext_org_id <> ''
|
||||
AND (person_phone = ? OR ext_party_id = ?)
|
||||
ORDER BY project_ext_org_id
|
||||
""", (rs, rowNum) -> rs.getString("project_ext_org_id"), username, username);
|
||||
""", (rs, rowNum) -> rs.getString("project_ext_org_id"), tenantId(), username, username);
|
||||
} catch (DataAccessException e) {
|
||||
log.warn("resolve app user project scope failed: {}", e.getMessage());
|
||||
return List.of();
|
||||
@@ -201,7 +204,7 @@ public class AihrCaseService {
|
||||
Integer count = jdbcTemplate.queryForObject("""
|
||||
SELECT COUNT(*)
|
||||
FROM aihr_org_snapshot
|
||||
WHERE tenant_id = '000000'
|
||||
WHERE tenant_id = ?
|
||||
AND employment_status = 'active'
|
||||
AND (person_phone = ? OR ext_party_id = ?)
|
||||
AND (position_level IN ('主管', '项目经理')
|
||||
@@ -209,7 +212,7 @@ public class AihrCaseService {
|
||||
OR position_name LIKE '%经理%'
|
||||
OR position_name LIKE '%负责人%'
|
||||
OR position_name LIKE '%组长%')
|
||||
""", Integer.class, username, username);
|
||||
""", Integer.class, tenantId(), username, username);
|
||||
return count != null && count > 0;
|
||||
} catch (DataAccessException e) {
|
||||
log.warn("resolve case contributor failed: {}", e.getMessage());
|
||||
@@ -222,7 +225,7 @@ public class AihrCaseService {
|
||||
jdbcTemplate.update("""
|
||||
INSERT INTO aihr_case_record
|
||||
(tenant_id, case_id, file_name, project_ext_org_id, title, type, status, transcript, summary, media_oss_id, media_url, owner, create_time, update_time)
|
||||
VALUES ('000000', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '培训组', now(), now())
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '培训组', now(), now())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
file_name = VALUES(file_name),
|
||||
project_ext_org_id = VALUES(project_ext_org_id),
|
||||
@@ -235,6 +238,7 @@ public class AihrCaseService {
|
||||
media_url = VALUES(media_url),
|
||||
update_time = now()
|
||||
""",
|
||||
tenantId(),
|
||||
state.id(),
|
||||
state.fileName(),
|
||||
firstNonBlank(state.projectExtOrgId(), ""),
|
||||
@@ -284,6 +288,10 @@ public class AihrCaseService {
|
||||
}
|
||||
}
|
||||
|
||||
private String tenantId() {
|
||||
return firstNonBlank(LoginHelper.getTenantId(), "000000");
|
||||
}
|
||||
|
||||
private Optional<CaseSummary> organizeWithModel(CaseState state) {
|
||||
String system = """
|
||||
你是物业培训案例编辑。请把转写内容整理成可复用案例。
|
||||
@@ -388,8 +396,8 @@ public class AihrCaseService {
|
||||
List<CaseState> persisted = jdbcTemplate.query("""
|
||||
SELECT case_id, file_name, project_ext_org_id, transcript, type
|
||||
, media_oss_id, media_url
|
||||
FROM aihr_case_record
|
||||
WHERE tenant_id = '000000' AND case_id = ?
|
||||
FROM aihr_case_record
|
||||
WHERE tenant_id = ? AND case_id = ?
|
||||
LIMIT 1
|
||||
""", (rs, rowNum) -> new CaseState(
|
||||
rs.getString("case_id"),
|
||||
@@ -400,7 +408,7 @@ public class AihrCaseService {
|
||||
null,
|
||||
rs.getObject("media_oss_id", Long.class),
|
||||
firstNonBlank(rs.getString("media_url"), "")
|
||||
), normalizedCaseId);
|
||||
), tenantId(), normalizedCaseId);
|
||||
state = persisted.stream().findFirst().orElse(null);
|
||||
if (state != null) {
|
||||
cases.put(normalizedCaseId, state);
|
||||
|
||||
+5
-5
@@ -39,8 +39,8 @@ class AihrCaseServiceTest {
|
||||
UploadResponse response = service.upload(new MockMultipartFile("file", "case.webm", "audio/webm", new byte[]{1}), "P1", null);
|
||||
|
||||
assertEquals("张*先生住在12栋****,手机号1390****1111,说2-****漏水", response.transcript());
|
||||
assertEquals(response.transcript(), jdbcTemplate.updateArgs[6]);
|
||||
assertEquals(response.transcript(), jdbcTemplate.updateArgs[7]);
|
||||
assertEquals(response.transcript(), jdbcTemplate.updateArgs[8]);
|
||||
assertFalse(response.transcript().contains("13900001111"));
|
||||
assertFalse(response.transcript().contains("1201"));
|
||||
assertFalse(response.transcript().contains("2-304"));
|
||||
@@ -67,8 +67,8 @@ class AihrCaseServiceTest {
|
||||
|
||||
assertEquals(123L, response.mediaOssId());
|
||||
assertEquals("https://oss.local/cases/case.webm", response.mediaUrl());
|
||||
assertEquals(123L, jdbcTemplate.updateArgs[8]);
|
||||
assertEquals("https://oss.local/cases/case.webm", jdbcTemplate.updateArgs[9]);
|
||||
assertEquals(123L, jdbcTemplate.updateArgs[9]);
|
||||
assertEquals("https://oss.local/cases/case.webm", jdbcTemplate.updateArgs[10]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -105,7 +105,7 @@ class AihrCaseServiceTest {
|
||||
assertEquals("业主投诉后完成跟进", detail.transcript());
|
||||
assertEquals("https://oss.local/cases/refreshed-case.webm", detail.mediaUrl());
|
||||
assertEquals(456L, detail.mediaOssId());
|
||||
assertEquals("P1", jdbcTemplate.lastArgs[1]);
|
||||
assertEquals("P1", jdbcTemplate.lastArgs[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,7 +158,7 @@ class AihrCaseServiceTest {
|
||||
|
||||
@Override
|
||||
public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) {
|
||||
this.lastCaseId = String.valueOf(args[0]);
|
||||
this.lastCaseId = String.valueOf(args[1]);
|
||||
this.lastArgs = args;
|
||||
try {
|
||||
ResultSet resultSet = mock(ResultSet.class);
|
||||
|
||||
@@ -92,3 +92,4 @@
|
||||
- 2026-07-14 生产 schema 修复:使用生产 `/opt/wygj/config/wygj.env` 中的数据库连接配置核对后,按仓库现有 `aihr_practice_mysql8.sql`/运行时建表定义执行 `CREATE TABLE IF NOT EXISTS`,补齐缺失的 `aihr_practice_audio`(9 列)和 `aihr_practice_calibration`(11 列);未写入任何业务行、未新增自定义字段。复核结果为 `org_active=22`、`org_phone_linked=0`、`calibration=0`、`sop_review=13`、`audio=0`,租户接口仍返回 200。该操作只解除 schema 漂移阻塞,不代表正式组织映射或 M5 试点完成。
|
||||
- 2026-07-14 候选人关联发布边界核对:生产根站点与 `/h5/` 返回 200,`wygj-aihr.service` active,线上后端仍为上一版 jar;远端管理端主 JS 未包含本批 `入职主体关联/candidate-links`,本批源码已提交但尚未发布。后续发布需按现有备份、静态资源同步、后端重启和浏览器回归流程执行。
|
||||
- 2026-07-14 门禁合同复核:`scripts/tests/demo-check-pilot-gates.test.sh` 通过,确认严格预检覆盖批次日期、唯一在职身份、1–2 个项目、每人至少 10 次训练、80% 完训、20 条校准、AI/人工分档一致率、SOP 可用率、满意度和音频/RAG schema;`scripts/tests/pilot-export-contract.test.mjs` 5/5 通过,AIHR 案例/对练定向测试 31/31 通过,`mobile-uni` 类型检查与 49 个单测通过。当前没有新增可安全实现的门禁缺口,剩余阻塞仍是正式组织映射、正式试点数据、视频样片和方言样本等外部输入。
|
||||
- 2026-07-14 租户边界复核:AI 面试结果、候选人入职主体关联和案例记录的查询、写入、组织身份解析均改为使用当前登录租户;无登录上下文时仅保留本地开发默认租户 `000000` 回退。该修复已覆盖案例服务的列表、详情、项目范围、贡献者校验、保存和持久化回读路径,仍需在正式多租户环境做隔离回归。
|
||||
|
||||
Reference in New Issue
Block a user