From 8fcc58fe22d37aa70824570c31466a30628e813c Mon Sep 17 00:00:00 2001 From: let5sne Date: Tue, 14 Jul 2026 11:07:43 +0800 Subject: [PATCH] fix(aihr): require explicit SOP review verdict --- .../org/dromara/aihr/service/AihrSopSeedService.java | 7 +++++++ .../org/dromara/aihr/service/AihrSopSeedServiceTest.java | 9 +++++++++ docs/BRD_IMPLEMENTATION_AUDIT.md | 1 + scripts/demo-check.sh | 1 + 4 files changed, 18 insertions(+) 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 c1d1973a..a28a6aa8 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 @@ -199,6 +199,9 @@ public class AihrSopSeedService { if (id == null) { return null; } + if (!hasExplicitSopReviewDecision(request)) { + throw new ServiceException("SOP评审必须明确选择可用或不可用"); + } ensureSopReviewTable(); int updated = jdbcTemplate.update(""" UPDATE aihr_sop_answer_review @@ -216,6 +219,10 @@ public class AihrSopSeedService { return updated == 0 ? null : sopReview(id); } + static boolean hasExplicitSopReviewDecision(SopReviewRequest request) { + return request != null && request.usable() != null; + } + public AnswerFeedbackResponse answerFeedback(AnswerFeedbackRequest request) { String queryText = request == null ? "" : Optional.ofNullable(request.queryText()).orElse("").trim(); String queryNorm = normalizeFeedbackQuery(queryText); 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 235f6ad4..4e8eb197 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 @@ -44,6 +44,15 @@ public class AihrSopSeedServiceTest { assertFalse(AihrSopSeedService.shouldCreateSopReview("物业费怎么交", "verify_demo_questions")); } + @Test + @Tag("dev") + public void sopReviewRequiresExplicitUsableDecision() { + assertFalse(AihrSopSeedService.hasExplicitSopReviewDecision(null)); + assertFalse(AihrSopSeedService.hasExplicitSopReviewDecision(new AihrSopDto.SopReviewRequest(null, null, null))); + assertTrue(AihrSopSeedService.hasExplicitSopReviewDecision(new AihrSopDto.SopReviewRequest(true, null, null))); + assertTrue(AihrSopSeedService.hasExplicitSopReviewDecision(new AihrSopDto.SopReviewRequest(false, null, null))); + } + @Test @Tag("dev") public void evidenceHitsKeepsNamedDocumentOnly() { diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index fbdfa2ca..851be8c6 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -184,3 +184,4 @@ - 2026-07-14 BRD 知识反馈关联复核:答案反馈原先直接接受客户端传入的 `reviewId`;现仅保留当前租户存在的 SOP 评审关联,非法或跨租户 ID 归一为空。 - 2026-07-14 BRD 候选资料审核留痕:候选资料审核此前只有状态三态,没有审核人和审核时间;现由服务端从当前 HR 登录态写入 `reviewer/reviewed_time`,管理端审核表同步展示。 - 2026-07-14 BRD 试点门禁租户参数化:严格试点预检此前将 M5 查询固定到 `tenant_id='000000'`,正式试点切换租户时会统计错误;现支持经过字符白名单校验的 `AIHR_PILOT_TENANT_ID`,默认仍为本地开发租户,试点命令和文档已同步。 +- 2026-07-14 BRD SOP 人工评审结论完整性:`POST /api/knowledge/reviews/{id}` 现在要求明确提交 `usable=true/false`,空请求或缺少结论会拒绝,不再把未作答误记为“不可用”;`reviewer` 仍由当前登录操作人写入。已补服务层回归测试与 `demo-check` marker,但这只修正评审数据完整性,不代表住宅 SOP 可用率已达到正式试点门槛。 diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index 68bf3f5b..2bc8ad51 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -498,6 +498,7 @@ contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/control contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "仅支持 txt/md/markdown/pdf/doc/docx/xls/xlsx/ppt/pptx/图片文件" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "/embeddings" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "aihr_knowledge_gap" +contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "hasExplicitSopReviewDecision" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "validateFeedbackFragmentOwnership" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "normalizeFeedbackReviewId" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrVideoService.java "处理输出已隐藏"