From a841215032c0f20cb247f81ac0869e8be8a7ae77 Mon Sep 17 00:00:00 2001 From: GeonWoo Date: Wed, 14 Feb 2024 15:30:59 +0900 Subject: [PATCH] =?UTF-8?q?Fix:=20=EC=8B=A0=EC=83=81=ED=92=88=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20=EC=B5=9C=EC=8B=A0=EC=88=9C=20=EC=9D=B8=EA=B8=B0?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=A1=B0=ED=9A=8C=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EB=88=84=EB=9D=BD=20=EC=97=86=EC=9D=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B0=80=EB=8A=A5=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=EB=A7=81=20=ED=95=A0=EC=9D=B8=EA=B0=80=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=A1=B0=ED=9A=8C=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EB=B3=84=20=EB=A6=AC=EB=B7=B0=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9D=BC=20=EA=B8=B0=EC=A4=80=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dpang/item/controller/ItemController.java | 4 +- .../item/controller/ReviewController.java | 5 +- .../dpang/item/repository/ItemRepository.java | 3 +- .../dpang/item/service/ItemServiceImpl.java | 58 +++++++++++-------- .../dpang/item/service/ReviewServiceImpl.java | 6 ++ 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/main/java/kea/dpang/item/controller/ItemController.java b/src/main/java/kea/dpang/item/controller/ItemController.java index 3885a95..c241435 100644 --- a/src/main/java/kea/dpang/item/controller/ItemController.java +++ b/src/main/java/kea/dpang/item/controller/ItemController.java @@ -130,7 +130,7 @@ public ResponseEntity>> getPopularItems(Page } @GetMapping("/new/list") - @Operation(summary = "신제품 리스트 조회", description = "최신 상품 정보를 페이지 정보에 따라 조회합니다.") + @Operation(summary = "신상품 리스트 조회", description = "최신 상품 정보를 페이지 정보에 따라 조회합니다.") public ResponseEntity>> getNewItems(Pageable pageable) { List newItems = itemService.getNewItems(pageable); return new ResponseEntity<>( @@ -164,7 +164,6 @@ public ResponseEntity deleteItem( ); } - @PutMapping("/stock") @Operation(summary = "재고 수량 변경", description = "(백엔드) 재고 수량을 변경합니다.") public ResponseEntity changeStock( @@ -178,7 +177,6 @@ public ResponseEntity changeStock( ); } - @PutMapping("/eventDiscount") @Operation(summary = "이벤트 할인 반영", description = "(백엔드) 상품에 이벤트에서 발생하는 할인을 반영합니다.") public ResponseEntity updateEventDiscounts( diff --git a/src/main/java/kea/dpang/item/controller/ReviewController.java b/src/main/java/kea/dpang/item/controller/ReviewController.java index 175a007..1ee4ff9 100644 --- a/src/main/java/kea/dpang/item/controller/ReviewController.java +++ b/src/main/java/kea/dpang/item/controller/ReviewController.java @@ -3,13 +3,16 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; + import kea.dpang.item.base.BaseResponse; import kea.dpang.item.base.SuccessResponse; import kea.dpang.item.dto.review.CreateReviewRequestDto; import kea.dpang.item.dto.review.PersonalReviewDto; import kea.dpang.item.service.ReviewService; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -37,7 +40,7 @@ public ResponseEntity createReview(@RequestBody CreateReviewReques ); } - @GetMapping("/reviewers/{reviewerId}/reviews") + @GetMapping("/{reviewerId}/list") @Operation(summary = "사용자별 리뷰 리스트 조회", description = "사용자 정보에 따라 리뷰 리스트를 조회합니다.") public ResponseEntity>> getReviewPersonalList( @PathVariable @Parameter(description = "리뷰 작성자 ID", example = "1") Long reviewerId, diff --git a/src/main/java/kea/dpang/item/repository/ItemRepository.java b/src/main/java/kea/dpang/item/repository/ItemRepository.java index 0225c7e..d1c52fe 100644 --- a/src/main/java/kea/dpang/item/repository/ItemRepository.java +++ b/src/main/java/kea/dpang/item/repository/ItemRepository.java @@ -19,7 +19,6 @@ public interface ItemRepository extends JpaRepository, JpaSpecificat List findAllByEventId(Long eventId); - List findByOrderByCreatedTime(Pageable pageable); + List findBy(Pageable pageable); } - diff --git a/src/main/java/kea/dpang/item/service/ItemServiceImpl.java b/src/main/java/kea/dpang/item/service/ItemServiceImpl.java index 91be5ba..3143cbf 100644 --- a/src/main/java/kea/dpang/item/service/ItemServiceImpl.java +++ b/src/main/java/kea/dpang/item/service/ItemServiceImpl.java @@ -13,7 +13,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ZSetOperations; @@ -88,28 +90,34 @@ public ItemDto getItemInfo(Long itemId) { @Transactional(readOnly = true) public List getPopularItems(Pageable pageable) { // Redis에서 조회수를 기반으로 인기 상품 ID와 점수를 가져옴 - Set> items = redisTemplate.opsForZSet() - .reverseRangeWithScores(ITEM_VIEW_COUNT_KEY, pageable.getOffset(), pageable.getOffset() + pageable.getPageSize() - 1); - - // 가져온 데이터를 PopularItemDto 리스트로 변환 + int count = 0; + int redisOffset = 0; List popularItems = new ArrayList<>(); - for (ZSetOperations.TypedTuple item : items) { - Long itemId = Long.valueOf(item.getValue()); - try { - Item foundItem = itemRepository.findById(itemId) - .orElseThrow(() -> new ItemNotFoundException(itemId)); - - // 판매자 이름을 가져옴 - ResponseEntity> sellerResponse = sellerServiceFeignClient.getSeller(foundItem.getSellerId()); - SellerDto seller = sellerResponse.getBody().getData(); - String sellerName = seller.getName(); - - popularItems.add(new ItemDetailDto(foundItem, sellerName)); - } catch (ItemNotFoundException e) { - log.error("상품을 찾을 수 없습니다. 상품 ID: {}", itemId, e); - // 상품을 찾을 수 없는 경우, 다음 상품으로 넘어감. - continue; + while (count < pageable.getPageSize()) { + Set> items = redisTemplate.opsForZSet() + .reverseRangeWithScores(ITEM_VIEW_COUNT_KEY, redisOffset, redisOffset + pageable.getPageSize() - 1); + + for (ZSetOperations.TypedTuple item : items) { + Long itemId = Long.valueOf(item.getValue()); + try { + Item foundItem = itemRepository.findById(itemId) + .orElseThrow(() -> new ItemNotFoundException(itemId)); + + // 판매자 이름을 가져옴 + ResponseEntity> sellerResponse = sellerServiceFeignClient.getSeller(foundItem.getSellerId()); + SellerDto seller = sellerResponse.getBody().getData(); + String sellerName = seller.getName(); + + popularItems.add(new ItemDetailDto(foundItem, sellerName)); + count++; + if (count >= pageable.getPageSize()) { + break; + } + } catch (ItemNotFoundException e) { + log.error("상품을 찾을 수 없습니다. 상품 ID: {}", itemId, e); + } } + redisOffset += pageable.getPageSize(); } return popularItems; } @@ -123,8 +131,9 @@ public void incrementViewCount(Long itemId) { // 신상품 조회 @Override public List getNewItems(Pageable pageable) { - log.info("신제품 리스트 조회를 시작합니다."); - return itemRepository.findByOrderByCreatedTime(pageable) + log.info("신상품 리스트 조회를 시작합니다."); + Pageable sortedByCreatedTimeDesc = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by("createdTime").descending()); + return itemRepository.findBy(sortedByCreatedTimeDesc) .stream() .map(ItemDto::new) .toList(); @@ -152,6 +161,7 @@ public ItemDetailDto getItemDetailInfo(Long itemId) { return new ItemDetailDto(item, sellerName); } + // 상품 리스트 조회 @Override public Page getItemList(Category category, SubCategory subCategory, Double minPrice, Double maxPrice, String keyword, Long sellerId, Pageable pageable) { log.info("상품 리스트 조회를 시작합니다 : 카테고리 = {}, 서브카테고리 = {}, 판매자ID = {}, 최소가격 = {}, 최대가격 = {}, 키워드 = {}, 페이지 요청 정보 = {}", category, subCategory, sellerId, minPrice, maxPrice, keyword, pageable); @@ -185,11 +195,11 @@ public Page filterItems(Category category, SubCategory subCategory, Long s } if (minPrice != null) { - spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.greaterThanOrEqualTo(root.get("price"), minPrice)); + spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.greaterThanOrEqualTo(root.get("discountPrice"), minPrice)); } if (maxPrice != null) { - spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.lessThanOrEqualTo(root.get("price"), maxPrice)); + spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.lessThanOrEqualTo(root.get("discountPrice"), maxPrice)); } if (keyword != null && !keyword.isEmpty()) { diff --git a/src/main/java/kea/dpang/item/service/ReviewServiceImpl.java b/src/main/java/kea/dpang/item/service/ReviewServiceImpl.java index c034538..decc508 100644 --- a/src/main/java/kea/dpang/item/service/ReviewServiceImpl.java +++ b/src/main/java/kea/dpang/item/service/ReviewServiceImpl.java @@ -14,7 +14,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -52,6 +54,9 @@ public void createReview(CreateReviewRequestDto dto) { @Override @Transactional public List getReviewList(Long itemId, Pageable pageable) { + // 정렬 조건 추가 + Sort sort = Sort.by(Sort.Direction.DESC, "createdTime"); + pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort); Page reviews = reviewRepository.findByItemId(itemId, pageable); @@ -74,6 +79,7 @@ public List getReviewList(Long itemId, Pageable pageable) { }).toList(); } + // 사용자별 리뷰 리스트 조회 @Override @Transactional