diff --git a/src/main/java/com/kt/common/exception/ErrorCode.java b/src/main/java/com/kt/common/exception/ErrorCode.java index 2c68efc1..19d364ad 100644 --- a/src/main/java/com/kt/common/exception/ErrorCode.java +++ b/src/main/java/com/kt/common/exception/ErrorCode.java @@ -50,6 +50,8 @@ public enum ErrorCode { CANNOT_REFUND_ORDER(HttpStatus.BAD_REQUEST, "주문 환불이 불가능합니다."), CANNOT_RETURN_ORDER(HttpStatus.BAD_REQUEST, "주문 반품이 불가능합니다."), CANNOT_UPDATE_ORDER_STATUS(HttpStatus.BAD_REQUEST, "주문 상태 변경이 불가능합니다."), + CONCURRENT_RESERVATION(HttpStatus.CONFLICT, "다시 시도해주세요"), + //shoppingaddress NOT_SHOPPING_ADDRESS_OWNER(HttpStatus.FORBIDDEN, "본인의 배송지만 수정/삭제할 수 있습니다."), diff --git a/src/main/java/com/kt/controller/payment/PaymentController.java b/src/main/java/com/kt/controller/payment/PaymentController.java index 44713330..1c8a5097 100644 --- a/src/main/java/com/kt/controller/payment/PaymentController.java +++ b/src/main/java/com/kt/controller/payment/PaymentController.java @@ -134,8 +134,6 @@ public ResponseEntity confirmPayment(@RequestBody PaymentTossConfirmRequest r return ResponseEntity.ok(responseBody); } catch (Exception e) { - System.out.println("결제 실패sdlkjfnmalskdmfklamsdklfmaklsdmfklamsdflkmasdklf"); - cancelTossPayment(paymentKey, "시스템 오류로 인한 자동 취소"); orderService.rollback(orderIdLong); @@ -242,7 +240,7 @@ public ApiResult> getClientKey() { return ApiResult.ok(Map.of("clientKey", tossPaymentsProperties.getClientKey())); } - /* 이 코드 service로 빼야하는지 등 검토좀 한번 ㅂ부탁드릴게요!*/ + private void cancelTossPayment(String paymentKey, String cancelReason) { String url = tossPaymentsProperties.getApiUrl() + "/" + paymentKey + "/cancel"; String auth = tossPaymentsProperties.getSecretKey() + ":"; diff --git a/src/main/java/com/kt/domain/product/Product.java b/src/main/java/com/kt/domain/product/Product.java index 0dfc7ca5..a3a776e5 100644 --- a/src/main/java/com/kt/domain/product/Product.java +++ b/src/main/java/com/kt/domain/product/Product.java @@ -14,6 +14,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import jakarta.persistence.Version; import lombok.Getter; import lombok.NoArgsConstructor; @@ -34,6 +35,9 @@ public class Product extends BaseEntity { private boolean deleted; + @Version + private Long version; + @ManyToOne @JoinColumn(name = "category_id") private Category category; diff --git a/src/main/java/com/kt/service/order/OrderService.java b/src/main/java/com/kt/service/order/OrderService.java index 184de968..4daddf43 100644 --- a/src/main/java/com/kt/service/order/OrderService.java +++ b/src/main/java/com/kt/service/order/OrderService.java @@ -8,6 +8,7 @@ import java.util.Objects; import org.springframework.data.domain.Page; +import org.springframework.orm.ObjectOptimisticLockingFailureException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -124,10 +125,16 @@ public void save(Long orderId){ var order = orderRepository.findByIdOrThrow(orderId, ErrorCode.NOT_FOUND_ORDER); // stock 차감 - order.getOrderProducts().forEach(newProduct -> { + for (OrderProduct newProduct : order.getOrderProducts()) { var product = newProduct.getProduct(); - product.updateStock(product.getStock() - newProduct.getCount()); - }); + + try { + product.updateStock(product.getStock() - newProduct.getCount()); + productRepository.saveAndFlush(product); // 버전 체크 + } catch (ObjectOptimisticLockingFailureException e) { + throw new CustomException(ErrorCode.CONCURRENT_RESERVATION); + } + } order.updateStatus(OrderStatus.PAID); }