Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

#231 Refactor: 와인 정보/리뷰 보기 수정, WineWishlist 리패키징 #232

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.drinkeg.drinkeg.controller;

import com.drinkeg.drinkeg.apipayLoad.ApiResponse;
import com.drinkeg.drinkeg.domain.Member;
import com.drinkeg.drinkeg.dto.WineWishlistDTO.request.WineWishlistRequestDTO;
import com.drinkeg.drinkeg.dto.WineWishlistDTO.response.WineWishlistResponseDTO;
import com.drinkeg.drinkeg.wineWishlist.dto.request.WineWishlistRequestDTO;
import com.drinkeg.drinkeg.wineWishlist.dto.response.WineWishlistResponseDTO;
import com.drinkeg.drinkeg.dto.loginDTO.commonDTO.PrincipalDetail;
import com.drinkeg.drinkeg.service.memberService.MemberService;
import com.drinkeg.drinkeg.service.wineWishlistService.WineWishlistService;
import com.drinkeg.drinkeg.wineWishlist.service.WineWishlistService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.drinkeg.drinkeg.domain.Member;
import com.drinkeg.drinkeg.wine.domain.Wine;
import com.drinkeg.drinkeg.domain.WineWishlist;
import com.drinkeg.drinkeg.dto.WineWishlistDTO.response.WineWishlistResponseDTO;
import com.drinkeg.drinkeg.wineWishlist.domain.WineWishlist;
import com.drinkeg.drinkeg.wineWishlist.dto.response.WineWishlistResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.SearchWineResponseDTO;

