From 88702867b80bfc9af5e3beb430c03fd1ccf83b38 Mon Sep 17 00:00:00 2001 From: let5sne Date: Tue, 14 Jul 2026 11:20:12 +0800 Subject: [PATCH] fix(aihr): scope pilot SOP metrics --- .../dromara/aihr/service/AihrSopSeedService.java | 2 ++ .../aihr/service/AihrSopSeedServiceTest.java | 13 +++++++++++++ docs/BRD_IMPLEMENTATION_AUDIT.md | 1 + scripts/demo-check.sh | 6 +++--- scripts/tests/demo-check-pilot-gates.test.sh | 12 +++++++----- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java index a28a6aa8..2965a36e 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java @@ -1933,6 +1933,7 @@ public class AihrSopSeedService { SELECT COUNT(*) AS total, COALESCE(SUM(CASE WHEN usable = 1 THEN 1 ELSE 0 END), 0) AS usable FROM aihr_sop_answer_review WHERE tenant_id = ? AND status = '已评审' + AND (LOWER(TRIM(COALESCE(category, ''))) = 'sop' OR category LIKE '%SOP%') """, (rs, rowNum) -> new SopReviewStats(rs.getInt("total"), rs.getInt("usable")), tenantId()); } @@ -1946,6 +1947,7 @@ public class AihrSopSeedService { SELECT COUNT(*) AS total, COALESCE(SUM(CASE WHEN usable = 1 THEN 1 ELSE 0 END), 0) AS usable FROM aihr_sop_answer_review WHERE tenant_id = ? AND status = '已评审' + AND (LOWER(TRIM(COALESCE(category, ''))) = 'sop' OR category LIKE '%SOP%') AND reviewed_time >= ? AND reviewed_time < ? """, (rs, rowNum) -> new SopReviewStats(rs.getInt("total"), rs.getInt("usable")), tenantId(), Timestamp.valueOf(startTime), Timestamp.valueOf(endTime)); diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrSopSeedServiceTest.java b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrSopSeedServiceTest.java index 4e8eb197..c04121a7 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrSopSeedServiceTest.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrSopSeedServiceTest.java @@ -53,6 +53,19 @@ public class AihrSopSeedServiceTest { assertTrue(AihrSopSeedService.hasExplicitSopReviewDecision(new AihrSopDto.SopReviewRequest(false, null, null))); } + @Test + @Tag("dev") + public void pilotSopStatsScopeToSopCategories() throws Exception { + Path source = Path.of("src/main/java/org/dromara/aihr/service/AihrSopSeedService.java"); + if (!Files.exists(source)) { + source = Path.of("ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java"); + } + String code = Files.readString(source); + + assertTrue(code.contains("LOWER(TRIM(COALESCE(category, ''))) = 'sop'")); + assertTrue(code.contains("category LIKE '%SOP%'")); + } + @Test @Tag("dev") public void evidenceHitsKeepsNamedDocumentOnly() { diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index 7ac4456e..3133cebf 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -189,3 +189,4 @@ - 2026-07-14 BRD 4.6 案例发布状态复核:员工端案例列表和详情原先只按租户/项目范围读取,未限制案例状态,理论上可能看到仍处于“已转写/已整理”的管理流程半成品;现对 APP 项目范围读取增加 `status='已入库'`,管理端 HR/管理员仍可查看全部状态以继续处理。新增案例服务回归测试,AIHR 全量测试 `81/81` 通过;视频样片、学习点和主管点评仍需正式业务输入。 - 2026-07-14 BRD 案例提交能力边界复核:移动端案例页原先对所有登录员工展示“提交素材”表单,但后端仅允许主管/项目负责人提交,普通员工点击后才得到权限错误;现新增只读 `GET /api/knowledge/case/capabilities`,复用服务端唯一贡献者判定,员工端仅在 `canSubmit=true` 时展示提交入口,其他员工显示案例学习说明。后端权限仍保留为最终防线。 - 2026-07-14 线上只读发布差异:生产根站和 `/h5/` 返回 `200`,生产仍加载 H5 `assets/index-D4-NrEpb.js`;本地 `b8be1bb6` 构建已生成 `mobile-uni/dist/build/h5/assets/index-u8NWYNWX.js`,案例状态过滤和提交能力入口尚未发布。本轮未执行生产静态资源同步、后端重启或业务数据写入。 +- 2026-07-14 BRD 4.7 SOP 指标口径复核:正式试点的 SOP 可用率与待评审数现只统计评审表中 `category='sop'` 或名称包含 `SOP` 的记录,并继续按租户和试点日期窗口过滤;培训类或其他知识问答不会混入正式 SOP 分母。后端导出、严格预检和单测夹具已统一该条件;岗位与住宅项目的正式适用性仍需组织/HR 规则输入,不能仅靠分类字符串替代。 diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index abbe07ca..dd3932ed 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -245,9 +245,9 @@ check_pilot_samples() { JOIN latest_calibration latest ON latest.id = c.id WHERE c.tenant_id = '$pilot_tenant'")" read -r calibration_count calibration_matched <<<"$calibration_stats" - sop_total="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_sop_answer_review WHERE tenant_id = '$pilot_tenant' AND status = '已评审' AND reviewed_time >= '${pilot_start} 00:00:00' AND reviewed_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)")" - sop_usable="$(pilot_sql_scalar "SELECT COALESCE(SUM(CASE WHEN usable = 1 THEN 1 ELSE 0 END), 0) FROM aihr_sop_answer_review WHERE tenant_id = '$pilot_tenant' AND status = '已评审' AND reviewed_time >= '${pilot_start} 00:00:00' AND reviewed_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)")" - sop_pending="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_sop_answer_review WHERE tenant_id = '$pilot_tenant' AND status <> '已评审' AND create_time >= '${pilot_start} 00:00:00' AND create_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)")" + sop_total="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_sop_answer_review WHERE tenant_id = '$pilot_tenant' AND status = '已评审' AND (LOWER(TRIM(COALESCE(category, ''))) = 'sop' OR category LIKE '%SOP%') AND reviewed_time >= '${pilot_start} 00:00:00' AND reviewed_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)")" + sop_usable="$(pilot_sql_scalar "SELECT COALESCE(SUM(CASE WHEN usable = 1 THEN 1 ELSE 0 END), 0) FROM aihr_sop_answer_review WHERE tenant_id = '$pilot_tenant' AND status = '已评审' AND (LOWER(TRIM(COALESCE(category, ''))) = 'sop' OR category LIKE '%SOP%') AND reviewed_time >= '${pilot_start} 00:00:00' AND reviewed_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)")" + sop_pending="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_sop_answer_review WHERE tenant_id = '$pilot_tenant' AND status <> '已评审' AND (LOWER(TRIM(COALESCE(category, ''))) = 'sop' OR category LIKE '%SOP%') AND create_time >= '${pilot_start} 00:00:00' AND create_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)")" satisfaction_count="$(pilot_sql_scalar " $org_identity_cte, formal_sessions AS ( diff --git a/scripts/tests/demo-check-pilot-gates.test.sh b/scripts/tests/demo-check-pilot-gates.test.sh index dd59f0f0..53bb0286 100644 --- a/scripts/tests/demo-check-pilot-gates.test.sh +++ b/scripts/tests/demo-check-pilot-gates.test.sh @@ -72,7 +72,7 @@ CREATE TABLE aihr_practice_calibration ( original_score int, corrected_score int, create_time datetime ); CREATE TABLE aihr_sop_answer_review ( - tenant_id varchar(20), status varchar(30), usable tinyint, + tenant_id varchar(20), category varchar(100), status varchar(30), usable tinyint, reviewed_time datetime, create_time datetime ); @@ -133,10 +133,12 @@ INSERT INTO aihr_practice_calibration (tenant_id,session_id,original_score,corre ('000000','unsafe-inside',80,40,'2026-07-08 11:00:00'), ('000000','e-out',80,40,'2026-07-06 11:00:00'); INSERT INTO aihr_sop_answer_review VALUES - ('000000','已评审',1,'2026-07-08 12:00:00','2026-07-08 11:00:00'), - ('000000','已评审',0,'2026-07-06 12:00:00','2026-07-06 11:00:00'), - ('000000','待评审',NULL,NULL,'2026-07-08 13:00:00'), - ('000000','待评审',NULL,NULL,'2026-07-06 13:00:00'); + ('000000','sop','已评审',1,'2026-07-08 12:00:00','2026-07-08 11:00:00'), + ('000000','sop','已评审',0,'2026-07-06 12:00:00','2026-07-06 11:00:00'), + ('000000','sop','待评审',NULL,NULL,'2026-07-08 13:00:00'), + ('000000','training','已评审',0,'2026-07-08 12:30:00','2026-07-08 11:30:00'), + ('000000','training','待评审',NULL,NULL,'2026-07-08 13:00:00'), + ('000000','training','待评审',NULL,NULL,'2026-07-06 13:00:00'); SQL export AIHR_PILOT_DB="$TEST_DB"