Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTOR] 리뷰 조회 리팩토링 #350

Merged
merged 14 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import com.somemore.domains.review.dto.response.ReviewDetailResponseDto;
import com.somemore.domains.review.dto.response.ReviewDetailWithNicknameResponseDto;
import com.somemore.domains.review.usecase.ReviewQueryUseCase;
import com.somemore.global.auth.annotation.RoleId;
import com.somemore.global.common.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
Expand Down Expand Up @@ -41,7 +43,7 @@ public ApiResponse<ReviewDetailResponseDto> getById(@PathVariable Long id) {
);
}

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

return ApiResponse.ok(
200,
reviewQueryUseCase.getDetailsWithNicknameByCenterId(centerId, condition),
"특정 기관 리뷰 리스트 조회 성공"
);
}

@Secured("ROLE_CENTER")
@Operation(summary = "기관 리뷰 조회", description = "기관 자신의 리뷰 조회")
@GetMapping("/reviews/center/me")
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getMyCenterReviews(
@RoleId UUID centerId,
@PageableDefault(sort = "created_at", direction = DESC) Pageable pageable,
@RequestParam(required = false) VolunteerCategory category
) {
ReviewSearchCondition condition = ReviewSearchCondition.builder()
.category(category)
.pageable(pageable)
.build();

return ApiResponse.ok(
200,
reviewQueryUseCase.getDetailsWithNicknameByCenterId(centerId, condition),
"기관 리뷰 리스트 조회 성공"
);
}

@Operation(summary = "봉사자 리뷰 조회", description = "봉사자 ID를 사용하여 리뷰 조회")
@Operation(summary = "특정 봉사자 리뷰 조회", description = "봉사자 ID를 사용하여 리뷰 조회")
@GetMapping("/reviews/volunteer/{volunteerId}")
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getReviewsByVolunteerId(
@PathVariable UUID volunteerId,
Expand All @@ -75,7 +97,27 @@ public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getReviewsByVolunt
return ApiResponse.ok(
200,
reviewQueryUseCase.getDetailsWithNicknameByVolunteerId(volunteerId, condition),
"유저 리뷰 리스트 조회 성공"
"특정 봉사자 리뷰 리스트 조회 성공"
);
}