public class WineWishlistConverter {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import com.drinkeg.drinkeg.apipayLoad.ApiResponse;
import com.drinkeg.drinkeg.wine.dto.response.SearchWineResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineResponseWithThreeReviewsDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewResponseDTO;
import com.drinkeg.drinkeg.dto.loginDTO.commonDTO.PrincipalDetail;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewResponseDTO;
import com.drinkeg.drinkeg.wine.service.WineService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -35,21 +35,23 @@ public ApiResponse<List<SearchWineResponseDTO>> searchWine(@AuthenticationPrinci
// 선택한 와인 정보 출력
@GetMapping("/{wineId}")
@Operation(summary = "선택 와인 정보 열람", description = "선택한 와인의 정보를 wineResponseDTO에 담아 반환")
public ApiResponse<WineResponseWithThreeReviewsDTO> showWine(@PathVariable("wineId") Long wineId) {
public ApiResponse<WineResponseWithThreeReviewsDTO> showWine(@AuthenticationPrincipal PrincipalDetail principalDetail,
@PathVariable("wineId") Long wineId) {

WineResponseWithThreeReviewsDTO wineResponseWithThreeReviewsDTO = wineService.getWineResponseByWineId(wineId);
WineResponseWithThreeReviewsDTO wineResponseWithThreeReviewsDTO = wineService.getWineResponseByWineId(wineId, principalDetail);

return ApiResponse.onSuccess(wineResponseWithThreeReviewsDTO);
}

// 와인 리뷰 보기
// 전체 와인 리뷰 보기
@GetMapping("/review/{wineId}")
@Operation(summary = "선택 와인 리뷰 열람", description = "선택한 와인 리뷰를 List로 반환")
public ApiResponse<List<WineReviewResponseDTO>> showWineReview(@PathVariable("wineId") Long wineId) {
public ApiResponse<WineReviewResponseDTO> showWineReview(@AuthenticationPrincipal PrincipalDetail principalDetail,
@PathVariable("wineId") Long wineId, @RequestParam Boolean orderByLatest) {

List<WineReviewResponseDTO> wineReviews = wineService.getWineReviewsByWineId(wineId);
WineReviewResponseDTO wineReviewResponseDTO = wineService.getWineReviewsAndIsLikedByWineId(wineId, principalDetail, orderByLatest);

return ApiResponse.onSuccess(wineReviews);
return ApiResponse.onSuccess(wineReviewResponseDTO);
}

// 와인 이미지 업로드
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ public class WineResponseDTO {

private float avgSatisfaction;

private boolean isLiked;


@QueryProjection
public WineResponseDTO(
Long wineId, String name, String imageUrl, int price, String sort, String area, float satisfaction,
float avgSugarContent, float avgAcidity, float avgTannin, float avgBody, float avgAlcohol,
WineNoteNose wineNoteNose, float avgSatisfaction) {
WineNoteNose wineNoteNose, float avgSatisfaction, boolean isLiked) {

this.wineId = wineId;
this.name = name;
Expand All @@ -54,6 +56,8 @@ public WineResponseDTO(

this.wineNoteNose = wineNoteNose;
this.avgSatisfaction = avgSatisfaction;

this.isLiked = isLiked;
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.drinkeg.drinkeg.wine.dto.response;

import com.querydsl.core.annotations.QueryProjection;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -11,10 +10,10 @@
@NoArgsConstructor
public class WineResponseWithThreeReviewsDTO {
WineResponseDTO wineResponseDTO;
List<WineReviewResponseDTO> recentReviews;
List<WineReviewDTO> recentReviews;

@QueryProjection
public WineResponseWithThreeReviewsDTO(WineResponseDTO wineResponseDTO, List<WineReviewResponseDTO> recentReviews) {
public WineResponseWithThreeReviewsDTO(WineResponseDTO wineResponseDTO, List<WineReviewDTO> recentReviews) {
this.wineResponseDTO = wineResponseDTO;
this.recentReviews = recentReviews;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.drinkeg.drinkeg.wine.dto.response;

import com.querydsl.core.annotations.QueryProjection;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor
public class WineReviewDTO {

// 회원이 설정한 이름
private String name;

private String review;

private float satisfaction;

private LocalDateTime createdAt;


@QueryProjection
public WineReviewDTO(String name, String review, float satisfaction, LocalDateTime createdAt) {
this.name = name;
this.review = review;
this.satisfaction = satisfaction;
this.createdAt = createdAt;

}

}
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
package com.drinkeg.drinkeg.wine.dto.response;

import com.drinkeg.drinkeg.tastingNote.dto.response.TastingNotePreviewResponseDTO;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

@Getter
@NoArgsConstructor
@Builder
public class WineReviewResponseDTO {

// 회원이 설정한 이름
private String name;

private String review;

private float satisfaction;

List<WineReviewDTO> wineReviews;
boolean isLiked;

@QueryProjection
public WineReviewResponseDTO(String name, String review, float satisfaction) {
this.name = name;
this.review = review;
this.satisfaction = satisfaction;
public WineReviewResponseDTO(List<WineReviewDTO> wineReviews, boolean isLiked) {
this.wineReviews = wineReviews;
}

public static WineReviewResponseDTO create(List<WineReviewDTO> wineReviews, boolean isLiked){
return WineReviewResponseDTO.builder()
.wineReviews(wineReviews)
.isLiked(isLiked)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
import com.drinkeg.drinkeg.dto.HomeDTO.RecommendWineDTO;
import com.drinkeg.drinkeg.wine.dto.response.SearchWineResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineResponseWithThreeReviewsDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewDTO;

import java.util.List;

public interface WineRepositoryCustom {
List<WineReviewResponseDTO> findWineReviewsById(Long wineId);
List<SearchWineResponseDTO> findWinesWithLikeStatus(String searchName, Long memberId);
WineResponseWithThreeReviewsDTO findWineResponseByWineId(Long wineId, Long memberID);

List<WineReviewDTO> findWineReviewsByWineIdAndMemberId(Long wineId, boolean orderByLatest);

WineResponseWithThreeReviewsDTO findWineResponseByWineId(Long wineId);
List<RecommendWineDTO> findRecommendWines(Member member);
List<SearchWineResponseDTO> findWinesWithLikeStatus(String searchName, Long memberId);
}
jeongyeon0208 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional을 사용하는 이유가 nullPointerExceptioin을 방지하기 위해서인데, 조회된 와인 리뷰가 없으면 null값을 반환하는 로직은 적합하지 않아보입니다.

조회되는 와인이 없는경우, 빈 리스트를 반환하도록 변경하는 것이 보안상 좋을것 같습니다.

return recentReviews.orElse(null); 이부분 수정 요청 드립니다.

Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
import com.drinkeg.drinkeg.dto.HomeDTO.RecommendWineDTO;
import com.drinkeg.drinkeg.wine.dto.response.*;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.drinkeg.drinkeg.domain.QWineWishlist.wineWishlist;
import static com.drinkeg.drinkeg.tastingNote.domain.QTastingNote.tastingNote;
import static com.drinkeg.drinkeg.wine.domain.QWine.wine;
import static com.drinkeg.drinkeg.wineWishlist.domain.QWineWishlist.wineWishlist;

@Repository
@RequiredArgsConstructor
Expand All @@ -27,23 +27,28 @@ public class WineRepositoryImpl implements WineRepositoryCustom {
private final JPAQueryFactory queryFactory;

@Override
public List<WineReviewResponseDTO> findWineReviewsById(Long wineId) {
return queryFactory
.select(new QWineReviewResponseDTO(
public List<WineReviewDTO> findWineReviewsByWineIdAndMemberId(Long wineId, boolean orderByLatest) {

Optional<List<WineReviewDTO>> recentReviews = Optional.ofNullable(queryFactory
.select(new QWineReviewDTO(
tastingNote.member.name,
tastingNote.review,
tastingNote.satisfaction
tastingNote.satisfaction,
tastingNote.createdAt
))
.from(tastingNote)
.join(tastingNote.wine, wine)
.where(wine.id.eq(wineId))
.fetch();
.where(tastingNote.wine.id.eq(wineId))
.orderBy(orderByLatest? tastingNote.createdAt.desc()
: tastingNote.satisfaction.desc()) // 최신순 정렬
.fetch());

return recentReviews.orElse(new ArrayList<>());
}



@Override
public WineResponseWithThreeReviewsDTO findWineResponseByWineId(Long wineId) {
public WineResponseWithThreeReviewsDTO findWineResponseByWineId(Long wineId, Long memberId) {

// Wine 데이터를 가져옴
WineResponseDTO wineResponseDTO = queryFactory
Expand All @@ -64,19 +69,23 @@ public WineResponseWithThreeReviewsDTO findWineResponseByWineId(Long wineId) {

wine.wineNote.wineNoteNose,

wine.wineNote.avgSatisfaction.as("avgSatisfaction")
wine.wineNote.avgSatisfaction.as("avgSatisfaction"),
wineWishlist.id.isNotNull().as("isLiked") // memberId와 wineId에 따라 isLiked 여부
))
.from(wine)
.leftJoin(wine.wineNote)
.leftJoin(wineWishlist)
.on(wineWishlist.wine.eq(wine).and(wineWishlist.member.id.eq(memberId)))
.where(wine.id.eq(wineId))
.fetchOne();

// 최근 생성된 3개의 TastingNote
Optional<List<WineReviewResponseDTO>> recentReviews = Optional.ofNullable(queryFactory
.select(new QWineReviewResponseDTO(
Optional<List<WineReviewDTO>> recentReviews = Optional.ofNullable(queryFactory
.select(new QWineReviewDTO(
tastingNote.member.name,
tastingNote.review,
tastingNote.satisfaction
tastingNote.satisfaction,
tastingNote.createdAt
))
.from(tastingNote)
.where(tastingNote.wine.id.eq(wineId))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.drinkeg.drinkeg.wine.service;

import com.drinkeg.drinkeg.domain.Member;
import com.drinkeg.drinkeg.wine.domain.Wine;
import com.drinkeg.drinkeg.dto.HomeDTO.HomeResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.SearchWineResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineResponseWithThreeReviewsDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.*;
import com.drinkeg.drinkeg.dto.loginDTO.commonDTO.PrincipalDetail;

import java.io.IOException;
Expand All @@ -17,9 +14,9 @@ public interface WineService {

public Wine findWineById(Long wineId);

public WineResponseWithThreeReviewsDTO getWineResponseByWineId(Long wineId);
public WineResponseWithThreeReviewsDTO getWineResponseByWineId(Long wineId, PrincipalDetail principalDetail);

public List<WineReviewResponseDTO> getWineReviewsByWineId(Long wineId);
public WineReviewResponseDTO getWineReviewsAndIsLikedByWineId(Long wineId, PrincipalDetail principalDetail, boolean orderByLatest);

public HomeResponseDTO getHomeResponse(PrincipalDetail principalDetail);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
import com.drinkeg.drinkeg.apipayLoad.code.status.ErrorStatus;
import com.drinkeg.drinkeg.domain.Member;
import com.drinkeg.drinkeg.repository.MemberRepository;
import com.drinkeg.drinkeg.wineWishlist.repository.WineWishlistRepository;
import com.drinkeg.drinkeg.wine.domain.Wine;
import com.drinkeg.drinkeg.dto.HomeDTO.HomeResponseDTO;
import com.drinkeg.drinkeg.dto.HomeDTO.RecommendWineDTO;
import com.drinkeg.drinkeg.wine.dto.response.SearchWineResponseDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineResponseWithThreeReviewsDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewResponseDTO;
import com.drinkeg.drinkeg.dto.loginDTO.commonDTO.PrincipalDetail;
import com.drinkeg.drinkeg.exception.GeneralException;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewDTO;
import com.drinkeg.drinkeg.wine.dto.response.WineReviewResponseDTO;
import com.drinkeg.drinkeg.wine.repository.WineRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -31,6 +33,7 @@ public class WineServiceImpl implements WineService {
private final MemberRepository memberRepository;

private final S3Service s3Service;
private final WineWishlistRepository wineWishlistRepository;

@Override
public List<SearchWineResponseDTO> searchWinesByName(String searchName, PrincipalDetail principalDetail) {
Expand All @@ -51,13 +54,24 @@ public Wine findWineById(Long wineId) {
}

@Override
public WineResponseWithThreeReviewsDTO getWineResponseByWineId(Long wineId){
return wineRepository.findWineResponseByWineId(wineId);
public WineResponseWithThreeReviewsDTO getWineResponseByWineId(Long wineId, PrincipalDetail principalDetail){
// 회원을 조회한다.
Member member = memberRepository.findByUsername(principalDetail.getUsername()).orElseThrow(
() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));

return wineRepository.findWineResponseByWineId(wineId, member.getId());
}

@Override
public List<WineReviewResponseDTO> getWineReviewsByWineId(Long wineId){
return wineRepository.findWineReviewsById(wineId);
public WineReviewResponseDTO getWineReviewsAndIsLikedByWineId(Long wineId, PrincipalDetail principalDetail, boolean orderByLatest){
// 회원을 조회한다.
Member member = memberRepository.findByUsername(principalDetail.getUsername()).orElseThrow(
() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));

List<WineReviewDTO> wineReviews = wineRepository.findWineReviewsByWineIdAndMemberId(wineId, orderByLatest);
boolean liked = wineWishlistRepository.existsByMemberIdAndWineId(member.getId(), wineId);

return WineReviewResponseDTO.create(wineReviews, liked);
}

@Override
Expand Down
Loading