Skip to content

Commit 7ae642e

Browse files
authored
dev -> prd
fix: 백오피스 기능 오류 해결
2 parents 7f343b6 + c25d864 commit 7ae642e

5 files changed

Lines changed: 75 additions & 7 deletions

File tree

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ project(":layer-admin") {
202202

203203
dependencies {
204204
implementation project(path: ':layer-event')
205+
implementation project(path: ':layer-domain')
205206

206207
compileOnly 'org.springframework.boot:spring-boot-starter-data-jpa'
207208
compileOnly 'org.springframework.boot:spring-boot-starter-web'

layer-admin/src/main/java/org/layer/admin/retrospect/service/AdminRetrospectService.java

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
import org.layer.admin.retrospect.repository.dto.RetrospectAnswerCompletionDto;
3838
import org.layer.admin.retrospect.repository.dto.SpaceRetrospectCountDto;
3939
import org.layer.admin.space.repository.AdminSpaceRepository;
40+
import org.layer.domain.retrospect.entity.Retrospect;
41+
import org.layer.domain.retrospect.entity.RetrospectStatus;
42+
import org.layer.domain.retrospect.repository.RetrospectRepository;
43+
import org.layer.domain.space.entity.MemberSpaceRelation;
44+
import org.layer.domain.space.entity.Team;
45+
import org.layer.domain.space.repository.MemberSpaceRelationRepository;
4046
import org.layer.event.retrospect.ClickRetrospectEvent;
4147
import org.layer.event.retrospect.CreateRetrospectEvent;
4248
import org.layer.event.retrospect.AnswerRetrospectEndEvent;
@@ -58,6 +64,8 @@ public class AdminRetrospectService {
5864
private final AdminRetrospectClickRepository adminRetrospectClickRepository;
5965
private final AdminMemberRepository adminMemberRepository;
6066
private final AdminSpaceRepository adminSpaceRepository;
67+
private final RetrospectRepository retrospectRepository;
68+
private final MemberSpaceRelationRepository memberSpaceRelationRepository;
6169

6270
public MeaningfulRetrospectMemberResponse getAllMeaningfulRetrospect(
6371
LocalDateTime startTime, LocalDateTime endTime, int retrospectLength, int retrospectCount) {
@@ -203,13 +211,60 @@ public RetrospectCompletionRateResponse getRetrospectCompletionRate(LocalDateTim
203211
List<RetrospectAnswerCompletionDto> answerHistories = adminRetrospectAnswerRepository.findRetrospectAnswerCompletionStatsBetween(
204212
startTime, endTime);
205213

206-
// 회고별 완수율 계산 (단위: %)
214+
if (answerHistories.isEmpty()) {
215+
return new RetrospectCompletionRateResponse(0.0);
216+
}
217+
218+
// 필요한 회고/스페이스/팀 정보를 미리 한 번에 로딩해서 N+1 방지
219+
List<Long> retrospectIds = answerHistories.stream()
220+
.map(RetrospectAnswerCompletionDto::retrospectId)
221+
.distinct()
222+
.toList();
223+
224+
List<Retrospect> retrospects = retrospectRepository.findAllById(retrospectIds);
225+
Map<Long, Retrospect> retrospectMap = retrospects.stream()
226+
.collect(Collectors.toMap(Retrospect::getId, r -> r));
227+
228+
List<Long> spaceIds = retrospects.stream()
229+
.map(Retrospect::getSpaceId)
230+
.distinct()
231+
.toList();
232+
233+
List<MemberSpaceRelation> allRelations = memberSpaceRelationRepository.findAllBySpaceIdIn(spaceIds);
234+
Map<Long, Team> teamBySpaceId = allRelations.stream()
235+
.collect(Collectors.groupingBy(
236+
relation -> relation.getSpace().getId(),
237+
Collectors.collectingAndThen(Collectors.toList(), Team::new)
238+
));
239+
240+
// 회고별 분모를 도메인 로직(Team, RetrospectStatus, deadline) 기반으로 계산
207241
List<Double> completionRates = answerHistories.stream()
208-
.filter(dto -> dto.targetAnswerCount() > 0) // division by zero 방지
209-
.map(dto -> (double) dto.actualAnswerCount() / dto.targetAnswerCount() * 100.0)
242+
.map(dto -> {
243+
Retrospect retrospect = retrospectMap.get(dto.retrospectId());
244+
if (retrospect == null) {
245+
return null;
246+
}
247+
248+
Team team = teamBySpaceId.get(retrospect.getSpaceId());
249+
if (team == null) {
250+
return null;
251+
}
252+
253+
long totalCount = team.getTeamMemberCount();
254+
if (retrospect.getRetrospectStatus().equals(RetrospectStatus.DONE)) {
255+
// 회고가 종료된 경우, deadline 시점의 팀원 수를 분모로 사용
256+
totalCount = team.getTeamMemberCountBefore(retrospect.getDeadline());
257+
}
258+
259+
if (totalCount == 0) {
260+
return null; // division by zero 방지
261+
}
262+
263+
return (double) dto.actualAnswerCount() / totalCount * 100.0;
264+
})
265+
.filter(Objects::nonNull)
210266
.toList();
211267

212-
// 평균 완수율 계산
213268
double averageCompletionRate = completionRates.isEmpty()
214269
? 0.0
215270
: completionRates.stream()

layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,16 @@ public RetrospectListGetResponse getRetrospects(Long spaceId, Long memberId) {
135135

136136
List<RetrospectGetResponse> retrospectDtos = retrospects.stream()
137137
.map(r -> {
138-
long writeCount = team.getTeamMemberCount();
138+
long totalCount = team.getTeamMemberCount();
139139
if (r.getRetrospectStatus().equals(RetrospectStatus.DONE)) {
140-
writeCount = answers.getWriteCount(r.getId());
140+
// 회고가 종료된 경우, 해당 회고의 deadline 시점의 팀원 수를 totalCount로 설정한다.
141+
// RetrospectStatus 가 DONE 으로 변경되면, deadline이 null 값이 될 수 없기 때문이다.
142+
totalCount = team.getTeamMemberCountBefore(r.getDeadline());
141143
}
142144

143145
return RetrospectGetResponse.of(r.getSpaceId(), r.getId(), r.getTitle(), r.getIntroduction(),
144146
answers.getWriteStatus(memberId, r.getId()), r.getRetrospectStatus(), r.getAnalysisStatus(),
145-
answers.getWriteCount(r.getId()), writeCount, r.getCreatedAt(), r.getDeadline());
147+
answers.getWriteCount(r.getId()), totalCount, r.getCreatedAt(), r.getDeadline());
146148
})
147149
.toList();
148150

layer-domain/src/main/java/org/layer/domain/space/entity/Team.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.layer.global.exception.MemberSpaceRelationExceptionType.*;
44

5+
import java.time.LocalDateTime;
56
import java.util.List;
67

78
import org.layer.domain.space.exception.MemberSpaceRelationException;
@@ -30,4 +31,10 @@ public List<Long> getMemberIds(){
3031
.map(MemberSpaceRelation::getMemberId)
3132
.toList();
3233
}
34+
35+
public long getTeamMemberCountBefore(LocalDateTime end) {
36+
return memberSpaceRelations.stream()
37+
.filter(memberSpaceRelation -> memberSpaceRelation.getCreatedAt().isBefore(end))
38+
.count();
39+
}
3340
}

layer-domain/src/main/java/org/layer/domain/space/repository/MemberSpaceRelationRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ public interface MemberSpaceRelationRepository extends JpaRepository<MemberSpace
1919

2020
List<MemberSpaceRelation> findAllBySpaceId(Long spaceId);
2121

22+
@Query("SELECT m FROM MemberSpaceRelation m WHERE m.space.id IN :spaceIds")
23+
List<MemberSpaceRelation> findAllBySpaceIdIn(@Param("spaceIds") List<Long> spaceIds);
24+
2225
@Query("SELECT new org.layer.domain.retrospect.dto.SpaceMemberCount(m.space.id, COUNT(m)) " +
2326
"FROM MemberSpaceRelation m " +
2427
"WHERE m.space.id IN :spaceIds " +

0 commit comments

Comments
 (0)