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

feat: 가게 및 메뉴 조회 api(페이지네이션 미적용) 추가 #41

Merged
merged 3 commits into from
Nov 17, 2023
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
2 changes: 1 addition & 1 deletion src/main/java/com/kusitms/jipbap/food/FoodRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.util.List;
import java.util.Optional;

public interface FoodRepository extends JpaRepository<Food, Long> {
public interface FoodRepository extends JpaRepository<Food, Long>, FoodRepositoryExtension {

List<Food> findAllByStore(Store store);

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/kusitms/jipbap/food/FoodRepositoryExtension.java
Original file line number Diff line number Diff line change
@@ -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<Food> searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order);
}
Original file line number Diff line number Diff line change
@@ -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<Food> searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order) {

List<OrderSpecifier<?>> 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<OrderSpecifier<?>> getAllOrderSpecifiersByPageable(Pageable pageable) {

List<OrderSpecifier<?>> 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;
}
}
33 changes: 28 additions & 5 deletions src/main/java/com/kusitms/jipbap/store/StoreController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -55,7 +52,7 @@ public CommonResponse<StoreDto> registerStore(
* @return Slice<?>: 슬라이스 단위
*/
@Operation(summary = "가게 리스트 검색")
@GetMapping
@GetMapping("/pagenation-deprecated")
public CommonResponse<Slice<StoreDetailResponseDto>> searchStore(
@Auth AuthInfo authInfo,
@RequestParam(required = false) String keyword,
Expand All @@ -73,6 +70,32 @@ public CommonResponse<Slice<StoreDetailResponseDto>> 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<StoreFoodResponseDto> 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<StoreDetailResponseDto> storeDetail(@Auth AuthInfo authInfo, @PathVariable Long storeId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Store, Long>, StoreRepositoryExtension {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

import java.util.List;

public interface StoreRepositoryExtension {

Slice<StoreDetailResponseDto> searchByKeywordOrderBySort(User user, Pageable pageable, String keyword, String standard, String order, Long lastId);
List<Store> searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order);
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand All @@ -29,7 +31,7 @@ public class StoreRepositoryExtensionImpl implements StoreRepositoryExtension{
@Override
public Slice<StoreDetailResponseDto> searchByKeywordOrderBySort(User user, Pageable pageable, String keyword, String standard, String order, Long lastId) {

List<OrderSpecifier<?>> orderSpecifiers = getAllOrderSpecifiers(pageable);
List<OrderSpecifier<?>> orderSpecifiers = getAllOrderSpecifiersByPageable(pageable);

List<Store> storeList = queryFactory.selectFrom(store)
.where(
Expand Down Expand Up @@ -71,6 +73,19 @@ public Slice<StoreDetailResponseDto> searchByKeywordOrderBySort(User user, Pagea
return new SliceImpl<>(dtoList, pageable, hasNext);
}

@Override
public List<Store> searchByNameOrderBySort(User user, Pageable pageable, String keyword, String standard, String order) {

List<OrderSpecifier<?>> 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);
Expand Down Expand Up @@ -125,7 +140,7 @@ private BooleanExpression containsKeyword(String keyword) {
return store.name.contains(keyword);
}

private List<OrderSpecifier<?>> getAllOrderSpecifiers(Pageable pageable) {
private List<OrderSpecifier<?>> getAllOrderSpecifiersByPageable(Pageable pageable) {

List<OrderSpecifier<?>> orderSpecifierList = new ArrayList<>();

Expand Down
41 changes: 29 additions & 12 deletions src/main/java/com/kusitms/jipbap/store/StoreService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -53,14 +51,12 @@ public StoreDto registerStore(String email, RegisterStoreRequestDto dto, List<Mu
}

//이미지가 null이 아닌 경우 s3 업로드
if(image != null && image.size() != 0) {
for(int i=0; i<3; i++) {
if(image.get(i)!=null) {
try {
imageUri[i] = S3Utils.saveFile(amazonS3, bucket, image.get(i));
} catch (IOException e) {
throw new S3RegisterFailureException("가게 이미지 저장 중 오류가 발생했습니다.");
}
if(image != null) {
for(int i=0; i<image.size(); i++) {
try {
imageUri[i] = S3Utils.saveFile(amazonS3, bucket, image.get(i));
} catch (IOException e) {
throw new S3RegisterFailureException("가게 이미지 저장 중 오류가 발생했습니다.");
}
}
}
Expand Down Expand Up @@ -104,6 +100,27 @@ public Slice<StoreDetailResponseDto> 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<StoreDetailResponseDto> 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<FoodDto> 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("유저 정보가 존재하지 않습니다."));
Expand Down
Original file line number Diff line number Diff line change
@@ -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<StoreDetailResponseDto> stores;
private List<FoodDto> foods;
}
Loading