feat(order): 주문 상세보기 API 추가
- 사용자 정보 Feign 클라이언트 호출 - 아이템 정보 Feign 클라이언트 호출 - 아이템 옵션 정보 Feign 클라이언트 호출
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package com.justpickup.orderservice.domain.order.dto;
|
||||
|
||||
import com.justpickup.orderservice.domain.order.entity.Order;
|
||||
import com.justpickup.orderservice.domain.orderItem.entity.OrderItem;
|
||||
import com.justpickup.orderservice.domain.orderItemOption.entity.OrderItemOption;
|
||||
import com.justpickup.orderservice.global.client.store.OptionType;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class OrderDetailDto {
|
||||
|
||||
private Long id;
|
||||
private LocalDateTime orderTime;
|
||||
private Long orderPrice;
|
||||
private OrderDetailUser user;
|
||||
private List<OrderDetailItem> orderItems = new ArrayList<>();
|
||||
|
||||
public static OrderDetailDto of(Order order, List<OrderDetailItem> orderItems, OrderDetailUser orderDetailUser) {
|
||||
OrderDetailDto orderDetailDto = new OrderDetailDto();
|
||||
orderDetailDto.id = order.getId();
|
||||
orderDetailDto.orderTime = order.getOrderTime();
|
||||
orderDetailDto.orderPrice = order.getOrderPrice();
|
||||
|
||||
orderDetailDto.user = orderDetailUser;
|
||||
orderDetailDto.orderItems = orderItems;
|
||||
return orderDetailDto;
|
||||
}
|
||||
|
||||
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public static class OrderDetailUser {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String phoneNumber;
|
||||
|
||||
@Builder
|
||||
public OrderDetailUser(Long id, String name, String phoneNumber) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.phoneNumber = phoneNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public static class OrderDetailItem {
|
||||
private Long id;
|
||||
private Long itemId;
|
||||
private long totalPrice;
|
||||
private long count;
|
||||
private String name;
|
||||
private List<OrderDetailItemOption> options = new ArrayList<>();
|
||||
|
||||
public static OrderDetailItem of(OrderItem orderItem, String name, List<OrderDetailItemOption> orderDetailItemOption) {
|
||||
OrderDetailItem orderDetailItem = new OrderDetailItem();
|
||||
orderDetailItem.id = orderItem.getId();
|
||||
orderDetailItem.itemId = orderItem.getItemId();
|
||||
orderDetailItem.totalPrice = orderItem.getTotalPrice();
|
||||
orderDetailItem.count = orderItem.getCount();
|
||||
orderDetailItem.name = name;
|
||||
orderDetailItem.options = orderDetailItemOption;
|
||||
return orderDetailItem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public static class OrderDetailItemOption {
|
||||
private Long id;
|
||||
private Long itemOptionId;
|
||||
private String name;
|
||||
private OptionType optionType;
|
||||
|
||||
public static OrderDetailItemOption of(OrderItemOption orderItemOption, String name, OptionType optionType) {
|
||||
OrderDetailItemOption orderDetailItemOption = new OrderDetailItemOption();
|
||||
orderDetailItemOption.id = orderItemOption.getId();
|
||||
orderDetailItemOption.itemOptionId = orderItemOption.getItemOptionId();
|
||||
orderDetailItemOption.name = name;
|
||||
orderDetailItemOption.optionType = optionType;
|
||||
return orderDetailItemOption;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,4 +15,5 @@ public interface OrderService {
|
||||
FetchOrderDto fetchOrder(Long userId);
|
||||
void saveOrder(Long userId);
|
||||
void modifyOrder(Long userId, OrderStatus orderStatus);
|
||||
OrderDetailDto findOrderDetail(Long orderId);
|
||||
}
|
||||
|
||||
@@ -8,11 +8,10 @@ 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.OrderItemRepositoryCustom;
|
||||
import com.justpickup.orderservice.domain.orderItemOption.entity.OrderItemOption;
|
||||
import com.justpickup.orderservice.global.client.store.GetItemResponse;
|
||||
import com.justpickup.orderservice.global.client.store.GetStoreResponse;
|
||||
import com.justpickup.orderservice.global.client.store.StoreByUserIdResponse;
|
||||
import com.justpickup.orderservice.global.client.store.StoreClient;
|
||||
import com.justpickup.orderservice.global.client.store.*;
|
||||
import com.justpickup.orderservice.global.client.user.GetCustomerResponse;
|
||||
import com.justpickup.orderservice.global.client.user.UserClient;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -26,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.justpickup.orderservice.domain.order.dto.OrderDetailDto.*;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@Service
|
||||
@@ -36,6 +36,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
|
||||
private final OrderRepository orderRepository;
|
||||
private final OrderRepositoryCustom orderRepositoryCustom;
|
||||
private final OrderItemRepositoryCustom orderItemRepositoryCustom;
|
||||
private final StoreClient storeClient;
|
||||
private final UserClient userClient;
|
||||
|
||||
@@ -234,4 +235,60 @@ public class OrderServiceImpl implements OrderService {
|
||||
order.setOrderStatus(orderStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderDetailDto findOrderDetail(Long orderId) {
|
||||
Order order = orderRepository.findById(orderId)
|
||||
.orElseThrow(() -> new OrderException(orderId + "는 없는 주문 번호입니다."));
|
||||
|
||||
List<OrderItem> orderItemsWithOptions = orderItemRepositoryCustom.getOrderItemsWithOptions(order.getId());
|
||||
|
||||
// 고객 정보 가져오기
|
||||
GetCustomerResponse customerInfo = userClient.getCustomerById(order.getUserId()).getData();
|
||||
|
||||
Set<Long> itemIds = new HashSet<>();
|
||||
Set<Long> itemOptionIds = new HashSet<>();
|
||||
|
||||
// 아이템 이름 및 옵션 이름 가져오기
|
||||
for (OrderItem orderItem : orderItemsWithOptions) {
|
||||
itemIds.add(orderItem.getItemId());
|
||||
for (OrderItemOption orderItemOption : orderItem.getOrderItemOptions()) {
|
||||
itemOptionIds.add(orderItemOption.getItemOptionId());
|
||||
}
|
||||
}
|
||||
|
||||
Map<Long, String> itemNameMap = storeClient.getItemNameMap(itemIds);
|
||||
Map<Long, ItemOptionsResponse> itemOptionMap = storeClient.getItemOptionMap(itemOptionIds);
|
||||
|
||||
List<OrderDetailItem> orderDetailItems = orderItemsWithOptions.stream()
|
||||
.map(orderItem -> {
|
||||
// 주문 상세 옵션 생성
|
||||
List<OrderDetailItemOption> orderDetailItemOptions = orderItem.getOrderItemOptions()
|
||||
.stream()
|
||||
.map(orderItemOption -> {
|
||||
// 옵션 아이디에 해당하는 아이템 옵션 객체 가져오기
|
||||
ItemOptionsResponse itemOptionsResponse = itemOptionMap.get(orderItemOption.getItemOptionId());
|
||||
|
||||
return OrderDetailItemOption.of(
|
||||
orderItemOption,
|
||||
itemOptionsResponse.getName(),
|
||||
itemOptionsResponse.getOptionType()
|
||||
);
|
||||
})
|
||||
.collect(toList());
|
||||
// 아이템 아이디에 해당하는 아이템 이름 가져오기
|
||||
String itemName = itemNameMap.get(orderItem.getItemId());
|
||||
return OrderDetailItem.of(orderItem, itemName, orderDetailItemOptions);
|
||||
})
|
||||
.collect(toList());
|
||||
|
||||
// 주문한 사용자 정보 생성
|
||||
OrderDetailUser orderDetailUser = OrderDetailUser.builder()
|
||||
.id(customerInfo.getUserId())
|
||||
.phoneNumber(customerInfo.getPhoneNumber())
|
||||
.name(customerInfo.getUserName())
|
||||
.build();
|
||||
|
||||
return OrderDetailDto.of(order, orderDetailItems, orderDetailUser);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.justpickup.orderservice.domain.order.web;
|
||||
|
||||
import com.justpickup.orderservice.domain.order.dto.OrderDetailDto;
|
||||
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.client.store.OptionType;
|
||||
import com.justpickup.orderservice.global.dto.Result;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -10,10 +12,12 @@ 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;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@@ -26,7 +30,7 @@ public class OrderController {
|
||||
public ResponseEntity<Result> patchOrder(@PathVariable("orderId") Long orderId,
|
||||
@RequestBody PatchOrderRequest patchOrderRequest) {
|
||||
OrderStatus orderStatus = patchOrderRequest.getOrderStatus();
|
||||
if (orderStatus == OrderStatus.PENDING && orderStatus != OrderStatus.FAILED) {
|
||||
if (orderStatus == OrderStatus.PENDING && orderStatus == OrderStatus.FAILED) {
|
||||
throw new OrderException(orderStatus.getMessage() + "는 변경 불가능합니다.");
|
||||
}
|
||||
|
||||
@@ -39,4 +43,80 @@ public class OrderController {
|
||||
static class PatchOrderRequest {
|
||||
private OrderStatus orderStatus;
|
||||
}
|
||||
|
||||
@GetMapping("/api/order-detail/{orderId}")
|
||||
public ResponseEntity<Result> getOrderDetail(@PathVariable Long orderId) {
|
||||
|
||||
OrderDetailDto orderDetail = orderService.findOrderDetail(orderId);
|
||||
|
||||
return ResponseEntity.ok(Result.createSuccessResult(new OrderDetailResponse(orderDetail)));
|
||||
}
|
||||
|
||||
@Data @NoArgsConstructor @AllArgsConstructor
|
||||
static class OrderDetailResponse {
|
||||
private Long id;
|
||||
private String orderTime;
|
||||
private Long orderPrice;
|
||||
private OrderDetailUserResponse user;
|
||||
private List<OrderDetailItemResponse> orderItems = new ArrayList<>();
|
||||
|
||||
public OrderDetailResponse(OrderDetailDto dto) {
|
||||
this.id = dto.getId();
|
||||
this.orderTime = dto.getOrderTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
this.orderPrice = dto.getOrderPrice();
|
||||
this.user = new OrderDetailUserResponse(dto.getUser());
|
||||
this.orderItems = dto.getOrderItems().stream()
|
||||
.map(OrderDetailItemResponse::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Data
|
||||
static class OrderDetailUserResponse {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String phoneNumber;
|
||||
|
||||
public OrderDetailUserResponse(OrderDetailDto.OrderDetailUser user) {
|
||||
this.id = user.getId();
|
||||
this.name = user.getName();
|
||||
this.phoneNumber = user.getPhoneNumber();
|
||||
}
|
||||
}
|
||||
|
||||
@Data @NoArgsConstructor
|
||||
static class OrderDetailItemResponse {
|
||||
private Long id;
|
||||
private Long itemId;
|
||||
private long totalPrice;
|
||||
private long count;
|
||||
private String name;
|
||||
private List<OrderDetailItemOptionResponse> options = new ArrayList<>();
|
||||
|
||||
public OrderDetailItemResponse(OrderDetailDto.OrderDetailItem orderDetailItem) {
|
||||
this.id = orderDetailItem.getId();
|
||||
this.itemId = orderDetailItem.getItemId();
|
||||
this.totalPrice = orderDetailItem.getTotalPrice();
|
||||
this.count = orderDetailItem.getCount();
|
||||
this.name = orderDetailItem.getName();
|
||||
this.options = orderDetailItem.getOptions().stream()
|
||||
.map(OrderDetailItemOptionResponse::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@Data @NoArgsConstructor
|
||||
static class OrderDetailItemOptionResponse {
|
||||
private Long id;
|
||||
private Long itemOptionId;
|
||||
private String name;
|
||||
private OptionType optionType;
|
||||
|
||||
public OrderDetailItemOptionResponse(OrderDetailDto.OrderDetailItemOption itemOption) {
|
||||
this.id = itemOption.getId();
|
||||
this.itemOptionId = itemOption.getItemOptionId();
|
||||
this.name = itemOption.getName();
|
||||
this.optionType = itemOption.getOptionType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.justpickup.orderservice.domain.orderItem.repository;
|
||||
|
||||
import com.justpickup.orderservice.domain.orderItem.entity.OrderItem;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.justpickup.orderservice.domain.orderItem.entity.QOrderItem.orderItem;
|
||||
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class OrderItemRepositoryCustom {
|
||||
|
||||
private final JPAQueryFactory queryFactory;
|
||||
|
||||
public List<OrderItem> getOrderItemsWithOptions(Long orderId) {
|
||||
return queryFactory.selectFrom(orderItem)
|
||||
.leftJoin(orderItem.orderItemOptions).fetchJoin()
|
||||
.where(
|
||||
orderItem.order.id.eq(orderId)
|
||||
)
|
||||
.distinct()
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.justpickup.orderservice.global.entity.Yn;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.justpickup.orderservice.global.client.store;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ItemOptionsResponse {
|
||||
private Long id;
|
||||
private OptionType optionType;
|
||||
private String name;
|
||||
}
|
||||
@@ -32,7 +32,10 @@ public interface StoreClient {
|
||||
Result<GetStoreResponse> getStore(@PathVariable(value = "storeId") String storeId);
|
||||
|
||||
@GetMapping("/api/customer/items/{itemId}")
|
||||
Result<List<GetItemResponse>> getItemAndItemOptions(@PathVariable(value = "itemId") List<Long> itemIds);
|
||||
Result<List<GetItemResponse>> getItemAndItemOptions(@PathVariable(value = "itemId") Iterable<Long> itemIds);
|
||||
|
||||
@GetMapping("/item-options/{itemOptionIds}")
|
||||
Result<List<ItemOptionsResponse>> getItemOptions(@PathVariable(value = "itemOptionIds") Iterable<Long> itemOptionIds);
|
||||
|
||||
default Map<Long, String> getStoreNameMap(Set<Long> storeIds) {
|
||||
List<GetStoreResponse> storeResponses = this.getStoreAllById(storeIds).getData();
|
||||
@@ -50,5 +53,11 @@ public interface StoreClient {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
default Map<Long, ItemOptionsResponse> getItemOptionMap(Iterable<Long> itemOptionIds) {
|
||||
List<ItemOptionsResponse> itemOptionsResponses = this.getItemOptions(itemOptionIds).getData();
|
||||
return itemOptionsResponses.stream()
|
||||
.collect(
|
||||
toMap(ItemOptionsResponse::getId, itemOptionsResponse -> itemOptionsResponse)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ public class GlobalExceptionHandler {
|
||||
HttpStatus status = ce.getStatus();
|
||||
Result errorResult = ce.getErrorResult();
|
||||
|
||||
log.warn("[CustomException] {}, {}", status, errorResult);
|
||||
|
||||
return ResponseEntity.status(status)
|
||||
.body(errorResult);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user