Skip to content

Commit beaa7ad

Browse files
authored
refactor: 리뷰 조회 리팩토링 (#350)
* refactor(review): 리뷰 상세 조회시, 모집글 아이디 응답 필드 추가 * test(review): 리뷰 상세 조회시, 모집글 아이디 응답 필드 추가 테스트 * refactor(review): 기존 봉사자 -> 새로운 봉사자 조회 리팩토링 * test(review): 기존 봉사자 -> 새로운 봉사자 조회 리팩토링 테스트 * refactor(review): 봉사자 테이블 변경에 따른 리뷰 조회 리팩토링 * test(review): 봉사자 테이블 변경에 따른 리뷰 조회 리팩토링 테스트 * refactor: sonarqube 이슈 해결 * refactor: sonarqube 이슈 해결 * refactor(review): 기존 Center -> NewCenter 변경 * test(review): 기존 Center -> NewCenter 변경 테스트 * feat(review): 기관 혹은 봉사자 자신의 리뷰 리스트 조회 API 기능 추가 * chore(review): 불필요한 import 제거 * fix(review): 오타 해결 updateAt -> updatedAt * refactor(review): 가독성 있게 변경
1 parent 7d07231 commit beaa7ad

File tree

17 files changed

+325
-117
lines changed

17 files changed

+325
-117
lines changed

src/main/java/com/somemore/domains/review/controller/ReviewQueryApiController.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
import com.somemore.domains.review.dto.response.ReviewDetailResponseDto;
66
import com.somemore.domains.review.dto.response.ReviewDetailWithNicknameResponseDto;
77
import com.somemore.domains.review.usecase.ReviewQueryUseCase;
8+
import com.somemore.global.auth.annotation.RoleId;
89
import com.somemore.global.common.response.ApiResponse;
910
import io.swagger.v3.oas.annotations.Operation;
1011
import io.swagger.v3.oas.annotations.tags.Tag;
1112
import lombok.RequiredArgsConstructor;
1213
import org.springframework.data.domain.Page;
1314
import org.springframework.data.domain.Pageable;
1415
import org.springframework.data.web.PageableDefault;
16+
import org.springframework.security.access.annotation.Secured;
1517
import org.springframework.web.bind.annotation.GetMapping;
1618
import org.springframework.web.bind.annotation.PathVariable;
1719
import org.springframework.web.bind.annotation.RequestMapping;
@@ -41,7 +43,7 @@ public ApiResponse<ReviewDetailResponseDto> getById(@PathVariable Long id) {
4143
);
4244
}
4345

44-
@Operation(summary = "기관별 리뷰 조회", description = "기관 ID를 사용하여 리뷰 조회")
46+
@Operation(summary = "특정 기관 리뷰 조회", description = "기관 ID를 사용하여 리뷰 조회")
4547
@GetMapping("/reviews/center/{centerId}")
4648
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getReviewsByCenterId(
4749
@PathVariable UUID centerId,
@@ -53,14 +55,34 @@ public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getReviewsByCenter
5355
.pageable(pageable)
5456
.build();
5557

58+
return ApiResponse.ok(
59+
200,
60+
reviewQueryUseCase.getDetailsWithNicknameByCenterId(centerId, condition),
61+
"특정 기관 리뷰 리스트 조회 성공"
62+
);
63+
}
64+
65+
@Secured("ROLE_CENTER")
66+
@Operation(summary = "기관 리뷰 조회", description = "기관 자신의 리뷰 조회")
67+
@GetMapping("/reviews/center/me")
68+
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getMyCenterReviews(
69+
@RoleId UUID centerId,
70+
@PageableDefault(sort = "created_at", direction = DESC) Pageable pageable,
71+
@RequestParam(required = false) VolunteerCategory category
72+
) {
73+
ReviewSearchCondition condition = ReviewSearchCondition.builder()
74+
.category(category)
75+
.pageable(pageable)
76+
.build();
77+
5678
return ApiResponse.ok(
5779
200,
5880
reviewQueryUseCase.getDetailsWithNicknameByCenterId(centerId, condition),
5981
"기관 리뷰 리스트 조회 성공"
6082
);
6183
}
6284

