feat(practice): streamline pilot content operations
This commit is contained in:
+3
-1
@@ -98,7 +98,9 @@ public final class AihrPracticeDto {
|
||||
String strategy,
|
||||
String goal,
|
||||
Boolean enabled,
|
||||
List<ScenarioRoundResponse> rounds
|
||||
List<ScenarioRoundResponse> rounds,
|
||||
String expectedContentVersion,
|
||||
String expectedContentHash
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
+26
-5
@@ -124,8 +124,10 @@ public class AihrPracticeSeedService {
|
||||
private static final Set<String> SCENARIO_REVIEW_STATUSES = Set.of("草稿", "待业务审核", "已发布", "已下线");
|
||||
private static final Set<String> SCENARIO_RISK_LEVELS = Set.of("待评估", "常规", "高风险");
|
||||
private static final List<String> MANDATORY_DUAL_REVIEW_TERMS = List.of(
|
||||
"投诉", "客诉", "纠纷", "收费", "催费", "费用", "停车费", "退款", "减免",
|
||||
"安全", "事故", "消防", "燃气", "漏电", "电梯", "高空", "受伤", "人身伤害", "舆情"
|
||||
"事故", "消防", "火灾", "起火", "爆炸", "燃气", "漏电", "触电", "带电",
|
||||
"高空", "困人", "受伤", "人身伤害", "摔倒", "暴力", "肢体冲突",
|
||||
"危险物品", "化学品", "医疗废弃", "针具", "锐器", "有限空间", "中毒",
|
||||
"舆情", "赔偿", "退款", "退费", "减免", "免单", "豁免"
|
||||
);
|
||||
private static final String UNCLASSIFIED_COMPETENCY = "待归类";
|
||||
private static final String DEFAULT_CURRICULUM_VERSION = "住宅五岗-v1";
|
||||
@@ -429,6 +431,7 @@ public class AihrPracticeSeedService {
|
||||
throw new ServiceException("训练场景不存在或内容未发布");
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ScenarioResponse saveScenario(ScenarioSaveRequest request) {
|
||||
ensureScenarioTable();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
@@ -437,6 +440,20 @@ public class AihrPracticeSeedService {
|
||||
String position = canonicalPracticePosition(request == null ? null : request.position());
|
||||
String scenarioType = firstNonBlank(request == null ? null : request.scenarioType(), "投诉处理");
|
||||
String projectType = firstNonBlank(request == null ? null : request.projectType(), "住宅");
|
||||
if (request != null && (!isBlank(request.expectedContentVersion()) || !isBlank(request.expectedContentHash()))) {
|
||||
List<String[]> current = jdbcTemplate.query("""
|
||||
SELECT content_version, content_hash
|
||||
FROM aihr_practice_scenario
|
||||
WHERE tenant_id = ? AND scenario_code = ?
|
||||
FOR UPDATE
|
||||
""", (rs, rowNum) -> new String[] {rs.getString("content_version"), rs.getString("content_hash")},
|
||||
tenantId(), code);
|
||||
if (current.isEmpty()
|
||||
|| !Objects.equals(current.get(0)[0], request.expectedContentVersion())
|
||||
|| !Objects.equals(current.get(0)[1], request.expectedContentHash())) {
|
||||
throw new ServiceException("训练场景已发生变更,请刷新后重新编辑");
|
||||
}
|
||||
}
|
||||
ScenarioCurriculumMetadata existingCurriculum = existingScenarioCurriculum(code);
|
||||
String growthLevel = normalizeGrowthLevel(firstNonBlank(request == null ? null : request.growthLevel(),
|
||||
existingCurriculum == null ? null : existingCurriculum.growthLevel()));
|
||||
@@ -7653,13 +7670,13 @@ public class AihrPracticeSeedService {
|
||||
return requiresMandatoryDualReview(content) ? "高风险" : riskLevel;
|
||||
}
|
||||
|
||||
private boolean requiresMandatoryDualReview(String... content) {
|
||||
static boolean requiresMandatoryDualReviewContent(String... content) {
|
||||
for (String value : Optional.ofNullable(content).orElse(new String[0])) {
|
||||
if (isBlank(value)) {
|
||||
if (value == null || value.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
String normalized = value.trim();
|
||||
if ("高风险".equals(normalized)) {
|
||||
if (normalized.contains("高风险")) {
|
||||
return true;
|
||||
}
|
||||
for (String term : MANDATORY_DUAL_REVIEW_TERMS) {
|
||||
@@ -7671,6 +7688,10 @@ public class AihrPracticeSeedService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean requiresMandatoryDualReview(String... content) {
|
||||
return requiresMandatoryDualReviewContent(content);
|
||||
}
|
||||
|
||||
private String normalizeReviewStatus(String value) {
|
||||
String status = firstNonBlank(value, "草稿");
|
||||
if (!SCENARIO_REVIEW_STATUSES.contains(status)) {
|
||||
|
||||
+13
-1
@@ -513,6 +513,8 @@ public class AihrPracticeSeedServiceTest {
|
||||
assertFalse(source.contains("WHEN enabled = 1 THEN '已发布' ELSE '待业务审核' END"));
|
||||
assertTrue(source.contains("content_hash <=> ?"));
|
||||
assertTrue(source.contains("训练场景已发生变更,请刷新后重新审核"));
|
||||
assertTrue(source.contains("expectedContentVersion"));
|
||||
assertTrue(source.contains("训练场景已发生变更,请刷新后重新编辑"));
|
||||
assertTrue(source.contains("boolean reviewDecision = \"待业务审核\".equals(current)"));
|
||||
assertTrue(source.contains("SCENARIO_RISK_LEVELS"));
|
||||
assertTrue(source.contains("approveHighRiskScenario"));
|
||||
@@ -577,6 +579,16 @@ public class AihrPracticeSeedServiceTest {
|
||||
assertEquals("已发布", jdbcTemplate.reviewStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericServiceTopicsDoNotRequireDualReviewWithoutMaterialRisk() {
|
||||
assertFalse(AihrPracticeSeedService.requiresMandatoryDualReviewContent(
|
||||
"投诉信息完整登记", "费用明细查询", "电梯轿厢日常保洁", "安全确认"
|
||||
));
|
||||
assertTrue(AihrPracticeSeedService.requiresMandatoryDualReviewContent("电梯困人信息收集与升级"));
|
||||
assertTrue(AihrPracticeSeedService.requiresMandatoryDualReviewContent("物业费减免申请"));
|
||||
assertTrue(AihrPracticeSeedService.requiresMandatoryDualReviewContent("高风险作业"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scenarioCannotPublishUntilContentRiskIsExplicitlyClassified() throws Exception {
|
||||
HighRiskScenarioJdbcTemplate jdbcTemplate = new HighRiskScenarioJdbcTemplate("待评估");
|
||||
@@ -800,7 +812,7 @@ public class AihrPracticeSeedServiceTest {
|
||||
));
|
||||
|
||||
assertEquals("待业务审核", jdbcTemplate.reviewStatus);
|
||||
assertEquals("高风险", jdbcTemplate.riskLevel);
|
||||
assertEquals("常规", jdbcTemplate.riskLevel);
|
||||
assertNull(jdbcTemplate.reviewer);
|
||||
assertNull(jdbcTemplate.reviewerUserId);
|
||||
assertNull(jdbcTemplate.secondReviewer);
|
||||
|
||||
Reference in New Issue
Block a user