diff --git a/src/main/java/com/somemore/global/exception/ExceptionMessage.java b/src/main/java/com/somemore/global/exception/ExceptionMessage.java index 27fca6ff3..613c87fc7 100644 --- a/src/main/java/com/somemore/global/exception/ExceptionMessage.java +++ b/src/main/java/com/somemore/global/exception/ExceptionMessage.java @@ -27,7 +27,8 @@ public enum ExceptionMessage { DUPLICATE_INTEREST_CENTER("이미 관심 표시한 기관입니다."), NOT_EXISTS_VOLUNTEER_APPLY("존재하지 않는 봉사 활동 지원입니다."), REVIEW_ALREADY_EXISTS("이미 작성한 리뷰가 존재합니다."), - REVIEW_RESTRICTED_TO_ATTENDED("리뷰는 참석한 봉사에 한해서만 작성할 수 있습니다.") + REVIEW_RESTRICTED_TO_ATTENDED("리뷰는 참석한 봉사에 한해서만 작성할 수 있습니다."), + NOT_EXISTS_REVIEW("존재하지 않는 리뷰입니다."), ; private final String message; diff --git a/src/main/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiController.java b/src/main/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiController.java index 4ddb6e58d..7d9fb7a7e 100644 --- a/src/main/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiController.java +++ b/src/main/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiController.java @@ -4,7 +4,7 @@ import com.somemore.global.common.response.ApiResponse; import com.somemore.recruitboard.domain.RecruitStatus; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; import com.somemore.recruitboard.dto.response.RecruitBoardDetailResponseDto; @@ -67,14 +67,14 @@ public ApiResponse> getAll( public ApiResponse> getAllBySearch( @PageableDefault(sort = "created_at", direction = DESC) Pageable pageable, @RequestParam(required = false) String keyword, - @RequestParam(required = false) VolunteerType type, + @RequestParam(required = false) VolunteerCategory category, @RequestParam(required = false) String region, @RequestParam(required = false) Boolean admitted, @RequestParam(required = false) RecruitStatus status ) { RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() .keyword(keyword) - .type(type) + .category(category) .region(region) .admitted(admitted) .status(status) @@ -118,14 +118,14 @@ public ApiResponse> getRecruitBoardsByCenterId( @PathVariable UUID centerId, @PageableDefault(sort = "created_at", direction = DESC) Pageable pageable, @RequestParam(required = false) String keyword, - @RequestParam(required = false) VolunteerType type, + @RequestParam(required = false) VolunteerCategory category, @RequestParam(required = false) String region, @RequestParam(required = false) Boolean admitted, @RequestParam(required = false) RecruitStatus status ) { RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() .keyword(keyword) - .type(type) + .category(category) .region(region) .admitted(admitted) .status(status) diff --git a/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java b/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java index 6d0c91f37..3eca63285 100644 --- a/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java +++ b/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java @@ -95,7 +95,7 @@ public void changeRecruitStatus(RecruitStatus newStatus, LocalDateTime currentDa private void updateRecruitmentInfo(RecruitBoardUpdateRequestDto dto) { recruitmentInfo.updateWith( dto.recruitmentCount(), - dto.volunteerType(), + dto.volunteerCategory(), dto.volunteerStartDateTime(), dto.volunteerEndDateTime(), dto.admitted() diff --git a/src/main/java/com/somemore/recruitboard/domain/RecruitmentInfo.java b/src/main/java/com/somemore/recruitboard/domain/RecruitmentInfo.java index 1b50bee28..1bed045d8 100644 --- a/src/main/java/com/somemore/recruitboard/domain/RecruitmentInfo.java +++ b/src/main/java/com/somemore/recruitboard/domain/RecruitmentInfo.java @@ -32,8 +32,8 @@ public class RecruitmentInfo { private LocalDateTime volunteerEndDateTime; @Enumerated(value = STRING) - @Column(name = "volunteer_type", nullable = false, length = 30) - private VolunteerType volunteerType; + @Column(name = "volunteer_category", nullable = false, length = 30) + private VolunteerCategory volunteerCategory; @Column(name = "admitted", nullable = false) private Boolean admitted; @@ -41,7 +41,7 @@ public class RecruitmentInfo { @Builder public RecruitmentInfo(String region, Integer recruitmentCount, LocalDateTime volunteerStartDateTime, LocalDateTime volunteerEndDateTime, - VolunteerType volunteerType, Boolean admitted) { + VolunteerCategory volunteerCategory, Boolean admitted) { validateVolunteerDateTime(volunteerStartDateTime, volunteerEndDateTime); @@ -49,7 +49,7 @@ public RecruitmentInfo(String region, Integer recruitmentCount, this.recruitmentCount = recruitmentCount; this.volunteerStartDateTime = volunteerStartDateTime.truncatedTo(MINUTES); this.volunteerEndDateTime = volunteerEndDateTime.truncatedTo(MINUTES); - this.volunteerType = volunteerType; + this.volunteerCategory = volunteerCategory; this.admitted = admitted; } @@ -62,14 +62,14 @@ public LocalTime calculateVolunteerTime() { return LocalTime.of((int) hours, (int) minutes); } - public void updateWith(Integer recruitmentCount, VolunteerType volunteerType, + public void updateWith(Integer recruitmentCount, VolunteerCategory volunteerCategory, LocalDateTime volunteerStartDateTime, LocalDateTime volunteerEndDateTime, Boolean admitted) { validateVolunteerDateTime(volunteerStartDateTime, volunteerEndDateTime); this.recruitmentCount = recruitmentCount; - this.volunteerType = volunteerType; + this.volunteerCategory = volunteerCategory; this.volunteerStartDateTime = volunteerStartDateTime.truncatedTo(MINUTES); this.volunteerEndDateTime = volunteerEndDateTime.truncatedTo(MINUTES); this.admitted = admitted; diff --git a/src/main/java/com/somemore/recruitboard/domain/VolunteerType.java b/src/main/java/com/somemore/recruitboard/domain/VolunteerCategory.java similarity index 95% rename from src/main/java/com/somemore/recruitboard/domain/VolunteerType.java rename to src/main/java/com/somemore/recruitboard/domain/VolunteerCategory.java index 65e54601e..9b7844261 100644 --- a/src/main/java/com/somemore/recruitboard/domain/VolunteerType.java +++ b/src/main/java/com/somemore/recruitboard/domain/VolunteerCategory.java @@ -5,7 +5,7 @@ @Getter @RequiredArgsConstructor -public enum VolunteerType { +public enum VolunteerCategory { LIVING_SUPPORT("생활편의지원"), HOUSING_ENVIRONMENT("주거환경"), diff --git a/src/main/java/com/somemore/recruitboard/dto/condition/RecruitBoardSearchCondition.java b/src/main/java/com/somemore/recruitboard/dto/condition/RecruitBoardSearchCondition.java index 5f3e8c775..6658901f6 100644 --- a/src/main/java/com/somemore/recruitboard/dto/condition/RecruitBoardSearchCondition.java +++ b/src/main/java/com/somemore/recruitboard/dto/condition/RecruitBoardSearchCondition.java @@ -1,14 +1,14 @@ package com.somemore.recruitboard.dto.condition; import com.somemore.recruitboard.domain.RecruitStatus; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import lombok.Builder; import org.springframework.data.domain.Pageable; @Builder public record RecruitBoardSearchCondition( String keyword, - VolunteerType type, + VolunteerCategory category, String region, Boolean admitted, RecruitStatus status, diff --git a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java index 8906c48a4..aeb2a38f6 100644 --- a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java @@ -5,7 +5,7 @@ import com.somemore.location.dto.request.LocationCreateRequestDto; import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitmentInfo; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -36,7 +36,7 @@ public record RecruitBoardCreateRequestDto( LocalDateTime volunteerEndDateTime, @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") @NotNull(message = "봉사 활동 유형은 필수 값입니다.") - VolunteerType volunteerType, + VolunteerCategory volunteerCategory, @Schema(description = "봉사 시간 인정 여부", example = "true") @NotNull(message = "시간 인정 여부는 필수 값입니다.") Boolean admitted, @@ -50,7 +50,7 @@ public RecruitBoard toEntity(UUID centerId, Long locationId, String imgUrl) { .recruitmentCount(recruitmentCount) .volunteerStartDateTime(volunteerStartDateTime) .volunteerEndDateTime(volunteerEndDateTime) - .volunteerType(volunteerType) + .volunteerCategory(volunteerCategory) .admitted(admitted) .build(); diff --git a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java index f1592b5a2..431056365 100644 --- a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -29,7 +29,7 @@ public record RecruitBoardUpdateRequestDto( LocalDateTime volunteerEndDateTime, @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") @NotNull(message = "봉사 활동 유형은 필수 값입니다.") - VolunteerType volunteerType, + VolunteerCategory volunteerCategory, @Schema(description = "봉사 시간 인정 여부", example = "true") @NotNull(message = "시간 인정 여부는 필수 값입니다.") Boolean admitted diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java index 9dbeadfea..50f89a751 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java @@ -7,7 +7,7 @@ import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.RecruitmentInfo; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; @@ -40,7 +40,7 @@ public record RecruitBoardDetailResponseDto( @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") LocalDateTime volunteerEndDateTime, @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerType volunteerType, + VolunteerCategory volunteerCategory, @Schema(description = "봉사 시간", example = "04:00:00") LocalTime volunteerTime, @Schema(description = "시간 인정 여부", example = "true") @@ -73,7 +73,7 @@ public static RecruitBoardDetailResponseDto from(RecruitBoardDetail recruitBoard .recruitmentCount(info.getRecruitmentCount()) .volunteerStartDateTime(info.getVolunteerStartDateTime()) .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerType(info.getVolunteerType()) + .volunteerCategory(info.getVolunteerCategory()) .volunteerTime(info.calculateVolunteerTime()) .admitted(info.getAdmitted()) .imgUrl(board.getImgUrl()) diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java index 8b57a1b24..323dd6d50 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java @@ -5,7 +5,7 @@ import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.RecruitmentInfo; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; import java.time.LocalTime; @@ -41,7 +41,7 @@ public record RecruitBoardResponseDto( @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") LocalDateTime volunteerEndDateTime, @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerType volunteerType, + VolunteerCategory volunteerCategory, @Schema(description = "봉사 시간", example = "04:00:00") LocalTime volunteerTime, @Schema(description = "시간 인정 여부", example = "true") @@ -65,7 +65,7 @@ public static RecruitBoardResponseDto from(RecruitBoard board) { .recruitmentCount(info.getRecruitmentCount()) .volunteerStartDateTime(info.getVolunteerStartDateTime()) .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerType(info.getVolunteerType()) + .volunteerCategory(info.getVolunteerCategory()) .volunteerTime(info.calculateVolunteerTime()) .admitted(info.getAdmitted()) .imgUrl(board.getImgUrl()) diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java index b4d90a000..da6013e34 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java @@ -6,7 +6,7 @@ import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.RecruitmentInfo; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.repository.mapper.RecruitBoardWithCenter; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; @@ -40,7 +40,7 @@ public record RecruitBoardWithCenterResponseDto( @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") LocalDateTime volunteerEndDateTime, @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerType volunteerType, + VolunteerCategory volunteerCategory, @Schema(description = "봉사 시간", example = "04:00:00") LocalTime volunteerTime, @Schema(description = "시간 인정 여부", example = "true") @@ -68,7 +68,7 @@ public static RecruitBoardWithCenterResponseDto from( .recruitmentCount(info.getRecruitmentCount()) .volunteerStartDateTime(info.getVolunteerStartDateTime()) .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerType(info.getVolunteerType()) + .volunteerCategory(info.getVolunteerCategory()) .volunteerTime(info.calculateVolunteerTime()) .admitted(info.getAdmitted()) .imgUrl(board.getImgUrl()) diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java index 0f60abc32..1c3d2e436 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java @@ -6,7 +6,7 @@ import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.RecruitmentInfo; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; @@ -41,7 +41,7 @@ public record RecruitBoardWithLocationResponseDto( @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") LocalDateTime volunteerEndDateTime, @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerType volunteerType, + VolunteerCategory volunteerCategory, @Schema(description = "봉사 시간", example = "04:00:00") LocalTime volunteerTime, @Schema(description = "시간 인정 여부", example = "true") @@ -69,7 +69,7 @@ public static RecruitBoardWithLocationResponseDto from( .recruitmentCount(info.getRecruitmentCount()) .volunteerStartDateTime(info.getVolunteerStartDateTime()) .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerType(info.getVolunteerType()) + .volunteerCategory(info.getVolunteerCategory()) .volunteerTime(info.calculateVolunteerTime()) .admitted(info.getAdmitted()) .imgUrl(board.getImgUrl()) diff --git a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java index 67d22e617..207942e50 100644 --- a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java +++ b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java @@ -18,7 +18,7 @@ import java.util.List; import com.somemore.recruitboard.domain.RecruitStatus; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; import com.somemore.recruitboard.repository.mapper.RecruitBoardWithCenter; import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; @@ -102,7 +102,7 @@ public Page findAllWithCenter(RecruitBoardSearchConditio Pageable pageable = condition.pageable(); BooleanExpression predicate = isNotDeleted() .and(keywordEq(condition.keyword())) - .and(volunteerTypeEq(condition.type())) + .and(volunteerCategoryEq(condition.category())) .and(regionEq(condition.region())) .and(admittedEq(condition.admitted())) .and(statusEq(condition.status())); @@ -167,7 +167,7 @@ public Page findAllByCenterId(UUID centerId, BooleanExpression predicate = isNotDeleted() .and(centerIdEq(centerId)) .and(keywordEq(condition.keyword())) - .and(volunteerTypeEq(condition.type())) + .and(volunteerCategoryEq(condition.category())) .and(regionEq(condition.region())) .and(admittedEq(condition.admitted())) .and(statusEq(condition.status())); @@ -211,8 +211,8 @@ private BooleanExpression keywordEq(String keyword) { keyword) : null; } - private BooleanExpression volunteerTypeEq(VolunteerType type) { - return type != null ? recruitBoard.recruitmentInfo.volunteerType.eq(type) + private BooleanExpression volunteerCategoryEq(VolunteerCategory category) { + return category != null ? recruitBoard.recruitmentInfo.volunteerCategory.eq(category) : null; } diff --git a/src/main/java/com/somemore/review/controller/ReviewQueryApiController.java b/src/main/java/com/somemore/review/controller/ReviewQueryApiController.java new file mode 100644 index 000000000..977219852 --- /dev/null +++ b/src/main/java/com/somemore/review/controller/ReviewQueryApiController.java @@ -0,0 +1,81 @@ +package com.somemore.review.controller; + +import static org.springframework.data.domain.Sort.Direction.DESC; + +import com.somemore.global.common.response.ApiResponse; +import com.somemore.recruitboard.domain.VolunteerCategory; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import com.somemore.review.dto.response.ReviewResponseDto; +import com.somemore.review.dto.response.ReviewWithNicknameResponseDto; +import com.somemore.review.usecase.ReviewQueryUseCase; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "Review Query API", description = "리뷰 조회 API") +@RequiredArgsConstructor +@RequestMapping("/api") +@RestController +public class ReviewQueryApiController { + + private final ReviewQueryUseCase reviewQueryUseCase; + + @Operation(summary = "리뷰 단건 조회", description = "리뷰 ID를 사용하여 단건 리뷰 조회") + @GetMapping("/review/{id}") + public ApiResponse getById(@PathVariable Long id) { + + return ApiResponse.ok( + 200, + reviewQueryUseCase.getReviewById(id), + "리뷰 단건 조회 성공" + ); + } + + @Operation(summary = "기관별 리뷰 조회", description = "기관 ID를 사용하여 리뷰 조회") + @GetMapping("/reviews/center/{centerId}") + public ApiResponse> getReviewsByCenterId( + @PathVariable 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.getReviewsByCenterId(centerId, condition), + "기관 리뷰 리스트 조회 성공" + ); + } + + @Operation(summary = "봉사자 리뷰 조회", description = "봉사자 ID를 사용하여 리뷰 조회") + @GetMapping("/reviews/volunteer/{volunteerId}") + public ApiResponse> getReviewsByVolunteerId( + @PathVariable UUID volunteerId, + @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.getReviewsByVolunteerId(volunteerId, condition), + "유저 리뷰 리스트 조회 성공" + ); + } + +} diff --git a/src/main/java/com/somemore/review/dto/condition/ReviewSearchCondition.java b/src/main/java/com/somemore/review/dto/condition/ReviewSearchCondition.java new file mode 100644 index 000000000..d9d9666e4 --- /dev/null +++ b/src/main/java/com/somemore/review/dto/condition/ReviewSearchCondition.java @@ -0,0 +1,13 @@ +package com.somemore.review.dto.condition; + +import com.somemore.recruitboard.domain.VolunteerCategory; +import lombok.Builder; +import org.springframework.data.domain.Pageable; + +@Builder +public record ReviewSearchCondition( + VolunteerCategory category, + Pageable pageable +) { + +} diff --git a/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java b/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java new file mode 100644 index 000000000..06d65a135 --- /dev/null +++ b/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java @@ -0,0 +1,41 @@ +package com.somemore.review.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.somemore.review.domain.Review; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; + +@Builder +@JsonNaming(SnakeCaseStrategy.class) +@Schema(description = "리뷰 응답 DTO") +public record ReviewResponseDto( + @Schema(description = "리뷰 ID", example = "123") + Long id, + @Schema(description = "봉사자(작성자) ID", example = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d") + UUID volunteerId, + @Schema(description = "리뷰 제목", example = "제 인생 최고의 봉사활동") + String title, + @Schema(description = "리뷰 내용", example = "정말 유익했습니다. 더보기..") + String content, + @Schema(description = "이미지 링크", example = "https://image.domain.com/links") + String imgUrl, + @Schema(description = "작성 일자", example = "2024-12-01T09:00:00") + LocalDateTime createdAt, + @Schema(description = "수정 일자", example = "2024-12-01T09:00:00") + LocalDateTime updateAt +) { + + public static ReviewResponseDto from(Review review) { + return ReviewResponseDto.builder() + .id(review.getId()) + .volunteerId(review.getVolunteerId()) + .title(review.getTitle()) + .content(review.getContent()) + .imgUrl(review.getImgUrl()) + .build(); + } + +} diff --git a/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java b/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java new file mode 100644 index 000000000..b7a274767 --- /dev/null +++ b/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java @@ -0,0 +1,44 @@ +package com.somemore.review.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.somemore.review.domain.Review; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; + +@Builder +@JsonNaming(SnakeCaseStrategy.class) +@Schema(description = "작성자 닉네임이 포함된 리뷰 응답 DTO") +public record ReviewWithNicknameResponseDto( + @Schema(description = "리뷰 ID", example = "123") + Long id, + @Schema(description = "봉사자(작성자) ID", example = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d") + UUID volunteerId, + @Schema(description = "작성자 닉네임", example = "volunteer123") + String volunteerNickname, + @Schema(description = "리뷰 제목", example = "제 인생 최고의 봉사활동") + String title, + @Schema(description = "리뷰 내용", example = "정말 유익했습니다. 더보기..") + String content, + @Schema(description = "이미지 링크", example = "https://image.domain.com/links") + String imgUrl, + @Schema(description = "작성 일자", example = "2024-12-01T09:00:00") + LocalDateTime createdAt, + @Schema(description = "수정 일자", example = "2024-12-01T09:00:00") + LocalDateTime updateAt +) { + + public static ReviewWithNicknameResponseDto from(Review review, String volunteerNickname) { + return ReviewWithNicknameResponseDto.builder() + .id(review.getId()) + .volunteerId(review.getVolunteerId()) + .volunteerNickname(volunteerNickname) + .title(review.getTitle()) + .content(review.getContent()) + .imgUrl(review.getImgUrl()) + .build(); + } + +} diff --git a/src/main/java/com/somemore/review/repository/ReviewRepository.java b/src/main/java/com/somemore/review/repository/ReviewRepository.java index 08b817fd8..9d983e1c3 100644 --- a/src/main/java/com/somemore/review/repository/ReviewRepository.java +++ b/src/main/java/com/somemore/review/repository/ReviewRepository.java @@ -1,13 +1,23 @@ package com.somemore.review.repository; import com.somemore.review.domain.Review; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import java.util.List; import java.util.Optional; +import java.util.UUID; +import org.springframework.data.domain.Page; public interface ReviewRepository { Review save(Review review); + List saveAll(List reviews); + Optional findById(Long id); boolean existsByVolunteerApplyId(Long volunteerApplyId); + + Page findAllByVolunteerIdAndSearch(UUID volunteerId, ReviewSearchCondition condition); + + Page findAllByCenterIdAndSearch(UUID centerId, ReviewSearchCondition condition); } diff --git a/src/main/java/com/somemore/review/repository/ReviewRepositoryImpl.java b/src/main/java/com/somemore/review/repository/ReviewRepositoryImpl.java index 856efe188..e9d06b964 100644 --- a/src/main/java/com/somemore/review/repository/ReviewRepositoryImpl.java +++ b/src/main/java/com/somemore/review/repository/ReviewRepositoryImpl.java @@ -1,9 +1,23 @@ package com.somemore.review.repository; +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.somemore.recruitboard.domain.QRecruitBoard; +import com.somemore.recruitboard.domain.VolunteerCategory; +import com.somemore.review.domain.QReview; import com.somemore.review.domain.Review; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import com.somemore.volunteerapply.domain.QVolunteerApply; +import jakarta.validation.constraints.NotNull; +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.Sort; +import org.springframework.data.support.PageableExecutionUtils; import org.springframework.stereotype.Repository; @RequiredArgsConstructor @@ -13,11 +27,20 @@ public class ReviewRepositoryImpl implements ReviewRepository { private final ReviewJpaRepository reviewJpaRepository; private final JPAQueryFactory queryFactory; + private final static QReview review = QReview.review; + private final static QVolunteerApply volunteerApply = QVolunteerApply.volunteerApply; + private final static QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; + @Override public Review save(Review review) { return reviewJpaRepository.save(review); } + @Override + public List saveAll(List reviews) { + return reviewJpaRepository.saveAll(reviews); + } + @Override public Optional findById(Long id) { return reviewJpaRepository.findByIdAndDeletedFalse(id); @@ -27,4 +50,79 @@ public Optional findById(Long id) { public boolean existsByVolunteerApplyId(Long volunteerApplyId) { return reviewJpaRepository.existsByVolunteerApplyId(volunteerApplyId); } + + @Override + public Page findAllByVolunteerIdAndSearch(UUID volunteerId, + ReviewSearchCondition condition) { + + BooleanExpression predicate = review.volunteerId.eq(volunteerId) + .and(eqVolunteerCategory(condition.category())) + .and(isNotDeleted()); + + return getReviews(condition, predicate); + + } + + @Override + public Page findAllByCenterIdAndSearch(UUID centerId, ReviewSearchCondition condition) { + + BooleanExpression predicate = recruitBoard.centerId.eq(centerId) + .and(eqVolunteerCategory(condition.category())) + .and(isNotDeleted()); + + return getReviews(condition, predicate); + } + + @NotNull + private Page getReviews(ReviewSearchCondition condition, BooleanExpression predicate) { + List content = queryFactory.select(review) + .from(review) + .join(volunteerApply).on(review.volunteerApplyId.eq(volunteerApply.id)) + .join(recruitBoard).on(recruitBoard.id.eq(volunteerApply.recruitBoardId)) + .where(predicate) + .offset(condition.pageable().getOffset()) + .limit(condition.pageable().getPageSize()) + .orderBy(toOrderSpecifiers(condition.pageable().getSort())) + .fetch(); + + JPAQuery countQuery = queryFactory + .select(review.count()) + .join(volunteerApply).on(review.volunteerApplyId.eq(volunteerApply.id)) + .join(recruitBoard).on(recruitBoard.id.eq(volunteerApply.recruitBoardId)) + .from(review) + .where(predicate); + + return PageableExecutionUtils.getPage(content, condition.pageable(), countQuery::fetchOne); + } + + private BooleanExpression isNotDeleted() { + return review.deleted.isFalse(); + } + + private BooleanExpression eqVolunteerCategory(VolunteerCategory category) { + return category != null + ? recruitBoard.recruitmentInfo.volunteerCategory.eq(category) : null; + } + + private OrderSpecifier[] toOrderSpecifiers(Sort sort) { + return sort.stream() + .map(order -> { + String property = order.getProperty(); + + if ("created_at".equals(property)) { + return order.isAscending() + ? review.createdAt.asc() + : review.createdAt.desc(); + } + if ("updated_at".equals(property)) { + return order.isAscending() + ? review.updatedAt.asc() + : review.updatedAt.desc(); + } + + throw new IllegalStateException("Invalid sort property: " + property); + + }) + .toArray(OrderSpecifier[]::new); + } } diff --git a/src/main/java/com/somemore/review/service/ReviewQueryService.java b/src/main/java/com/somemore/review/service/ReviewQueryService.java new file mode 100644 index 000000000..713a7eb54 --- /dev/null +++ b/src/main/java/com/somemore/review/service/ReviewQueryService.java @@ -0,0 +1,89 @@ +package com.somemore.review.service; + +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_REVIEW; + +import com.somemore.center.usecase.query.CenterQueryUseCase; +import com.somemore.global.exception.BadRequestException; +import com.somemore.review.domain.Review; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import com.somemore.review.dto.response.ReviewResponseDto; +import com.somemore.review.dto.response.ReviewWithNicknameResponseDto; +import com.somemore.review.repository.ReviewRepository; +import com.somemore.review.usecase.ReviewQueryUseCase; +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.usecase.VolunteerQueryUseCase; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class ReviewQueryService implements ReviewQueryUseCase { + + private final ReviewRepository reviewRepository; + private final VolunteerQueryUseCase volunteerQueryUseCase; + private final CenterQueryUseCase centerQueryUseCase; + + @Override + public Review getById(Long id) { + return reviewRepository.findById(id).orElseThrow( + () -> new BadRequestException(NOT_EXISTS_REVIEW) + ); + } + + @Override + public ReviewResponseDto getReviewById(Long id) { + Review review = getById(id); + return ReviewResponseDto.from(review); + } + + @Override + public Page getReviewsByVolunteerId( + UUID volunteerId, + ReviewSearchCondition condition + ) { + String nickname = volunteerQueryUseCase.getNicknameById(volunteerId); + Page reviews = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId, + condition); + + return reviews.map( + review -> ReviewWithNicknameResponseDto.from(review, nickname) + ); + } + + @Override + public Page getReviewsByCenterId( + UUID centerId, + ReviewSearchCondition condition + ) { + centerQueryUseCase.validateCenterExists(centerId); + + Page reviews = reviewRepository.findAllByCenterIdAndSearch(centerId, condition); + List volunteerIds = reviews.get().map(Review::getVolunteerId).toList(); + Map volunteerNicknames = getVolunteerNicknames(volunteerIds); + + return reviews.map( + review -> { + String nickname = volunteerNicknames.getOrDefault(review.getVolunteerId(), + "삭제된 아이디"); + return ReviewWithNicknameResponseDto.from(review, nickname); + }); + } + + private Map getVolunteerNicknames(List volunteerIds) { + List volunteers = volunteerQueryUseCase.getAllByIds(volunteerIds); + + Map volunteerNicknames = new HashMap<>(); + for (Volunteer volunteer : volunteers) { + volunteerNicknames.put(volunteer.getId(), volunteer.getNickname()); + } + + return volunteerNicknames; + } +} diff --git a/src/main/java/com/somemore/review/usecase/ReviewQueryUseCase.java b/src/main/java/com/somemore/review/usecase/ReviewQueryUseCase.java new file mode 100644 index 000000000..05f10216e --- /dev/null +++ b/src/main/java/com/somemore/review/usecase/ReviewQueryUseCase.java @@ -0,0 +1,22 @@ +package com.somemore.review.usecase; + +import com.somemore.review.domain.Review; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import com.somemore.review.dto.response.ReviewResponseDto; +import com.somemore.review.dto.response.ReviewWithNicknameResponseDto; +import java.util.UUID; +import org.springframework.data.domain.Page; + +public interface ReviewQueryUseCase { + + Review getById(Long id); + + ReviewResponseDto getReviewById(Long id); + + Page getReviewsByVolunteerId(UUID volunteerId, + ReviewSearchCondition condition); + + Page getReviewsByCenterId(UUID centerId, + ReviewSearchCondition condition); + +} diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java index be4afdb52..0d63a373f 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java @@ -1,7 +1,12 @@ package com.somemore.volunteer.repository; import com.somemore.volunteer.domain.Volunteer; +import java.util.List; +import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; public interface VolunteerJpaRepository extends JpaRepository { + + List findAllByIdInAndDeletedFalse(List ids); + } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java index 364db842b..b099617af 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java @@ -1,16 +1,23 @@ package com.somemore.volunteer.repository; import com.somemore.volunteer.domain.Volunteer; -import org.springframework.stereotype.Repository; - +import java.util.List; import java.util.Optional; import java.util.UUID; +import org.springframework.stereotype.Repository; @Repository public interface VolunteerRepository { + Volunteer save(Volunteer volunteer); + Optional findById(UUID id); + Optional findByOauthId(String oauthId); + String findNicknameById(UUID id); + void deleteAllInBatch(); + + List findAllByIds(List volunteerIds); } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java index 779d04cac..a78b7c7f5 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java @@ -5,11 +5,11 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import com.somemore.volunteer.domain.QVolunteer; import com.somemore.volunteer.domain.Volunteer; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; - +import java.util.List; import java.util.Optional; import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; @RequiredArgsConstructor @Repository @@ -46,6 +46,11 @@ public void deleteAllInBatch() { volunteerJpaRepository.deleteAllInBatch(); } + @Override + public List findAllByIds(List volunteerIds) { + return volunteerJpaRepository.findAllByIdInAndDeletedFalse(volunteerIds); + } + private Optional findOne(BooleanExpression condition) { return Optional.ofNullable( diff --git a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java index 4e57e2bef..c62bc8133 100644 --- a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java +++ b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java @@ -1,5 +1,7 @@ package com.somemore.volunteer.service; +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; + import com.somemore.facade.validator.VolunteerDetailAccessValidator; import com.somemore.global.exception.BadRequestException; import com.somemore.volunteer.domain.Volunteer; @@ -8,15 +10,13 @@ import com.somemore.volunteer.repository.VolunteerDetailRepository; import com.somemore.volunteer.repository.VolunteerRepository; import com.somemore.volunteer.usecase.VolunteerQueryUseCase; +import java.util.List; +import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.UUID; - -import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; - @Slf4j @Service @RequiredArgsConstructor @@ -45,7 +45,8 @@ public VolunteerProfileResponseDto getVolunteerProfile(UUID volunteerId) { } @Override - public VolunteerProfileResponseDto getVolunteerDetailedProfile(UUID volunteerId, UUID centerId) { + public VolunteerProfileResponseDto getVolunteerDetailedProfile(UUID volunteerId, + UUID centerId) { volunteerDetailAccessValidator.validateByCenterId(centerId, volunteerId); return VolunteerProfileResponseDto.from( @@ -72,6 +73,11 @@ public String getNicknameById(UUID id) { return nickname; } + @Override + public List getAllByIds(List volunteerIds) { + return volunteerRepository.findAllByIds(volunteerIds); + } + private Volunteer findVolunteer(UUID volunteerId) { return volunteerRepository.findById(volunteerId) .orElseThrow(() -> new BadRequestException(NOT_EXISTS_VOLUNTEER)); diff --git a/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java b/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java index 18b00a044..c5b9111f7 100644 --- a/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java +++ b/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java @@ -1,7 +1,8 @@ package com.somemore.volunteer.usecase; +import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.dto.response.VolunteerProfileResponseDto; - +import java.util.List; import java.util.UUID; public interface VolunteerQueryUseCase { @@ -15,4 +16,6 @@ public interface VolunteerQueryUseCase { UUID getVolunteerIdByOAuthId(String oAuthId); String getNicknameById(UUID id); + + List getAllByIds(List volunteerIds); } diff --git a/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java index cd160a1fd..b79438b93 100644 --- a/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java +++ b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java @@ -10,8 +10,14 @@ public interface VolunteerApplyRepository { VolunteerApply save(VolunteerApply volunteerApply); + + List saveAll(List volunteerApplies); + Optional findById(Long id); + List findVolunteerIdsByRecruitIds(List recruitIds); + Page findAllByRecruitId(Long recruitId, Pageable pageable); + Optional findByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId); } diff --git a/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java index 3c0031234..9e53aa1a5 100644 --- a/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java @@ -29,6 +29,11 @@ public VolunteerApply save(VolunteerApply volunteerApply) { return volunteerApplyJpaRepository.save(volunteerApply); } + @Override + public List saveAll(List volunteerApplies) { + return volunteerApplyJpaRepository.saveAll(volunteerApplies); + } + @Override public Optional findById(Long id) { return findOne(volunteerApply.id.eq(id)); diff --git a/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java b/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java index d9af6099e..36fd6e65d 100644 --- a/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java +++ b/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java @@ -1,17 +1,16 @@ package com.somemore.common.fixture; +import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; + import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.RecruitmentInfo; -import com.somemore.recruitboard.domain.VolunteerType; - +import com.somemore.recruitboard.domain.VolunteerCategory; import java.lang.reflect.Field; import java.time.LocalDateTime; import java.util.UUID; -import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; -import static com.somemore.recruitboard.domain.VolunteerType.OTHER; - public class RecruitBoardFixture { public static final String REGION = "경기"; @@ -23,7 +22,7 @@ public class RecruitBoardFixture { public static final String TITLE = "봉사모집제목"; public static final String CONTENT = "봉사모집내용"; public static final String IMG_URL = "https://image.domain.com/links"; - public static final VolunteerType VOLUNTEER_TYPE = OTHER; + public static final VolunteerCategory VOLUNTEER_CATEGORY = OTHER; private RecruitBoardFixture() { } @@ -35,7 +34,7 @@ public static RecruitBoard createRecruitBoard() { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -56,7 +55,7 @@ public static RecruitBoard createRecruitBoard(String title) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -77,7 +76,7 @@ public static RecruitBoard createRecruitBoard(String title, UUID centerId, Long .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -98,7 +97,7 @@ public static RecruitBoard createRecruitBoard(String title, UUID centerId) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -112,14 +111,14 @@ public static RecruitBoard createRecruitBoard(String title, UUID centerId) { .build(); } - public static RecruitBoard createRecruitBoard(VolunteerType type, UUID centerId) { + public static RecruitBoard createRecruitBoard(VolunteerCategory category, UUID centerId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() .region(REGION) .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(type) + .volunteerCategory(category) .admitted(ADMITTED) .build(); @@ -140,7 +139,7 @@ public static RecruitBoard createRecruitBoard(Boolean admitted, UUID centerId) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(admitted) .build(); @@ -161,7 +160,7 @@ public static RecruitBoard createRecruitBoard(Long locationId) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -182,7 +181,7 @@ public static RecruitBoard createRecruitBoard(UUID centerId) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -203,7 +202,7 @@ public static RecruitBoard createRecruitBoard(UUID centerId, Long locationId) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -217,14 +216,14 @@ public static RecruitBoard createRecruitBoard(UUID centerId, Long locationId) { .build(); } - public static RecruitBoard createRecruitBoard(String region, VolunteerType volunteerType) { + public static RecruitBoard createRecruitBoard(String region, VolunteerCategory volunteerCategory) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() .region(region) .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(volunteerType) + .volunteerCategory(volunteerCategory) .admitted(ADMITTED) .build(); @@ -245,7 +244,7 @@ public static RecruitBoard createRecruitBoard(Long locationId, String title) { .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(VOLUNTEER_CATEGORY) .admitted(ADMITTED) .build(); @@ -259,19 +258,18 @@ public static RecruitBoard createRecruitBoard(Long locationId, String title) { .build(); } - public static RecruitBoard createCompletedRecruitBoard() { - + public static RecruitBoard createCompletedRecruitBoard(UUID centerId, VolunteerCategory category) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() .region(REGION) .recruitmentCount(RECRUITMENT_COUNT) .volunteerStartDateTime(START_DATE_TIME) .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) + .volunteerCategory(category) .admitted(ADMITTED) .build(); RecruitBoard recruitBoard = RecruitBoard.builder() - .centerId(UUID.randomUUID()) + .centerId(centerId) .locationId(LOCATION_ID) .title(TITLE) .content(CONTENT) @@ -284,6 +282,19 @@ public static RecruitBoard createCompletedRecruitBoard() { return recruitBoard; } + public static RecruitBoard createCompletedRecruitBoard(VolunteerCategory category) { + RecruitBoard recruitBoard = createCompletedRecruitBoard(UUID.randomUUID(), category); + setRecruitStatusCompleted(recruitBoard); + return recruitBoard; + } + + public static RecruitBoard createCompletedRecruitBoard() { + RecruitBoard recruitBoard = createCompletedRecruitBoard(UUID.randomUUID(), + VOLUNTEER_CATEGORY); + setRecruitStatusCompleted(recruitBoard); + return recruitBoard; + } + private static void setRecruitStatusCompleted(RecruitBoard recruitBoard) { try { Field recruitStatusField = RecruitBoard.class.getDeclaredField("recruitStatus"); diff --git a/src/test/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiControllerTest.java b/src/test/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiControllerTest.java index 7d88f64aa..8ab7bd10f 100644 --- a/src/test/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiControllerTest.java +++ b/src/test/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiControllerTest.java @@ -2,6 +2,7 @@ import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; import static com.somemore.recruitboard.domain.RecruitStatus.CLOSED; +import static com.somemore.recruitboard.domain.VolunteerCategory.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; @@ -21,7 +22,7 @@ import com.somemore.imageupload.usecase.ImageUploadUseCase; import com.somemore.location.dto.request.LocationCreateRequestDto; import com.somemore.recruitboard.domain.RecruitStatus; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.dto.request.RecruitBoardCreateRequestDto; import com.somemore.recruitboard.dto.request.RecruitBoardLocationUpdateRequestDto; import com.somemore.recruitboard.dto.request.RecruitBoardStatusUpdateRequestDto; @@ -84,7 +85,7 @@ void createRecruitBoard_success() throws Exception { .recruitmentCount(10) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(VolunteerType.OTHER) + .volunteerCategory(OTHER) .admitted(true) .location(location) .build(); @@ -137,7 +138,7 @@ void updateRecruitBoard() throws Exception { .recruitmentCount(10) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(VolunteerType.OTHER) + .volunteerCategory(OTHER) .admitted(true) .build(); diff --git a/src/test/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiControllerTest.java b/src/test/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiControllerTest.java index c441dd9e7..5a48b9775 100644 --- a/src/test/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiControllerTest.java +++ b/src/test/java/com/somemore/recruitboard/controller/RecruitBoardQueryApiControllerTest.java @@ -1,6 +1,6 @@ package com.somemore.recruitboard.controller; -import static com.somemore.recruitboard.domain.VolunteerType.ADMINISTRATIVE_SUPPORT; +import static com.somemore.recruitboard.domain.VolunteerCategory.ADMINISTRATIVE_SUPPORT; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.any; @@ -92,7 +92,7 @@ void getAllBySearch() throws Exception { // then mockMvc.perform(get("/api/recruit-boards/search") .param("keyword", "volunteer") - .param("type", ADMINISTRATIVE_SUPPORT.name()) + .param("category", ADMINISTRATIVE_SUPPORT.name()) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) @@ -143,7 +143,7 @@ void getRecruitBoardsByCenterId() throws Exception { // then mockMvc.perform(get("/api/recruit-boards/center/{centerId}", centerId) .param("keyword", "volunteer") - .param("type", ADMINISTRATIVE_SUPPORT.name()) + .param("category", ADMINISTRATIVE_SUPPORT.name()) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.data").exists()) diff --git a/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java b/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java index 2ac18c467..e6a5e822c 100644 --- a/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java +++ b/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java @@ -6,7 +6,7 @@ import static com.somemore.recruitboard.domain.RecruitStatus.CLOSED; import static com.somemore.recruitboard.domain.RecruitStatus.COMPLETED; import static com.somemore.recruitboard.domain.RecruitStatus.RECRUITING; -import static com.somemore.recruitboard.domain.VolunteerType.OTHER; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -70,7 +70,7 @@ void updateRecruitBoard() { .recruitmentCount(10) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(OTHER) + .volunteerCategory(OTHER) .admitted(true).build(); // when @@ -206,7 +206,7 @@ private static RecruitBoard createRecruitBoard(UUID centerId, LocalDateTime star .recruitmentCount(1) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(OTHER) + .volunteerCategory(OTHER) .admitted(true) .build(); diff --git a/src/test/java/com/somemore/recruitboard/domain/RecruitmentInfoTest.java b/src/test/java/com/somemore/recruitboard/domain/RecruitmentInfoTest.java index df46af4eb..2e491947a 100644 --- a/src/test/java/com/somemore/recruitboard/domain/RecruitmentInfoTest.java +++ b/src/test/java/com/somemore/recruitboard/domain/RecruitmentInfoTest.java @@ -2,8 +2,9 @@ import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; import static com.somemore.common.fixture.LocalDateTimeFixture.createUpdateStartDateTime; -import static com.somemore.recruitboard.domain.VolunteerType.ADMINISTRATIVE_SUPPORT; -import static com.somemore.recruitboard.domain.VolunteerType.SAFETY_PREVENTION; +import static com.somemore.recruitboard.domain.VolunteerCategory.ADMINISTRATIVE_SUPPORT; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; +import static com.somemore.recruitboard.domain.VolunteerCategory.SAFETY_PREVENTION; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -55,18 +56,18 @@ void updateRecruitmentInfo() { RecruitmentInfo recruitmentInfo = createRecruitmentInfo(); Integer count = 2; - VolunteerType volunteerType = SAFETY_PREVENTION; + VolunteerCategory volunteerCategory = SAFETY_PREVENTION; LocalDateTime startDateTime = createUpdateStartDateTime(); LocalDateTime endDateTime = startDateTime.plusHours(2); Boolean admitted = false; // when - recruitmentInfo.updateWith(count, volunteerType, startDateTime, + recruitmentInfo.updateWith(count, volunteerCategory, startDateTime, endDateTime, admitted); // then assertThat(recruitmentInfo.getRecruitmentCount()).isEqualTo(count); - assertThat(recruitmentInfo.getVolunteerType()).isEqualTo(volunteerType); + assertThat(recruitmentInfo.getVolunteerCategory()).isEqualTo(volunteerCategory); assertThat(recruitmentInfo.getVolunteerStartDateTime().compareTo(startDateTime)).isZero(); assertThat(recruitmentInfo.getVolunteerEndDateTime().compareTo(endDateTime)).isZero(); assertThat(recruitmentInfo.getAdmitted()).isEqualTo(admitted); @@ -111,7 +112,7 @@ private static RecruitmentInfo createRecruitmentInfo(LocalDateTime startDateTime .recruitmentCount(1) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(VolunteerType.OTHER) + .volunteerCategory(OTHER) .admitted(true) .build(); } diff --git a/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java b/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java index 1f320beda..d639a36d2 100644 --- a/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java +++ b/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java @@ -7,7 +7,7 @@ import com.somemore.location.repository.LocationRepository; import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; -import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.domain.VolunteerCategory; import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; @@ -35,7 +35,7 @@ import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard; import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard; import static com.somemore.recruitboard.domain.RecruitStatus.CLOSED; -import static com.somemore.recruitboard.domain.VolunteerType.ADMINISTRATIVE_SUPPORT; +import static com.somemore.recruitboard.domain.VolunteerCategory.ADMINISTRATIVE_SUPPORT; import static org.assertj.core.api.Assertions.assertThat; @Transactional @@ -160,7 +160,7 @@ void findAllWithCenterByKeyword() { @DisplayName("봉사활동 유형으로 조회할 수 있다") @Test - void findAllWithCenterByType() { + void findAllWithCenterByCategory() { // given Center center = createCenter(); centerRepository.save(center); @@ -169,9 +169,9 @@ void findAllWithCenterByType() { recruitBoardRepository.save(recruitBoard); Pageable pageable = getPageable(); - VolunteerType type = ADMINISTRATIVE_SUPPORT; + VolunteerCategory category = ADMINISTRATIVE_SUPPORT; RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .type(type) + .category(category) .pageable(pageable) .build(); @@ -186,7 +186,7 @@ void findAllWithCenterByType() { assertThat(result.getContent()).hasSize(1); assertThat(result.getContent().getFirst().recruitBoard().getRecruitmentInfo() - .getVolunteerType()).isEqualTo(type); + .getVolunteerCategory()).isEqualTo(category); } @DisplayName("지역으로 조회할 수 있다") diff --git a/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java b/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java index b3c05a859..4ccf311aa 100644 --- a/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java +++ b/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java @@ -1,13 +1,13 @@ package com.somemore.recruitboard.service.command; import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; import static org.assertj.core.api.Assertions.assertThat; import com.somemore.IntegrationTestSupport; import com.somemore.location.dto.request.LocationCreateRequestDto; import com.somemore.location.repository.LocationRepository; import com.somemore.recruitboard.domain.RecruitBoard; -import com.somemore.recruitboard.domain.VolunteerType; import com.somemore.recruitboard.dto.request.RecruitBoardCreateRequestDto; import com.somemore.recruitboard.repository.RecruitBoardJpaRepository; import com.somemore.recruitboard.repository.RecruitBoardRepository; @@ -60,7 +60,7 @@ void createRecruitBoardWithDto() { .recruitmentCount(10) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(VolunteerType.OTHER) + .volunteerCategory(OTHER) .admitted(true) .location(locationDto) .build(); diff --git a/src/test/java/com/somemore/recruitboard/service/command/DeleteRecruitBoardServiceTest.java b/src/test/java/com/somemore/recruitboard/service/command/DeleteRecruitBoardServiceTest.java index 731b7a0ff..8a7a13244 100644 --- a/src/test/java/com/somemore/recruitboard/service/command/DeleteRecruitBoardServiceTest.java +++ b/src/test/java/com/somemore/recruitboard/service/command/DeleteRecruitBoardServiceTest.java @@ -1,7 +1,7 @@ package com.somemore.recruitboard.service.command; import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; -import static com.somemore.recruitboard.domain.VolunteerType.OTHER; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -84,7 +84,7 @@ private static RecruitBoard createRecruitBoard() { .recruitmentCount(1) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(OTHER) + .volunteerCategory(OTHER) .admitted(true) .build(); diff --git a/src/test/java/com/somemore/recruitboard/service/command/UpdateRecruitBoardServiceTest.java b/src/test/java/com/somemore/recruitboard/service/command/UpdateRecruitBoardServiceTest.java index f78db125d..8f25d2559 100644 --- a/src/test/java/com/somemore/recruitboard/service/command/UpdateRecruitBoardServiceTest.java +++ b/src/test/java/com/somemore/recruitboard/service/command/UpdateRecruitBoardServiceTest.java @@ -3,8 +3,8 @@ import static com.somemore.common.fixture.LocalDateTimeFixture.createCurrentDateTime; import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; import static com.somemore.common.fixture.LocalDateTimeFixture.createUpdateStartDateTime; -import static com.somemore.recruitboard.domain.VolunteerType.ADMINISTRATIVE_SUPPORT; -import static com.somemore.recruitboard.domain.VolunteerType.OTHER; +import static com.somemore.recruitboard.domain.VolunteerCategory.ADMINISTRATIVE_SUPPORT; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; import static org.assertj.core.api.Assertions.assertThat; import com.somemore.IntegrationTestSupport; @@ -73,7 +73,7 @@ void updateRecruitBoard() { .recruitmentCount(1111) .volunteerStartDateTime(newStartDateTime) .volunteerEndDateTime(newEndDateTime) - .volunteerType(ADMINISTRATIVE_SUPPORT) + .volunteerCategory(ADMINISTRATIVE_SUPPORT) .admitted(false) .build(); @@ -91,7 +91,7 @@ void updateRecruitBoard() { RecruitmentInfo recruitmentInfo = updatedRecruitBoard.getRecruitmentInfo(); assertThat(recruitmentInfo.getRecruitmentCount()).isEqualTo(dto.recruitmentCount()); - assertThat(recruitmentInfo.getVolunteerType()).isEqualTo(dto.volunteerType()); + assertThat(recruitmentInfo.getVolunteerCategory()).isEqualTo(dto.volunteerCategory()); assertThat(recruitmentInfo.getAdmitted()).isEqualTo(dto.admitted()); assertThat(recruitmentInfo.getVolunteerStartDateTime()) @@ -143,7 +143,7 @@ void updateRecruitBoardWhenCenterIdIsWrong() { .recruitmentCount(1111) .volunteerStartDateTime(newStartDateTime) .volunteerEndDateTime(newEndDateTime) - .volunteerType(ADMINISTRATIVE_SUPPORT) + .volunteerCategory(ADMINISTRATIVE_SUPPORT) .admitted(false) .build(); @@ -188,7 +188,7 @@ private static RecruitBoard createRecruitBoard(UUID centerId, Long locationId, .recruitmentCount(1) .volunteerStartDateTime(startDateTime) .volunteerEndDateTime(endDateTime) - .volunteerType(OTHER) + .volunteerCategory(OTHER) .admitted(true) .build(); diff --git a/src/test/java/com/somemore/review/repository/ReviewRepositoryImplTest.java b/src/test/java/com/somemore/review/repository/ReviewRepositoryImplTest.java index 5a7697c8a..f98ee5ed9 100644 --- a/src/test/java/com/somemore/review/repository/ReviewRepositoryImplTest.java +++ b/src/test/java/com/somemore/review/repository/ReviewRepositoryImplTest.java @@ -1,14 +1,36 @@ package com.somemore.review.repository; +import static com.somemore.auth.oauth.OAuthProvider.NAVER; +import static com.somemore.common.fixture.CenterFixture.createCenter; +import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard; +import static com.somemore.recruitboard.domain.VolunteerCategory.COUNSELING; +import static com.somemore.recruitboard.domain.VolunteerCategory.CULTURAL_EVENT; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; +import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED; import static org.assertj.core.api.Assertions.assertThat; import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import com.somemore.center.repository.CenterRepository; +import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.domain.VolunteerCategory; +import com.somemore.recruitboard.repository.RecruitBoardRepository; import com.somemore.review.domain.Review; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.repository.VolunteerRepository; +import com.somemore.volunteerapply.domain.VolunteerApply; +import com.somemore.volunteerapply.repository.VolunteerApplyRepository; +import java.util.List; import java.util.Optional; import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.transaction.annotation.Transactional; @Transactional @@ -17,17 +39,23 @@ class ReviewRepositoryImplTest extends IntegrationTestSupport { @Autowired private ReviewRepositoryImpl reviewRepository; - @DisplayName("리뷰 생성 및 조회") + @Autowired + private RecruitBoardRepository recruitBoardRepository; + + @Autowired + private VolunteerApplyRepository volunteerApplyRepository; + + @Autowired + private CenterRepository centerRepository; + + @Autowired + private VolunteerRepository volunteerRepository; + + @DisplayName("리뷰를 저장하고 조회할 수 있다") @Test void saveAndFind() { // given - Review review = Review.builder() - .volunteerApplyId(1L) - .volunteerId(UUID.randomUUID()) - .title("리뷰 제목") - .content("리뷰 내용") - .imgUrl("") - .build(); + Review review = createReview(1L, UUID.randomUUID(), "리뷰 내용"); reviewRepository.save(review); // when @@ -43,13 +71,7 @@ void saveAndFind() { void existsByVolunteerApplyId() { // given Long volunteerApplyId = 1L; - Review review = Review.builder() - .volunteerApplyId(volunteerApplyId) - .volunteerId(UUID.randomUUID()) - .title("리뷰 제목") - .content("리뷰 내용") - .imgUrl("") - .build(); + Review review = createReview(volunteerApplyId, UUID.randomUUID(), "리뷰 내용"); reviewRepository.save(review); // when @@ -59,4 +81,188 @@ void existsByVolunteerApplyId() { assertThat(result).isTrue(); } + @DisplayName("봉사자 ID로 조건 없이 리뷰를 조회할 수 있다") + @Test + void findAllByVolunteerIdAndSearchWithoutCondition() { + // given + UUID volunteerId = UUID.randomUUID(); + + VolunteerCategory category = CULTURAL_EVENT; + RecruitBoard board1 = createCompletedRecruitBoard(category); + RecruitBoard board2 = createCompletedRecruitBoard(OTHER); + recruitBoardRepository.saveAll(List.of(board1, board2)); + + VolunteerApply apply1 = createApply(volunteerId, board1.getId()); + VolunteerApply apply2 = createApply(volunteerId, board2.getId()); + + volunteerApplyRepository.saveAll(List.of(apply1, apply2)); + + Review review1 = createReview(apply1.getId(), volunteerId, "제 인생 최고의 봉사활동"); + Review review2 = createReview(apply2.getId(), volunteerId, "보람있는 봉사활동"); + reviewRepository.saveAll(List.of(review1, review2)); + + ReviewSearchCondition conditionWithoutCategory = ReviewSearchCondition.builder() + .pageable(getPageable()) + .build(); + + // when + Page result = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId, + conditionWithoutCategory); + + // then + assertThat(result.getTotalElements()).isEqualTo(2); + assertThat(result.getContent()).extracting("title") + .containsExactlyInAnyOrder("제 인생 최고의 봉사활동", "보람있는 봉사활동"); + + assertThat(result.getPageable().getPageSize()).isEqualTo(5); + assertThat(result.getPageable().getPageNumber()).isZero(); + } + + @DisplayName("기관 ID와 봉사 유형으로 리뷰 목록을 조회할 수 있다") + @Test + void findAllByVolunteerIdAndSearchWithCondition() { + // given + UUID volunteerId = UUID.randomUUID(); + + VolunteerCategory category = CULTURAL_EVENT; + RecruitBoard board1 = createCompletedRecruitBoard(category); + RecruitBoard board2 = createCompletedRecruitBoard(OTHER); + recruitBoardRepository.saveAll(List.of(board1, board2)); + + VolunteerApply apply1 = createApply(volunteerId, board1.getId()); + VolunteerApply apply2 = createApply(volunteerId, board2.getId()); + + volunteerApplyRepository.saveAll(List.of(apply1, apply2)); + + Review review1 = createReview(apply1.getId(), volunteerId, "제 인생 최고의 봉사활동"); + Review review2 = createReview(apply2.getId(), volunteerId, "보람있는 봉사활동"); + reviewRepository.saveAll(List.of(review1, review2)); + + ReviewSearchCondition conditionWithCategory = ReviewSearchCondition.builder() + .category(category) + .pageable(getPageable()) + .build(); + + // when + Page result = reviewRepository.findAllByVolunteerIdAndSearch(volunteerId, + conditionWithCategory); + + // then + assertThat(result.getTotalElements()).isEqualTo(1); + assertThat(result.getContent()).extracting("title") + .containsExactlyInAnyOrder("제 인생 최고의 봉사활동"); + + assertThat(result.getPageable().getPageSize()).isEqualTo(5); + assertThat(result.getPageable().getPageNumber()).isZero(); + } + + @DisplayName("기관 ID로 봉사 유형 없이 리뷰 목록을 조회할 수 있다") + @Test + void findAllByCenterIdAndSearchWithoutCategory() { + // given + Center center = createCenter("Test Center"); + centerRepository.save(center); + + RecruitBoard board1 = createCompletedRecruitBoard(center.getId(), COUNSELING); + RecruitBoard board2 = createCompletedRecruitBoard(center.getId(), CULTURAL_EVENT); + recruitBoardRepository.saveAll(List.of(board1, board2)); + + Volunteer volunteer = createVolunteer(); + volunteerRepository.save(volunteer); + + VolunteerApply apply1 = createApply(volunteer.getId(), board1.getId()); + VolunteerApply apply2 = createApply(volunteer.getId(), board2.getId()); + volunteerApplyRepository.saveAll(List.of(apply1, apply2)); + + Review review1 = createReview(apply1.getId(), volunteer.getId(), "제목제목"); + Review review2 = createReview(apply2.getId(), volunteer.getId(), "제목제목제목"); + reviewRepository.saveAll(List.of(review1, review2)); + + ReviewSearchCondition condition = ReviewSearchCondition.builder() + .pageable(getPageable()) + .build(); + + // when + Page result = reviewRepository.findAllByCenterIdAndSearch(center.getId(), + condition); + + assertThat(result.getContent()).hasSize(2); + + assertThat(result.getContent()) + .extracting("title") + .containsExactlyInAnyOrder("제목제목", "제목제목제목"); + + assertThat(result.getTotalElements()).isEqualTo(2); + assertThat(result.getTotalPages()).isEqualTo(1); + } + + @DisplayName("기관 ID와 검색 조건으로 리뷰 목록을 조회할 수 있다.") + @Test + void findAllByCenterIdAndSearchWithCategory() { + // given + Center center = createCenter("Test Center"); + centerRepository.save(center); + + RecruitBoard board1 = createCompletedRecruitBoard(center.getId(), COUNSELING); + RecruitBoard board2 = createCompletedRecruitBoard(center.getId(), CULTURAL_EVENT); + recruitBoardRepository.saveAll(List.of(board1, board2)); + + Volunteer volunteer = createVolunteer(); + volunteerRepository.save(volunteer); + + VolunteerApply apply1 = createApply(volunteer.getId(), board1.getId()); + VolunteerApply apply2 = createApply(volunteer.getId(), board2.getId()); + volunteerApplyRepository.saveAll(List.of(apply1, apply2)); + + Review review1 = createReview(apply1.getId(), volunteer.getId(), "제목제목"); + Review review2 = createReview(apply2.getId(), volunteer.getId(), "제목제목제목"); + reviewRepository.saveAll(List.of(review1, review2)); + + ReviewSearchCondition condition = ReviewSearchCondition.builder() + .category(CULTURAL_EVENT) + .pageable(getPageable()) + .build(); + + // when + Page result = reviewRepository.findAllByCenterIdAndSearch(center.getId(), + condition); + + assertThat(result.getContent()).hasSize(1); + + assertThat(result.getContent()) + .extracting("title") + .containsExactly("제목제목제목"); + + assertThat(result.getTotalElements()).isEqualTo(1); + assertThat(result.getTotalPages()).isEqualTo(1); + } + + private static Volunteer createVolunteer() { + return Volunteer.createDefault(NAVER, "naver"); + } + + private Review createReview(Long applyId, UUID volunteerId, String title) { + return Review.builder() + .volunteerApplyId(applyId) + .volunteerId(volunteerId) + .title(title) + .content("내용내용") + .imgUrl("이미지링크") + .build(); + } + + private static VolunteerApply createApply(UUID volunteerId, Long recruitId) { + return VolunteerApply.builder() + .volunteerId(volunteerId) + .recruitBoardId(recruitId) + .status(APPROVED) + .attended(false) + .build(); + } + + private Pageable getPageable() { + Sort sort = Sort.by(Sort.Order.desc("created_at")); + return PageRequest.of(0, 5, sort); + } + } diff --git a/src/test/java/com/somemore/review/service/ReviewQueryServiceTest.java b/src/test/java/com/somemore/review/service/ReviewQueryServiceTest.java new file mode 100644 index 000000000..7cb0c3c09 --- /dev/null +++ b/src/test/java/com/somemore/review/service/ReviewQueryServiceTest.java @@ -0,0 +1,227 @@ +package com.somemore.review.service; + +import static com.somemore.auth.oauth.OAuthProvider.NAVER; +import static com.somemore.common.fixture.CenterFixture.createCenter; +import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard; +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_REVIEW; +import static com.somemore.recruitboard.domain.VolunteerCategory.COUNSELING; +import static com.somemore.recruitboard.domain.VolunteerCategory.CULTURAL_EVENT; +import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER; +import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import com.somemore.center.repository.CenterRepository; +import com.somemore.global.exception.BadRequestException; +import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.domain.VolunteerCategory; +import com.somemore.recruitboard.repository.RecruitBoardRepository; +import com.somemore.review.domain.Review; +import com.somemore.review.dto.condition.ReviewSearchCondition; +import com.somemore.review.dto.response.ReviewResponseDto; +import com.somemore.review.dto.response.ReviewWithNicknameResponseDto; +import com.somemore.review.repository.ReviewRepository; +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.repository.VolunteerRepository; +import com.somemore.volunteerapply.domain.VolunteerApply; +import com.somemore.volunteerapply.repository.VolunteerApplyRepository; +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +class ReviewQueryServiceTest extends IntegrationTestSupport { + + @Autowired + private ReviewQueryService reviewQueryService; + + @Autowired + private ReviewRepository reviewRepository; + + @Autowired + private RecruitBoardRepository recruitBoardRepository; + + @Autowired + private VolunteerApplyRepository volunteerApplyRepository; + + @Autowired + private VolunteerRepository volunteerRepository; + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("아이디로 리뷰를 조회할 수 있다.") + @Test + void getReviewById() { + // given + Review review = createReview(1L, UUID.randomUUID()); + reviewRepository.save(review); + + // when + ReviewResponseDto findOne = reviewQueryService.getReviewById(review.getId()); + + // then + assertThat(findOne).extracting("id").isEqualTo(review.getId()); + assertThat(findOne).extracting("volunteerId").isEqualTo(review.getVolunteerId()); + assertThat(findOne).extracting("title").isEqualTo(review.getTitle()); + assertThat(findOne).extracting("content").isEqualTo(review.getContent()); + assertThat(findOne).extracting("imgUrl").isEqualTo(review.getImgUrl()); + } + + @DisplayName("존재하지 않는 아이디로 리뷰를 조회하면 에러가 발생한다.") + @Test + void getReviewByIdWhenWrongId() { + // given + Long wrongId = 10000000L; + + // when + // then + assertThatThrownBy( + () -> reviewQueryService.getReviewById(wrongId) + ).isInstanceOf(BadRequestException.class) + .hasMessage(NOT_EXISTS_REVIEW.getMessage()); + } + + @DisplayName("봉사자 ID로 리뷰 리스트를 조회할 수 있다.") + @Test + void getReviewsByVolunteerId() { + // given + Volunteer volunteer = Volunteer.createDefault(NAVER, "naver"); + volunteerRepository.save(volunteer); + + String nickname = volunteer.getNickname(); + UUID volunteerId = volunteer.getId(); + + VolunteerCategory category = CULTURAL_EVENT; + RecruitBoard board1 = createCompletedRecruitBoard(category); + RecruitBoard board2 = createCompletedRecruitBoard(OTHER); + recruitBoardRepository.saveAll(List.of(board1, board2)); + + VolunteerApply apply1 = createApply(volunteerId, board1.getId()); + VolunteerApply apply2 = createApply(volunteerId, board2.getId()); + + volunteerApplyRepository.saveAll(List.of(apply1, apply2)); + + Review review1 = createReview(apply1.getId(), volunteerId, "제 인생 최고의 봉사활동", + "정말 유익했습니다. 더보기..", + "https://image.domain.com/links1"); + Review review2 = createReview(apply2.getId(), volunteerId, "보람있는 봉사활동", + "많은 사람들에게 도움을 주었어요.", + "https://image.domain.com/links2"); + reviewRepository.saveAll(List.of(review1, review2)); + + ReviewSearchCondition conditionWithoutCategory = ReviewSearchCondition.builder() + .pageable(getPageable()) + .build(); + + // when + Page result = reviewQueryService.getReviewsByVolunteerId( + volunteerId, + conditionWithoutCategory); + + // then + assertThat(result.getContent()) + .extracting("id", "title", "volunteerNickname") + .containsExactlyInAnyOrder( + tuple(review1.getId(), "제 인생 최고의 봉사활동", nickname), + tuple(review2.getId(), "보람있는 봉사활동", nickname) + ); + + assertThat(result.getPageable().getPageSize()).isEqualTo(5); + assertThat(result.getPageable().getPageNumber()).isZero(); + } + + @DisplayName("센터 ID로 리뷰 리스트를 조회할 수 있다.") + @Test + void getReviewsByCenterId() { + // given + Center center = createCenter("Test Center"); + centerRepository.save(center); + + RecruitBoard board1 = createCompletedRecruitBoard(center.getId(), COUNSELING); + RecruitBoard board2 = createCompletedRecruitBoard(center.getId(), CULTURAL_EVENT); + recruitBoardRepository.saveAll(List.of(board1, board2)); + + Volunteer volunteer1 = Volunteer.createDefault(NAVER, "naver"); + Volunteer volunteer2 = Volunteer.createDefault(NAVER, "naver"); + volunteer2.markAsDeleted(); + volunteerRepository.save(volunteer1); + volunteerRepository.save(volunteer2); + + VolunteerApply apply1 = createApply(volunteer1.getId(), board1.getId()); + VolunteerApply apply2 = createApply(volunteer2.getId(), board2.getId()); + volunteerApplyRepository.saveAll(List.of(apply1, apply2)); + + Review review1 = createReview(apply1.getId(), volunteer1.getId(), "제 인생 최고의 봉사활동", + "정말 유익했습니다. 더보기..", + "https://image.domain.com/links1"); + Review review2 = createReview(apply2.getId(), volunteer2.getId(), "보람있는 봉사활동", + "많은 사람들에게 도움을 주었어요.", + "https://image.domain.com/links2"); + reviewRepository.saveAll(List.of(review1, review2)); + + ReviewSearchCondition condition = ReviewSearchCondition.builder() + .pageable(getPageable()) + .build(); + + // when + Page result = reviewQueryService.getReviewsByCenterId( + center.getId(), + condition); + + // then + assertThat(result.getContent()) + .extracting("id", "title", "volunteerNickname") + .containsExactlyInAnyOrder( + tuple(review1.getId(), "제 인생 최고의 봉사활동", volunteer1.getNickname()), + tuple(review2.getId(), "보람있는 봉사활동", "삭제된 아이디") + ); + + assertThat(result.getPageable().getPageSize()).isEqualTo(5); + assertThat(result.getPageable().getPageNumber()).isZero(); + } + + private Review createReview(Long applyId, UUID volunteerId) { + return Review.builder() + .volunteerApplyId(applyId) + .volunteerId(volunteerId) + .title("리뷰 제목") + .content("리뷰 내용") + .imgUrl("") + .build(); + } + + private Review createReview(Long applyId, UUID volunteerId, String title, String content, + String imgUrl) { + return Review.builder() + .volunteerApplyId(applyId) + .volunteerId(volunteerId) + .title(title) + .content(content) + .imgUrl(imgUrl) + .build(); + } + + private Pageable getPageable() { + Sort sort = Sort.by(Sort.Order.desc("created_at")); + return PageRequest.of(0, 5, sort); + } + + private static VolunteerApply createApply(UUID volunteerId, Long recruitId) { + return VolunteerApply.builder() + .volunteerId(volunteerId) + .recruitBoardId(recruitId) + .status(APPROVED) + .attended(false) + .build(); + } + +} diff --git a/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java b/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java index c0f63d749..28c823244 100644 --- a/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java +++ b/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java @@ -1,19 +1,19 @@ package com.somemore.volunteer.repository; +import static org.assertj.core.api.Assertions.assertThat; + import com.somemore.IntegrationTestSupport; import com.somemore.auth.oauth.OAuthProvider; import com.somemore.volunteer.domain.Volunteer; +import java.util.List; +import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; - @Transactional class VolunteerRepositoryTest extends IntegrationTestSupport { @@ -22,7 +22,7 @@ class VolunteerRepositoryTest extends IntegrationTestSupport { String oAuthId; Volunteer volunteer; - + @BeforeEach void setup() { oAuthId = "example-oauth-id"; @@ -76,4 +76,29 @@ void findByOauthId() { assertThat(foundVolunteer.get().getOauthId()).isEqualTo(oAuthId); assertThat(foundVolunteer.get().getNickname()).isEqualTo(volunteer.getNickname()); } -} \ No newline at end of file + + @DisplayName("아이디 리스트로 봉사자를 조회할 수있다.") + @Test + void findAllByIds() { + // given + Volunteer volunteer1 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + Volunteer volunteer2 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + Volunteer volunteer3 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + Volunteer volunteer4 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + volunteer4.markAsDeleted(); + + volunteerRepository.save(volunteer1); + volunteerRepository.save(volunteer2); + volunteerRepository.save(volunteer3); + volunteerRepository.save(volunteer4); + + // when + List volunteers = volunteerRepository.findAllByIds( + List.of(volunteer1.getId(), volunteer2.getId(), volunteer3.getId(), + volunteer4.getId() + )); + + // then + assertThat(volunteers).hasSize(3); + } +} diff --git a/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java b/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java index 000cfe1a5..d9e36cbba 100644 --- a/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java +++ b/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java @@ -1,5 +1,11 @@ package com.somemore.volunteer.service; +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; +import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_VOLUNTEER_DETAIL; +import static com.somemore.volunteer.domain.Volunteer.createDefault; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import com.somemore.IntegrationTestSupport; import com.somemore.auth.oauth.OAuthProvider; import com.somemore.global.exception.BadRequestException; @@ -9,19 +15,13 @@ import com.somemore.volunteer.dto.response.VolunteerProfileResponseDto; import com.somemore.volunteer.repository.VolunteerDetailRepository; import com.somemore.volunteer.repository.VolunteerRepository; +import java.util.List; +import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; -import java.util.UUID; - -import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; -import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_VOLUNTEER_DETAIL; -import static com.somemore.volunteer.domain.Volunteer.createDefault; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - @Transactional class VolunteerQueryServiceTest extends IntegrationTestSupport { @@ -123,7 +123,8 @@ void getVolunteerProfile() { volunteerDetailRepository.save(volunteerDetail); // when - VolunteerProfileResponseDto response = volunteerQueryService.getVolunteerProfile(volunteerId); + VolunteerProfileResponseDto response = volunteerQueryService.getVolunteerProfile( + volunteerId); // then assertThat(response).isNotNull(); @@ -147,11 +148,38 @@ void getVolunteerDetailedProfile() { // when // then - assertThatThrownBy(() -> volunteerQueryService.getVolunteerDetailedProfile(volunteerId, centerId)) + assertThatThrownBy( + () -> volunteerQueryService.getVolunteerDetailedProfile(volunteerId, centerId)) .isInstanceOf(BadRequestException.class) .hasMessage(UNAUTHORIZED_VOLUNTEER_DETAIL.getMessage()); } + @DisplayName("아이디 리스트로 봉사자를 조회할 수있다.") + @Test + void findAllByIds() { + // given + Volunteer volunteer1 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + Volunteer volunteer2 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + Volunteer volunteer3 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + Volunteer volunteer4 = Volunteer.createDefault(OAuthProvider.NAVER, "1234"); + volunteer3.markAsDeleted(); + volunteer4.markAsDeleted(); + + volunteerRepository.save(volunteer1); + volunteerRepository.save(volunteer2); + volunteerRepository.save(volunteer3); + volunteerRepository.save(volunteer4); + + // when + List volunteers = volunteerQueryService.getAllByIds( + List.of(volunteer1.getId(), volunteer2.getId(), volunteer3.getId(), + volunteer4.getId(), UUID.randomUUID() + )); + + // then + assertThat(volunteers).hasSize(2); + } + private static VolunteerDetail createVolunteerDetail(UUID volunteerId) { VolunteerRegisterRequestDto volunteerRegisterRequestDto =