Skip to content
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 @@ -4,8 +4,10 @@
import org.springframework.stereotype.Repository;
import umc.catchy.domain.course.domain.Course;
import umc.catchy.domain.courseReview.domain.CourseReview;
import umc.catchy.domain.member.domain.Member;

@Repository
public interface CourseReviewRepository extends JpaRepository<CourseReview, Long>, CourseReviewRepositoryCustom {
Integer countAllByCourse(Course course);
Integer countAllByMemberId(Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import umc.catchy.domain.courseReview.dto.response.PostCourseReviewResponse;
import umc.catchy.domain.reviewReport.dto.response.MyPageReviewsResponse;

public interface CourseReviewRepositoryCustom {
Slice<PostCourseReviewResponse.newCourseReviewResponseDTO> getAllCourseReviewByCourseId(Long courseId,int pageSize,Long lastReviewId);
Slice<MyPageReviewsResponse.CourseReviewDTO> getAllCourseReviewByMemberId(Long memberId, int pageSize, Long lastReviewId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import umc.catchy.domain.courseReview.dto.response.PostCourseReviewResponse;
import umc.catchy.domain.reviewReport.dto.response.MyPageReviewsResponse;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.querydsl.core.group.GroupBy.groupBy;
import static com.querydsl.core.group.GroupBy.list;
import static umc.catchy.domain.course.domain.QCourse.course;
import static umc.catchy.domain.courseReview.domain.QCourseReview.*;
import static umc.catchy.domain.courseReviewImage.domain.QCourseReviewImage.*;
import static umc.catchy.domain.member.domain.QMember.*;
Expand Down Expand Up @@ -81,4 +85,65 @@ private Slice<PostCourseReviewResponse.newCourseReviewResponseDTO> checkLastPage

return new SliceImpl<>(results, PageRequest.of(0,pageSize), hasNext);
}

@Override
public Slice<MyPageReviewsResponse.CourseReviewDTO> getAllCourseReviewByMemberId(Long memberId, int pageSize, Long lastReviewId){
List<Long> reviewIds = queryFactory
.select(courseReview.id)
.from(courseReview)
.where(
memberIdEq(memberId),
lastCourseReviewId(lastReviewId)
)
.orderBy(courseReview.createdDate.desc())
.limit(pageSize + 1)
.fetch();

List<MyPageReviewsResponse.CourseReviewDTO> result = queryFactory.selectFrom(courseReview)
.leftJoin(courseReview.course, course).on(courseReview.course.id.eq(course.id))
.leftJoin(courseReviewImage).on(courseReviewImage.courseReview.id.eq(courseReview.id))
.where(
courseReview.id.in(reviewIds)
)
.orderBy(courseReview.createdDate.desc())
.transform(groupBy(courseReview.id).list(
Projections.fields(MyPageReviewsResponse.CourseReviewDTO.class,
courseReview.id.as("reviewId"),
courseReview.course.courseName.as("name"),
courseReview.comment.as("comment"),
list(
Projections.fields(MyPageReviewsResponse.ReviewImagesDTO.class,
courseReviewImage.id.as("reviewImageId"),
courseReviewImage.imageUrl.as("imageUrl")
)
).as("reviewImages"),
courseReview.course.courseType.as("courseType")
)
))
.stream()
.peek(dto -> {
// 리뷰 이미지가 null일 경우 빈 리스트로 대체
if (dto.getReviewImages().get(0).getReviewImageId() == null) {
dto.setReviewImages(Collections.emptyList());
}
})
.collect(Collectors.toList());

return checkLastPageOfMyReviews(pageSize, result);
}

private BooleanExpression memberIdEq(Long memberId) {
return memberId == null ? null : courseReview.member.id.eq(memberId);
}

private Slice<MyPageReviewsResponse.CourseReviewDTO> checkLastPageOfMyReviews(int pageSize, List<MyPageReviewsResponse.CourseReviewDTO> results) {
boolean hasNext = false;

if (results.size() > pageSize) {
hasNext = true;
results.remove(pageSize);
}

return new SliceImpl<>(results, PageRequest.of(0,pageSize), hasNext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
public interface PlaceReviewRepository extends JpaRepository<PlaceReview, Long>, PlaceReviewRepositoryCustom {
List<PlaceReview> findAllByPlace(Place place);
Long countByPlaceId(Long placeId);
Integer countAllByMemberId(Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.data.domain.Slice;
import umc.catchy.domain.placeReview.dto.response.PostPlaceReviewResponse;
import umc.catchy.domain.reviewReport.dto.response.MyPageReviewsResponse;

import java.util.List;
import java.util.Optional;
Expand All @@ -10,4 +11,5 @@ public interface PlaceReviewRepositoryCustom {
List<PostPlaceReviewResponse.placeReviewRatingResponseDTO> findRatingList(Long placeId);
Slice<PostPlaceReviewResponse.newPlaceReviewResponseDTO> findPlaceReviewSliceByPlaceId(Long placeId, int pageSize, Long lastPlaceReviewId);
Optional<Double> findAverageRatingByPlaceId(Long placeId);
Slice<MyPageReviewsResponse.PlaceReviewDTO> getAllPlaceReviewByMemberId(Long memberId, int pageSize, Long lastPlaceReviewId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import umc.catchy.domain.placeReview.dto.response.PostPlaceReviewResponse;
import umc.catchy.domain.reviewReport.dto.response.MyPageReviewsResponse;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.querydsl.core.group.GroupBy.*;
import static umc.catchy.domain.member.domain.QMember.*;
import static umc.catchy.domain.place.domain.QPlace.place;
import static umc.catchy.domain.placeReview.domain.QPlaceReview.placeReview;
import static umc.catchy.domain.placeReviewImage.domain.QPlaceReviewImage.*;

Expand Down Expand Up @@ -107,4 +112,64 @@ private Slice<PostPlaceReviewResponse.newPlaceReviewResponseDTO> checkLastPage(i

return new SliceImpl<>(results, PageRequest.of(0,pageSize), hasNext);
}

@Override
public Slice<MyPageReviewsResponse.PlaceReviewDTO> getAllPlaceReviewByMemberId(Long memberId, int pageSize, Long lastPlaceReviewId){
List<Long> reviewIds = queryFactory
.select(placeReview.id)
.from(placeReview)
.where(
memberIdEq(memberId),
lastPlaceReviewId(lastPlaceReviewId)
)
.orderBy(placeReview.visitedDate.desc())
.limit(pageSize + 1)
.fetch();

List<MyPageReviewsResponse.PlaceReviewDTO> results = queryFactory.selectFrom(placeReview)
.leftJoin(placeReview.place, place).on(placeReview.place.id.eq(place.id))
.leftJoin(placeReviewImage).on(placeReviewImage.placeReview.id.eq(placeReview.id))
.where(
placeReview.id.in(reviewIds)
)
.orderBy(placeReview.visitedDate.desc())
.transform(groupBy(placeReview.id).list(
Projections.fields(MyPageReviewsResponse.PlaceReviewDTO.class,
placeReview.id.as("reviewId"),
placeReview.place.placeName.as("name"),
placeReview.comment.as("comment"),
list(
Projections.fields(MyPageReviewsResponse.ReviewImagesDTO.class,
placeReviewImage.id.as("reviewImageId"),
placeReviewImage.imageUrl.as("imageUrl"))
).as("reviewImages"),
placeReview.rating.as("rating"),
placeReview.visitedDate.as("visitedDate"))
))
.stream()
.peek(dto -> {
// 리뷰 이미지가 null일 경우 빈 리스트로 대체
if (dto.getReviewImages().get(0).getReviewImageId() == null) {
dto.setReviewImages(Collections.emptyList());
}
})
.collect(Collectors.toList());

return checkLastPageOfMyReviews(pageSize, results);
}

private BooleanExpression memberIdEq(Long memberId) {
return memberId == null ? null : placeReview.member.id.eq(memberId);
}

private Slice<MyPageReviewsResponse.PlaceReviewDTO> checkLastPageOfMyReviews(int pageSize, List<MyPageReviewsResponse.PlaceReviewDTO> results) {
boolean hasNext = false;

if (results.size() > pageSize) {
hasNext = true;
results.remove(pageSize);
}

return new SliceImpl<>(results, PageRequest.of(0, pageSize), hasNext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.web.bind.annotation.*;
import umc.catchy.domain.reviewReport.dto.request.PostReviewReportRequest;
import umc.catchy.domain.reviewReport.dto.response.DeleteReviewResponse;
import umc.catchy.domain.reviewReport.dto.response.MyPageReviewsResponse;
import umc.catchy.domain.reviewReport.dto.response.PostReviewReportResponse;
import umc.catchy.domain.reviewReport.service.ReviewReportService;
import umc.catchy.global.common.response.BaseResponse;
Expand Down Expand Up @@ -37,4 +38,15 @@ public ResponseEntity<BaseResponse<DeleteReviewResponse>> deleteReview(
DeleteReviewResponse response = reviewReportService.deleteReview(reviewId, reviewType);
return ResponseEntity.ok(BaseResponse.onSuccess(SuccessStatus._OK, response));
}

@Operation(summary = "마이페이지/내 리뷰 조회 API", description = "내가 작성한 리뷰를 조회하는 API입니다.")
@GetMapping("mypage/reviews")
public ResponseEntity<BaseResponse<MyPageReviewsResponse.ReviewsDTO>> getMyReviews(
@RequestParam String reviewType,
@RequestParam int pageSize,
@RequestParam(required = false) Long lastReviewId
){
MyPageReviewsResponse.ReviewsDTO response = reviewReportService.getMyReviews(reviewType, pageSize, lastReviewId);
return ResponseEntity.ok(BaseResponse.onSuccess(SuccessStatus._OK, response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package umc.catchy.domain.reviewReport.dto.response;

import lombok.*;
import umc.catchy.domain.course.domain.CourseType;
import umc.catchy.domain.reviewReport.domain.ReviewType;

import java.time.LocalDate;
import java.util.List;

public class MyPageReviewsResponse {

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ReviewImagesDTO{
Long reviewImageId;
String imageUrl;
}

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public static class BaseReviewDTO{
Long reviewId;
String name; //장소이름 또는 코스이름
String comment;
List<ReviewImagesDTO> reviewImages;
}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class PlaceReviewDTO extends BaseReviewDTO {
//TODO 카테고리 리스트
Integer rating;
LocalDate visitedDate;
}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class CourseReviewDTO extends BaseReviewDTO {
CourseType courseType;
}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ReviewsDTO{
ReviewType reviewType;
Integer reviewCount;
List<? extends BaseReviewDTO> content;
Boolean last;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package umc.catchy.domain.reviewReport.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import umc.catchy.domain.courseReview.dao.CourseReviewRepository;
Expand All @@ -19,6 +20,7 @@
import umc.catchy.domain.reviewReport.domain.ReviewType;
import umc.catchy.domain.reviewReport.dto.request.PostReviewReportRequest;
import umc.catchy.domain.reviewReport.dto.response.DeleteReviewResponse;
import umc.catchy.domain.reviewReport.dto.response.MyPageReviewsResponse;
import umc.catchy.domain.reviewReport.dto.response.PostReviewReportResponse;
import umc.catchy.global.common.response.status.ErrorStatus;
import umc.catchy.global.error.exception.GeneralException;
Expand Down Expand Up @@ -50,6 +52,43 @@ private ReviewType parseReviewType(String reviewType) {
.orElseThrow(()-> new GeneralException(ErrorStatus._BAD_REQUEST, "리뷰 타입은 COURSE 또는 PLACE 입니다."));
}

private MyPageReviewsResponse.ReviewsDTO toReviewsDTO(
ReviewType type,
Integer totalCount,
List<? extends MyPageReviewsResponse.BaseReviewDTO> content,
Boolean last
){
return MyPageReviewsResponse.ReviewsDTO.builder()
.reviewType(type)
.reviewCount(totalCount)
.content(content)
.last(last)
.build();
}

//마이페이지 : 내 리뷰 조회
public MyPageReviewsResponse.ReviewsDTO getMyReviews(String reviewType, int pageSize, Long lastReviewId){
Long memberId = SecurityUtil.getCurrentMemberId();
ReviewType type = parseReviewType(reviewType);

if(type==ReviewType.PLACE){
Integer totalCount = placeReviewRepository.countAllByMemberId(memberId);
Slice<MyPageReviewsResponse.PlaceReviewDTO> placeReviewResponse
= placeReviewRepository.getAllPlaceReviewByMemberId(memberId, pageSize, lastReviewId);
List<MyPageReviewsResponse.PlaceReviewDTO> content = placeReviewResponse.getContent();
Boolean last = placeReviewResponse.isLast();
return toReviewsDTO(type, totalCount, content, last);
}
else{
Integer totalCount = courseReviewRepository.countAllByMemberId(memberId);
Slice<MyPageReviewsResponse.CourseReviewDTO> courseReviewResponse
= courseReviewRepository.getAllCourseReviewByMemberId(memberId, pageSize, lastReviewId);
List<MyPageReviewsResponse.CourseReviewDTO> content = courseReviewResponse.getContent();
Boolean last = courseReviewResponse.isLast();
return toReviewsDTO(type, totalCount, content, last);
}
}

//리뷰 신고하기
//TODO 해당 리뷰의 state 변경
//TODO report 중복 판단
Expand Down