63-
@Operation(summary = "봉사자 리뷰 조회", description = "봉사자 ID를 사용하여 리뷰 조회")
85+
@Operation(summary = "특정 봉사자 리뷰 조회", description = "봉사자 ID를 사용하여 리뷰 조회")
6486
@GetMapping("/reviews/volunteer/{volunteerId}")
6587
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getReviewsByVolunteerId(
6688
@PathVariable UUID volunteerId,
@@ -75,7 +97,27 @@ public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getReviewsByVolunt
7597
return ApiResponse.ok(
7698
200,
7799
reviewQueryUseCase.getDetailsWithNicknameByVolunteerId(volunteerId, condition),
78-
"유저 리뷰 리스트 조회 성공"
100+
"특정 봉사자 리뷰 리스트 조회 성공"
101+
);
102+
}
103+
104+
@Secured("ROLE_VOLUNTEER")
105+
@Operation(summary = "봉사자 리뷰 조회", description = "봉사자 자신의 리뷰 조회")
106+
@GetMapping("/reviews/volunteer/me")
107+
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getMyVolunteerReviews(
108+
@RoleId UUID volunteerId,
109+
@PageableDefault(sort = "created_at", direction = DESC) Pageable pageable,
110+
@RequestParam(required = false) VolunteerCategory category
111+
) {
112+
ReviewSearchCondition condition = ReviewSearchCondition.builder()
113+
.category(category)
114+
.pageable(pageable)
115+
.build();
116+
117+
return ApiResponse.ok(
118+
200,
119+
reviewQueryUseCase.getDetailsWithNicknameByVolunteerId(volunteerId, condition),
120+
"봉사자 리뷰 리스트 조회 성공"
79121
);
80122
}
81123

