From e07d31c0c6e99c86c31c91e12ead2515670da0c7 Mon Sep 17 00:00:00 2001 From: eckrin Date: Fri, 17 Nov 2023 09:54:20 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EA=B0=80=EA=B2=8C=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EC=A1=B0=ED=9A=8C(=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98=20=EB=AF=B8=EC=A0=81?= =?UTF-8?q?=EC=9A=A9)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kusitms/jipbap/food/FoodRepository.java | 2 +- .../jipbap/food/FoodRepositoryExtension.java | 10 +++ .../food/FoodRepositoryExtensionImpl.java | 83 +++++++++++++++++++ .../kusitms/jipbap/store/StoreController.java | 33 ++++++-- .../kusitms/jipbap/store/StoreRepository.java | 1 + .../store/StoreRepositoryExtension.java | 3 + .../store/StoreRepositoryExtensionImpl.java | 19 ++++- .../kusitms/jipbap/store/StoreService.java | 27 +++++- .../store/dto/StoreFoodResponseDto.java | 19 +++++ 9 files changed, 185 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtension.java create mode 100644 src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtensionImpl.java create mode 100644 src/main/java/com/kusitms/jipbap/store/dto/StoreFoodResponseDto.java diff --git a/src/main/java/com/kusitms/jipbap/food/FoodRepository.java b/src/main/java/com/kusitms/jipbap/food/FoodRepository.java index 502e4e1..8eb939c 100644 --- a/src/main/java/com/kusitms/jipbap/food/FoodRepository.java +++ b/src/main/java/com/kusitms/jipbap/food/FoodRepository.java @@ -8,7 +8,7 @@ import java.util.List; import java.util.Optional; -public interface FoodRepository extends JpaRepository { +public interface FoodRepository extends JpaRepository, FoodRepositoryExtension { List findAllByStore(Store store); diff --git a/src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtension.java b/src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtension.java new file mode 100644 index 0000000..c9b15ef --- /dev/null +++ b/src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtension.java @@ -0,0 +1,10 @@ +package com.kusitms.jipbap.food; + +import com.kusitms.jipbap.user.User; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +public interface FoodRepositoryExtension { + List searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order); +} diff --git a/src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtensionImpl.java b/src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtensionImpl.java new file mode 100644 index 0000000..5fbd9ba --- /dev/null +++ b/src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtensionImpl.java @@ -0,0 +1,83 @@ +package com.kusitms.jipbap.food; + +import com.kusitms.jipbap.common.utils.QueryDslUtils; +import com.kusitms.jipbap.order.Review; +import com.kusitms.jipbap.order.ReviewRepositoryExtension; +import com.kusitms.jipbap.store.Store; +import com.kusitms.jipbap.user.User; +import com.querydsl.core.types.Order; +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.util.ArrayList; +import java.util.List; + +import static com.kusitms.jipbap.food.QFood.food; +import static com.kusitms.jipbap.order.QOrder.order; +import static com.kusitms.jipbap.order.QReview.review; +import static com.kusitms.jipbap.store.QStore.store; +import static org.springframework.util.ObjectUtils.isEmpty; + +@RequiredArgsConstructor +public class FoodRepositoryExtensionImpl implements FoodRepositoryExtension { + + private final JPAQueryFactory queryFactory; + + + @Override + public List searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order) { + + List> orderSpecifiers = getAllOrderSpecifiersByPageable(pageable); + + return queryFactory.selectFrom(food) + .where( + containsKeyword(keyword) + ) + .orderBy(orderSpecifiers.toArray(OrderSpecifier[]::new)) + .fetch(); + } + + private BooleanExpression containsKeyword(String keyword) { + if(keyword == null) { + return null; + } + return food.name.contains(keyword); + } + + private List> getAllOrderSpecifiersByPageable(Pageable pageable) { + + List> orderSpecifierList = new ArrayList<>(); + + if (!isEmpty(pageable.getSort())) { + for (Sort.Order order : pageable.getSort()) { + Order direction = order.getDirection().isAscending() ? Order.ASC : Order.DESC; + switch (order.getProperty()) { + // 기본 정렬조건: 추천순 + case "bookmark": // 추천순 + orderSpecifierList.add(QueryDslUtils.getSortedColumn(direction, store, "bookmarkCount")); + orderSpecifierList.add(QueryDslUtils.getSortedColumn(Order.DESC, store, "id")); + break; + case "review": // 후기순 + orderSpecifierList.add(QueryDslUtils.getSortedColumn(direction, store, "reviewCount")); + orderSpecifierList.add(QueryDslUtils.getSortedColumn(Order.DESC, store, "id")); + break; + case "rate": // 평점순 + orderSpecifierList.add(QueryDslUtils.getSortedColumn(direction, store, "avgRate")); + orderSpecifierList.add(QueryDslUtils.getSortedColumn(Order.DESC, store, "id")); + break; + case "id": // 최신순 + orderSpecifierList.add(QueryDslUtils.getSortedColumn(direction, store, "id")); + break; + default: + break; + } + } + } + + return orderSpecifierList; + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/jipbap/store/StoreController.java b/src/main/java/com/kusitms/jipbap/store/StoreController.java index 4b7d415..0437d25 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreController.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreController.java @@ -6,10 +6,7 @@ import com.kusitms.jipbap.order.dto.OrderDto; import com.kusitms.jipbap.security.Auth; import com.kusitms.jipbap.security.AuthInfo; -import com.kusitms.jipbap.store.dto.BookmarkedStoreListResponseDto; -import com.kusitms.jipbap.store.dto.RegisterStoreRequestDto; -import com.kusitms.jipbap.store.dto.StoreDetailResponseDto; -import com.kusitms.jipbap.store.dto.StoreDto; +import com.kusitms.jipbap.store.dto.*; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; @@ -55,7 +52,7 @@ public CommonResponse registerStore( * @return Slice: 슬라이스 단위 */ @Operation(summary = "가게 리스트 검색") - @GetMapping + @GetMapping("/pagenation-deprecated") public CommonResponse> searchStore( @Auth AuthInfo authInfo, @RequestParam(required = false) String keyword, @@ -73,6 +70,32 @@ public CommonResponse> searchStore( return new CommonResponse<>(storeService.searchStoreList(authInfo.getEmail(), pageable, keyword, field, direction, lastId)); } + /** + * 가게 및 음식 검색 api - 페이지네이션 미적용 + * + * @param keyword: 검색 키워드 (키워드가 포함한 가게를 검색한다) + * @param field: 검색 기준 (추천-bookmark, 후기-review, 평점-rate, 가격-price, 최신-id) + * (추천순: 가게 즐겨찾기 개수 순서, 후기: 가게에 속한 주문에 달린 리뷰 수) + * @param direction: 정렬 기준 (ASC, DESC) + */ + @Operation(summary = "가게 또는 메뉴 검색 (페이지네이션 미적용)") + @GetMapping + public CommonResponse searchStoreAndFood( + @Auth AuthInfo authInfo, + @RequestParam(required = false) String keyword, + @RequestParam String field, + @RequestParam String direction + ) { + Sort sort; + if ("asc".equals(direction) || "ASC".equals(direction)) { + sort = Sort.by(Sort.Direction.ASC, field); + } else { + sort = Sort.by(Sort.Direction.DESC, field); + } + Pageable pageable = PageRequest.of(0, 10000, sort); + return new CommonResponse<>(storeService.searchStoresAndFoods(authInfo.getEmail(), pageable, keyword, field, direction)); + } + @Operation(summary = "가게 상세정보") @GetMapping("/{storeId}") public CommonResponse storeDetail(@Auth AuthInfo authInfo, @PathVariable Long storeId) { diff --git a/src/main/java/com/kusitms/jipbap/store/StoreRepository.java b/src/main/java/com/kusitms/jipbap/store/StoreRepository.java index a4d6653..6be8bf6 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreRepository.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreRepository.java @@ -3,6 +3,7 @@ import com.kusitms.jipbap.user.User; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface StoreRepository extends JpaRepository, StoreRepositoryExtension { diff --git a/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtension.java b/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtension.java index 8d00fc1..beb033e 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtension.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtension.java @@ -5,7 +5,10 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import java.util.List; + public interface StoreRepositoryExtension { Slice searchByKeywordOrderBySort(User user, Pageable pageable, String keyword, String standard, String order, Long lastId); + List searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order); } diff --git a/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtensionImpl.java b/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtensionImpl.java index 427439d..b652157 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtensionImpl.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreRepositoryExtensionImpl.java @@ -1,6 +1,7 @@ package com.kusitms.jipbap.store; import com.kusitms.jipbap.common.utils.QueryDslUtils; +import com.kusitms.jipbap.food.Food; import com.kusitms.jipbap.store.dto.StoreDetailResponseDto; import com.kusitms.jipbap.store.dto.StoreDto; import com.kusitms.jipbap.user.User; @@ -17,6 +18,7 @@ import java.util.ArrayList; import java.util.List; +import static com.kusitms.jipbap.food.QFood.food; import static com.kusitms.jipbap.store.QStore.store; import static org.springframework.util.ObjectUtils.isEmpty; @@ -29,7 +31,7 @@ public class StoreRepositoryExtensionImpl implements StoreRepositoryExtension{ @Override public Slice searchByKeywordOrderBySort(User user, Pageable pageable, String keyword, String standard, String order, Long lastId) { - List> orderSpecifiers = getAllOrderSpecifiers(pageable); + List> orderSpecifiers = getAllOrderSpecifiersByPageable(pageable); List storeList = queryFactory.selectFrom(store) .where( @@ -71,6 +73,19 @@ public Slice searchByKeywordOrderBySort(User user, Pagea return new SliceImpl<>(dtoList, pageable, hasNext); } + @Override + public List searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order) { + + List> orderSpecifiers = getAllOrderSpecifiersByPageable(pageable); + + return queryFactory.selectFrom(store) + .where( + containsKeyword(keyword) + ) + .orderBy(orderSpecifiers.toArray(OrderSpecifier[]::new)) + .fetch(); + } + // user가 즐겨찾기한 store인지 검사 private Boolean isUserBookmarkedStore(User user, Store store) { return storeBookmarkRepository.existsByUserAndStore(user, store); @@ -125,7 +140,7 @@ private BooleanExpression containsKeyword(String keyword) { return store.name.contains(keyword); } - private List> getAllOrderSpecifiers(Pageable pageable) { + private List> getAllOrderSpecifiersByPageable(Pageable pageable) { List> orderSpecifierList = new ArrayList<>(); diff --git a/src/main/java/com/kusitms/jipbap/store/StoreService.java b/src/main/java/com/kusitms/jipbap/store/StoreService.java index 3d65afb..36e6a2d 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreService.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreService.java @@ -6,10 +6,8 @@ import com.amazonaws.services.s3.AmazonS3; import com.kusitms.jipbap.common.exception.S3RegisterFailureException; import com.kusitms.jipbap.common.utils.S3Utils; -import com.kusitms.jipbap.store.dto.BookmarkedStoreListResponseDto; -import com.kusitms.jipbap.store.dto.RegisterStoreRequestDto; -import com.kusitms.jipbap.store.dto.StoreDetailResponseDto; -import com.kusitms.jipbap.store.dto.StoreDto; +import com.kusitms.jipbap.food.dto.FoodDto; +import com.kusitms.jipbap.store.dto.*; import com.kusitms.jipbap.store.exception.StoreExistsException; import com.kusitms.jipbap.store.exception.StoreNotExistsException; import com.kusitms.jipbap.user.User; @@ -102,6 +100,27 @@ public Slice searchStoreList(String email, Pageable page return storeRepository.searchByKeywordOrderBySort(user, pageable, keyword, standard, order, lastId); } + @Transactional + public StoreFoodResponseDto searchStoresAndFoods(String email, Pageable pageable, String keyword, String standard, String order) { + User user = userRepository.findByEmail(email).orElseThrow(()-> new UserNotFoundException("유저 정보가 존재하지 않습니다.")); + + List storeList = storeRepository.searchByNameOrderBySort(user, pageable, keyword, standard, order) + .stream().map(s -> new StoreDetailResponseDto( + new StoreDto( + s.getId(), s.getName(), s.getDescription(), s.getKoreanYn(), s.getAvgRate(), s.getMinOrderAmount(), + new String[]{s.getImage(), s.getImage2(), s.getImage3()} + ), storeBookmarkRepository.existsByUserAndStore(user, s)) + ) + .collect(Collectors.toList()); + + List foodList = foodRepository.searchByNameOrderBySort(user, pageable, keyword, standard, order) + .stream().map(f -> new FoodDto(f.getId(), f.getStore().getId(), f.getCategory().getId(), f.getName(), f.getPrice(), f.getDescription(), f.getImage())) + .collect(Collectors.toList()); + + + return new StoreFoodResponseDto(storeList, foodList); + } + @Transactional public StoreDetailResponseDto getStoreDetail(String email, Long storeId) { User user = userRepository.findByEmail(email).orElseThrow(()-> new UserNotFoundException("유저 정보가 존재하지 않습니다.")); diff --git a/src/main/java/com/kusitms/jipbap/store/dto/StoreFoodResponseDto.java b/src/main/java/com/kusitms/jipbap/store/dto/StoreFoodResponseDto.java new file mode 100644 index 0000000..b6c541c --- /dev/null +++ b/src/main/java/com/kusitms/jipbap/store/dto/StoreFoodResponseDto.java @@ -0,0 +1,19 @@ +package com.kusitms.jipbap.store.dto; + +import com.kusitms.jipbap.food.dto.FoodDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class StoreFoodResponseDto { + + private List stores; + private List foods; +} From 04360381f99882fc97e2c997c29e437fe8c82389 Mon Sep 17 00:00:00 2001 From: eckrin Date: Fri, 17 Nov 2023 10:57:40 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EA=B0=80?= =?UTF-8?q?=203=EA=B0=9C=EA=B0=80=20=EC=95=84=EB=8B=8C=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/kusitms/jipbap/store/StoreService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kusitms/jipbap/store/StoreService.java b/src/main/java/com/kusitms/jipbap/store/StoreService.java index 36e6a2d..2b9bb5a 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreService.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreService.java @@ -51,8 +51,8 @@ public StoreDto registerStore(String email, RegisterStoreRequestDto dto, List Date: Fri, 17 Nov 2023 11:10:59 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20Price=EB=A5=BC=20dollar=EB=9E=91=20c?= =?UTF-8?q?anada=20Dollar=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/kusitms/jipbap/food/dto/FoodDto.java | 1 - src/main/java/com/kusitms/jipbap/store/StoreService.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/kusitms/jipbap/food/dto/FoodDto.java b/src/main/java/com/kusitms/jipbap/food/dto/FoodDto.java index e5f65f3..eeaa5b8 100644 --- a/src/main/java/com/kusitms/jipbap/food/dto/FoodDto.java +++ b/src/main/java/com/kusitms/jipbap/food/dto/FoodDto.java @@ -20,5 +20,4 @@ public class FoodDto { private String description; private String image; - } diff --git a/src/main/java/com/kusitms/jipbap/store/StoreService.java b/src/main/java/com/kusitms/jipbap/store/StoreService.java index 2b9bb5a..397b6b4 100644 --- a/src/main/java/com/kusitms/jipbap/store/StoreService.java +++ b/src/main/java/com/kusitms/jipbap/store/StoreService.java @@ -114,7 +114,7 @@ public StoreFoodResponseDto searchStoresAndFoods(String email, Pageable pageable .collect(Collectors.toList()); List foodList = foodRepository.searchByNameOrderBySort(user, pageable, keyword, standard, order) - .stream().map(f -> new FoodDto(f.getId(), f.getStore().getId(), f.getCategory().getId(), f.getName(), f.getPrice(), f.getDescription(), f.getImage())) + .stream().map(f -> new FoodDto(f.getId(), f.getStore().getId(), f.getCategory().getId(), f.getName(), f.getDollarPrice(), f.getCanadaPrice(), f.getDescription(), f.getImage())) .collect(Collectors.toList());