|
|
@@ -7,6 +7,8 @@ import com.emoon.okr.entity.AssessmentPeriod;
|
|
|
import com.emoon.okr.entity.KpiConfig;
|
|
|
import com.emoon.okr.entity.PerformanceFeedback;
|
|
|
import com.emoon.okr.entity.PerformanceScore;
|
|
|
+import com.emoon.okr.entity.PeerReviewInvitation;
|
|
|
+import com.emoon.okr.entity.PeerReviewRequest;
|
|
|
import com.emoon.okr.entity.ScoreAppeal;
|
|
|
import com.emoon.okr.entity.SysDepartment;
|
|
|
import com.emoon.okr.entity.SysUser;
|
|
|
@@ -18,6 +20,8 @@ import com.emoon.okr.mapper.KpiConfigMapper;
|
|
|
import com.emoon.okr.mapper.OkrObjectiveMapper;
|
|
|
import com.emoon.okr.mapper.PerformanceFeedbackMapper;
|
|
|
import com.emoon.okr.mapper.PerformanceScoreMapper;
|
|
|
+import com.emoon.okr.mapper.PeerReviewInvitationMapper;
|
|
|
+import com.emoon.okr.mapper.PeerReviewRequestMapper;
|
|
|
import com.emoon.okr.mapper.ScoreAppealMapper;
|
|
|
import com.emoon.okr.mapper.SysDepartmentMapper;
|
|
|
import com.emoon.okr.mapper.SysUserMapper;
|
|
|
@@ -33,6 +37,7 @@ import org.springframework.test.annotation.DirtiesContext;
|
|
|
import org.springframework.test.web.servlet.MockMvc;
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
+import java.time.LocalDateTime;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
|
|
|
@@ -64,6 +69,8 @@ class PerformanceLifecycleApiIntegrationTest {
|
|
|
@Autowired PerformanceScoreMapper scoreMapper;
|
|
|
@Autowired PerformanceFeedbackMapper feedbackMapper;
|
|
|
@Autowired ScoreAppealMapper appealMapper;
|
|
|
+ @Autowired PeerReviewRequestMapper peerReviewRequestMapper;
|
|
|
+ @Autowired PeerReviewInvitationMapper peerReviewInvitationMapper;
|
|
|
|
|
|
@Test
|
|
|
void httpApiSupportsFullPerformanceLifecycle() throws Exception {
|
|
|
@@ -81,7 +88,9 @@ class PerformanceLifecycleApiIntegrationTest {
|
|
|
Long periodId = postForData(hrToken, "/api/periods", Map.of(
|
|
|
"name", "API 端到端周期",
|
|
|
"periodType", PeriodType.MONTHLY.name(),
|
|
|
- "startDate", LocalDate.of(2026, 6, 1).toString()
|
|
|
+ "startDate", LocalDate.of(2026, 6, 1).toString(),
|
|
|
+ "peerInvitationDeadline", "2026-06-30T18:00:00",
|
|
|
+ "peerReviewDeadline", "2026-07-02T18:00:00"
|
|
|
)).get("id").asLong();
|
|
|
|
|
|
putJson(hrToken, "/api/periods/" + periodId + "/status", Map.of("status", PeriodStatus.OKR_ALIGN.name()));
|
|
|
@@ -103,6 +112,7 @@ class PerformanceLifecycleApiIntegrationTest {
|
|
|
putJson(hrToken, "/api/periods/" + periodId + "/status", Map.of("status", PeriodStatus.ASSESSING.name()));
|
|
|
|
|
|
postForData(employeeToken, "/api/scores/self", scoreBody(periodId, null, 54, 32));
|
|
|
+ seedCompletedPeerReviews(periodId, employee.getId(), manager.getId(), hr.getId(), manager.getId());
|
|
|
postForData(managerToken, "/api/scores/superior", scoreBody(periodId, employee.getId(), 55, 33));
|
|
|
postForData(managerToken, "/api/scores/publish", Map.of("periodId", periodId, "userId", employee.getId()));
|
|
|
|
|
|
@@ -165,7 +175,9 @@ class PerformanceLifecycleApiIntegrationTest {
|
|
|
Long periodId = postForData(hrToken, "/api/periods", Map.of(
|
|
|
"name", "多目标周期",
|
|
|
"periodType", PeriodType.MONTHLY.name(),
|
|
|
- "startDate", LocalDate.of(2026, 8, 1).toString()
|
|
|
+ "startDate", LocalDate.of(2026, 8, 1).toString(),
|
|
|
+ "peerInvitationDeadline", "2026-08-31T18:00:00",
|
|
|
+ "peerReviewDeadline", "2026-09-02T18:00:00"
|
|
|
)).get("id").asLong();
|
|
|
putJson(hrToken, "/api/periods/" + periodId + "/status", Map.of("status", PeriodStatus.OKR_ALIGN.name()));
|
|
|
|
|
|
@@ -193,6 +205,30 @@ class PerformanceLifecycleApiIntegrationTest {
|
|
|
assertEquals(403, objectMapper.readTree(forbidden).get("code").asInt());
|
|
|
}
|
|
|
|
|
|
+ private void seedCompletedPeerReviews(Long periodId, Long subjectId, Long leaderId,
|
|
|
+ Long firstReviewerId, Long secondReviewerId) {
|
|
|
+ PeerReviewRequest request = new PeerReviewRequest();
|
|
|
+ request.setPeriodId(periodId);
|
|
|
+ request.setSubjectUserId(subjectId);
|
|
|
+ request.setLeaderId(leaderId);
|
|
|
+ request.setStatus("IN_PROGRESS");
|
|
|
+ peerReviewRequestMapper.insert(request);
|
|
|
+ for (Long reviewerId : List.of(firstReviewerId, secondReviewerId)) {
|
|
|
+ PeerReviewInvitation invitation = new PeerReviewInvitation();
|
|
|
+ invitation.setRequestId(request.getId());
|
|
|
+ invitation.setReviewerId(reviewerId);
|
|
|
+ invitation.setRelationTypeSnapshot("CROSS_DEPARTMENT");
|
|
|
+ invitation.setStatus("SUBMITTED");
|
|
|
+ invitation.setGoalContributionScore(4);
|
|
|
+ invitation.setCollaborationScore(4);
|
|
|
+ invitation.setAccountabilityScore(4);
|
|
|
+ invitation.setStrengths("能够稳定推进目标并主动协作补位");
|
|
|
+ invitation.setImprovementSuggestion("建议进一步加强风险识别和提前同步");
|
|
|
+ invitation.setSubmittedAt(LocalDateTime.now());
|
|
|
+ peerReviewInvitationMapper.insert(invitation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private JsonNode postForData(String token, String path, Object body) throws Exception {
|
|
|
String response = mockMvc.perform(post(path)
|
|
|
.header("Authorization", "Bearer " + token)
|