11package com .loopers .application .order ;
22
3+ import com .loopers .domain .order .OrderItemModel ;
4+ import com .loopers .domain .order .OrderItemStatus ;
35import com .loopers .domain .order .OrderModel ;
46import com .loopers .domain .order .OrderService ;
7+ import com .loopers .domain .product .ProductModel ;
58import com .loopers .domain .product .ProductService ;
69import com .loopers .domain .user .UserModel ;
710import com .loopers .domain .user .UserService ;
11+ import com .loopers .support .error .CoreException ;
12+ import com .loopers .support .error .ErrorType ;
813import lombok .RequiredArgsConstructor ;
914import org .springframework .stereotype .Service ;
1015import org .springframework .transaction .annotation .Transactional ;
@@ -20,42 +25,112 @@ public class UserOrderProductFacade {
2025 private final UserService userService ;
2126
2227 @ Transactional (readOnly = true )
23- public boolean preOrder (Long userPkId , List <OrderLineCommand > orderLines ) {
24- productService .markCurrentStockStatus (orderLines );
25- UserModel userModel = userService .getUser (userPkId );
26- Integer total = productService .getTotalAmountOfAvailStock (orderLines );
27- return userModel .hasEnoughPoint (total );
28+ public OrderResult .PreOrderResult preOrder (OrderCommand .Order orderCommand ) {
29+ UserModel userModel = userService .getUser (orderCommand .userId ());
30+ StockResult result = readAllStocks (orderCommand .orderLineRequests ());
31+ if (!userModel .hasEnoughPoint (result .requiringPrice ())) {
32+ throw new CoreException (ErrorType .BAD_REQUEST , "포인트가 부족합니다." );
33+ }
34+
35+ return OrderResult .PreOrderResult .of (
36+ userModel .getUserId (),
37+ result .requiringPrice (),
38+ result .successLines (),
39+ result .failedLines ()
40+ );
2841 }
2942
43+ /**
44+ *
45+ * @param orderCommand
46+ */
3047 @ Transactional
31- public void placeOrder (Long userPkId , List <OrderLineCommand > orderLines ) {
32- OrderModel order = orderService .putOrder (orderLines );
33- StockDecreaseResult stockResult = decreaseAllStocks (orderLines );
34- // TODO 클린 아키텍처 고려하기
35- orderService .putFailStatus (order , stockResult .failedLines ());
36- Integer totalAmountPoint = stockResult .totalAmount ();
37-
38- // 포인트 부족 시 예외 → 전체 롤백
39- userService .decreaseUserPoint (userPkId , totalAmountPoint );
48+ public OrderResult .PlaceOrderResult placeOrder (OrderCommand .Order orderCommand ) {
49+ UserModel userModel = userService .getUser (orderCommand .userId ());
50+ List <OrderItemModel > orderItems = toDomainOrderItem (orderCommand .orderLineRequests ());
51+ OrderModel orderModel = orderService .createPendingOrder (userModel , orderItems );
52+
53+ StockResult stockResult = decreaseAllStocks (orderItems );
54+
55+ Integer requiringPoints = stockResult .requiringPrice ();
56+ // 포인트 부족 시 롤백
57+ if (!userModel .hasEnoughPoint (requiringPoints )) {
58+ throw new CoreException (ErrorType .BAD_REQUEST , "포인트가 부족합니다. 다시 확인해주세요" );
59+ }
60+
61+ userService .decreaseUserPoint (userModel .getId (), requiringPoints );
62+
63+ boolean hasOutOfStockCase = !stockResult .failedLines ().isEmpty ();
64+ if (hasOutOfStockCase ) {
65+ orderService .updateOrderAsPartialSuccess (orderModel , stockResult .requiringPrice () , stockResult .errorPrice ());
66+ } else {
67+ orderService .updateOrderAsSuccess (orderModel , stockResult .requiringPrice ());
68+ }
69+
70+
71+ return OrderResult .PlaceOrderResult .of (
72+ userModel .getUserId (),
73+ orderModel .getId (),
74+ stockResult .requiringPrice (),
75+ stockResult .errorPrice (),
76+ stockResult .successLines (),
77+ stockResult .failedLines ()
78+ );
4079 }
4180
4281 @ Transactional
43- protected StockDecreaseResult decreaseAllStocks (List <OrderLineCommand > lines ) {
44- List <OrderLineCommand > success = new ArrayList <>();
45- List <OrderLineCommand > failed = new ArrayList <>();
46- int total = 0 ;
82+ protected StockResult decreaseAllStocks (List <OrderItemModel > items ) {
83+ List <OrderCommand . OrderLine > success = new ArrayList <>();
84+ List <OrderCommand . OrderLine > failed = new ArrayList <>();
85+ int total = 0 , fail = 0 ;
4786
48- for (OrderLineCommand line : lines ) {
87+ for (OrderItemModel item : items ) {
88+ ProductModel p = item .getProduct ();
89+ boolean ok = productService .decreaseStock (p .getId (), item .getQuantity ());
90+ OrderCommand .OrderLine line = OrderCommand .OrderLine .from (item );
91+ int requiringPoint = productService .getPrice (p .getId (), item .getQuantity ());
92+ if (ok ) {
93+ item .setStatus (OrderItemStatus .SUCCESS );
94+ total += requiringPoint ;
95+ success .add (line );
96+ } else {
97+ item .setStatus (OrderItemStatus .FAILED );
98+ fail += requiringPoint ;
99+ failed .add (line );
100+ }
101+ }
102+
103+ return StockResult .of (success , failed , total , fail );
104+ }
105+
106+ protected StockResult readAllStocks (List <OrderCommand .OrderLine > lines ) {
107+ List <OrderCommand .OrderLine > success = new ArrayList <>();
108+ List <OrderCommand .OrderLine > failed = new ArrayList <>();
109+ int requiringPrice = 0 , errorPrice = 0 ;
110+
111+ for (OrderCommand .OrderLine line : lines ) {
49112 // TODO 엔티티 클래스에서 예외 발생시 포인트 계산 제대로 되는지 확인 필요
50- boolean ok = productService .decreaseStock (line .productId (), line .quantity ());
113+ boolean ok = productService .hasStock (line .productId (), line .quantity ());
114+ int point = productService .getPrice (line .productId (), line .quantity ());
51115 if (ok ) {
52116 success .add (line );
53- total += productService . getPrice ( line . productId (), line . quantity ()) ;
117+ requiringPrice += point ;
54118 } else {
55119 failed .add (line );
120+ errorPrice += point ;
56121 }
57122 }
123+ return StockResult .of (success , failed , requiringPrice , errorPrice );
124+ }
125+
126+
127+ public List <OrderItemModel > toDomainOrderItem (List <OrderCommand .OrderLine > lines ) {
128+ return lines .stream ()
129+ .map (l -> {
130+ ProductModel p = productService .getProductDetail (l .productId ());
131+ return OrderItemModel .of (p , l .quantity ());
132+ })
133+ .toList ();
58134
59- return StockDecreaseResult .of (success , failed , total );
60135 }
61136}
0 commit comments