Skip to content

Commit 339132b

Browse files
authored
Merge pull request #95 from JVHE/round3
Round3: Product, Brand, Like, Order
2 parents 34df8d5 + 4ca321e commit 339132b

95 files changed

Lines changed: 7075 additions & 93 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/commerce-api/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
dependencies {
22
// add-ons
33
implementation(project(":modules:jpa"))
4-
implementation(project(":modules:redis"))
4+
// implementation(project(":modules:redis"))
55
implementation(project(":supports:jackson"))
66
implementation(project(":supports:logging"))
77
implementation(project(":supports:monitoring"))
@@ -18,5 +18,5 @@ dependencies {
1818

1919
// test-fixtures
2020
testImplementation(testFixtures(project(":modules:jpa")))
21-
testImplementation(testFixtures(project(":modules:redis")))
21+
// testImplementation(testFixtures(project(":modules:redis")))
2222
}

apps/commerce-api/src/main/java/com/loopers/CommerceApiApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import org.springframework.boot.SpringApplication;
55
import org.springframework.boot.autoconfigure.SpringBootApplication;
66
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
7+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
8+
79
import java.util.TimeZone;
810

911
@ConfigurationPropertiesScan
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.loopers.application.like.product;
2+
3+
import com.loopers.domain.brand.Brand;
4+
import com.loopers.domain.brand.BrandService;
5+
import com.loopers.domain.like.product.LikeProduct;
6+
import com.loopers.domain.like.product.LikeProductService;
7+
import com.loopers.domain.metrics.product.ProductMetrics;
8+
import com.loopers.domain.metrics.product.ProductMetricsService;
9+
import com.loopers.domain.product.Product;
10+
import com.loopers.domain.product.ProductService;
11+
import com.loopers.domain.supply.Supply;
12+
import com.loopers.domain.supply.SupplyService;
13+
import com.loopers.domain.user.User;
14+
import com.loopers.domain.user.UserService;
15+
import com.loopers.support.error.CoreException;
16+
import com.loopers.support.error.ErrorType;
17+
import lombok.RequiredArgsConstructor;
18+
import org.springframework.data.domain.Page;
19+
import org.springframework.data.domain.Pageable;
20+
import org.springframework.stereotype.Component;
21+
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.Set;
25+
import java.util.stream.Collectors;
26+
27+
@RequiredArgsConstructor
28+
@Component
29+
public class LikeProductFacade {
30+
private final LikeProductService likeProductService;
31+
private final UserService userService;
32+
private final ProductService productService;
33+
private final ProductMetricsService productMetricsService;
34+
private final BrandService brandService;
35+
private final SupplyService supplyService;
36+
37+
public void likeProduct(String userId, Long productId) {
38+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
39+
if (!productService.existsById(productId)) {
40+
throw new CoreException(ErrorType.NOT_FOUND, "상품을 찾을 수 없습니다.");
41+
}
42+
likeProductService.likeProduct(user.getId(), productId);
43+
}
44+
45+
public void unlikeProduct(String userId, Long productId) {
46+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
47+
if (!productService.existsById(productId)) {
48+
throw new CoreException(ErrorType.NOT_FOUND, "상품을 찾을 수 없습니다.");
49+
}
50+
likeProductService.unlikeProduct(user.getId(), productId);
51+
}
52+
53+
public Page<LikeProductInfo> getLikedProducts(String userId, Pageable pageable) {
54+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
55+
Page<LikeProduct> likedProducts = likeProductService.getLikedProducts(user.getId(), pageable);
56+
57+
List<Long> productIds = likedProducts.map(LikeProduct::getProductId).toList();
58+
Map<Long, Product> productMap = productService.getProductMapByIds(productIds);
59+
60+
Set<Long> brandIds = productMap.values().stream().map(Product::getBrandId).collect(Collectors.toSet());
61+
62+
Map<Long, ProductMetrics> metricsMap = productMetricsService.getMetricsMapByProductIds(productIds);
63+
Map<Long, Supply> supplyMap = supplyService.getSupplyMapByProductIds(productIds);
64+
Map<Long, Brand> brandMap = brandService.getBrandMapByBrandIds(brandIds);
65+
66+
return likedProducts.map(likeProduct -> {
67+
Product product = productMap.get(likeProduct.getProductId());
68+
ProductMetrics metrics = metricsMap.get(product.getId());
69+
Brand brand = brandMap.get(product.getBrandId());
70+
Supply supply = supplyMap.get(product.getId());
71+
72+
return new LikeProductInfo(
73+
product.getId(),
74+
product.getName(),
75+
brand.getName(),
76+
product.getPrice().amount(),
77+
metrics.getLikeCount(),
78+
supply.getStock().quantity()
79+
);
80+
});
81+
82+
}
83+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.loopers.application.like.product;
2+
3+
public record LikeProductInfo(
4+
Long id,
5+
String name,
6+
String brand,
7+
int price,
8+
int likes,
9+
int stock
10+
) {
11+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.loopers.application.order;
2+
3+
import com.loopers.domain.order.Order;
4+
import com.loopers.domain.order.OrderService;
5+
import com.loopers.domain.point.PointService;
6+
import com.loopers.domain.product.Product;
7+
import com.loopers.domain.product.ProductService;
8+
import com.loopers.domain.supply.SupplyService;
9+
import com.loopers.domain.user.User;
10+
import com.loopers.domain.user.UserService;
11+
import com.loopers.support.error.CoreException;
12+
import com.loopers.support.error.ErrorType;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.data.domain.Page;
15+
import org.springframework.data.domain.Pageable;
16+
import org.springframework.stereotype.Component;
17+
import org.springframework.transaction.annotation.Transactional;
18+
19+
import java.util.Map;
20+
import java.util.stream.Collectors;
21+
22+
@RequiredArgsConstructor
23+
@Component
24+
public class OrderFacade {
25+
private final UserService userService;
26+
private final OrderService orderService;
27+
private final ProductService productService;
28+
private final PointService pointService;
29+
private final SupplyService supplyService;
30+
31+
@Transactional(readOnly = true)
32+
public OrderInfo getOrderInfo(String userId, Long orderId) {
33+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
34+
Order order = orderService.getOrderByIdAndUserId(orderId, user.getId());
35+
36+
return OrderInfo.from(order);
37+
}
38+
39+
@Transactional(readOnly = true)
40+
public Page<OrderInfo> getOrderList(String userId, Pageable pageable) {
41+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
42+
Page<Order> orders = orderService.getOrdersByUserId(user.getId(), pageable);
43+
return orders.map(OrderInfo::from);
44+
}
45+
46+
@Transactional
47+
public OrderInfo createOrder(String userId, OrderRequest request) {
48+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
49+
50+
Map<Long, Integer> productIdQuantityMap = request.items().stream()
51+
.collect(Collectors.toMap(OrderItemRequest::productId, OrderItemRequest::quantity));
52+
53+
Map<Long, Product> productMap = productService.getProductMapByIds(productIdQuantityMap.keySet());
54+
55+
request.items().forEach(item -> {
56+
supplyService.checkAndDecreaseStock(item.productId(), item.quantity());
57+
});
58+
59+
Integer totalAmount = productService.calculateTotalAmount(productIdQuantityMap);
60+
pointService.checkAndDeductPoint(user.getId(), totalAmount);
61+
62+
Order order = orderService.createOrder(request.items(), productMap, user.getId());
63+
64+
return OrderInfo.from(order);
65+
}
66+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.loopers.application.order;
2+
3+
import com.loopers.domain.order.Order;
4+
5+
import java.util.List;
6+
7+
public record OrderInfo(
8+
Long orderId,
9+
Long userId,
10+
Integer totalPrice,
11+
List<OrderItemInfo> items
12+
) {
13+
public static OrderInfo from(Order order) {
14+
return new OrderInfo(
15+
order.getId(),
16+
order.getUserId(),
17+
order.getTotalPrice().amount(),
18+
OrderItemInfo.fromList(order.getOrderItems())
19+
);
20+
}
21+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.loopers.application.order;
2+
3+
import com.loopers.domain.order.OrderItem;
4+
5+
import java.util.List;
6+
7+
public record OrderItemInfo(
8+
Long productId,
9+
String productName,
10+
Integer quantity,
11+
Integer totalPrice
12+
) {
13+
public static OrderItemInfo from(OrderItem orderItem) {
14+
return new OrderItemInfo(
15+
orderItem.getProductId(),
16+
orderItem.getProductName(),
17+
orderItem.getQuantity(),
18+
orderItem.getTotalPrice()
19+
);
20+
}
21+
22+
public static List<OrderItemInfo> fromList(List<OrderItem> items) {
23+
return items.stream()
24+
.map(OrderItemInfo::from)
25+
.toList();
26+
}
27+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.loopers.application.order;
2+
3+
public record OrderItemRequest(
4+
Long productId,
5+
Integer quantity
6+
) {
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.loopers.application.order;
2+
3+
import java.util.List;
4+
5+
public record OrderRequest(
6+
List<OrderItemRequest> items
7+
) {
8+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.loopers.application.point;
2+
3+
import com.loopers.domain.point.PointService;
4+
import com.loopers.domain.user.User;
5+
import com.loopers.domain.user.UserService;
6+
import com.loopers.support.error.CoreException;
7+
import com.loopers.support.error.ErrorType;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.stereotype.Component;
10+
import org.springframework.transaction.annotation.Transactional;
11+
12+
@RequiredArgsConstructor
13+
@Component
14+
public class PointFacade {
15+
private final PointService pointService;
16+
private final UserService userService;
17+
18+
@Transactional(readOnly = true)
19+
public Long getCurrentPoint(String userId) {
20+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
21+
22+
return pointService.getCurrentPoint(user.getId())
23+
.orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
24+
}
25+
26+
@Transactional
27+
public Long chargePoint(String userId, int amount) {
28+
User user = userService.findByUserIdForUpdate(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
29+
30+
return pointService.chargePoint(user.getId(), amount);
31+
}
32+
}

0 commit comments

Comments
 (0)