Skip to content

Commit

Permalink
Merge pull request #33 from ShwimPing/feat/lhj/mypage
Browse files Browse the repository at this point in the history
[FEAT] 마이페이지 기능 구현
  • Loading branch information
Amepistheo authored Sep 26, 2024
2 parents c2acdde + 8c67742 commit 9b41adb
Show file tree
Hide file tree
Showing 17 changed files with 380 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.shwimping.be.bookmark.application;

import com.shwimping.be.bookmark.domain.BookMark;
import com.shwimping.be.bookmark.dto.response.BookMarkPlaceResponse;
import com.shwimping.be.bookmark.dto.response.BookMarkPlaceResponseList;
import com.shwimping.be.bookmark.repository.BookMarkRepository;
import com.shwimping.be.place.application.PlaceService;
import com.shwimping.be.place.domain.Place;
Expand All @@ -11,6 +13,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
Expand All @@ -32,4 +36,16 @@ public void saveBookMark(Long userId, Long placeId) {
bookMarkRepository::delete,
() -> bookMarkRepository.save(BookMark.of(user, place)));
}

public BookMarkPlaceResponseList getMyBookMark(Long userId, Long lastBookMarkId, Long size) {
if (lastBookMarkId == 0) {
lastBookMarkId = bookMarkRepository.countBookMarkByUserId(userId);
}

List<BookMarkPlaceResponse> bookMarkList = bookMarkRepository.getBookMarkList(userId, lastBookMarkId, size);

Boolean hasNext = bookMarkRepository.hasNext(userId, lastBookMarkId, size);

return BookMarkPlaceResponseList.of(hasNext, bookMarkList);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.shwimping.be.bookmark.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.shwimping.be.place.domain.type.Category;
import lombok.Builder;

import java.time.LocalTime;

@Builder
public record BookMarkPlaceResponse(
Long bookMarkId,
Long placeId,
String name,
String address,
Category category,
@JsonFormat(pattern = "HH:mm")
LocalTime openTime,
@JsonFormat(pattern = "HH:mm")
LocalTime closeTime,
Double rating,
Long reviewCount
) {
@JsonProperty("rating")
public Double getFormattedRating() {
return Math.round(rating * 10) / 10.0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.shwimping.be.bookmark.dto.response;

import java.util.List;

public record BookMarkPlaceResponseList(
Boolean hasNext,
List<BookMarkPlaceResponse> bookMarkList
) {
public static BookMarkPlaceResponseList of(Boolean hasNext, List<BookMarkPlaceResponse> bookMarkPlaceResponseList) {
return new BookMarkPlaceResponseList(hasNext, bookMarkPlaceResponseList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import com.shwimping.be.bookmark.domain.BookMark;
import com.shwimping.be.place.domain.Place;
import com.shwimping.be.user.domain.User;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface BookMarkRepository extends JpaRepository<BookMark, Long> {
public interface BookMarkRepository extends JpaRepository<BookMark, Long>, BookMarkRepositoryCustom {

Optional<BookMark> findByUserAndPlace(User user, Place place);

Long countBookMarkByUserId(Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.shwimping.be.bookmark.repository;

import com.shwimping.be.bookmark.dto.response.BookMarkPlaceResponse;

import java.util.List;

public interface BookMarkRepositoryCustom {

List<BookMarkPlaceResponse> getBookMarkList(Long userId, Long lastBookMarkId, Long size);

Boolean hasNext(Long userId, Long lastBookMarkId, Long size);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.shwimping.be.bookmark.repository;

import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shwimping.be.bookmark.dto.response.BookMarkPlaceResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;

import static com.shwimping.be.bookmark.domain.QBookMark.bookMark;
import static com.shwimping.be.place.domain.QPlace.place;
import static com.shwimping.be.review.domain.QReview.review;

@Repository
@RequiredArgsConstructor
public class BookMarkRepositoryImpl implements BookMarkRepositoryCustom {

private final JPAQueryFactory queryFactory;

@Override
public List<BookMarkPlaceResponse> getBookMarkList(Long userId, Long lastBookMarkId, Long size) {
return queryFactory.select(
Projections.constructor(BookMarkPlaceResponse.class,
bookMark.id, // bookmarkId
place.id, // placeId
place.name, // name
place.address, // address
place.category, // category
place.openTime, // openTime
place.closeTime, // closeTime
review.rating.avg().coalesce(0.0), // averageRating
review.id.count().coalesce(0L) // reviewCount
)
)
.from(bookMark) // 북마크 테이블에서 시작
.join(bookMark.place, place) // 북마크와 장소 조인
.leftJoin(place.reviewList, review) // 장소와 리뷰를 왼쪽 조인
.where(bookMark.user.id.eq(userId), // 사용자 ID 필터
bookMark.id.lt(lastBookMarkId)) // 마지막 북마크 ID 필터
.groupBy(bookMark.id) // 그룹화 추가
.orderBy(bookMark.id.desc()) // 내림차순 정렬
.limit(size) // 제한
.fetch();
}



@Override
public Boolean hasNext(Long userId, Long lastBookMarkId, Long size) {
return queryFactory.selectOne()
.from(bookMark)
.where(bookMark.user.id.eq(userId), bookMark.id.lt(lastBookMarkId - size))
.fetchFirst() != null;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.shwimping.be.place.application;

import com.shwimping.be.bookmark.domain.BookMark;
import com.shwimping.be.bookmark.dto.response.BookMarkPlaceResponse;
import com.shwimping.be.place.application.type.SortType;
import com.shwimping.be.place.domain.Place;
import com.shwimping.be.place.domain.type.Category;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.shwimping.be.place.domain.type.Category;
import com.shwimping.be.place.dto.response.PlaceDetailWithReviews;
import com.shwimping.be.place.dto.response.SearchPlaceResponse;

import java.util.List;

public interface PlaceRepositoryCustom {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package com.shwimping.be.place.repository;

import static com.shwimping.be.bookmark.domain.QBookMark.bookMark;
import static com.shwimping.be.place.domain.QPlace.place;
import static com.shwimping.be.review.domain.QReview.review;

import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
Expand All @@ -26,6 +22,10 @@

import java.util.List;

import static com.shwimping.be.bookmark.domain.QBookMark.bookMark;
import static com.shwimping.be.place.domain.QPlace.place;
import static com.shwimping.be.review.domain.QReview.review;

@RequiredArgsConstructor
@Repository
public class PlaceRepositoryImpl implements PlaceRepositoryCustom {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ public ReviewSimpleResponseList getReviewSimpleResponse(Long placeId, Long lastR
return ReviewSimpleResponseList.of(hasNext, reviewSimpleResponse);
}

public ReviewSimpleResponseList getMyReview(Long userId, Long lastReviewId, Long size) {

List<ReviewSimpleResponse> reviewSimpleResponse = (lastReviewId == 0)
? reviewRepository.getMyFirstReview(userId) : reviewRepository.getMyReview(userId, lastReviewId, size);

Boolean hasNext = reviewRepository.hasNextMyReview(userId, lastReviewId, size);

return ReviewSimpleResponseList.of(hasNext, reviewSimpleResponse);
}

@Transactional
public void uploadReview(Long userId, ReviewUploadRequest reviewUploadRequest, MultipartFile file) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@ public interface ReviewRepositoryCustom {

List<ReviewSimpleResponse> getReviewSimpleResponse(Long placeId, Long lastReviewId, Long size);

List<ReviewSimpleResponse> getMyFirstReview(Long userId);

List<ReviewSimpleResponse> getMyReview(Long userId, Long lastReviewId, Long size);

Boolean hasNext(Long placeId, Long lastReviewId, Long size);

Boolean hasNextMyReview(Long userId, Long lastReviewId, Long size);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,57 @@ public List<ReviewSimpleResponse> getReviewSimpleResponse(Long placeId, Long las
.fetch();
}

@Override
public List<ReviewSimpleResponse> getMyFirstReview(Long userId) {
// 리뷰를 최신 5개만 가져오기 위한 서브쿼리
return jpaQueryFactory.select(Projections.constructor(ReviewSimpleResponse.class,
review.id,
review.user.nickname,
review.content,
review.rating,
review.date,
review.reviewImageUrl
))
.from(review)
.leftJoin(review.user)
.where(review.user.id.eq(userId))
.orderBy(review.date.desc())
.limit(5)
.fetch();
}

@Override
public List<ReviewSimpleResponse> getMyReview(Long userId, Long lastReviewId, Long size) {
return jpaQueryFactory.select(
Projections.constructor(ReviewSimpleResponse.class,
review.id,
review.user.nickname,
review.content,
review.rating,
review.date,
review.reviewImageUrl
)
)
.from(review)
.where(review.user.id.eq(userId), review.id.lt(lastReviewId)) // lastReviewId를 기준으로 필터링
.orderBy(review.id.desc())
.limit(size) // 가져올 리뷰 수 제한
.fetch();
}

@Override
public Boolean hasNext(Long placeId, Long lastReviewId, Long size) {
return jpaQueryFactory.selectOne()
.from(review)
.where(review.place.id.eq(placeId), review.id.lt(lastReviewId - size))
.fetchFirst() != null;
}

@Override
public Boolean hasNextMyReview(Long userId, Long lastReviewId, Long size) {
return jpaQueryFactory.selectOne()
.from(review)
.where(review.user.id.eq(userId), review.id.lt(lastReviewId - size))
.fetchFirst() != null;
}
}
Loading

0 comments on commit 9b41adb

Please sign in to comment.