diff --git a/order-service/src/main/java/com/justpickup/orderservice/OrderServiceApplication.java b/order-service/src/main/java/com/justpickup/orderservice/OrderServiceApplication.java index 28ddf86..a785347 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/OrderServiceApplication.java +++ b/order-service/src/main/java/com/justpickup/orderservice/OrderServiceApplication.java @@ -26,7 +26,7 @@ public class OrderServiceApplication { @Transactional CommandLineRunner run(OrderRepository orderRepository) { return args -> { - Long userId = 1L; + Long userId = 2L; Long userCouponId = null; Long storeId = 1L; Long orderPrice = 1000L; @@ -45,6 +45,12 @@ public class OrderServiceApplication { Order order = Order.of(userId, userCouponId, storeId, orderPrice * i, transaction, orderItem, orderItem1); + if (i % 2 == 0) { + order.placed(); + } else { + order.order(); + } + orderRepository.save(order); } }; diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderMainDto.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderMainDto.java new file mode 100644 index 0000000..37be351 --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderMainDto.java @@ -0,0 +1,68 @@ +package com.justpickup.orderservice.domain.order.dto; + +import com.justpickup.orderservice.domain.order.entity.Order; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; +import com.justpickup.orderservice.domain.orderItem.entity.OrderItem; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +@Getter @Builder +public class OrderMainDto { + private List<_Order> orders; + private boolean hasNext; + + // == constructor == // + public static OrderMainDto of(List orders, boolean hasNext) { + return OrderMainDto.builder() + .orders(orders.stream().map(_Order::of).collect(toList())) + .hasNext(hasNext) + .build(); + } + + // == inner class == // + @Getter @Builder + public static class _Order { + private Long id; + private Long userId; + private OrderStatus orderStatus; + private LocalDateTime orderTime; + private List<_OrderItem> orderItems; + + private String userName; + private String storeName; + + public static _Order of(Order order) { + List<_OrderItem> orderItems = order.getOrderItems() + .stream() + .map(_OrderItem::of) + .collect(toList()); + + return _Order.builder() + .id(order.getId()) + .userId(order.getUserId()) + .orderStatus(order.getOrderStatus()) + .orderTime(order.getOrderTime()) + .orderItems(orderItems) + .build(); + } + } + + @Getter @Builder + public static class _OrderItem { + private Long id; + private Long itemId; + private String itemName; + + public static _OrderItem of(OrderItem orderItem) { + return _OrderItem.builder() + .id(orderItem.getId()) + .itemId(orderItem.getItemId()) + .build(); + } + } +} diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderMainResult.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderMainResult.java new file mode 100644 index 0000000..df54ae4 --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderMainResult.java @@ -0,0 +1,14 @@ +package com.justpickup.orderservice.domain.order.dto; + +import com.justpickup.orderservice.domain.order.entity.Order; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor(staticName = "of") +public class OrderMainResult { + private List orders; + private boolean hasNext; +} diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java index aa4d9a6..173b20d 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java @@ -96,4 +96,16 @@ public class Order extends BaseEntity { this.orderStatus = orderStatus; return this; } + + public void placed() { + this.orderStatus = OrderStatus.PLACED; + } + + public void order() { + this.orderStatus = OrderStatus.ORDER; + } + + public void reject() { + this.orderStatus = OrderStatus.REJECT; + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderListener.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderListener.java new file mode 100644 index 0000000..14fcdf7 --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderListener.java @@ -0,0 +1,20 @@ +package com.justpickup.orderservice.domain.order.entity; + +import lombok.extern.slf4j.Slf4j; + +import javax.persistence.PostUpdate; + +@Slf4j +public class OrderListener { + + @PostUpdate + private void postUpdate(Order order) { + OrderStatus orderStatus = order.getOrderStatus(); + if (orderStatus == OrderStatus.ORDER) { + // TODO: 2022/03/10 Kafka 알림 전송 + log.info("[OrderListener] {}", OrderStatus.ORDER.name()); + } else if (orderStatus == OrderStatus.PLACED) { + log.info("[OrderListener] {}", OrderStatus.PLACED.name()); + } + } +} diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderStatus.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderStatus.java index 2ff4f7f..1a1f748 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderStatus.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/OrderStatus.java @@ -1,8 +1,15 @@ package com.justpickup.orderservice.domain.order.entity; public enum OrderStatus { - PENDING, - PLACED, - CANCELED, - FAILED + PENDING("주문대기"), + ORDER("주문"), + PLACED("주문수락"), + REJECT("주문거절"), + FAIL("주문실패"); + + private String message; + + OrderStatus(String message) { + this.message = message; + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java index e90e0a5..e308431 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java @@ -1,5 +1,6 @@ package com.justpickup.orderservice.domain.order.repository; +import com.justpickup.orderservice.domain.order.dto.OrderMainResult; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; import com.justpickup.orderservice.domain.order.entity.Order; @@ -36,22 +37,33 @@ public class OrderRepositoryCustom { ORDER BY id desc LIMIT 페이지 사이즈 */ - public List findOrderMain(OrderSearchCondition condition, Long storeId) { + public OrderMainResult findOrderMain(OrderSearchCondition condition, Long storeId) { LocalDateTime start = condition.getOrderStartTime(); LocalDateTime end = condition.getOrderEndTime(); + int pageSize = 6; - return queryFactory + List orders = queryFactory .selectFrom(order) .join(order.transaction).fetchJoin() .where( - order.orderTime.between(start, end), - order.storeId.eq(storeId), - orderIdLt(condition.getLastOrderId()) + orderIdLt(condition.getLastOrderId()), + order.orderTime.between(start, end), + order.storeId.eq(storeId), + order.orderStatus.ne(OrderStatus.PENDING), + order.orderStatus.ne(OrderStatus.FAIL) ) - .orderBy(order.orderTime.desc()) - .limit(6) + .orderBy(order.id.desc()) + .limit(pageSize + 1) .distinct() .fetch(); + + boolean hasNext = false; + if (orders.size() > pageSize) { + orders.remove(pageSize); + hasNext = true; + } + + return OrderMainResult.of(orders, hasNext); } private BooleanExpression orderIdLt(Long lastOrderId) { @@ -124,4 +136,5 @@ public class OrderRepositoryCustom { .fetchOne()); } + } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java index 6f9f98c..a2f0577 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java @@ -2,20 +2,22 @@ package com.justpickup.orderservice.domain.order.service; import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; +import com.justpickup.orderservice.domain.order.dto.OrderMainDto; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; -import java.util.List; - public interface OrderService { - List findOrderMain(OrderSearchCondition condition, Long storeId); + OrderMainDto findOrderMain(OrderSearchCondition condition, Long storeId); Page findPrevOrderMain(PrevOrderSearch search, Pageable pageable, Long storeId); SliceImpl findOrderHistory(Pageable pageable, Long userId); void addItemToBasket(OrderItemDto orderItemDto,Long storeId, Long userId); FetchOrderDto fetchOrder(Long userId); void saveOrder(Long userId); + + void modifyOrder(Long userId, OrderStatus orderStatus); } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java index b2e8b22..7211c12 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java @@ -1,9 +1,6 @@ package com.justpickup.orderservice.domain.order.service; -import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; -import com.justpickup.orderservice.domain.order.dto.OrderDto; -import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; -import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; +import com.justpickup.orderservice.domain.order.dto.*; import com.justpickup.orderservice.domain.order.entity.Order; import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.order.exception.OrderException; @@ -11,14 +8,8 @@ import com.justpickup.orderservice.domain.order.repository.OrderRepository; import com.justpickup.orderservice.domain.order.repository.OrderRepositoryCustom; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; import com.justpickup.orderservice.domain.orderItem.entity.OrderItem; -import com.justpickup.orderservice.domain.orderItem.repository.OrderItemRepository; import com.justpickup.orderservice.domain.orderItemOption.entity.OrderItemOption; -import com.justpickup.orderservice.domain.orderItemOption.repository.OrderItemOptionRepository; -import com.justpickup.orderservice.global.client.store.GetItemResponse; -import com.justpickup.orderservice.global.client.store.StoreClient; -import com.justpickup.orderservice.global.client.user.GetCustomerResponse; -import com.justpickup.orderservice.global.client.user.UserClient; -import lombok.*; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -29,7 +20,8 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; @Service @RequiredArgsConstructor @@ -38,28 +30,18 @@ import java.util.stream.Collectors; public class OrderServiceImpl implements OrderService { private final OrderRepository orderRepository; - private final OrderItemRepository orderItemRepository; - private final OrderItemOptionRepository orderItemOptionRepository; private final OrderRepositoryCustom orderRepositoryCustom; - private final StoreClient storeClient; - private final UserClient userClient; private final OrderSender orderSender; - - @Override - public List findOrderMain(OrderSearchCondition condition, Long storeId) { + public OrderMainDto findOrderMain(OrderSearchCondition condition, Long storeId) { // 주문 가져오기 - List orderDtoList = - orderRepositoryCustom.findOrderMain(condition, storeId) - .stream() - .map(OrderDto::createFullField) - .collect(Collectors.toList()); + OrderMainResult orderMainResult = orderRepositoryCustom.findOrderMain(condition, storeId); // 사용자명 및 아이템 이름 가져오기 // getUserNameAndItemName(orderDtoList); - return orderDtoList; + return OrderMainDto.of(orderMainResult.getOrders(), orderMainResult.isHasNext()); } @Override @@ -69,7 +51,7 @@ public class OrderServiceImpl implements OrderService { List orderDtoList = orderPage.getContent() .stream() .map(OrderDto::createFullField) - .collect(Collectors.toList()); + .collect(toList()); // 사용자명 및 아이템 이름 가져오기 // getUserNameAndItemName(orderDtoList); @@ -84,28 +66,13 @@ public class OrderServiceImpl implements OrderService { List contents = orderHistory.getContent() .stream() .map(OrderDto::createFullField) - .collect(Collectors.toList()); + .collect(toList()); // TODO: 2022/03/07 Feign Client 통신 return new SliceImpl<>(contents, pageable, orderHistory.hasNext()); } - private void getUserNameAndItemName(List orderDtoList) { - orderDtoList.forEach(orderDto -> { - GetCustomerResponse getCustomerResponse = - userClient.getUser(orderDto.getUserId()).getData(); - orderDto.setUserName(getCustomerResponse.getUserName()); - - orderDto.getOrderItemDtoList() - .forEach(orderItemDto -> { - GetItemResponse getItemResponse = - storeClient.getItem(orderItemDto.getItemId()).getData(); - orderItemDto.setItemName(getItemResponse.getName()); - }); - }); - } - @Override @Transactional public void addItemToBasket(OrderItemDto orderItemDto,Long storeId, Long userId) { @@ -113,7 +80,7 @@ public class OrderServiceImpl implements OrderService { //orderItemOption Entity를 생성한다. List orderItemOptions = orderItemDto.getOrderItemOptionDtoList() .stream().map(orderItemOptionDto -> OrderItemOption.of(orderItemDto.getId())) - .collect(Collectors.toList()); + .collect(toList()); //orderItem을 Entity를 생성한다. OrderItem orderItem = OrderItem.of(orderItemDto.getItemId() @@ -155,7 +122,13 @@ public class OrderServiceImpl implements OrderService { } } + @Override + @Transactional + public void modifyOrder(Long orderId, OrderStatus orderStatus) { + Order order = orderRepository.findById(orderId) + .orElseThrow(() -> new OrderException(orderId + "는 없는 주문 번호입니다.")); - + order.setOrderStatus(orderStatus); + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderController.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderController.java index a626a48..07f68d5 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderController.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderController.java @@ -1,7 +1,17 @@ package com.justpickup.orderservice.domain.order.web; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; +import com.justpickup.orderservice.domain.order.exception.OrderException; +import com.justpickup.orderservice.domain.order.service.OrderService; +import com.justpickup.orderservice.global.dto.Result; +import lombok.Data; +import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @@ -9,4 +19,23 @@ import org.springframework.web.bind.annotation.RestController; @Slf4j public class OrderController { + private final OrderService orderService; + + @PatchMapping("/order/{orderId}") + public ResponseEntity patchOrder(@PathVariable("orderId") Long orderId, + @RequestBody PatchOrderRequest patchOrderRequest) { + OrderStatus orderStatus = patchOrderRequest.getOrderStatus(); + if (orderStatus != OrderStatus.PLACED && orderStatus != OrderStatus.REJECT) { + throw new OrderException("주문 수락, 거절 외에는 변경 불가능합니다."); + } + + orderService.modifyOrder(orderId, orderStatus); + + return ResponseEntity.ok(Result.createSuccessResult(null)); + } + + @Data @NoArgsConstructor + static class PatchOrderRequest { + private OrderStatus orderStatus; + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderOwnerApiController.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderOwnerApiController.java index 4e81f5c..91d32c1 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderOwnerApiController.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderOwnerApiController.java @@ -1,6 +1,7 @@ package com.justpickup.orderservice.domain.order.web; import com.justpickup.orderservice.domain.order.dto.OrderDto; +import com.justpickup.orderservice.domain.order.dto.OrderMainDto; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; import com.justpickup.orderservice.domain.order.entity.OrderStatus; @@ -27,7 +28,8 @@ import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; @RestController @RequestMapping("/api/owner/order") @@ -40,56 +42,59 @@ public class OrderOwnerApiController { @GetMapping("/order-main") public ResponseEntity orderMain(@Valid OrderSearchCondition condition) { + // TODO: 2022/03/10 Feign client storeId 가져오기 구현 필요 Long userId = 1L; Long storeId = 1L; - List orderDto = orderService.findOrderMain(condition, storeId); + OrderMainDto orderMainDto = orderService.findOrderMain(condition, storeId); - List orderMainResponses = orderDto.stream() - .map(OrderMainResponse::new) - .collect(Collectors.toList()); + OrderMainResponse orderMainResponse = new OrderMainResponse(orderMainDto); return ResponseEntity.status(HttpStatus.OK) - .body(Result.createSuccessResult(orderMainResponses)); + .body(Result.createSuccessResult(orderMainResponse)); } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Data @NoArgsConstructor static class OrderMainResponse { - private Long orderId; - private Long userId; - private String userName; - private List orderItemResponses; - private OrderStatus orderStatus; - private String orderTime; + private boolean hasNext; + private List<_Order> orders; - public OrderMainResponse(OrderDto orderDto) { - List orderItemDtoList = orderDto.getOrderItemDtoList() + public OrderMainResponse(OrderMainDto orderMainDto) { + this.hasNext = orderMainDto.isHasNext(); + this.orders = orderMainDto.getOrders() .stream() - .map(OrderItemResponse::new) - .collect(Collectors.toList()); - - this.orderId = orderDto.getId(); - this.userId = orderDto.getUserId(); - this.userName = orderDto.getUserName(); - this.orderItemResponses = orderItemDtoList; - this.orderStatus = orderDto.getOrderStatus(); - this.orderTime = orderDto.getOrderTime() - .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + .map(_Order::new) + .collect(toList()); } - } - @Data - static class OrderItemResponse { - private Long orderItemId; - private Long itemId; - private String itemName; + @Data + static class _Order { + private Long id; + private String orderTime; + private String orderStatus; + private String userName; + private String storeName; + private List<_OrderItem> orderItems; - public OrderItemResponse(OrderItemDto orderItemDto) { - this.orderItemId = orderItemDto.getId(); - this.itemId = orderItemDto.getItemId(); - this.itemName = orderItemDto.getItemName(); + public _Order(OrderMainDto._Order order) { + this.id = order.getId(); + this.orderTime = order.getOrderTime() + .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + this.orderStatus = order.getOrderStatus().name(); + this.userName = order.getUserName(); + this.storeName = order.getStoreName(); + this.orderItems = order.getOrderItems() + .stream().map(_OrderItem::new).collect(toList()); + } + } + + @Data + static class _OrderItem { + private String itemName; + + public _OrderItem(OrderMainDto._OrderItem orderItem) { + this.itemName = orderItem.getItemName(); + } } } @@ -117,7 +122,7 @@ public class OrderOwnerApiController { private Page page; public ResponsePrevOrder(List orderDtoList, int startPage, int totalPage) { - orders = orderDtoList.stream().map(OrderVo::new).collect(Collectors.toList()); + orders = orderDtoList.stream().map(OrderVo::new).collect(toList()); page = new Page(startPage, totalPage); } @@ -137,7 +142,7 @@ public class OrderOwnerApiController { this.orderPrice = orderDto.getOrderPrice(); this.userName = orderDto.getUserName(); this.orderItems = orderDto.getOrderItemDtoList() - .stream().map(OrderItemVo::new).collect(Collectors.toList()); + .stream().map(OrderItemVo::new).collect(toList()); } }