Skip to content

Commit

Permalink
feature: 스토어 별 매출 #225
Browse files Browse the repository at this point in the history
  • Loading branch information
jjt4515 committed Nov 19, 2024
1 parent 9d16110 commit b963a70
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package poomasi.domain.admin.statistics.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
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;

@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) {

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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package poomasi.domain.admin.statistics.dto.response;

import java.math.BigDecimal;

public record CategoryMonthlySalesResponse(
String categoryName,
int count,
BigDecimal totalSales
) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package poomasi.domain.admin.statistics.dto.response;

import poomasi.domain.store.entity.Store;

import java.math.BigDecimal;

public record StoreMonthlySalesResponse(
Store store,
BigDecimal totalSales
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package poomasi.domain.admin.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.order.entity.Order;
import poomasi.domain.order.service.OrderService;
import poomasi.domain.admin.statistics.dto.response.CategoryMonthlySalesResponse;


import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class StatisticsService {
private final OrderService orderService;

@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");
end = end.withDayOfMonth(end.lengthOfMonth());

LocalDateTime startDate = start.atStartOfDay();
LocalDateTime endDate = end.atTime(23, 59, 59);

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))
.map(orderedProduct -> {
BigDecimal totalSales = orderedProduct.getPrice().multiply(BigDecimal.valueOf(orderedProduct.getCount()));
return new StoreMonthlySalesResponse(orderedProduct.getProduct().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());

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

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/image")
@RequestMapping("/api/images")
public class ImageController {
private final ImageService imageService;

Expand Down
29 changes: 29 additions & 0 deletions src/main/java/poomasi/domain/order/repository/OrderRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
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;
import java.util.List;
import java.util.Optional;

Expand All @@ -14,4 +18,29 @@ public interface OrderRepository extends JpaRepository<Order, Long> {
Optional<Order> findByMerchantUid(String merchantUid);
Page<Order> findById(Long id, Pageable pageable);
Page<Order> findByMemberId(Long memberId, Pageable pageable);

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

}
10 changes: 10 additions & 0 deletions src/main/java/poomasi/domain/order/service/OrderService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
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 All @@ -33,6 +35,7 @@
import poomasi.payment.util.PaymentUtil;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -212,6 +215,13 @@ private Member getMember() {
return member;
}

public List<Order> getOrdersByUpdateAtBetween(LocalDateTime startDate, LocalDateTime endDate) {
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 b963a70

Please sign in to comment.