fix(aihr): expose reviewed promotion evidence scores

This commit is contained in:
2026-07-14 13:23:25 +08:00
parent b9cce62cf1
commit 1c0c47a757
8 changed files with 88 additions and 4 deletions
@@ -335,7 +335,10 @@ public final class AihrPracticeDto {
List<DimensionResponse> dimensions,
List<RecordResponse> latestRecords,
List<PracticeAssignmentResponse> assignments,
List<String> evidenceItems
List<String> evidenceItems,
Integer humanAssessmentScore,
Integer finalAdoptedScore,
Integer calibrationCount
) {
}
}
@@ -1605,11 +1605,14 @@ public class AihrPracticeSeedService {
public PromotionEvidenceResponse promotionEvidence(String extPartyId) {
String party = isBlank(extPartyId) ? "" : extPartyId.trim();
CompetencyResponse profile = competency(party);
EvidenceScoreSnapshot scores = evidenceScores(party);
List<RecordResponse> latestRecords = mobileHistory(party, 5);
List<PracticeAssignmentResponse> assignmentRows = assignments(party, 5);
List<String> evidenceItems = new ArrayList<>();
evidenceItems.add("累计完成 " + profile.completed() + " 次移动端AI陪练,训练时长约 " + profile.trainingMinutes() + " 分钟");
evidenceItems.add("AI测评分 " + profile.assessmentScore() + ",训练画像参考等级 " + profile.aiLevel() + "(需人工复核)");
evidenceItems.add("AI测评分 " + scores.aiScore() + ";人工校准分 "
+ (scores.humanScore() == null ? "未采集" : scores.humanScore())
+ ";最终采用分 " + scores.finalScore() + ";训练画像参考等级 " + profile.aiLevel() + "(需人工复核)");
evidenceItems.add("训练贡献度 " + profile.contribution() + ",待主管复盘 " + profile.pendingReview() + " 条");
if (!latestRecords.isEmpty()) {
RecordResponse latest = latestRecords.get(0);
@@ -1626,10 +1629,40 @@ public class AihrPracticeSeedService {
profile.dimensions(),
latestRecords,
assignmentRows,
evidenceItems
evidenceItems,
scores.humanScore(),
scores.finalScore(),
scores.calibrationCount()
);
}
private EvidenceScoreSnapshot evidenceScores(String extPartyId) {
ensureCalibrationTable();
String party = isBlank(extPartyId) ? "" : extPartyId.trim();
List<EvidenceScoreSnapshot> rows = jdbcTemplate.query("""
WITH latest_calibration AS (
SELECT tenant_id, session_id, corrected_score,
ROW_NUMBER() OVER (PARTITION BY tenant_id, session_id ORDER BY id DESC) AS row_num
FROM aihr_practice_calibration
WHERE tenant_id = ?
)
SELECT COALESCE(ROUND(AVG(s.total_score)), 0) AS ai_score,
CASE WHEN COUNT(lc.corrected_score) = 0 THEN NULL ELSE ROUND(AVG(lc.corrected_score)) END AS human_score,
COALESCE(ROUND(AVG(COALESCE(lc.corrected_score, s.total_score))), 0) AS final_score,
COUNT(lc.corrected_score) AS calibration_count
FROM aihr_practice_session s
LEFT JOIN latest_calibration lc
ON lc.tenant_id = s.tenant_id AND lc.session_id = s.session_id AND lc.row_num = 1
WHERE s.tenant_id = ? AND s.mode = 'mobile' AND (? = '' OR s.ext_party_id = ?)
""", (rs, rowNum) -> new EvidenceScoreSnapshot(
rs.getInt("ai_score"),
rs.getObject("human_score") == null ? null : rs.getInt("human_score"),
rs.getInt("final_score"),
rs.getInt("calibration_count")
), tenantId(), tenantId(), party, party);
return rows.isEmpty() ? new EvidenceScoreSnapshot(0, null, 0, 0) : rows.get(0);
}
private String aiLevel(int completed, int score) {
if (completed <= 0) {
return "未评级";
@@ -3814,6 +3847,9 @@ public class AihrPracticeSeedService {
private record CompetencySnapshot(Integer completed, Integer score, Integer pendingReview, Integer compliance, Integer communication, Integer emotion, Integer marketing, Integer incentivePoints) {
}
private record EvidenceScoreSnapshot(Integer aiScore, Integer humanScore, Integer finalScore, Integer calibrationCount) {
}
private record SessionAnnotationSource(String scenarioId, String dialogueJson, String annotationsJson) {
}
@@ -608,6 +608,19 @@ public class AihrPracticeSeedServiceTest {
assertTrue(profile.growthPath().stream().allMatch(item -> Integer.valueOf(0).equals(item.progress())));
}
@Test
public void promotionEvidenceIncludesHumanCalibrationAndFinalScore() throws Exception {
String source = Files.readString(Path.of("src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java"));
int methodStart = source.indexOf("public PromotionEvidenceResponse promotionEvidence");
int methodEnd = source.indexOf("private EvidenceScoreSnapshot evidenceScores", methodStart);
assertTrue(methodStart >= 0 && methodEnd > methodStart);
String method = source.substring(methodStart, methodEnd);
assertTrue(method.contains("scores.humanScore()"));
assertTrue(method.contains("scores.finalScore()"));
assertTrue(source.contains("ROW_NUMBER() OVER (PARTITION BY tenant_id, session_id ORDER BY id DESC)"));
assertTrue(source.contains("COALESCE(lc.corrected_score, s.total_score)"));
}
@Test
public void competencyGrowthProgressStopsAtWeakRequirement() {
JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);