From 7546f982cf823d04684b44f343576aa4159ca3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:57:59 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=B6=9C=20=ED=86=B5?= =?UTF-8?q?=EA=B3=84=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20#225?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryMonthlySalesResponse.java | 20 ------ .../response/StoreMonthlySalesResponse.java | 10 --- .../poomasi/domain/image/entity/Image.java | 2 + .../domain/order/entity/OrderedProduct.java | 12 +++- .../domain/order/service/OrderService.java | 5 -- .../controller/StatisticsController.java | 17 ++--- .../CategoryMonthlySalesResponse.java | 11 +++ .../response/StoreMonthlySalesResponse.java | 9 +++ .../statistics/service/StatisticsService.java | 72 ++++++++----------- .../domain/store/dto/StoreResponse.java | 5 +- 10 files changed, 75 insertions(+), 88 deletions(-) delete mode 100644 src/main/java/poomasi/domain/admin/statistics/dto/response/CategoryMonthlySalesResponse.java delete mode 100644 src/main/java/poomasi/domain/admin/statistics/dto/response/StoreMonthlySalesResponse.java rename src/main/java/poomasi/domain/{admin => }/statistics/controller/StatisticsController.java (73%) create mode 100644 src/main/java/poomasi/domain/statistics/dto/response/CategoryMonthlySalesResponse.java create mode 100644 src/main/java/poomasi/domain/statistics/dto/response/StoreMonthlySalesResponse.java rename src/main/java/poomasi/domain/{admin => }/statistics/service/StatisticsService.java (50%) diff --git a/src/main/java/poomasi/domain/admin/statistics/dto/response/CategoryMonthlySalesResponse.java b/src/main/java/poomasi/domain/admin/statistics/dto/response/CategoryMonthlySalesResponse.java deleted file mode 100644 index 778719a1..00000000 --- a/src/main/java/poomasi/domain/admin/statistics/dto/response/CategoryMonthlySalesResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package poomasi.domain.admin.statistics.dto.response; - -import lombok.Getter; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -public class CategoryMonthlySalesResponse { - private String categoryName; - private int count; - private BigDecimal totalSales; - - public CategoryMonthlySalesResponse(String categoryName, int count, BigDecimal totalSales) { - this.categoryName = categoryName; - this.count = count; - this.totalSales = totalSales; - } -} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/admin/statistics/dto/response/StoreMonthlySalesResponse.java b/src/main/java/poomasi/domain/admin/statistics/dto/response/StoreMonthlySalesResponse.java deleted file mode 100644 index b1b40165..00000000 --- a/src/main/java/poomasi/domain/admin/statistics/dto/response/StoreMonthlySalesResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package poomasi.domain.admin.statistics.dto.response; - -import poomasi.domain.store.entity.Store; - -import java.math.BigDecimal; - -public record StoreMonthlySalesResponse( - Store store, - BigDecimal totalSales -) {} diff --git a/src/main/java/poomasi/domain/image/entity/Image.java b/src/main/java/poomasi/domain/image/entity/Image.java index 1b0d2318..b1a02321 100644 --- a/src/main/java/poomasi/domain/image/entity/Image.java +++ b/src/main/java/poomasi/domain/image/entity/Image.java @@ -1,5 +1,6 @@ package poomasi.domain.image.entity; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; @@ -17,6 +18,7 @@ @Setter @NoArgsConstructor @SQLDelete(sql = "UPDATE image SET deleted_at = current_timestamp WHERE id = ?") +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) public class Image { @Id diff --git a/src/main/java/poomasi/domain/order/entity/OrderedProduct.java b/src/main/java/poomasi/domain/order/entity/OrderedProduct.java index c4052446..7446df35 100644 --- a/src/main/java/poomasi/domain/order/entity/OrderedProduct.java +++ b/src/main/java/poomasi/domain/order/entity/OrderedProduct.java @@ -15,6 +15,8 @@ import jakarta.persistence.Table; import java.math.BigDecimal; +import java.time.Month; + import jdk.jfr.Description; import lombok.Builder; import lombok.Getter; @@ -159,8 +161,16 @@ public Store getStore() { return getProduct().getStore(); } - public Long getStoreId(){ + public Long getStoreId() { return getStore().getId(); } + + public Long getCategoryId() { + return getProduct().getCategoryId(); + } + + public Month getUpdateMonth() { + return getOrder().getUpdateAt().getMonth(); + } } diff --git a/src/main/java/poomasi/domain/order/service/OrderService.java b/src/main/java/poomasi/domain/order/service/OrderService.java index 93ce7d53..7300cc1d 100644 --- a/src/main/java/poomasi/domain/order/service/OrderService.java +++ b/src/main/java/poomasi/domain/order/service/OrderService.java @@ -3,15 +3,10 @@ import jdk.jfr.Description; 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.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import poomasi.domain.admin.statistics.dto.response.CategoryMonthlySalesResponse; import poomasi.domain.auth.security.userdetail.UserDetailsImpl; import poomasi.domain.member.entity.Member; import poomasi.domain.order.dto.request.PreOrderRequest; diff --git a/src/main/java/poomasi/domain/admin/statistics/controller/StatisticsController.java b/src/main/java/poomasi/domain/statistics/controller/StatisticsController.java similarity index 73% rename from src/main/java/poomasi/domain/admin/statistics/controller/StatisticsController.java rename to src/main/java/poomasi/domain/statistics/controller/StatisticsController.java index c5679770..a8ddcfcf 100644 --- a/src/main/java/poomasi/domain/admin/statistics/controller/StatisticsController.java +++ b/src/main/java/poomasi/domain/statistics/controller/StatisticsController.java @@ -1,4 +1,4 @@ -package poomasi.domain.admin.statistics.controller; +package poomasi.domain.statistics.controller; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -6,15 +6,15 @@ import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import poomasi.domain.admin.statistics.dto.response.CategoryMonthlySalesResponse; -import poomasi.domain.admin.statistics.dto.response.StoreMonthlySalesResponse; -import poomasi.domain.admin.statistics.service.StatisticsService; +import poomasi.domain.statistics.dto.response.CategoryMonthlySalesResponse; +import poomasi.domain.statistics.dto.response.StoreMonthlySalesResponse; +import poomasi.domain.statistics.service.StatisticsService; import java.time.LocalDate; @RestController @RequiredArgsConstructor -@RequestMapping("/api/admin/statistics") +@RequestMapping("/api/statistics") public class StatisticsController { private final StatisticsService statisticsService; @@ -30,13 +30,14 @@ public ResponseEntity> getMonthlyStoreSales( return ResponseEntity.ok(salesResponses); } - @GetMapping("/categories/monthly-sales") - public ResponseEntity> getCategoryMonthlySales( + @GetMapping("/stores/{storeId}/categories/six-month-sales") + public ResponseEntity> getSixMonthCategorySales( + @PathVariable Long storeId, @RequestParam String startMonth, @PageableDefault(size = 10) Pageable pageable) { LocalDate startDate = LocalDate.parse(startMonth + "-01"); - Page salesResponses = statisticsService.getCategoryMonthlySales(startDate, pageable); + Page salesResponses = statisticsService.getSixMonthCategorySales(storeId, startDate, pageable); return ResponseEntity.ok(salesResponses); } } diff --git a/src/main/java/poomasi/domain/statistics/dto/response/CategoryMonthlySalesResponse.java b/src/main/java/poomasi/domain/statistics/dto/response/CategoryMonthlySalesResponse.java new file mode 100644 index 00000000..2e5000dd --- /dev/null +++ b/src/main/java/poomasi/domain/statistics/dto/response/CategoryMonthlySalesResponse.java @@ -0,0 +1,11 @@ +package poomasi.domain.statistics.dto.response; + + +import java.math.BigDecimal; + +public record CategoryMonthlySalesResponse ( + Long storeId, + Long categoryId, + BigDecimal totalSales) { + +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/statistics/dto/response/StoreMonthlySalesResponse.java b/src/main/java/poomasi/domain/statistics/dto/response/StoreMonthlySalesResponse.java new file mode 100644 index 00000000..30ed6987 --- /dev/null +++ b/src/main/java/poomasi/domain/statistics/dto/response/StoreMonthlySalesResponse.java @@ -0,0 +1,9 @@ +package poomasi.domain.statistics.dto.response; + +import java.math.BigDecimal; + +public record StoreMonthlySalesResponse( + Long storeId, + String month, + BigDecimal totalSales +) {} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/admin/statistics/service/StatisticsService.java b/src/main/java/poomasi/domain/statistics/service/StatisticsService.java similarity index 50% rename from src/main/java/poomasi/domain/admin/statistics/service/StatisticsService.java rename to src/main/java/poomasi/domain/statistics/service/StatisticsService.java index 063dd430..ae614fce 100644 --- a/src/main/java/poomasi/domain/admin/statistics/service/StatisticsService.java +++ b/src/main/java/poomasi/domain/statistics/service/StatisticsService.java @@ -1,4 +1,4 @@ -package poomasi.domain.admin.statistics.service; +package poomasi.domain.statistics.service; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -6,23 +6,17 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import poomasi.domain.admin.statistics.dto.response.StoreMonthlySalesResponse; +import poomasi.domain.statistics.dto.response.StoreMonthlySalesResponse; import poomasi.domain.order.entity.Order; import poomasi.domain.order.entity.OrderedProduct; import poomasi.domain.order.entity.OrderedProductStatus; import poomasi.domain.order.service.OrderService; -import poomasi.domain.admin.statistics.dto.response.CategoryMonthlySalesResponse; -import poomasi.domain.product._category.entity.Category; -import poomasi.domain.product._category.service.CategoryService; -import poomasi.domain.product.entity.Product; +import poomasi.domain.statistics.dto.response.CategoryMonthlySalesResponse; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; @RequiredArgsConstructor @@ -30,7 +24,6 @@ @Service public class StatisticsService { private final OrderService orderService; - private final CategoryService categoryService; private List getDeliveredProducts(List orders) { return orders.stream() @@ -47,24 +40,6 @@ private LocalDateTime[] calculateDateRange(LocalDate startDate, int months) { }; } - private StoreMonthlySalesResponse createStoreSalesResponse(OrderedProduct orderedProduct) { - BigDecimal totalSales = orderedProduct.getPrice().multiply(BigDecimal.valueOf(orderedProduct.getCount())); - return new StoreMonthlySalesResponse(orderedProduct.getStore(), totalSales); - } - - private void updateCategorySales(Map salesMap, OrderedProduct orderedProduct) { - Product product = orderedProduct.getProduct(); - Category category = categoryService.getCategory(product.getCategoryId()); - - CategoryMonthlySalesResponse salesResponse = salesMap.computeIfAbsent(category, k -> - new CategoryMonthlySalesResponse(category.getName(), 0, BigDecimal.ZERO) - ); - - salesResponse.setCount(salesResponse.getCount() + 1); - BigDecimal productTotal = product.getPrice().multiply(BigDecimal.valueOf(orderedProduct.getCount())); - salesResponse.setTotalSales(salesResponse.getTotalSales().add(productTotal)); - } - public Page getMonthlyStoreSales(Long storeId, String startMonth, String endMonth, Pageable pageable) { LocalDate start = LocalDate.parse(startMonth + "-01"); LocalDate end = LocalDate.parse(endMonth + "-01").withDayOfMonth(LocalDate.parse(endMonth + "-01").lengthOfMonth()); @@ -73,32 +48,43 @@ public Page getMonthlyStoreSales(Long storeId, String LocalDateTime endDate = end.atTime(23, 59, 59); List orders = orderService.getOrdersByUpdateAtBetween(startDate, endDate); - List deliveredProducts = getDeliveredProducts(orders); - List salesResponses = deliveredProducts.stream() + // 월별 매출 계산 + List monthlySales = deliveredProducts.stream() .filter(orderedProduct -> orderedProduct.getStoreId().equals(storeId)) - .map(this::createStoreSalesResponse) + .collect(Collectors.groupingBy(OrderedProduct::getUpdateMonth)) + .entrySet().stream() + .map(entry -> { + BigDecimal totalSales = entry.getValue().stream() + .map(orderedProduct -> orderedProduct.getPrice().multiply(BigDecimal.valueOf(orderedProduct.getCount()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + return new StoreMonthlySalesResponse(storeId, entry.getKey().name(), totalSales); + }) .collect(Collectors.toList()); - return new PageImpl<>(salesResponses, pageable, salesResponses.size()); + return new PageImpl<>(monthlySales, pageable, monthlySales.size()); } - public Page getCategoryMonthlySales(LocalDate startDate, Pageable pageable) { + public Page getSixMonthCategorySales(Long storeId, LocalDate startDate, Pageable pageable) { LocalDateTime[] dateRange = calculateDateRange(startDate, 5); List orders = orderService.getOrdersByUpdateAtBetween(dateRange[0], dateRange[1]); - List deliveredProducts = getDeliveredProducts(orders); - Map salesMap = new HashMap<>(); - - deliveredProducts.forEach(orderedProduct -> updateCategorySales(salesMap, orderedProduct)); - - List responseList = new ArrayList<>(salesMap.values()); + List categorySales = deliveredProducts.stream() + .filter(orderedProduct -> orderedProduct.getStoreId().equals(storeId)) + .collect(Collectors.groupingBy(OrderedProduct::getCategoryId)) + .entrySet().stream() + .map(entry -> { + BigDecimal totalSales = entry.getValue().stream() + .map(orderedProduct -> orderedProduct.getPrice().multiply(BigDecimal.valueOf(orderedProduct.getCount()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + return new CategoryMonthlySalesResponse(storeId, entry.getKey(), totalSales); + }) + .collect(Collectors.toList()); - int start = (int) pageable.getOffset(); - int end = Math.min(start + pageable.getPageSize(), responseList.size()); - return new PageImpl<>(responseList.subList(start, end), pageable, responseList.size()); + return new PageImpl<>(categorySales, pageable, categorySales.size()); } -} +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/store/dto/StoreResponse.java b/src/main/java/poomasi/domain/store/dto/StoreResponse.java index a18fba1f..d5916253 100644 --- a/src/main/java/poomasi/domain/store/dto/StoreResponse.java +++ b/src/main/java/poomasi/domain/store/dto/StoreResponse.java @@ -10,6 +10,8 @@ @Builder public record StoreResponse( + Long id, + @NotNull String name, @@ -19,7 +21,7 @@ public record StoreResponse( String phone, @Comment("사업자 번호") - @NotNull + // @NotNull String businessNumber, @NotNull @@ -30,6 +32,7 @@ public record StoreResponse( public static StoreResponse fromEntity(Store store) { return StoreResponse.builder() + .id(store.getId()) .name(store.getName()) .address(store.getAddress()) .phone(store.getPhone())