feat(aihr): add employee mistake book audit
This commit is contained in:
+6
@@ -13,6 +13,7 @@ import org.dromara.aihr.domain.AihrPracticeDto.PracticeAssignmentResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.PracticeTeamResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.PromotionEvidenceResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.RecordResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.MistakeResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.ReviewAdviceRequest;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.ReviewDetailResponse;
|
||||
import org.dromara.aihr.domain.vo.AihrMobileDto.HomeResponse;
|
||||
@@ -91,6 +92,11 @@ public class AihrMobileController {
|
||||
return detail == null ? R.fail("训练记录不存在") : R.ok(reviewDetailPayload(detail));
|
||||
}
|
||||
|
||||
@GetMapping("/practice/mistakes")
|
||||
public R<List<MistakeResponse>> practiceMistakes(@RequestParam(required = false) String extPartyId) {
|
||||
return R.ok(mobileSeedService.practiceMistakes(ownMobileExtPartyId(extPartyId)));
|
||||
}
|
||||
|
||||
@GetMapping("/practice/reviews")
|
||||
public R<List<RecordResponse>> practiceReviews(@RequestParam(required = false) String projectCode,
|
||||
@RequestParam(required = false) String extPartyId,
|
||||
|
||||
+14
@@ -142,6 +142,20 @@ public final class AihrPracticeDto {
|
||||
public record RecordResponse(Long id, String sessionId, String time, String trainee, String scene, Integer score, String status, String summary, String extPartyId) {
|
||||
}
|
||||
|
||||
public record MistakeResponse(
|
||||
Long id,
|
||||
String sessionId,
|
||||
String scenarioId,
|
||||
String scenarioName,
|
||||
Integer score,
|
||||
String cause,
|
||||
Long retryAssignmentId,
|
||||
String retryStatus,
|
||||
String time,
|
||||
String summary
|
||||
) {
|
||||
}
|
||||
|
||||
public record DialogueResponse(String role, String label, String text, String audioUrl, Long audioOssId, Integer emotion, Integer trust, Boolean redFlag, String coachHint) {
|
||||
public DialogueResponse(String role, String label, String text) {
|
||||
this(role, label, text, "", null, null, null, null, "");
|
||||
|
||||
+5
@@ -9,6 +9,7 @@ import org.dromara.aihr.domain.AihrPracticeDto.PracticeAssignmentResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.PracticeTeamResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.PromotionEvidenceResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.RecordResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.MistakeResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.ReviewAdviceRequest;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.ReviewDetailResponse;
|
||||
import org.dromara.aihr.domain.vo.AihrMobileDto.HomeResponse;
|
||||
@@ -49,6 +50,10 @@ public class AihrMobileSeedService {
|
||||
return practiceSeedService.mobileHistory(extPartyId, 5);
|
||||
}
|
||||
|
||||
public List<MistakeResponse> practiceMistakes(String extPartyId) {
|
||||
return practiceSeedService.mobileMistakes(extPartyId, 20);
|
||||
}
|
||||
|
||||
public List<RecordResponse> practiceReviews() {
|
||||
return practiceSeedService.pendingReviewRecords(5);
|
||||
}
|
||||
|
||||
+60
@@ -25,6 +25,7 @@ import org.dromara.aihr.domain.AihrPracticeDto.PromptTemplateRequest;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.PromptTemplateResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.PromotionEvidenceResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.RecordResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.MistakeResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.ReviewAdviceRequest;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.ReviewDetailResponse;
|
||||
import org.dromara.aihr.domain.AihrPracticeDto.RubricDimensionResponse;
|
||||
@@ -722,6 +723,65 @@ public class AihrPracticeSeedService {
|
||||
""", this::mapRecord, TENANT_ID, extPartyId.trim(), safeLimit);
|
||||
}
|
||||
|
||||
public List<MistakeResponse> mobileMistakes(String extPartyId, int limit) {
|
||||
ensurePracticeTable();
|
||||
ensureAssignmentTable();
|
||||
if (isBlank(extPartyId)) {
|
||||
return List.of();
|
||||
}
|
||||
int safeLimit = normalizeLimit(limit);
|
||||
return jdbcTemplate.query("""
|
||||
SELECT s.id,
|
||||
s.session_id,
|
||||
s.scenario_id,
|
||||
s.scenario_name,
|
||||
s.total_score,
|
||||
CASE
|
||||
WHEN s.dialogue_json LIKE '%"redFlag":true%' THEN '红线话术'
|
||||
WHEN COALESCE(s.dim_emotion, 100) < 60 THEN '情绪承接'
|
||||
WHEN COALESCE(s.dim_compliance, 100) < 60 THEN '流程合规'
|
||||
ELSE '综合得分不足'
|
||||
END AS cause,
|
||||
(SELECT a.id
|
||||
FROM aihr_practice_assignment a
|
||||
WHERE a.tenant_id = s.tenant_id
|
||||
AND a.ext_party_id = s.ext_party_id
|
||||
AND a.scenario_id = s.scenario_id
|
||||
AND a.source = 'retry'
|
||||
ORDER BY a.id DESC
|
||||
LIMIT 1) AS retry_assignment_id,
|
||||
COALESCE((SELECT a.status
|
||||
FROM aihr_practice_assignment a
|
||||
WHERE a.tenant_id = s.tenant_id
|
||||
AND a.ext_party_id = s.ext_party_id
|
||||
AND a.scenario_id = s.scenario_id
|
||||
AND a.source = 'retry'
|
||||
ORDER BY a.id DESC
|
||||
LIMIT 1), '未生成') AS retry_status,
|
||||
s.finished_time,
|
||||
s.summary
|
||||
FROM aihr_practice_session s
|
||||
WHERE s.tenant_id = ?
|
||||
AND s.mode = 'mobile'
|
||||
AND s.ext_party_id = ?
|
||||
AND s.finished_time IS NOT NULL
|
||||
AND (s.total_score < 80 OR s.dialogue_json LIKE '%"redFlag":true%')
|
||||
ORDER BY s.finished_time DESC, s.id DESC
|
||||
LIMIT ?
|
||||
""", (rs, rowNum) -> new MistakeResponse(
|
||||
rs.getLong("id"),
|
||||
rs.getString("session_id"),
|
||||
rs.getString("scenario_id"),
|
||||
firstNonBlank(rs.getString("scenario_name"), "场景训练"),
|
||||
rs.getInt("total_score"),
|
||||
firstNonBlank(rs.getString("cause"), "综合得分不足"),
|
||||
rs.getObject("retry_assignment_id") == null ? null : rs.getLong("retry_assignment_id"),
|
||||
firstNonBlank(rs.getString("retry_status"), "未生成"),
|
||||
rs.getTimestamp("finished_time") == null ? "" : rs.getTimestamp("finished_time").toLocalDateTime().format(TIME_FORMATTER),
|
||||
firstNonBlank(rs.getString("summary"), "建议回看训练对话和导师改写")
|
||||
), TENANT_ID, extPartyId.trim(), safeLimit);
|
||||
}
|
||||
|
||||
public PracticeTeamResponse practiceTeamSnapshot(String supervisorExtPartyId, int limit) {
|
||||
TeamScope scope = teamScope(supervisorExtPartyId);
|
||||
int safeLimit = normalizeTeamLimit(limit);
|
||||
|
||||
Reference in New Issue
Block a user