src/main/java/com/somemore/domains/review/dto/response/ReviewDetailResponseDto.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
public record ReviewDetailResponseDto(
1616
@Schema(description = "리뷰 ID", example = "123")
1717
Long id,
18+
@Schema(description = "봉사 지원 ID", example = "1")
19+
Long volunteerApplyId,
20+
@Schema(description = "모집글 ID", example = "1")
21+
Long recruitBoardId,
1822
@Schema(description = "봉사자(작성자) ID", example = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d")
1923
UUID volunteerId,
2024
@Schema(description = "리뷰 제목", example = "제 인생 최고의 봉사활동")
@@ -27,9 +31,11 @@ public record ReviewDetailResponseDto(
2731
LocalDateTime updatedAt
2832
) {
2933

30-
public static ReviewDetailResponseDto from(Review review) {
34+
public static ReviewDetailResponseDto of(Review review, Long recruitBoardId) {
3135
return ReviewDetailResponseDto.builder()
3236
.id(review.getId())
37+
.volunteerApplyId(review.getVolunteerApplyId())
38+
.recruitBoardId(recruitBoardId)
3339
.volunteerId(review.getVolunteerId())
3440
.title(review.getTitle())
3541
.content(review.getContent())

src/main/java/com/somemore/domains/review/dto/response/ReviewDetailWithNicknameResponseDto.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
import com.fasterxml.jackson.databind.annotation.JsonNaming;
55
import com.somemore.domains.review.domain.Review;
66
import io.swagger.v3.oas.annotations.media.Schema;
7-
import lombok.Builder;
8-
97
import java.time.LocalDateTime;
108
import java.util.UUID;
9+
import lombok.Builder;
1110

1211
@Builder
1312
@JsonNaming(SnakeCaseStrategy.class)
@@ -26,18 +25,18 @@ public record ReviewDetailWithNicknameResponseDto(
2625
@Schema(description = "작성 일자", example = "2024-12-01T09:00:00", type = "string")
2726
LocalDateTime createdAt,
2827
@Schema(description = "수정 일자", example = "2024-12-01T09:00:00", type = "string")
29-
LocalDateTime updateAt
28+
LocalDateTime updatedAt
3029
) {
3130

32-
public static ReviewDetailWithNicknameResponseDto from(Review review, String volunteerNickname) {
31+
public static ReviewDetailWithNicknameResponseDto of(Review review, String volunteerNickname) {
3332
return ReviewDetailWithNicknameResponseDto.builder()
3433
.id(review.getId())
3534
.volunteerId(review.getVolunteerId())
3635
.volunteerNickname(volunteerNickname)
3736
.title(review.getTitle())
3837
.content(review.getContent())
3938
.createdAt(review.getCreatedAt())
40-
.updateAt(review.getUpdatedAt())
39+
.updatedAt(review.getUpdatedAt())
4140
.build();
4241
}
4342

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
11
package com.somemore.domains.review.service;
22

3-
import com.somemore.domains.center.usecase.query.CenterQueryUseCase;
3+
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_REVIEW;
4+
45
import com.somemore.domains.review.domain.Review;
56
import com.somemore.domains.review.dto.condition.ReviewSearchCondition;
67
import com.somemore.domains.review.dto.response.ReviewDetailResponseDto;
78
import com.somemore.domains.review.dto.response.ReviewDetailWithNicknameResponseDto;
89
import com.somemore.domains.review.repository.ReviewRepository;
910
import com.somemore.domains.review.usecase.ReviewQueryUseCase;
10-
import com.somemore.domains.volunteer.domain.Volunteer;
11-
import com.somemore.domains.volunteer.usecase.VolunteerQueryUseCase;
11+
import com.somemore.domains.volunteerapply.usecase.VolunteerApplyQueryUseCase;
1212
import com.somemore.global.exception.NoSuchElementException;
13+
import com.somemore.volunteer.repository.record.VolunteerNicknameAndId;
14+
import com.somemore.volunteer.usecase.NEWVolunteerQueryUseCase;
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.UUID;
18+
import java.util.stream.Collectors;
1319
import lombok.RequiredArgsConstructor;
1420
import org.springframework.data.domain.Page;
1521
import org.springframework.stereotype.Service;
1622
import org.springframework.transaction.annotation.Transactional;
1723

18-
import java.util.HashMap;
19-
import java.util.List;
20-
import java.util.Map;
21-
import java.util.UUID;
22-
23-
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_REVIEW;
24-
2524
@RequiredArgsConstructor
2625
@Transactional(readOnly = true)
2726
@Service
2827
public class ReviewQueryService implements ReviewQueryUseCase {
2928

3029
private final ReviewRepository reviewRepository;
31-
private final VolunteerQueryUseCase volunteerQueryUseCase;
32-
private final CenterQueryUseCase centerQueryUseCase;
30+
private final NEWVolunteerQueryUseCase volunteerQueryUseCase;
31+
private final VolunteerApplyQueryUseCase volunteerApplyQueryUseCase;
3332

3433
@Override
3534
public boolean existsByVolunteerApplyId(Long volunteerApplyId) {
@@ -45,7 +44,9 @@ public Review getById(Long id) {
4544
@Override
4645
public ReviewDetailResponseDto getDetailById(Long id) {
4746
Review review = getById(id);
48-
return ReviewDetailResponseDto.from(review);
47+
Long recruitBoardId = volunteerApplyQueryUseCase.getRecruitBoardIdById(
48+
review.getVolunteerApplyId());
49+
return ReviewDetailResponseDto.of(review, recruitBoardId);
4950
}
5051

5152
@Override
@@ -54,10 +55,11 @@ public Page<ReviewDetailWithNicknameResponseDto> getDetailsWithNicknameByVolunte
5455
ReviewSearchCondition condition
5556
) {
5657
String nickname = volunteerQueryUseCase.getNicknameById(volunteerId);
57-
Page<Review> reviews = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId, condition);
58+
Page<Review> reviews = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId,
59+
condition);
5860

5961
return reviews.map(
60-
review -> ReviewDetailWithNicknameResponseDto.from(review, nickname)
62+
review -> ReviewDetailWithNicknameResponseDto.of(review, nickname)
6163
);
6264
}
6365

@@ -66,28 +68,20 @@ public Page<ReviewDetailWithNicknameResponseDto> getDetailsWithNicknameByCenterI
6668
UUID centerId,
6769
ReviewSearchCondition condition
6870
) {
69-
centerQueryUseCase.validateCenterExists(centerId);
70-
7171
Page<Review> reviews = reviewRepository.findAllByCenterIdAndSearch(centerId, condition);
7272
List<UUID> volunteerIds = reviews.get().map(Review::getVolunteerId).toList();
73-
Map<UUID, String> volunteerNicknames = getVolunteerNicknames(volunteerIds);
73+
Map<UUID, String> volunteerNicknames = mapVolunteerIdsToNicknames(volunteerIds);
7474

75-
return reviews.map(
76-
review -> {
77-
String nickname = volunteerNicknames.getOrDefault(review.getVolunteerId(),
78-
"삭제된 아이디");
79-
return ReviewDetailWithNicknameResponseDto.from(review, nickname);
80-
});
75+
return reviews.map(review ->
76+
ReviewDetailWithNicknameResponseDto.of(review,
77+
volunteerNicknames.get(review.getVolunteerId()))
78+
);
8179
}
8280

83-
private Map<UUID, String> getVolunteerNicknames(List<UUID> volunteerIds) {
84-
List<Volunteer> volunteers = volunteerQueryUseCase.getAllByIds(volunteerIds);
85-
86-
Map<UUID, String> volunteerNicknames = new HashMap<>();
87-
for (Volunteer volunteer : volunteers) {
88-
volunteerNicknames.put(volunteer.getId(), volunteer.getNickname());
89-
}
90-
91-
return volunteerNicknames;
81+
private Map<UUID, String> mapVolunteerIdsToNicknames(List<UUID> volunteerIds) {
82+
return volunteerQueryUseCase.getVolunteerNicknameAndIdsByIds(volunteerIds)
83+
.stream()
84+
.collect(Collectors.toMap(VolunteerNicknameAndId::id,
85+
VolunteerNicknameAndId::nickname));
9286
}
9387
}

src/main/java/com/somemore/domains/volunteerapply/repository/VolunteerApplyRepository.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
import com.somemore.domains.volunteerapply.domain.VolunteerApply;
44
import com.somemore.domains.volunteerapply.dto.condition.VolunteerApplySearchCondition;
5-
import org.springframework.data.domain.Page;
6-
import org.springframework.data.domain.Pageable;
7-
85
import java.util.List;
96
import java.util.Optional;
107
import java.util.UUID;
8+
import org.springframework.data.domain.Page;
9+
import org.springframework.data.domain.Pageable;
1110

1211
public interface VolunteerApplyRepository {
1312

@@ -19,6 +18,8 @@ public interface VolunteerApplyRepository {
1918

2019
Optional<VolunteerApply> findByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId);
2120

21+
Optional<Long> findRecruitBoardIdById(Long volunteerApplyId);
22+
2223
boolean existsByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId);
2324

2425
List<UUID> findVolunteerIdsByRecruitIds(List<Long> recruitIds);
@@ -27,9 +28,12 @@ public interface VolunteerApplyRepository {
2728

2829
List<VolunteerApply> findAllByRecruitId(Long recruitId);
2930

30-
Page<VolunteerApply> findAllByRecruitId(Long recruitId, VolunteerApplySearchCondition condition);
31+
Page<VolunteerApply> findAllByRecruitId(Long recruitId,
32+
VolunteerApplySearchCondition condition);
3133

32-
Page<VolunteerApply> findAllByVolunteerId(UUID volunteerId, VolunteerApplySearchCondition condition);
34+
Page<VolunteerApply> findAllByVolunteerId(UUID volunteerId,
35+
VolunteerApplySearchCondition condition);
3336

3437
List<VolunteerApply> findAllByIds(List<Long> ids);
38+
3539
}

src/main/java/com/somemore/domains/volunteerapply/repository/VolunteerApplyRepositoryImpl.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77
import com.somemore.domains.volunteerapply.domain.QVolunteerApply;
88
import com.somemore.domains.volunteerapply.domain.VolunteerApply;
99
import com.somemore.domains.volunteerapply.dto.condition.VolunteerApplySearchCondition;
10+
import java.util.List;
11+
import java.util.Optional;
12+
import java.util.UUID;
1013
import lombok.RequiredArgsConstructor;
1114
import org.springframework.data.domain.Page;
1215
import org.springframework.data.domain.PageImpl;
1316
import org.springframework.data.domain.Pageable;
1417
import org.springframework.data.domain.Sort;
1518
import org.springframework.stereotype.Repository;
1619

17-
import java.util.List;
18-
import java.util.Optional;
19-
import java.util.UUID;
20-
2120
@RequiredArgsConstructor
2221
@Repository
2322
public class VolunteerApplyRepositoryImpl implements VolunteerApplyRepository {
@@ -39,7 +38,7 @@ public List<VolunteerApply> saveAll(List<VolunteerApply> volunteerApplies) {
3938

4039
@Override
4140
public Optional<VolunteerApply> findById(Long id) {
42-
return findOne(volunteerApply.id.eq(id));
41+
return findOne(idEq(id));
4342
}
4443

4544
@Override
@@ -91,7 +90,7 @@ public List<VolunteerApply> findAllByRecruitId(Long recruitId) {
9190

9291
@Override
9392
public Page<VolunteerApply> findAllByRecruitId(Long recruitId,
94-
VolunteerApplySearchCondition condition) {
93+
VolunteerApplySearchCondition condition) {
9594

9695
BooleanExpression exp = recruitIdEq(recruitId)
9796
.and(attendedEq(condition.attended()))
@@ -117,7 +116,7 @@ public Page<VolunteerApply> findAllByRecruitId(Long recruitId,
117116

118117
@Override
119118
public Page<VolunteerApply> findAllByVolunteerId(UUID volunteerId,
120-
VolunteerApplySearchCondition condition) {
119+
VolunteerApplySearchCondition condition) {
121120

122121
BooleanExpression exp = volunteerIdEq(volunteerId)
123122
.and(attendedEq(condition.attended()))
@@ -154,12 +153,26 @@ public List<VolunteerApply> findAllByIds(List<Long> ids) {
154153

155154
@Override
156155
public Optional<VolunteerApply> findByRecruitIdAndVolunteerId(Long recruitId,
157-
UUID volunteerId) {
156+
UUID volunteerId) {
158157
BooleanExpression exp = recruitIdEq(recruitId)
159158
.and(volunteerApply.volunteerId.eq(volunteerId));
160159
return findOne(exp);
161160
}
162161

162+
@Override
163+
public Optional<Long> findRecruitBoardIdById(Long id) {
164+
return Optional.ofNullable(
165+
queryFactory
166+
.select(volunteerApply.recruitBoardId)
167+
.from(volunteerApply)
168+
.where(
169+
idEq(id),
170+
isNotDeleted()
171+
)
172+
.fetchOne()
173+
);
174+
}
175+
163176
@Override
164177
public boolean existsByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId) {
165178
return queryFactory
@@ -191,6 +204,10 @@ private Optional<VolunteerApply> findOne(BooleanExpression condition) {
191204
);
192205
}
193206

207+
private static BooleanExpression idEq(Long id) {
208+
return volunteerApply.id.eq(id);
209+
}
210+
194211
private static BooleanExpression recruitIdEq(Long recruitId) {
195212
return volunteerApply.recruitBoardId.eq(recruitId);
196213
}

src/main/java/com/somemore/domains/volunteerapply/service/VolunteerApplyQueryService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public VolunteerApply getByRecruitIdAndVolunteerId(Long recruitId, UUID voluntee
3737
() -> new NoSuchElementException(NOT_EXISTS_VOLUNTEER_APPLY));
3838
}
3939

40+
@Override
41+
public Long getRecruitBoardIdById(Long id) {
42+
return volunteerApplyRepository.findRecruitBoardIdById(id).orElseThrow(
43+
() -> new NoSuchElementException(NOT_EXISTS_VOLUNTEER_APPLY)
44+
);
45+
}
46+
4047
@Override
4148
public VolunteerApplySummaryResponseDto getSummaryByRecruitId(Long recruitId) {
4249

0 commit comments

Comments
 (0)