Skip to content

Commit 7dc1b19

Browse files
authored
Merge pull request #8 from Kimjipang/round03
Round03
2 parents 1ed162f + 7214996 commit 7dc1b19

30 files changed

Lines changed: 574 additions & 15 deletions
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.loopers.application.order;
2+
3+
import com.loopers.application.orderitem.OrderItemInfo;
4+
import com.loopers.domain.order.Order;
5+
import com.loopers.domain.order.OrderRepository;
6+
import com.loopers.domain.orderitem.OrderItem;
7+
import com.loopers.domain.orderitem.OrderItemRepository;
8+
import com.loopers.domain.product.Product;
9+
import com.loopers.domain.product.ProductRepository;
10+
import com.loopers.domain.user.UserRepository;
11+
import com.loopers.interfaces.api.order.OrderV1Dto;
12+
import com.loopers.support.error.CoreException;
13+
import com.loopers.support.error.ErrorType;
14+
import lombok.RequiredArgsConstructor;
15+
import org.springframework.stereotype.Component;
16+
import org.springframework.transaction.annotation.Transactional;
17+
18+
import java.math.BigDecimal;
19+
import java.util.List;
20+
21+
@Component
22+
@RequiredArgsConstructor
23+
public class OrderFacade {
24+
private final OrderRepository orderRepository;
25+
private final OrderItemRepository orderItemRepository;
26+
private final UserRepository userRepository;
27+
private final ProductRepository productRepository;
28+
29+
@Transactional
30+
public OrderResultInfo createOrder(OrderV1Dto.OrderRequest request) {
31+
/*
32+
- [ ] 사용자 존재 여부 확인
33+
- [ ] OrderRequest 내에서 OrderItemRequest 목록을 순회하며 상품 존재 여부 확인
34+
- [ ] OrderItem 목록 생성
35+
*/
36+
37+
Long userId = request.userId();
38+
39+
userRepository.findById(userId).orElseThrow(
40+
() -> new CoreException(ErrorType.BAD_REQUEST, "존재하는 유저가 아닙니다.")
41+
);
42+
43+
List<OrderV1Dto.OrderItemRequest> orderItemRequests = request.orderItems();
44+
45+
List<OrderItem> orderItems = orderItemRequests.stream()
46+
.map(item -> {
47+
Long productId = item.productId();
48+
Product product = productRepository.findById(productId).orElseThrow(
49+
() -> new CoreException(ErrorType.NOT_FOUND, "존재하는 상품이 아닙니다.")
50+
);
51+
52+
OrderItem orderItem = item.toEntity(
53+
null,
54+
product.getPrice().multiply(BigDecimal.valueOf(item.quantity()))
55+
);
56+
return orderItem;
57+
58+
})
59+
.toList();
60+
61+
BigDecimal totalPrice = orderItems.stream()
62+
.map(OrderItem::getOrderPrice)
63+
.reduce(BigDecimal.ZERO, BigDecimal::add);
64+
65+
Order order = request.toEntity(totalPrice);
66+
67+
Order saved = orderRepository.save(order);
68+
69+
orderItems.forEach(item -> item.assignOrderId(saved.getId()));
70+
orderItemRepository.saveAll(orderItems);
71+
72+
orderItems.forEach(item -> {
73+
Long productId = item.getProductId();
74+
75+
Product product = productRepository.findById(productId).orElseThrow(
76+
() -> new CoreException(ErrorType.NOT_FOUND, "존재하는 상품이 아닙니다.")
77+
);
78+
79+
product.decreaseStock(item.getQuantity());
80+
81+
});
82+
83+
List<OrderItemInfo> orderItemInfos = orderItems.stream()
84+
.map(orderItem -> OrderItemInfo.from(orderItem, orderItem.getOrderPrice()))
85+
.toList();
86+
87+
return new OrderResultInfo(OrderInfo.from(saved), orderItemInfos);
88+
}
89+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.loopers.application.order;
2+
3+
import com.loopers.domain.order.Order;
4+
import com.loopers.domain.order.OrderStatus;
5+
6+
import java.math.BigDecimal;
7+
import java.time.ZonedDateTime;
8+
9+
public record OrderInfo(
10+
Long id,
11+
Long userId,
12+
OrderStatus orderStatus,
13+
BigDecimal totalPrice,
14+
ZonedDateTime createdAt
15+
) {
16+
public static OrderInfo from(Order order) {
17+
return new OrderInfo(
18+
order.getId(),
19+
order.getUserId(),
20+
order.getOrderStatus(),
21+
order.getTotalPrice(),
22+
order.getCreatedAt()
23+
);
24+
}
25+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.loopers.application.order;
2+
3+
import com.loopers.application.orderitem.OrderItemInfo;
4+
5+
import java.util.List;
6+
7+
public record OrderResultInfo(
8+
OrderInfo orderInfo,
9+
List<OrderItemInfo> orderItemInfos
10+
) {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.loopers.application.orderitem;
2+
3+
import com.loopers.domain.orderitem.OrderItem;
4+
5+
import java.math.BigDecimal;
6+
7+
public record OrderItemInfo(Long id, Long orderId, Long productId, int quantity, BigDecimal orderPrice) {
8+
public static OrderItemInfo from(OrderItem orderItem, BigDecimal productPrice) {
9+
return new OrderItemInfo(
10+
orderItem.getId(),
11+
orderItem.getOrderId(),
12+
orderItem.getProductId(),
13+
orderItem.getQuantity(),
14+
productPrice.multiply(BigDecimal.valueOf(orderItem.getQuantity()))
15+
);
16+
}
17+
}

apps/commerce-api/src/main/java/com/loopers/application/product/ProductFacade.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.loopers.domain.like.LikeRepository;
44
import com.loopers.domain.product.Product;
55
import com.loopers.domain.product.ProductRepository;
6-
import com.loopers.domain.user.UserRepository;
76
import com.loopers.interfaces.api.product.ProductV1Dto;
87
import com.loopers.support.error.CoreException;
98
import com.loopers.support.error.ErrorType;
@@ -28,7 +27,7 @@ public ProductInfo registerProduct(ProductV1Dto.ProductRequest request) {
2827
return ProductInfo.from(product, 0);
2928
}
3029

31-
@Transactional
30+
@Transactional(readOnly = true)
3231
public List<ProductInfo> findAllProducts() {
3332
List<Product> products = productRepository.findAll();
3433

@@ -51,4 +50,17 @@ public ProductInfo findProductById(Long id) {
5150
return ProductInfo.from(product, likeCount);
5251
}
5352

53+
@Transactional(readOnly = true)
54+
public List<ProductInfo> searchProductsByCondition(ProductV1Dto.SearchProductRequest request) {
55+
request.sortCondition().conditionValidate();
56+
57+
List<Product> products = productRepository.searchProductsByCondition(request);
58+
59+
return products.stream()
60+
.map(product -> {
61+
int likeCount = likeRepository.countByProductId(product.getId());
62+
return ProductInfo.from(product, likeCount);
63+
})
64+
.toList();
65+
}
5466
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.loopers.domain.brand;
2+
3+
import com.loopers.domain.BaseEntity;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.Table;
7+
import lombok.AccessLevel;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
11+
@Getter
12+
@Entity
13+
@Table(name = "brand")
14+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
15+
public class Brand extends BaseEntity {
16+
@Column(name = "name", nullable = false)
17+
private String name;
18+
19+
@Column(name = "description", nullable = false)
20+
private String description;
21+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.loopers.domain.order;
2+
3+
import com.loopers.domain.BaseEntity;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.Table;
7+
import lombok.AccessLevel;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
11+
import java.math.BigDecimal;
12+
13+
@Entity
14+
@Getter
15+
@Table(name = "orders")
16+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
17+
public class Order extends BaseEntity {
18+
@Column(name = "ref_user_id", nullable = false)
19+
private Long userId;
20+
21+
@Column(name = "total_price", nullable = false)
22+
private BigDecimal totalPrice;
23+
24+
@Column(name = "order_status", nullable = false)
25+
private OrderStatus orderStatus;
26+
27+
public Order(Long userId, BigDecimal totalPrice, OrderStatus orderStatus) {
28+
this.userId = userId;
29+
this.totalPrice = totalPrice;
30+
this.orderStatus = orderStatus;
31+
}
32+
33+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.loopers.domain.order;
2+
3+
public interface OrderRepository {
4+
Order save(Order order);
5+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.loopers.domain.order;
2+
3+
import lombok.Getter;
4+
5+
@Getter
6+
public enum OrderStatus {
7+
READY("준비중"),
8+
SHIPPING("배송중"),
9+
DELIVERED("배송완료"),
10+
CANCELLED("배송취소");
11+
12+
private final String description;
13+
14+
OrderStatus(String description) {
15+
this.description = description;
16+
}
17+
18+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.loopers.domain.orderitem;
2+
3+
import com.loopers.domain.BaseEntity;
4+
import com.loopers.support.error.CoreException;
5+
import com.loopers.support.error.ErrorType;
6+
import jakarta.persistence.Column;
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Table;
9+
import lombok.AccessLevel;
10+
import lombok.Getter;
11+
import lombok.NoArgsConstructor;
12+
13+
import java.math.BigDecimal;
14+
15+
@Entity
16+
@Table(name = "order_item")
17+
@Getter
18+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
19+
public class OrderItem extends BaseEntity {
20+
@Column(name = "ref_order_id", nullable = false)
21+
private Long orderId;
22+
23+
@Column(name = "ref_product_id", nullable = false)
24+
private Long productId;
25+
26+
@Column(name = "quantity", nullable = false)
27+
private int quantity;
28+
29+
@Column(name = "order_price", nullable = false)
30+
private BigDecimal orderPrice;
31+
32+
public OrderItem(Long orderId, Long productId, int quantity, BigDecimal orderPrice) {
33+
if (quantity <= 0) {
34+
throw new CoreException(ErrorType.BAD_REQUEST, "주문 수량은 0보다 커야 합니다.");
35+
}
36+
37+
if (orderPrice.compareTo(BigDecimal.ZERO) < 0) {
38+
throw new CoreException(ErrorType.BAD_REQUEST, "주문 가격은 음수일 수 없습니다.");
39+
}
40+
41+
this.orderId = orderId;
42+
this.productId = productId;
43+
this.quantity = quantity;
44+
this.orderPrice = orderPrice;
45+
}
46+
47+
public void updateQuantity(int quantity) {
48+
if (quantity <= 0) {
49+
throw new CoreException(ErrorType.BAD_REQUEST, "주문 수량은 0보다 커야 합니다.");
50+
}
51+
this.quantity = quantity;
52+
}
53+
54+
public void assignOrderId(Long orderId) {
55+
this.orderId = orderId;
56+
}
57+
58+
59+
60+
}

0 commit comments

Comments
 (0)