Browse Source

fix(backend): 评分明细结构化写入 + 修复集成测试评分值

wangkangyjy 1 week ago
parent
commit
b74680f056

+ 43 - 0
backend/src/main/java/com/yimeng/okr/service/PerformanceService.java

@@ -10,6 +10,7 @@ import com.yimeng.okr.enums.ScoreType;
 import com.yimeng.okr.event.NotificationEvent;
 import com.yimeng.okr.exception.BusinessException;
 import com.yimeng.okr.mapper.*;
+import com.yimeng.okr.entity.PerformanceScoreItem;
 import java.time.LocalDateTime;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -37,6 +38,7 @@ public class PerformanceService {
     private final PerformanceFeedbackMapper feedbackMapper;
     private final AssessmentPeriodMapper periodMapper;
     private final SysUserMapper userMapper;
+    private final PerformanceScoreItemMapper scoreItemMapper;
     private final AuditCorrectionMapper auditCorrectionMapper;
     private final OkrService okrService;
     private final AuthorizationService authorizationService;
@@ -72,6 +74,7 @@ public class PerformanceService {
         score.setStatus(STATUS_SELF_SUBMITTED);
         score.setCommentsJson(commentsJson);
         scoreMapper.insert(score);
+        writeScoreItems(score.getId(), commentsJson);
         return score;
     }
 
@@ -121,6 +124,7 @@ public class PerformanceService {
         score.setStatus(STATUS_SUPERIOR_SUBMITTED);
         score.setCommentsJson(commentsJson);
         scoreMapper.insert(score);
+        writeScoreItems(score.getId(), commentsJson);
 
         // Also create a FINAL record
         PerformanceScore finalScore = new PerformanceScore();
@@ -348,6 +352,45 @@ public class PerformanceService {
         }
     }
 
+
+    private void writeScoreItems(Long scoreId, String commentsJson) {
+        if (commentsJson == null || commentsJson.isBlank()) return;
+        try {
+            var node = objectMapper.readTree(commentsJson);
+            int sortOrder = 0;
+            var krScores = node.get("krScores");
+            if (krScores != null && krScores.isArray()) {
+                for (var krNode : krScores) {
+                    PerformanceScoreItem item = new PerformanceScoreItem();
+                    item.setScoreId(scoreId);
+                    item.setItemType("KR");
+                    item.setReferenceId(krNode.has("krId") ? krNode.get("krId").asLong() : null);
+                    item.setName(krNode.has("title") ? krNode.get("title").asText("") : "");
+                    item.setMaxScore(1.0);
+                    item.setScore(krNode.has("score") ? krNode.get("score").asDouble() : 0);
+                    item.setSortOrder(sortOrder++);
+                    scoreItemMapper.insert(item);
+                }
+            }
+            var dimensions = node.get("dimensions");
+            if (dimensions != null && dimensions.isArray()) {
+                for (var dimNode : dimensions) {
+                    PerformanceScoreItem item = new PerformanceScoreItem();
+                    item.setScoreId(scoreId);
+                    item.setItemType("DIMENSION");
+                    item.setReferenceId(dimNode.has("id") ? dimNode.get("id").asLong() : null);
+                    item.setName(dimNode.has("name") ? dimNode.get("name").asText("") : "");
+                    item.setMaxScore(dimNode.has("maxScore") ? dimNode.get("maxScore").asDouble() : 0);
+                    item.setScore(dimNode.has("score") ? dimNode.get("score").asDouble() : 0);
+                    item.setSortOrder(sortOrder++);
+                    scoreItemMapper.insert(item);
+                }
+            }
+        } catch (Exception e) {
+            log.warn("Failed to write structured score items for score_id={}: {}", scoreId, e.getMessage());
+        }
+    }
+
     private String toJson(Object value) {
         try {
             return objectMapper.writeValueAsString(value);

+ 2 - 2
backend/src/test/java/com/yimeng/okr/integration/PerformanceLifecycleApiIntegrationTest.java

@@ -96,8 +96,8 @@ class PerformanceLifecycleApiIntegrationTest {
         putJson(hrToken, "/api/periods/" + periodId + "/status", Map.of("status", PeriodStatus.EXECUTING.name()));
         putJson(hrToken, "/api/periods/" + periodId + "/status", Map.of("status", PeriodStatus.ASSESSING.name()));
 
-        postForData(employeeToken, "/api/scores/self", scoreBody(periodId, null, 34, 52));
-        postForData(managerToken, "/api/scores/superior", scoreBody(periodId, employee.getId(), 35, 53));
+        postForData(employeeToken, "/api/scores/self", scoreBody(periodId, null, 54, 32));
+        postForData(managerToken, "/api/scores/superior", scoreBody(periodId, employee.getId(), 55, 33));
         postForData(hrToken, "/api/scores/publish", Map.of("periodId", periodId, "userId", employee.getId()));
 
         Long appealId = postForData(employeeToken, "/api/score-appeals",

+ 2 - 2
backend/src/test/java/com/yimeng/okr/integration/PerformanceLifecycleIntegrationTest.java

@@ -97,8 +97,8 @@ class PerformanceLifecycleIntegrationTest {
         periodService.transitionStatus(period.getId(), PeriodStatus.EXECUTING);
         periodService.transitionStatus(period.getId(), PeriodStatus.ASSESSING);
 
-        performanceService.submitSelfScore(period.getId(), employee.getId(), 34.0, 52.0, 0.0, 0.0, "{}");
-        performanceService.submitSuperiorScore(period.getId(), employee.getId(), manager.getId(), 35.0, 53.0, 0.0, 0.0, "{}");
+        performanceService.submitSelfScore(period.getId(), employee.getId(), 54.0, 32.0, 0.0, 0.0, "{}");
+        performanceService.submitSuperiorScore(period.getId(), employee.getId(), manager.getId(), 55.0, 33.0, 0.0, 0.0, "{}");
         performanceService.publishFinalScore(period.getId(), employee.getId(), hr.getId());
         ScoreAppeal appeal = appealService.submitAppeal(period.getId(), employee.getId(), "希望复核评分依据");
         appealService.resolveAppeal(appeal.getId(), hr.getId(), "REJECTED", "评分依据充分");