Skip to content

Commit

Permalink
feat: 카테고리별 매출 추가 #225
Browse files Browse the repository at this point in the history
  • Loading branch information
jjt4515 committed Nov 19, 2024
1 parent 4edc909 commit 84984fc
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@
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.order.service.OrderService;

import java.time.LocalDate;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/admin/statistics")
public class StatisticsController {

private final StatisticsService statisticsService;
private final OrderService orderService;

@GetMapping("/stores/{storeId}/monthly-sales")
public ResponseEntity<Page<StoreMonthlySalesResponse>> getMonthlyStoreSales(
@PathVariable Long storeId,
@RequestParam String startMonth,
@RequestParam String endMonth,
Pageable pageable) {
@PageableDefault(size = 10) Pageable pageable) {

Page<StoreMonthlySalesResponse> salesResponses = statisticsService.getMonthlyStoreSales(storeId, startMonth, endMonth, pageable);
return ResponseEntity.ok(salesResponses);
}

@GetMapping("/categories/monthly-sales")
public ResponseEntity<Page<CategoryMonthlySalesResponse>> getCategoryMonthlySales(
@RequestParam Long categoryId,
@RequestParam String startMonth,
@RequestParam String endMonth,
Pageable pageable
) {
Page<CategoryMonthlySalesResponse> sales = statisticsService.getCategoryMonthlySales(categoryId, startMonth, endMonth, pageable);
return ResponseEntity.ok(sales);
@PageableDefault(size = 10) Pageable pageable) {

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

import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;

public record CategoryMonthlySalesResponse(
String categoryName,
int count,
BigDecimal totalSales
) { }
@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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@
import org.springframework.transaction.annotation.Transactional;
import poomasi.domain.admin.statistics.dto.response.StoreMonthlySalesResponse;
import poomasi.domain.order.entity.Order;
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 java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
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;

@Transactional(readOnly = true)
public Page<StoreMonthlySalesResponse> getMonthlyStoreSales(Long storeId, String startMonth, String endMonth, Pageable pageable) {
LocalDate start = LocalDate.parse(startMonth + "-01");
LocalDate end = LocalDate.parse(endMonth + "-01");
Expand All @@ -36,25 +42,51 @@ public Page<StoreMonthlySalesResponse> getMonthlyStoreSales(Long storeId, String

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

// 주문 목록에서 각 OrderedProduct를 순회하여 storeId와 일치하는 주문 품목의 매출을 계산
List<StoreMonthlySalesResponse> salesResponses = orders.stream()
.flatMap(order -> order.getOrderedProducts().stream())
.filter(orderedProduct -> orderedProduct.getProduct().getStore().getId().equals(storeId))
.filter(orderedProduct -> orderedProduct.getStoreId()
.equals(storeId) && orderedProduct.getOrderedProductStatus() == OrderedProductStatus.DELIVERED)
.map(orderedProduct -> {
BigDecimal totalSales = orderedProduct.getPrice().multiply(BigDecimal.valueOf(orderedProduct.getCount()));
return new StoreMonthlySalesResponse(orderedProduct.getProduct().getStore(), totalSales);
return new StoreMonthlySalesResponse(orderedProduct.getStore(), totalSales);
})
.collect(Collectors.toList());

return new PageImpl<>(salesResponses, pageable, salesResponses.size());
}

public Page<CategoryMonthlySalesResponse> getCategoryMonthlySales(Long categoryId, String startMonth, String endMonth, Pageable pageable) {
LocalDate start = LocalDate.parse(startMonth + "-01");
LocalDate end = LocalDate.parse(endMonth + "-01");
end = end.withDayOfMonth(end.lengthOfMonth());
public Page<CategoryMonthlySalesResponse> getCategoryMonthlySales(LocalDate startDate, Pageable pageable) {

LocalDate endDate = startDate.plusMonths(5);

List<Order> orders = orderService.getOrdersByUpdateAtBetween(startDate.atStartOfDay(), endDate.atTime(23, 59, 59));

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

orders.stream()
.flatMap(order -> order.getOrderedProducts().stream())
.filter(orderedProduct -> orderedProduct.getOrderedProductStatus() == OrderedProductStatus.DELIVERED)
.forEach(orderedProduct -> {
Product product = orderedProduct.getProduct();
Long categoryId = product.getCategoryId();
Category category = categoryService.getCategory(categoryId);

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));
});

List<CategoryMonthlySalesResponse> responseList = new ArrayList<>(salesMap.values());

int start = (int) pageable.getOffset();
int end = Math.min((start + pageable.getPageSize()), responseList.size());
Page<CategoryMonthlySalesResponse> page = new PageImpl<>(responseList.subList(start, end), pageable, responseList.size());

return orderService.getCategoryMonthlySales(categoryId, start.atStartOfDay(), end.atTime(LocalTime.MAX), pageable);
return page;
}
}

15 changes: 9 additions & 6 deletions src/main/java/poomasi/domain/order/entity/OrderedProduct.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import jakarta.persistence.*;
import jdk.jfr.Description;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -28,10 +24,9 @@
import poomasi.domain.member.entity.Member;
import poomasi.domain.product.entity.Product;
import poomasi.domain.review.entity.Review;
import poomasi.domain.store.entity.Store;
import poomasi.payment.entity.Payment;

import java.math.BigDecimal;

import static poomasi.domain.order.entity.OrderedProductStatus.PENDING_SELLER_APPROVAL;

@Entity
Expand Down Expand Up @@ -159,5 +154,13 @@ public BigDecimal calculateRefundAmount(){
BigDecimal count = new BigDecimal(this.count);
return this.price.multiply(count);
}

public Store getStore() {
return getProduct().getStore();
}

public Long getStoreId(){
return getStore().getId();
}
}

21 changes: 0 additions & 21 deletions src/main/java/poomasi/domain/order/repository/OrderRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import poomasi.domain.admin.statistics.dto.response.CategoryMonthlySalesResponse;
import poomasi.domain.order.entity.Order;

import java.time.LocalDateTime;
Expand All @@ -23,24 +22,4 @@ public interface OrderRepository extends JpaRepository<Order, Long> {
@Query("SELECT o FROM Order o WHERE o.updateAt BETWEEN :startDate AND :endDate")
List<Order> findAllByUpdateAtBetween(@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate);

@Query("""
SELECT new poomasi.domain.admin.statistics.dto.response.CategoryMonthlySalesResponse(
p.category,
COUNT(op.id),
SUM(op.price * op.quantity)
)
FROM Order o
JOIN o.orderedProducts op
JOIN op.product p
WHERE p.category.id = :categoryId
AND o.createdAt BETWEEN :startDate AND :endDate
GROUP BY p.category
""")
Page<CategoryMonthlySalesResponse> findCategoryMonthlySales(
@Param("categoryId") Long categoryId,
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate,
Pageable pageable
);
}
4 changes: 0 additions & 4 deletions src/main/java/poomasi/domain/order/service/OrderService.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,6 @@ public List<Order> getOrdersByUpdateAtBetween(LocalDateTime startDate, LocalDate
return orderRepository.findAllByUpdateAtBetween(startDate, endDate);
}

public Page<CategoryMonthlySalesResponse> getCategoryMonthlySales(Long categoryId, LocalDateTime startDate, LocalDateTime endDate, Pageable pageable){
return orderRepository.findCategoryMonthlySales(categoryId, startDate, endDate, pageable);
}

}


Expand Down

0 comments on commit 84984fc

Please sign in to comment.