@Secured("ROLE_VOLUNTEER")
@Operation(summary = "봉사자 리뷰 조회", description = "봉사자 자신의 리뷰 조회")
@GetMapping("/reviews/volunteer/me")
public ApiResponse<Page<ReviewDetailWithNicknameResponseDto>> getMyVolunteerReviews(
@RoleId UUID volunteerId,
@PageableDefault(sort = "created_at", direction = DESC) Pageable pageable,
@RequestParam(required = false) VolunteerCategory category
) {
ReviewSearchCondition condition = ReviewSearchCondition.builder()
.category(category)
.pageable(pageable)
.build();
leebs0521 marked this conversation as resolved.
Show resolved Hide resolved

return ApiResponse.ok(
200,
reviewQueryUseCase.getDetailsWithNicknameByVolunteerId(volunteerId, condition),
"봉사자 리뷰 리스트 조회 성공"
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
public record ReviewDetailResponseDto(
@Schema(description = "리뷰 ID", example = "123")
Long id,
@Schema(description = "봉사 지원 ID", example = "1")
Long volunteerApplyId,
@Schema(description = "모집글 ID", example = "1")
Long recruitBoardId,
@Schema(description = "봉사자(작성자) ID", example = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d")
UUID volunteerId,
@Schema(description = "리뷰 제목", example = "제 인생 최고의 봉사활동")
Expand All @@ -27,9 +31,11 @@ public record ReviewDetailResponseDto(
LocalDateTime updatedAt
) {

public static ReviewDetailResponseDto from(Review review) {
public static ReviewDetailResponseDto of(Review review, Long recruitBoardId) {
return ReviewDetailResponseDto.builder()
.id(review.getId())
.volunteerApplyId(review.getVolunteerApplyId())
.recruitBoardId(recruitBoardId)
.volunteerId(review.getVolunteerId())
.title(review.getTitle())
.content(review.getContent())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.somemore.domains.review.domain.Review;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;

import java.time.LocalDateTime;
import java.util.UUID;
import lombok.Builder;

@Builder
@JsonNaming(SnakeCaseStrategy.class)
Expand All @@ -26,18 +25,18 @@ public record ReviewDetailWithNicknameResponseDto(
@Schema(description = "작성 일자", example = "2024-12-01T09:00:00", type = "string")
LocalDateTime createdAt,
@Schema(description = "수정 일자", example = "2024-12-01T09:00:00", type = "string")
LocalDateTime updateAt
LocalDateTime updatedAt
) {

public static ReviewDetailWithNicknameResponseDto from(Review review, String volunteerNickname) {
public static ReviewDetailWithNicknameResponseDto of(Review review, String volunteerNickname) {
return ReviewDetailWithNicknameResponseDto.builder()
.id(review.getId())
.volunteerId(review.getVolunteerId())
.volunteerNickname(volunteerNickname)
.title(review.getTitle())
.content(review.getContent())
.createdAt(review.getCreatedAt())
.updateAt(review.getUpdatedAt())
.updatedAt(review.getUpdatedAt())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
package com.somemore.domains.review.service;

import com.somemore.domains.center.usecase.query.CenterQueryUseCase;
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_REVIEW;

import com.somemore.domains.review.domain.Review;
import com.somemore.domains.review.dto.condition.ReviewSearchCondition;
import com.somemore.domains.review.dto.response.ReviewDetailResponseDto;
import com.somemore.domains.review.dto.response.ReviewDetailWithNicknameResponseDto;
import com.somemore.domains.review.repository.ReviewRepository;
import com.somemore.domains.review.usecase.ReviewQueryUseCase;
import com.somemore.domains.volunteer.domain.Volunteer;
import com.somemore.domains.volunteer.usecase.VolunteerQueryUseCase;
import com.somemore.domains.volunteerapply.usecase.VolunteerApplyQueryUseCase;
import com.somemore.global.exception.NoSuchElementException;
import com.somemore.volunteer.repository.record.VolunteerNicknameAndId;
import com.somemore.volunteer.usecase.NEWVolunteerQueryUseCase;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_REVIEW;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class ReviewQueryService implements ReviewQueryUseCase {

private final ReviewRepository reviewRepository;
private final VolunteerQueryUseCase volunteerQueryUseCase;
private final CenterQueryUseCase centerQueryUseCase;
private final NEWVolunteerQueryUseCase volunteerQueryUseCase;
private final VolunteerApplyQueryUseCase volunteerApplyQueryUseCase;

@Override
public boolean existsByVolunteerApplyId(Long volunteerApplyId) {
Expand All @@ -45,7 +44,9 @@ public Review getById(Long id) {
@Override
public ReviewDetailResponseDto getDetailById(Long id) {
Review review = getById(id);
return ReviewDetailResponseDto.from(review);
Long recruitBoardId = volunteerApplyQueryUseCase.getRecruitBoardIdById(
review.getVolunteerApplyId());
return ReviewDetailResponseDto.of(review, recruitBoardId);
}

@Override
Expand All @@ -54,10 +55,11 @@ public Page<ReviewDetailWithNicknameResponseDto> getDetailsWithNicknameByVolunte
ReviewSearchCondition condition
) {
String nickname = volunteerQueryUseCase.getNicknameById(volunteerId);
Page<Review> reviews = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId, condition);
Page<Review> reviews = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId,
condition);

return reviews.map(
review -> ReviewDetailWithNicknameResponseDto.from(review, nickname)
review -> ReviewDetailWithNicknameResponseDto.of(review, nickname)
);
}

Expand All @@ -66,28 +68,20 @@ public Page<ReviewDetailWithNicknameResponseDto> getDetailsWithNicknameByCenterI
UUID centerId,
ReviewSearchCondition condition
) {
centerQueryUseCase.validateCenterExists(centerId);

Page<Review> reviews = reviewRepository.findAllByCenterIdAndSearch(centerId, condition);
List<UUID> volunteerIds = reviews.get().map(Review::getVolunteerId).toList();
Map<UUID, String> volunteerNicknames = getVolunteerNicknames(volunteerIds);
Map<UUID, String> volunteerNicknames = mapVolunteerIdsToNicknames(volunteerIds);

return reviews.map(
review -> {
String nickname = volunteerNicknames.getOrDefault(review.getVolunteerId(),
"삭제된 아이디");
return ReviewDetailWithNicknameResponseDto.from(review, nickname);
});
return reviews.map(review ->
ReviewDetailWithNicknameResponseDto.of(review,
volunteerNicknames.get(review.getVolunteerId()))
);
}

private Map<UUID, String> getVolunteerNicknames(List<UUID> volunteerIds) {
List<Volunteer> volunteers = volunteerQueryUseCase.getAllByIds(volunteerIds);

Map<UUID, String> volunteerNicknames = new HashMap<>();
for (Volunteer volunteer : volunteers) {
volunteerNicknames.put(volunteer.getId(), volunteer.getNickname());
}

return volunteerNicknames;
private Map<UUID, String> mapVolunteerIdsToNicknames(List<UUID> volunteerIds) {
return volunteerQueryUseCase.getVolunteerNicknameAndIdsByIds(volunteerIds)
.stream()
.collect(Collectors.toMap(VolunteerNicknameAndId::id,
VolunteerNicknameAndId::nickname));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

import com.somemore.domains.volunteerapply.domain.VolunteerApply;
import com.somemore.domains.volunteerapply.dto.condition.VolunteerApplySearchCondition;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface VolunteerApplyRepository {

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

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

Optional<Long> findRecruitBoardIdById(Long volunteerApplyId);

boolean existsByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId);

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

List<VolunteerApply> findAllByRecruitId(Long recruitId);

Page<VolunteerApply> findAllByRecruitId(Long recruitId, VolunteerApplySearchCondition condition);
Page<VolunteerApply> findAllByRecruitId(Long recruitId,
VolunteerApplySearchCondition condition);

Page<VolunteerApply> findAllByVolunteerId(UUID volunteerId, VolunteerApplySearchCondition condition);
Page<VolunteerApply> findAllByVolunteerId(UUID volunteerId,
VolunteerApplySearchCondition condition);

List<VolunteerApply> findAllByIds(List<Long> ids);

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@
import com.somemore.domains.volunteerapply.domain.QVolunteerApply;
import com.somemore.domains.volunteerapply.domain.VolunteerApply;
import com.somemore.domains.volunteerapply.dto.condition.VolunteerApplySearchCondition;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@RequiredArgsConstructor
@Repository
public class VolunteerApplyRepositoryImpl implements VolunteerApplyRepository {
Expand All @@ -39,7 +38,7 @@ public List<VolunteerApply> saveAll(List<VolunteerApply> volunteerApplies) {

@Override
public Optional<VolunteerApply> findById(Long id) {
return findOne(volunteerApply.id.eq(id));
return findOne(idEq(id));
}

@Override
Expand Down Expand Up @@ -91,7 +90,7 @@ public List<VolunteerApply> findAllByRecruitId(Long recruitId) {

@Override
public Page<VolunteerApply> findAllByRecruitId(Long recruitId,
VolunteerApplySearchCondition condition) {
VolunteerApplySearchCondition condition) {

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

@Override
public Page<VolunteerApply> findAllByVolunteerId(UUID volunteerId,
VolunteerApplySearchCondition condition) {
VolunteerApplySearchCondition condition) {

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

@Override
public Optional<VolunteerApply> findByRecruitIdAndVolunteerId(Long recruitId,
UUID volunteerId) {
UUID volunteerId) {
BooleanExpression exp = recruitIdEq(recruitId)
.and(volunteerApply.volunteerId.eq(volunteerId));
return findOne(exp);
}

@Override
public Optional<Long> findRecruitBoardIdById(Long id) {
return Optional.ofNullable(
queryFactory
.select(volunteerApply.recruitBoardId)
.from(volunteerApply)
.where(
idEq(id),
isNotDeleted()
)
.fetchOne()
);
}

@Override
public boolean existsByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId) {
return queryFactory
Expand Down Expand Up @@ -191,6 +204,10 @@ private Optional<VolunteerApply> findOne(BooleanExpression condition) {
);
}

private static BooleanExpression idEq(Long id) {
return volunteerApply.id.eq(id);
}

private static BooleanExpression recruitIdEq(Long recruitId) {
return volunteerApply.recruitBoardId.eq(recruitId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public VolunteerApply getByRecruitIdAndVolunteerId(Long recruitId, UUID voluntee
() -> new NoSuchElementException(NOT_EXISTS_VOLUNTEER_APPLY));
}

@Override
public Long getRecruitBoardIdById(Long id) {
return volunteerApplyRepository.findRecruitBoardIdById(id).orElseThrow(
() -> new NoSuchElementException(NOT_EXISTS_VOLUNTEER_APPLY)
);
}

@Override
public VolunteerApplySummaryResponseDto getSummaryByRecruitId(Long recruitId) {

Expand Down
Loading