4444import org .springframework .http .HttpHeaders ;
4545import org .springframework .http .MediaType ;
4646import org .springframework .http .ResponseEntity ;
47+ import org .springframework .scheduling .annotation .Async ;
4748import org .springframework .stereotype .Service ;
4849import org .springframework .transaction .annotation .Transactional ;
4950import org .springframework .web .client .HttpClientErrorException ;
@@ -204,6 +205,9 @@ public OrderApproveResponseDto approveOrder(Long memberId, OrderApproveRequestDt
204205 // 최초 구매 시 포인트 지급
205206 pointCommandService .addFirstPurchasePointsIfPossible (member );
206207
208+ // 30초 후 배송 시작 스케줄링
209+ scheduleShippingStart (order .getId ());
210+
207211 return OrderApproveResponseDto .of (order );
208212
209213 } catch (HttpClientErrorException e ) { // 400번대 에러
@@ -215,6 +219,9 @@ public OrderApproveResponseDto approveOrder(Long memberId, OrderApproveRequestDt
215219 } catch (Exception e ) {
216220 log .error ("[OrderCommandService] 주문 생성 실패 - 회원ID: {}, 에러: {}" , memberId , e .getMessage (), e );
217221 order .updateStatus (OrderStatus .ABORTED );
222+ // OrderProduct도 함께 취소 상태로 변경
223+ order .getOrderProducts ().forEach (orderProduct ->
224+ orderProduct .updateStatus (OrderStatus .ABORTED ));
218225 throw new GeneralException (ErrorStatus ._INTERNAL_SERVER_ERROR );
219226 }
220227 }
@@ -308,6 +315,9 @@ public OrderRefundResponseDto refundOrder(Long memberId, OrderRefundRequestDto r
308315 }
309316
310317 order .updateStatus (OrderStatus .REFUNDED );
318+ // OrderProduct도 함께 환불 상태로 변경
319+ order .getOrderProducts ().forEach (orderProduct ->
320+ orderProduct .updateStatus (OrderStatus .REFUNDED ));
311321
312322 // 환불 성공 시 구매 통계에서 판매 개수만큼 수량 줄이기
313323 order .getOrderProducts ()
@@ -333,6 +343,9 @@ public OrderRefundResponseDto refundOrder(Long memberId, OrderRefundRequestDto r
333343 throw new TossPaymentException (ErrorStatus .TOSS_PAYMENT_SERVER_ERROR );
334344 } catch (Exception e ) {
335345 order .updateStatus (OrderStatus .REFUND_FAILED );
346+ // OrderProduct도 함께 환불 실패 상태로 변경
347+ order .getOrderProducts ().forEach (orderProduct ->
348+ orderProduct .updateStatus (OrderStatus .REFUND_FAILED ));
336349 log .error ("[OrderCommandService] 환불 처리 실패 - 주문ID: {}, 에러: {}" , request .orderId (), e .getMessage (), e );
337350 throw new GeneralException (ErrorStatus .REFUND_FAILED );
338351 }
@@ -443,4 +456,38 @@ private HttpHeaders getHeaders() {
443456
444457 return headers ;
445458 }
459+
460+ @ Async ("orderTaskExecutor" )
461+ protected void scheduleShippingStart (Long orderId ) {
462+ try {
463+ Thread .sleep (30000 ); // 30초 대기
464+ startShipping (orderId );
465+ } catch (InterruptedException e ) {
466+ log .error ("[OrderCommandService] 배송 시작 스케줄링 중단 - 주문ID: {}" , orderId , e );
467+ Thread .currentThread ().interrupt ();
468+ } catch (Exception e ) {
469+ log .error ("[OrderCommandService] 배송 시작 스케줄링 실패 - 주문ID: {}" , orderId , e );
470+ }
471+ }
472+
473+ @ Override
474+ @ Transactional
475+ public void startShipping (Long orderId ) {
476+ try {
477+ Order order = orderRepository .findById (orderId )
478+ .orElseThrow (() -> new BadRequestException (ErrorStatus .ORDER_NOT_FOUND ));
479+
480+ if (order .getOrderStatus () == OrderStatus .DONE ) {
481+ order .updateStatus (OrderStatus .SHIPPING );
482+ // OrderProduct들도 함께 배송 상태로 변경
483+ order .getOrderProducts ().forEach (orderProduct ->
484+ orderProduct .updateStatus (OrderStatus .SHIPPING ));
485+ log .info ("[OrderCommandService] 배송 시작 - 주문ID: {}" , orderId );
486+ } else {
487+ log .warn ("[OrderCommandService] 배송 시작 불가 - 주문ID: {}, 현재상태: {}" , orderId , order .getOrderStatus ());
488+ }
489+ } catch (Exception e ) {
490+ log .error ("[OrderCommandService] 배송 시작 실패 - 주문ID: {}" , orderId , e );
491+ }
492+ }
446493}
0 commit comments