feat(order-service): 주문 상태변경 로직 추가 및 조회 쿼리 변경

- 주문 수락 및 거절 상태변경 로직 추가
- 주문 내역 조회 dto 리팩토링
This commit is contained in:
bum12ark
2022-03-10 16:44:46 +09:00
parent 713e0d2a1a
commit f12f7bab9d
11 changed files with 247 additions and 98 deletions

View File

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

View File

@@ -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<Order> 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();
}
}
}

View File

@@ -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<Order> orders;
private boolean hasNext;
}

View File

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

View File

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

View File

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

View File

@@ -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<Order> 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<Order> 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());
}
}

View File

@@ -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<OrderDto> findOrderMain(OrderSearchCondition condition, Long storeId);
OrderMainDto findOrderMain(OrderSearchCondition condition, Long storeId);
Page<OrderDto> findPrevOrderMain(PrevOrderSearch search, Pageable pageable, Long storeId);
SliceImpl<OrderDto> 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);
}

View File

@@ -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<OrderDto> findOrderMain(OrderSearchCondition condition, Long storeId) {
public OrderMainDto findOrderMain(OrderSearchCondition condition, Long storeId) {
// 주문 가져오기
List<OrderDto> 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<OrderDto> orderDtoList = orderPage.getContent()
.stream()
.map(OrderDto::createFullField)
.collect(Collectors.toList());
.collect(toList());
// 사용자명 및 아이템 이름 가져오기
// getUserNameAndItemName(orderDtoList);
@@ -84,28 +66,13 @@ public class OrderServiceImpl implements OrderService {
List<OrderDto> 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<OrderDto> 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<OrderItemOption> 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);
}
}

View File

@@ -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<Result> 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;
}
}

View File

@@ -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<Result> orderMain(@Valid OrderSearchCondition condition) {
// TODO: 2022/03/10 Feign client storeId 가져오기 구현 필요
Long userId = 1L;
Long storeId = 1L;
List<OrderDto> orderDto = orderService.findOrderMain(condition, storeId);
OrderMainDto orderMainDto = orderService.findOrderMain(condition, storeId);
List<OrderMainResponse> 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<OrderItemResponse> orderItemResponses;
private OrderStatus orderStatus;
private String orderTime;
private boolean hasNext;
private List<_Order> orders;
public OrderMainResponse(OrderDto orderDto) {
List<OrderItemResponse> 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<OrderDto> 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());
}
}