-
Notifications
You must be signed in to change notification settings - Fork 4
feat: 주문 현황 기간/상태/금액 필터링 추가 #250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "\uC870\uC608\uB9B0"
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package kr.inventory.domain.sales.controller.dto.request; | ||
|
|
||
| import jakarta.validation.constraints.NotNull; | ||
| import kr.inventory.domain.sales.entity.enums.SalesOrderStatus; | ||
|
|
||
| import java.math.BigDecimal; | ||
| import java.time.OffsetDateTime; | ||
|
|
||
| public record SalesOrderSearchRequest( | ||
| OffsetDateTime from, | ||
| OffsetDateTime to, | ||
| SalesOrderStatus status, | ||
| BigDecimal amountMin, | ||
| BigDecimal amountMax | ||
| ) {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |
| import kr.inventory.domain.reference.repository.MenuRepository; | ||
| import kr.inventory.domain.sales.controller.dto.request.SalesOrderCreateRequest; | ||
| import kr.inventory.domain.sales.controller.dto.request.SalesOrderItemRequest; | ||
| import kr.inventory.domain.sales.controller.dto.request.SalesOrderSearchRequest; | ||
| import kr.inventory.domain.sales.controller.dto.response.SalesOrderResponse; | ||
| import kr.inventory.domain.sales.entity.SalesOrder; | ||
| import kr.inventory.domain.sales.entity.SalesOrderItem; | ||
|
|
@@ -155,12 +156,14 @@ public SalesOrderResponse getOrder(UUID orderPublicId, Long userId, UUID storePu | |
| return SalesOrderResponse.from(order, items); | ||
| } | ||
|
|
||
| public PageResponse<SalesOrderResponse> getStoreOrders(Long userId, UUID storePublicId, Pageable pageable) { | ||
| public PageResponse<SalesOrderResponse> getStoreOrders(Long userId, UUID storePublicId, SalesOrderSearchRequest request, Pageable pageable) { | ||
| validateSearchPeriod(request.from(), request.to()); | ||
| validateAmountRange(request.amountMin(), request.amountMax()); | ||
|
|
||
| Long storeId = storeAccessValidator.validateAndGetStoreId(userId, storePublicId); | ||
|
|
||
| Page<SalesOrder> page = salesOrderRepository.findStoreOrders(storeId, pageable); | ||
| Page<SalesOrder> page = salesOrderRepository.findStoreOrders(storeId, request, pageable); | ||
|
|
||
| // N+1 방지: 모든 주문 ID를 한번에 조회 | ||
| List<Long> orderIds = page.getContent().stream() | ||
| .map(SalesOrder::getSalesOrderId) | ||
| .toList(); | ||
|
|
@@ -169,11 +172,9 @@ public PageResponse<SalesOrderResponse> getStoreOrders(Long userId, UUID storePu | |
| ? Collections.emptyList() | ||
| : salesOrderItemRepository.findBySalesOrderSalesOrderIdIn(orderIds); | ||
|
|
||
| // 주문 ID별로 항목 그룹핑 | ||
| Map<Long, List<SalesOrderItem>> itemsByOrderId = allItems.stream() | ||
| .collect(Collectors.groupingBy(item -> item.getSalesOrder().getSalesOrderId())); | ||
|
|
||
| // PageResponse로 변환 | ||
| Page<SalesOrderResponse> responsePage = page.map(order -> { | ||
| List<SalesOrderItem> items = itemsByOrderId.getOrDefault( | ||
| order.getSalesOrderId(), | ||
|
|
@@ -217,48 +218,17 @@ public SalesOrderResponse refundOrder(UUID orderPublicId, Long userId, UUID stor | |
| return SalesOrderResponse.from(order, items); | ||
| } | ||
|
|
||
| /** | ||
| * 재료별 필요 수량 계산 | ||
| */ | ||
| private Map<Long, BigDecimal> calculateIngredientUsage(List<SalesOrderItem> items) { | ||
| Map<Long, BigDecimal> usageMap = new HashMap<>(); | ||
|
|
||
| for (SalesOrderItem item : items) { | ||
| Menu menu = item.getMenu(); | ||
| JsonNode ingredientsJson = menu.getIngredientsJson(); | ||
|
|
||
| if (ingredientsJson == null || ingredientsJson.isEmpty()) { | ||
| continue; | ||
| } | ||
|
|
||
| if (ingredientsJson.has("ingredients") && ingredientsJson.get("ingredients").isArray()) { | ||
| for (JsonNode ingredientNode : ingredientsJson.get("ingredients")) { | ||
| // ingredientId 검증 | ||
| if (!ingredientNode.has("ingredientId")) { | ||
| throw new SalesOrderException(SalesOrderErrorCode.INVALID_INGREDIENT_DATA); | ||
| } | ||
|
|
||
| // quantity 검증 및 변환 | ||
| if (!ingredientNode.has("quantity")) { | ||
| throw new SalesOrderException(SalesOrderErrorCode.INVALID_INGREDIENT_DATA); | ||
| } | ||
|
|
||
| Long ingredientId = ingredientNode.get("ingredientId").asLong(); | ||
|
|
||
| BigDecimal quantity; | ||
| try { | ||
| quantity = new BigDecimal(ingredientNode.get("quantity").asText()); | ||
| } catch (NumberFormatException e) { | ||
| // 잘못된 형식의 재료 수량 데이터 | ||
| throw new SalesOrderException(SalesOrderErrorCode.INVALID_INGREDIENT_DATA); | ||
| } | ||
|
|
||
| BigDecimal totalQuantity = quantity.multiply(BigDecimal.valueOf(item.getQuantity())); | ||
| usageMap.merge(ingredientId, totalQuantity, BigDecimal::add); | ||
| } | ||
| } | ||
| private void validateSearchPeriod(OffsetDateTime from, OffsetDateTime to) { | ||
| if (from != null && to != null && from.isAfter(to)) { | ||
| throw new SalesOrderException(SalesOrderErrorCode.INVALID_SEARCH_PERIOD); | ||
| } | ||
| } | ||
|
|
||
| return usageMap; | ||
| private void validateAmountRange(BigDecimal amountMin, BigDecimal amountMax) { | ||
| if (amountMin != null && amountMax != null && amountMin.compareTo(amountMax) > 0) { | ||
| throw new SalesOrderException(SalesOrderErrorCode.INVALID_AMOUNT_RANGE); | ||
| } | ||
| } | ||
|
Comment on lines
+221
to
231
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
References
|
||
|
|
||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jakarta.validation.constraints.NotNullimport가 사용되지 않고 있습니다. 레포지토리 스타일 가이드의 "import 정리 및 unused 제거" 규칙(66번 라인)에 따라 불필요한 import는 제거하는 것이 좋습니다.References