From 5d9d9ede8e4b7a88c9b81d127c7d0d2ca60f5e67 Mon Sep 17 00:00:00 2001 From: Sangdon Park Date: Wed, 7 Aug 2024 01:53:08 +0900 Subject: [PATCH] feat: search API on admin page (#129) * feature: Search by userId * feat: add date filter to clothing sales status * fix: search API on admin page * fix: merge methods --- .../api/ClothingSalesController.java | 10 ++++--- .../repository/ClothingSalesRepository.java | 3 ++ .../service/ClothingSalesService.java | 30 +++++++++++++------ .../repository/ProductRepositoryCustom.java | 2 +- .../repository/ProductRepositoryImpl.java | 11 +++++-- .../repick/global/page/DateCondition.java | 14 +++++++++ 6 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/example/repick/global/page/DateCondition.java diff --git a/src/main/java/com/example/repick/domain/clothingSales/api/ClothingSalesController.java b/src/main/java/com/example/repick/domain/clothingSales/api/ClothingSalesController.java index df38459b..2b4a850d 100644 --- a/src/main/java/com/example/repick/domain/clothingSales/api/ClothingSalesController.java +++ b/src/main/java/com/example/repick/domain/clothingSales/api/ClothingSalesController.java @@ -5,6 +5,7 @@ import com.example.repick.domain.clothingSales.service.BoxService; import com.example.repick.domain.clothingSales.service.ClothingSalesService; import com.example.repick.domain.product.entity.ProductStateType; +import com.example.repick.global.page.DateCondition; import com.example.repick.global.page.PageCondition; import com.example.repick.global.page.PageResponse; import com.example.repick.global.response.SuccessResponse; @@ -105,8 +106,8 @@ public SuccessResponse updateProductPrice(@RequestBody List>> getClothingSalesStatus(@ParameterObject PageCondition pageCondition) { - return SuccessResponse.success(clothingSalesService.getClothingSalesInformation(pageCondition)); + public SuccessResponse>> getClothingSalesStatus(@ParameterObject PageCondition pageCondition, @ParameterObject DateCondition dateCondition) { + return SuccessResponse.success(clothingSalesService.getClothingSalesInformation(pageCondition, dateCondition)); } @Operation(summary = "옷장 정리 상태 업데이트") @@ -117,8 +118,9 @@ public SuccessResponse updateClothingSalesStatus(@RequestBody PostCloth @Operation(summary = "상품 종합 현황") @GetMapping("/product-count") - public SuccessResponse>> getClothingSalesProductCount(@ParameterObject PageCondition pageCondition) { - return SuccessResponse.success(clothingSalesService.getClothingSalesProductCount(pageCondition)); + public SuccessResponse>> getClothingSalesProductCount(@RequestParam(required = false) Long userId, + @ParameterObject PageCondition pageCondition) { + return SuccessResponse.success(clothingSalesService.getClothingSalesProductCount(userId, pageCondition)); } @Operation(summary = "유저 상품 현황") diff --git a/src/main/java/com/example/repick/domain/clothingSales/repository/ClothingSalesRepository.java b/src/main/java/com/example/repick/domain/clothingSales/repository/ClothingSalesRepository.java index 4bca7071..ec0cc522 100644 --- a/src/main/java/com/example/repick/domain/clothingSales/repository/ClothingSalesRepository.java +++ b/src/main/java/com/example/repick/domain/clothingSales/repository/ClothingSalesRepository.java @@ -7,12 +7,15 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; public interface ClothingSalesRepository extends JpaRepository { Page findAllByOrderByCreatedDateDesc(Pageable pageable); List findByUserAndClothingSalesState(User user, ClothingSalesStateType clothingSalesStateType); + Page findByCreatedDateBetweenOrderByCreatedDateDesc(LocalDateTime startDate, LocalDateTime endDate, Pageable pageable); List findByUserOrderByCreatedDateDesc(User user); Optional findByUserAndClothingSalesCount(User user, Integer clothingSalesCount); int countByUser(User user); diff --git a/src/main/java/com/example/repick/domain/clothingSales/service/ClothingSalesService.java b/src/main/java/com/example/repick/domain/clothingSales/service/ClothingSalesService.java index 95c229c5..438212d6 100644 --- a/src/main/java/com/example/repick/domain/clothingSales/service/ClothingSalesService.java +++ b/src/main/java/com/example/repick/domain/clothingSales/service/ClothingSalesService.java @@ -4,7 +4,6 @@ import com.example.repick.domain.clothingSales.entity.ClothingSales; import com.example.repick.domain.clothingSales.entity.ClothingSalesState; import com.example.repick.domain.clothingSales.entity.ClothingSalesStateType; -import com.example.repick.domain.clothingSales.repository.BagCollectRepository; import com.example.repick.domain.clothingSales.repository.ClothingSalesRepository; import com.example.repick.domain.clothingSales.repository.ClothingSalesStateRepository; import com.example.repick.domain.clothingSales.validator.ClothingSalesValidator; @@ -17,6 +16,7 @@ import com.example.repick.domain.user.entity.User; import com.example.repick.domain.user.repository.UserRepository; import com.example.repick.global.error.exception.CustomException; +import com.example.repick.global.page.DateCondition; import com.example.repick.global.page.PageCondition; import com.example.repick.global.page.PageResponse; import lombok.RequiredArgsConstructor; @@ -24,13 +24,14 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - +import java.time.LocalTime; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static com.example.repick.global.error.exception.ErrorCode.*; @@ -172,11 +173,23 @@ private ProductQuantityCounter countProductQuantity(List> getClothingSalesInformation(PageCondition pageCondition){ - // 수거 신청 정보 조회 - Page clothingSalesPage = clothingSalesRepository.findAllByOrderByCreatedDateDesc(pageCondition.toPageable()); + public PageResponse> getClothingSalesInformation(PageCondition PageCondition, DateCondition dateCondition) {Page clothingSalesPage; + if (dateCondition.hasValidDateRange()) { + // 날짜 범위에 맞는 데이터 페이징 처리 + LocalDateTime startDateTime = dateCondition.startDate().atStartOfDay(); // 시작일의 자정 + LocalDateTime endDateTime = dateCondition.endDate().atTime(LocalTime.MAX); // 종료일의 마지막 시간 + clothingSalesPage = clothingSalesRepository.findByCreatedDateBetweenOrderByCreatedDateDesc( + startDateTime, endDateTime, PageCondition.toPageable() + ); + } else { + // 날짜 조건이 없으면 전체 데이터 페이징 처리 + clothingSalesPage = clothingSalesRepository.findAllByOrderByCreatedDateDesc(PageCondition.toPageable()); + } + List clothingSalesList = clothingSalesPage.stream() - .map(GetClothingSales::of).toList(); + .map(GetClothingSales::of) + .collect(Collectors.toList()); + // 페이지 응답 반환 return PageResponse.of(clothingSalesList, clothingSalesPage.getTotalPages(), clothingSalesPage.getTotalElements()); } @@ -196,10 +209,9 @@ public Boolean updateClothingSalesState(PostClothingSalesState postClothingSales } @Transactional - public PageResponse> getClothingSalesProductCount(PageCondition pageCondition) { - Page pages = productRepository.getClothingSalesProductCount(pageCondition.toPageable()); + public PageResponse> getClothingSalesProductCount(Long userId, PageCondition pageCondition) { + Page pages = productRepository.getClothingSalesProductCount(pageCondition.toPageable(), userId); return PageResponse.of(pages.getContent(), pages.getTotalPages(), pages.getTotalElements()); - } @Transactional diff --git a/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryCustom.java b/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryCustom.java index 3b343fca..5672c438 100644 --- a/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryCustom.java +++ b/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryCustom.java @@ -50,7 +50,7 @@ Page findHighestDiscountProducts( List findRecommendation(Long userId); - Page getClothingSalesProductCount(Pageable pageable); + Page getClothingSalesProductCount(Pageable pageable, Long userId); Page getClothingSalesPendingProduct(Long clothingSalesId, ProductStateType productStateType, Pageable pageable); diff --git a/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryImpl.java b/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryImpl.java index 6e8fb273..c6b1029f 100644 --- a/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryImpl.java +++ b/src/main/java/com/example/repick/domain/product/repository/ProductRepositoryImpl.java @@ -378,7 +378,7 @@ public List findRecommendation(Long userId) { } @Override - public Page getClothingSalesProductCount(Pageable pageable) { + public Page getClothingSalesProductCount(Pageable pageable, Long userId) { JPAQuery query = jpaQueryFactory .select(Projections.constructor(GetClothingSalesProductCount.class, product.user.id.stringValue().concat("-").concat(product.clothingSalesCount.stringValue()), @@ -395,9 +395,16 @@ public Page getClothingSalesProductCount(Pageable )) .from(product) .leftJoin(clothingSales).on(product.clothingSales.id.eq(clothingSales.id)) - .groupBy(product.user.id, product.clothingSalesCount) + .groupBy( + product.clothingSales.id + ) + .orderBy(clothingSales.createdDate.max().desc()); + if (userId != null) { + query.where(product.user.id.eq(userId)); + } + long total = query.stream().count(); List content = query .offset(pageable.getOffset()) diff --git a/src/main/java/com/example/repick/global/page/DateCondition.java b/src/main/java/com/example/repick/global/page/DateCondition.java new file mode 100644 index 00000000..7752cad0 --- /dev/null +++ b/src/main/java/com/example/repick/global/page/DateCondition.java @@ -0,0 +1,14 @@ +package com.example.repick.global.page; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDate; + +public record DateCondition( + @Schema(description = "검색 시작 날짜", nullable = true) LocalDate startDate, + @Schema(description = "검색 종료 날짜", nullable = true) LocalDate endDate +) { + public boolean hasValidDateRange() { + return startDate != null && endDate != null && !startDate.isAfter(endDate); + } +}