Skip to content

Commit

Permalink
주문 상세조회 API (#126)
Browse files Browse the repository at this point in the history
* feat(#112): 주문 취소 API 구현

* feat(#112): 주문 취소 API 구현

* feat(#112): 충돌 해결

* feat(#112): 주문 생성 - 결제 연결

* feat(#112): 주문 생성 - 결제 연결 완료

* fix(#112): order 모듈 payment_dto로 실행되는 오류 해결

* feat(#112): 주문 상세조회 API 구현
  • Loading branch information
eggnee authored Oct 15, 2024
1 parent f5f4383 commit 463c627
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 6 deletions.
9 changes: 6 additions & 3 deletions service/order/server/docs/OrderApiTest.http
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ Content-Type: application/json
}
],
"pointPrice": 1,
"addressId": 1,
"userEmail": "linavely99@gmail.com"
"addressId": 1
}

### 주문 취소
PATCH http://localhost:{{Port}}/api/orders/19152/cancel
PATCH http://localhost:{{Port}}/api/orders/19149/cancel
Authorization: Bearer {{access_token}}

### 상품 재고 조회
GET http://localhost:{{Port}}/api/products/800504d0-be21-450e-8598-0dc3d382d7ea
Authorization: Bearer {{access_token}}

### 주문 단건 조회
GET http://localhost:{{Port}}/api/orders/19152
Authorization: Bearer {{access_token}}
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,20 @@ public Long createOrder(Long userId, OrderCreateRequest request) {
ProductDto::getDiscountedPrice)
);

Map<String, String> productNames = products.stream().collect(
Collectors.toMap(
product -> product.getProductId().toString(),
product -> product.getProductName()
)
);

// 주문 상품 하나씩 생성 TODO couponDto
request.getOrderProductInfos()
.forEach(
productInfo -> createAndSaveOrderProduct(productInfo, null,
productPrices.get(productInfo.getProductId()), order));

productPrices.get(productInfo.getProductId()),
productNames.get(productInfo.getProductId()), order));

PaymentInternalDto.Create payment = new PaymentInternalDto.Create(
userId, savedOrderId, order.getOrderNo(), request.getUserEmail(),
order.getTotalRealAmount().longValue());
Expand Down Expand Up @@ -150,11 +158,12 @@ private boolean isDuplicateOrderNo(String orderNo) {


private void createAndSaveOrderProduct(OrderProductInfo productInfo, String couponDto,
BigDecimal productPrice,
BigDecimal productPrice, String productName,
Order order) {
OrderProduct orderProduct = OrderProduct.createOrderProduct(
productInfo.getProductId(),
productPrice,
productName,
productInfo.getQuantity(),
couponDto,
order
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.sparta.order.server.infrastructure.client.ProductClient;
import com.sparta.order.server.infrastructure.client.UserClient;
import com.sparta.order.server.infrastructure.event.PaymentCompletedEvent;
import com.sparta.order.server.presentation.dto.OrderDto.OrderGetResponse;
import com.sparta.order.server.presentation.dto.OrderDto.OrderProductResponse;
import com.sparta.payment_dto.infrastructure.PaymentInternalDto;
import com.sparta.payment_dto.infrastructure.PaymentInternalDto.Cancel;
import com.sparta.user.user_dto.infrastructure.PointHistoryDto;
Expand Down Expand Up @@ -46,6 +48,8 @@ public Long cancelOrder(Long userId, Long orderId) {
UserDto user = userClient.getUser(userId);
Order order = validateOrderExists(orderId);

order.validateOrderPermission(userId);

if (!order.getState().equals(OrderState.PENDING_PAYMENT)
&& !order.getState().equals(OrderState.COMPLETED)) {
throw new OrderException(OrderErrorCode.CANNOT_CANCEL_WHILE_SHIPPING, orderId);
Expand Down Expand Up @@ -103,6 +107,20 @@ public void handlePaymentCompletedEvent(String event) {
}
}

public OrderGetResponse getOrder(Long userId, Long orderId) {
UserDto user = userClient.getUser(userId);
Order order = validateOrderExists(orderId);

order.validateOrderPermission(userId);

final List<OrderProduct> orderProducts = orderProductRepository.findByOrder(order);
final List<OrderProductResponse> orderProductResponses = orderProducts.stream().map(
OrderProductResponse::fromEntity).toList();
final PaymentInternalDto.Get payment = paymentClient.getPayment(orderId);

return OrderGetResponse.from(order, orderProductResponses, payment);
}

private Order validateOrderExists(Long orderId) {
return orderRepository.findById(orderId).orElseThrow(
() -> new OrderException(OrderErrorCode.ORDER_NOT_FOUND)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ private static String generateRandomNumber() {
return sb.toString();
}

public void validateOrderPermission(Long userId) {
if (!this.userId.equals(userId)) {
throw new OrderException(OrderErrorCode.ORDER_PERMISSION_DENIED);
}
}

@AllArgsConstructor
private static class PriceInfo {

Expand All @@ -198,4 +204,5 @@ private static class PriceInfo {

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class OrderProduct extends BaseEntity {
@Column(nullable = false)
private String productId;
@Column(nullable = false)
private String productName;
@Column(nullable = false)
private int quantity;
@Column(nullable = false)
private BigDecimal purchasePrice;
Expand All @@ -45,6 +47,7 @@ public class OrderProduct extends BaseEntity {

// TODO productId -> productDto 설정
public static OrderProduct createOrderProduct(String productId, BigDecimal productPrice,
String productName,
int quantity, String couponDto, Order order) {

return OrderProduct.builder()
Expand All @@ -55,6 +58,7 @@ public static OrderProduct createOrderProduct(String productId, BigDecimal produ
couponDto != null ? productPrice.multiply(BigDecimal.valueOf(quantity))
.subtract(BigDecimal.valueOf(100))
: productPrice.multiply(BigDecimal.valueOf(quantity)))
.productName(productName)
.userCouponId(couponDto != null ? 1L : null)
.couponPrice(couponDto != null ? BigDecimal.valueOf(100) : BigDecimal.ZERO)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

@Getter
public enum OrderErrorCode {
ORDER_PERMISSION_DENIED(HttpStatus.FORBIDDEN, "자신의 주문만 조회할 수 있습니다."),
ORDER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 주문입니다."),
CANNOT_CANCEL_WHILE_SHIPPING(HttpStatus.FORBIDDEN, "배송이 시작된 주문은 취소할 수 없습니다. : [%s]"),
INSUFFICIENT_POINT(HttpStatus.BAD_REQUEST, "포인트가 부족합니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.sparta.payment_dto.infrastructure.PaymentInternalDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

Expand All @@ -14,4 +16,7 @@ public interface PaymentClient {
@PostMapping("/internal/payments/cancel")
void cancelPayment(@RequestBody PaymentInternalDto.Cancel cancelRequest);

@GetMapping("/internal/payments/{orderId}")
PaymentInternalDto.Get getPayment(@PathVariable(name = "orderId") Long orderId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import com.sparta.order.server.application.service.OrderCreateService;
import com.sparta.order.server.application.service.OrderService;
import com.sparta.order.server.presentation.dto.OrderDto.OrderCreateRequest;
import com.sparta.order.server.presentation.dto.OrderDto.OrderGetResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -34,4 +36,10 @@ public ApiResponse<Long> cancelOrder(@AuthenticationPrincipal JwtClaim userClaim
return ApiResponse.ok(orderService.cancelOrder(userClaim.getUserId(), orderId));
}

@GetMapping("/{orderId}")
public ApiResponse<OrderGetResponse> getOrder(@AuthenticationPrincipal JwtClaim userClaim,
@PathVariable(name = "orderId") Long orderId) {
return ApiResponse.ok(orderService.getOrder(userClaim.getUserId(), orderId));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.sparta.order.server.presentation.dto;

import com.sparta.order.server.domain.model.Order;
import com.sparta.order.server.domain.model.OrderProduct;
import com.sparta.payment_dto.infrastructure.PaymentInternalDto;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -33,4 +36,79 @@ public static class OrderProductInfo {

}

@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class OrderGetResponse {

private Long orderId;
private Long userId;
private String orderNo;
private String orderType;
private String orderState;
private List<OrderProductResponse> orderProducts = new ArrayList<>();
private Integer totalQuantity;
private BigDecimal totalAmount;
private BigDecimal shippingAmount;
private BigDecimal totalRealAmount;
private BigDecimal pointPrice;
private BigDecimal couponPrice;
private String invoiceNumber;
private String recipient;
private String phoneNumber;
private String zipcode;
private String shippingAddress;
private Long paymentId;
private PaymentInternalDto.Get payment;

public static OrderDto.OrderGetResponse from(Order order,
List<OrderProductResponse> orderProductResponses,
PaymentInternalDto.Get payment) {
return new OrderGetResponse(
order.getOrderId(),
order.getUserId(),
order.getOrderNo(),
order.getType().getDescription(),
order.getState().getDescription(),
orderProductResponses,
order.getTotalQuantity(),
order.getTotalAmount(),
order.getShippingAmount(),
order.getTotalRealAmount(),
order.getPointPrice(),
order.getCouponPrice(),
order.getInvoiceNumber(),
order.getRecipient(),
order.getPhoneNumber(),
order.getZipcode(),
order.getShippingAddress(),
order.getPaymentId(),
payment);
}

}

@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class OrderProductResponse {

private Long productId;
private String productName;
private Integer quantity;
private BigDecimal purchasePrice;
private BigDecimal couponPrice;

public static OrderProductResponse fromEntity(OrderProduct orderProduct) {
return new OrderProductResponse(
orderProduct.getOrderProductId(),
orderProduct.getProductName(),
orderProduct.getQuantity(),
orderProduct.getPurchasePrice(),
orderProduct.getCouponPrice()
);
}

}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.sparta.payment_dto.infrastructure;

import java.time.LocalDateTime;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand Down Expand Up @@ -29,4 +31,35 @@ public static class Cancel {

}

@Getter
@Setter
public static class Get {

private Long paymentId;
private Long orderId;
private PaymentState state;
private String orderName;
private Long amount;
private LocalDateTime createdAt;
private List<PaymentHistoryDto> histories;

}

@Getter
@Setter
public static class PaymentHistoryDto {

private Long amount;
private PaymentState type;
private String cancelReason;
private LocalDateTime createdAt;

}

public enum PaymentState {
// 결제 완료, 결제 대기, 결제 실패, 결제 취소, 환불 대기, 환불 완료
PAYMENT, PENDING, FAILED, CANCEL, REFUND_PENDING, REFUND

}

}

0 comments on commit 463c627

Please sign in to comment.