diff --git a/src/main/java/com/cvsgo/dto/product/ReadProductRequestDto.java b/src/main/java/com/cvsgo/dto/product/ReadProductRequestDto.java index 3b7cd83a..b7e36bd3 100644 --- a/src/main/java/com/cvsgo/dto/product/ReadProductRequestDto.java +++ b/src/main/java/com/cvsgo/dto/product/ReadProductRequestDto.java @@ -1,22 +1,20 @@ package com.cvsgo.dto.product; import com.cvsgo.entity.EventType; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; import java.util.List; import lombok.Getter; @Getter public class ReadProductRequestDto { - @Enumerated(EnumType.STRING) private final ProductSortBy sortBy; + private Boolean isEvent; + private List convenienceStoreIds; private List categoryIds; - @Enumerated(EnumType.STRING) private List eventTypes; private Integer lowestPrice; @@ -25,10 +23,11 @@ public class ReadProductRequestDto { private String keyword; - public ReadProductRequestDto(ProductSortBy sortBy, List convenienceStoreIds, - List categoryIds, List eventTypes, Integer lowestPrice, - Integer highestPrice, String keyword) { + public ReadProductRequestDto(ProductSortBy sortBy, Boolean isEvent, + List convenienceStoreIds, List categoryIds, List eventTypes, + Integer lowestPrice, Integer highestPrice, String keyword) { this.sortBy = sortBy; + this.isEvent = isEvent; this.convenienceStoreIds = convenienceStoreIds; this.categoryIds = categoryIds; this.eventTypes = eventTypes; diff --git a/src/main/java/com/cvsgo/repository/ProductCustomRepositoryImpl.java b/src/main/java/com/cvsgo/repository/ProductCustomRepositoryImpl.java index c0ed4f71..b08ab762 100644 --- a/src/main/java/com/cvsgo/repository/ProductCustomRepositoryImpl.java +++ b/src/main/java/com/cvsgo/repository/ProductCustomRepositoryImpl.java @@ -71,6 +71,7 @@ public List findAllByFilter(User loginUser, .from(sellAt) .leftJoin(event).on(sellAt.product.eq(event.product)) .where( + isEvent(searchFilter.getIsEvent()), convenienceStoreEq(searchFilter.getConvenienceStoreIds()), eventTypeEq(searchFilter.getEventTypes()), categoryEq(searchFilter.getCategoryIds()), @@ -99,6 +100,7 @@ public Long countByFilter(ReadProductRequestDto searchFilter) { .from(sellAt) .leftJoin(event).on(sellAt.product.eq(event.product)) .where( + isEvent(searchFilter.getIsEvent()), convenienceStoreEq(searchFilter.getConvenienceStoreIds()), eventTypeEq(searchFilter.getEventTypes()), categoryEq(searchFilter.getCategoryIds()), @@ -349,6 +351,10 @@ private BooleanExpression priceGreaterOrEqual(Integer lowestPrice) { return lowestPrice != null ? product.price.goe(lowestPrice) : null; } + private BooleanExpression isEvent(Boolean isEvent) { + return isEvent != null && isEvent ? event.product.isNotNull() : null; + } + private BooleanBuilder searchKeyword(String keyword, StringExpression productAndManufacturerName) { BooleanBuilder builder = new BooleanBuilder(); diff --git a/src/test/java/com/cvsgo/controller/ProductControllerTest.java b/src/test/java/com/cvsgo/controller/ProductControllerTest.java index 8968667d..77394d41 100644 --- a/src/test/java/com/cvsgo/controller/ProductControllerTest.java +++ b/src/test/java/com/cvsgo/controller/ProductControllerTest.java @@ -106,7 +106,7 @@ void setup(WebApplicationContext webApplicationContext, @Test @DisplayName("상품 목록을 정상적으로 조회하면 HTTP 200을 응답한다") void respond_200_when_read_product_list_successfully() throws Exception { - ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.SCORE, + ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.SCORE, false, List.of(1L), List.of(1L), List.of(EventType.BOGO), 0, 10000, "500"); Page responseDto = new PageImpl<>(getProductsResponse()); @@ -122,6 +122,7 @@ void respond_200_when_read_product_list_successfully() throws Exception { getDocumentResponse(), requestFields( fieldWithPath("sortBy").type(JsonFieldType.STRING).description("정렬 기준").optional(), + fieldWithPath("isEvent").type(JsonFieldType.BOOLEAN).description("행사 상품만 조회할지 여부"), fieldWithPath("convenienceStoreIds").type(JsonFieldType.ARRAY).description("편의점 ID 리스트"), fieldWithPath("categoryIds").type(JsonFieldType.ARRAY).description("제품 카테고리 ID 리스트"), fieldWithPath("eventTypes").type(JsonFieldType.ARRAY).description("이벤트타입 리스트"), diff --git a/src/test/java/com/cvsgo/repository/ProductRepositoryTest.java b/src/test/java/com/cvsgo/repository/ProductRepositoryTest.java index 43b7e945..c27f6da3 100644 --- a/src/test/java/com/cvsgo/repository/ProductRepositoryTest.java +++ b/src/test/java/com/cvsgo/repository/ProductRepositoryTest.java @@ -69,19 +69,6 @@ class ProductRepositoryTest { @Autowired ProductBookmarkRepository productBookmarkRepository; - User user1; - User user2; - Category category1; - Category category2; - Product product1; - Product product2; - BogoEvent bogoEvent; - BtgoEvent btgoEvent; - DiscountEvent discountEvent; - Review review1; - Review review2; - Review review3; - @BeforeEach void initData() { user1 = User.create("abc@naver.com", "password1!", "닉네임", new ArrayList<>()); @@ -108,14 +95,19 @@ void initData() { .category(category1) .manufacturer(manufacturer) .build(); - product2 = Product.builder() .name("상품2") .price(5000) .category(category1) .manufacturer(manufacturer) .build(); - productRepository.saveAll(List.of(product1, product2)); + product3 = Product.builder() + .name("이벤트 안하는 상품") + .price(500) + .category(category1) + .manufacturer(manufacturer) + .build(); + productRepository.saveAll(List.of(product1, product2, product3)); ConvenienceStore cvs = ConvenienceStore.builder() .name("GS25") @@ -200,7 +192,7 @@ void succeed_to_find_first_by_order_by_price_desc() { @DisplayName("상품 목록을 조회한다") void succeed_to_find_all_by_filter() { // given - ReadProductRequestDto request = new ReadProductRequestDto(null, null, + ReadProductRequestDto request = new ReadProductRequestDto(null, false, null, null, null, 0, 1000, null); ReadProductQueryDto productResponse1 = new ReadProductQueryDto(product1.getId(), @@ -226,7 +218,7 @@ void succeed_to_find_all_by_filter() { @Test @DisplayName("랭킹 내림차순으로 정렬하여 특정 상품을 조회하면 첫번째 상품 랭킹이 마지막 상품 랭킹보다 크거나 같아야 한다") void score_of_first_product_should_greater_than_or_equal_to_score_of_last_product_when_sorted_by_score_descending_order() { - ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.SCORE, null, + ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.SCORE, false, null, null, null, 0, 10000, null); List foundProducts = productRepository.findAllByFilter(user1, request, @@ -239,7 +231,7 @@ void score_of_first_product_should_greater_than_or_equal_to_score_of_last_produc @Test @DisplayName("별점 내림차순으로 정렬하여 특정 상품을 조회하면 첫번째 상품 평균 별점이 마지막 상품 평균 별점보다 크거나 같아야 한다") void rating_of_first_product_should_greater_than_or_equal_to_rating_of_last_product_when_sorted_by_rating_descending_order() { - ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.RATING, null, + ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.RATING, false, null, null, null, 0, 1000, null); List foundProducts = productRepository.findAllByFilter(user1, request, @@ -252,7 +244,7 @@ void rating_of_first_product_should_greater_than_or_equal_to_rating_of_last_prod @Test @DisplayName("리뷰순으로 정렬하여 특정 상품을 조회하면 첫번째 상품의 리뷰 개수가 마지막 상품의 리뷰 개수보다 크거나 같아야 한다") void review_count_of_first_product_should_greater_than_or_equal_to_review_count_of_last_product_when_sorted_by_review_count_descending_order() { - ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.REVIEW_COUNT, null, + ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.REVIEW_COUNT, false, null, null, null, 0, 1000, null); List foundProducts = productRepository.findAllByFilter(user1, request, @@ -262,11 +254,28 @@ void review_count_of_first_product_should_greater_than_or_equal_to_review_count_ foundProducts.get(foundProducts.size() - 1).getReviewCount()); } + @Test + @DisplayName("이벤트 여부 필터를 적용하면 행사 상품만 조회된다 ") + void succeed_to_find_product_by_is_event_filter() { + ReadProductRequestDto request = new ReadProductRequestDto(null, false, null, + null, null, 0, 10000, null); + + List foundProducts = productRepository.findAllByFilter(user1, request, + PageRequest.of(0, 20)); + + assertThat(foundProducts).hasSize(2); + List foundProductIds = foundProducts.stream().map(ReadProductQueryDto::getProductId) + .toList(); + assertThat(product1.getId()).isIn(foundProductIds); + assertThat(product2.getId()).isIn(foundProductIds); + assertThat(product3.getId()).isNotIn(foundProductIds); + } + @Test @DisplayName("카테고리 필터를 적용하여 특정 상품을 조회하면 해당하는 상품들만 조회된다 ") void succeed_to_find_product_by_category_filter() { Long categoryId = category1.getId(); - ReadProductRequestDto request = new ReadProductRequestDto(null, null, + ReadProductRequestDto request = new ReadProductRequestDto(null, false, null, List.of(categoryId), null, 0, 1000, null); List foundProducts = productRepository.findAllByFilter(user1, request, @@ -280,7 +289,7 @@ void succeed_to_find_product_by_category_filter() { @DisplayName("이벤트 타입 필터를 적용하여 특정 상품을 조회하면 해당하는 상품들만 조회된다 ") void succeed_to_find_product_by_event_type_filter() { EventType eventType = EventType.BOGO; - ReadProductRequestDto request = new ReadProductRequestDto(null, null, + ReadProductRequestDto request = new ReadProductRequestDto(null, false, null, null, List.of(eventType), 0, 1000, null); List foundProducts = productRepository.findAllByFilter(user1, request, @@ -293,7 +302,7 @@ void succeed_to_find_product_by_event_type_filter() { @DisplayName("키워드를 입력하여 특정 상품을 조회하면 해당하는 상품들만 조회된다 ") void succeed_to_find_product_by_keyword_filter() { String keyword = "상품1"; - ReadProductRequestDto request = new ReadProductRequestDto(null, null, + ReadProductRequestDto request = new ReadProductRequestDto(null, false, null, null, null, 0, 1000, keyword); List foundProducts = productRepository.findAllByFilter(user1, request, @@ -306,7 +315,7 @@ void succeed_to_find_product_by_keyword_filter() { @DisplayName("상품 목록 요소의 전체 개수를 조회한다") void succeed_to_count_by_filter() { // given - ReadProductRequestDto request = new ReadProductRequestDto(null, null, + ReadProductRequestDto request = new ReadProductRequestDto(null, false, null, null, null, 0, 1000, null); // when @@ -448,4 +457,18 @@ void succeed_to_find_convenience_store_events_by_product_id() { foundProducts.stream().map(ConvenienceStoreEventQueryDto::getEvent).toList()); } + User user1; + User user2; + Category category1; + Category category2; + Product product1; + Product product2; + Product product3; + BogoEvent bogoEvent; + BtgoEvent btgoEvent; + DiscountEvent discountEvent; + Review review1; + Review review2; + Review review3; + } \ No newline at end of file diff --git a/src/test/java/com/cvsgo/service/ProductServiceTest.java b/src/test/java/com/cvsgo/service/ProductServiceTest.java index c1752cd9..1526014d 100644 --- a/src/test/java/com/cvsgo/service/ProductServiceTest.java +++ b/src/test/java/com/cvsgo/service/ProductServiceTest.java @@ -76,7 +76,7 @@ class ProductServiceTest { @DisplayName("상품 목록을 정상적으로 조회한다") void succeed_to_read_product_list() { Pageable pageable = PageRequest.of(0, 20); - ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.SCORE, + ReadProductRequestDto request = new ReadProductRequestDto(ProductSortBy.SCORE, false, List.of(1L), List.of(1L), List.of(EventType.BOGO), 0, 10000, null); given(productRepository.findAllByFilter(any(), any(), any())).willReturn(getProductList());