fix(project): preserve completed task history

This commit is contained in:
sechmachine
2026-08-15 01:18:19 +07:00
parent c3f92d4e31
commit 3d954dd512
2 changed files with 53 additions and 2 deletions
@@ -71,7 +71,9 @@ public class ProjectQueryService {
@Transactional(readOnly = true)
public List<ProjectMemberView> members(long actorUserId, long projectId) {
var project = visibleProject(actorUserId, projectId);
var leaderUserId = project.currentLeader().internUserId();
Long leaderUserId = project.status() == ProjectStatus.COMPLETED
? null
: project.currentLeader().internUserId();
return project.memberships().stream()
.map(membership -> new ProjectMemberView(
membership.id(),
@@ -79,7 +81,9 @@ public class ProjectQueryService {
displayName(membership.internUserId()),
membership.joinedAt(),
membership.leftAt(),
membership.isCurrent() && membership.internUserId() == leaderUserId))
membership.isCurrent()
&& leaderUserId != null
&& membership.internUserId() == leaderUserId))
.toList();
}
@@ -103,6 +107,16 @@ public class ProjectQueryService {
ProjectTaskContext taskContext(long actorUserId, ProjectEntity project) {
requireVisibleProject(actorUserId, project);
if (project.status() == ProjectStatus.COMPLETED) {
return new ProjectTaskContext(
project.id(),
project.mentorUserId(),
project.status().name(),
project.startDate(),
project.endDate(),
null,
List.of());
}
var activeMembers = project.memberships().stream()
.filter(membership -> membership.isCurrent() && isEligibleIntern(membership.internUserId()))
.map(membership -> new ProjectTaskMemberView(
@@ -1,6 +1,7 @@
package com.lab.labtimesheet.feature.project.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -178,6 +179,42 @@ class ProjectServiceIntegrationTest {
assertEquals(1, projectPages.dashboardSummary(mentorId).distinctActiveMemberCount());
}
@Test
void completedProjectQueriesReturnHistoricalMembersWithoutRequiringACurrentLeader() {
long mentorId = user("mentor-history@example.test", "MENTOR");
long leaderId = intern("leader-history@example.test", "I012");
long memberId = intern("member-history@example.test", "I013");
long projectId = createProject(mentorId, leaderId, "Completed history");
projectService.addMember(mentorId, projectId, memberId);
var activatedAt = dbTime(NOW.plusSeconds(30));
var completedAt = dbTime(NOW.plusSeconds(60));
jdbc.update("""
update project_leadership_terms
set ended_at = ?, ended_by_mentor_user_id = ?
where project_id = ? and ended_at is null
""", completedAt, mentorId, projectId);
jdbc.update("""
update project_memberships
set left_at = ?, removed_by_mentor_user_id = ?, updated_at = ?
where project_id = ? and left_at is null
""", completedAt, mentorId, completedAt, projectId);
jdbc.update("""
update projects
set status = 'COMPLETED', activated_at = ?, completed_at = ?, updated_at = ?
where id = ?
""", activatedAt, completedAt, completedAt, projectId);
entityManager.clear();
var taskContext = projectPages.taskContext(memberId, projectId);
assertEquals("COMPLETED", taskContext.status());
assertNull(taskContext.currentLeaderMembershipId());
assertEquals(List.of(), taskContext.activeMembers());
var members = projectPages.members(memberId, projectId);
assertEquals(2, members.size());
assertTrue(members.stream().allMatch(member -> member.leftAt() != null));
assertTrue(members.stream().noneMatch(member -> member.currentLeader()));
}
private long createProject(long mentorId, long leaderId, String name) {
return projectService.create(
mentorId,