Skip to content

Commit

Permalink
refactor: 매출 통계 리팩토링 #225
Browse files Browse the repository at this point in the history
  • Loading branch information
jjt4515 committed Nov 20, 2024
1 parent e610adb commit 7546f98
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 88 deletions.

This file was deleted.

This file was deleted.

2 changes: 2 additions & 0 deletions src/main/java/poomasi/domain/image/entity/Image.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package poomasi.domain.image.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -17,6 +18,7 @@
@Setter
@NoArgsConstructor
@SQLDelete(sql = "UPDATE image SET deleted_at = current_timestamp WHERE id = ?")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Image {

@Id
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/poomasi/domain/order/entity/OrderedProduct.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
}

5 changes: 0 additions & 5 deletions src/main/java/poomasi/domain/order/service/OrderService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package poomasi.domain.admin.statistics.controller;
package poomasi.domain.statistics.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
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;
Expand All @@ -30,13 +30,14 @@ public ResponseEntity<Page<StoreMonthlySalesResponse>> getMonthlyStoreSales(
return ResponseEntity.ok(salesResponses);
}

@GetMapping("/categories/monthly-sales")
public ResponseEntity<Page<CategoryMonthlySalesResponse>> getCategoryMonthlySales(
@GetMapping("/stores/{storeId}/categories/six-month-sales")
public ResponseEntity<Page<CategoryMonthlySalesResponse>> getSixMonthCategorySales(
@PathVariable Long storeId,
@RequestParam String startMonth,
@PageableDefault(size = 10) Pageable pageable) {

LocalDate startDate = LocalDate.parse(startMonth + "-01");
Page<CategoryMonthlySalesResponse> salesResponses = statisticsService.getCategoryMonthlySales(startDate, pageable);
Page<CategoryMonthlySalesResponse> salesResponses = statisticsService.getSixMonthCategorySales(storeId, startDate, pageable);
return ResponseEntity.ok(salesResponses);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package poomasi.domain.statistics.dto.response;


import java.math.BigDecimal;

public record CategoryMonthlySalesResponse (
Long storeId,
Long categoryId,
BigDecimal totalSales) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package poomasi.domain.statistics.dto.response;

import java.math.BigDecimal;

public record StoreMonthlySalesResponse(
Long storeId,
String month,
BigDecimal totalSales
) {}
Original file line number Diff line number Diff line change
@@ -1,36 +1,29 @@
package poomasi.domain.admin.statistics.service;
package poomasi.domain.statistics.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
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
@Transactional(readOnly = true)
@Service
public class StatisticsService {
private final OrderService orderService;
private final CategoryService categoryService;

private List<OrderedProduct> getDeliveredProducts(List<Order> orders) {
return orders.stream()
Expand All @@ -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<Category, CategoryMonthlySalesResponse> 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<StoreMonthlySalesResponse> 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());
Expand All @@ -73,32 +48,43 @@ public Page<StoreMonthlySalesResponse> getMonthlyStoreSales(Long storeId, String
LocalDateTime endDate = end.atTime(23, 59, 59);

List<Order> orders = orderService.getOrdersByUpdateAtBetween(startDate, endDate);

List<OrderedProduct> deliveredProducts = getDeliveredProducts(orders);

List<StoreMonthlySalesResponse> salesResponses = deliveredProducts.stream()
// 월별 매출 계산
List<StoreMonthlySalesResponse> 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<CategoryMonthlySalesResponse> getCategoryMonthlySales(LocalDate startDate, Pageable pageable) {
public Page<CategoryMonthlySalesResponse> getSixMonthCategorySales(Long storeId, LocalDate startDate, Pageable pageable) {
LocalDateTime[] dateRange = calculateDateRange(startDate, 5);
List<Order> orders = orderService.getOrdersByUpdateAtBetween(dateRange[0], dateRange[1]);

List<OrderedProduct> deliveredProducts = getDeliveredProducts(orders);

Map<Category, CategoryMonthlySalesResponse> salesMap = new HashMap<>();

deliveredProducts.forEach(orderedProduct -> updateCategorySales(salesMap, orderedProduct));

List<CategoryMonthlySalesResponse> responseList = new ArrayList<>(salesMap.values());
List<CategoryMonthlySalesResponse> 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());
}
}

}
5 changes: 4 additions & 1 deletion src/main/java/poomasi/domain/store/dto/StoreResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

@Builder
public record StoreResponse(
Long id,

@NotNull
String name,

Expand All @@ -19,7 +21,7 @@ public record StoreResponse(
String phone,

@Comment("사업자 번호")
@NotNull
// @NotNull
String businessNumber,

@NotNull
Expand All @@ -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())
Expand Down

0 comments on commit 7546f98

Please sign in to comment.