Skip to content

Commit c74e6ad

Browse files
committed
round3: 좋아요 내림차순 정렬 오류 수정
1 parent aa374c3 commit c74e6ad

6 files changed

Lines changed: 82 additions & 14 deletions

File tree

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,21 @@
88
import com.loopers.domain.product.ProductService;
99
import com.loopers.domain.supply.Supply;
1010
import com.loopers.domain.supply.SupplyService;
11+
import com.loopers.support.error.CoreException;
12+
import com.loopers.support.error.ErrorType;
1113
import lombok.RequiredArgsConstructor;
14+
import org.apache.commons.lang3.StringUtils;
1215
import org.springframework.data.domain.Page;
16+
import org.springframework.data.domain.PageRequest;
1317
import org.springframework.data.domain.Pageable;
18+
import org.springframework.data.domain.Sort;
1419
import org.springframework.stereotype.Component;
1520
import org.springframework.transaction.annotation.Transactional;
1621

1722
import java.util.List;
1823
import java.util.Map;
1924
import java.util.Set;
25+
import java.util.stream.Collectors;
2026

2127
@RequiredArgsConstructor
2228
@Component
@@ -28,6 +34,14 @@ public class ProductFacade {
2834

2935
@Transactional(readOnly = true)
3036
public Page<ProductInfo> getProductList(Pageable pageable) {
37+
String sortStr = pageable.getSort().toString().split(":")[0];
38+
if (StringUtils.equals(sortStr, "like_desc")) {
39+
int page = pageable.getPageNumber();
40+
int size = pageable.getPageSize();
41+
Sort sort = Sort.by(Sort.Direction.DESC, "likeCount");
42+
return getProductsByLikeCount(PageRequest.of(page, size, sort));
43+
}
44+
3145
Page<Product> products = productService.getProducts(pageable);
3246

3347
List<Long> productIds = products.map(Product::getId).toList();
@@ -39,8 +53,50 @@ public Page<ProductInfo> getProductList(Pageable pageable) {
3953

4054
return products.map(product -> {
4155
ProductMetrics metrics = metricsMap.get(product.getId());
56+
if (metrics == null) {
57+
throw new CoreException(ErrorType.NOT_FOUND, "해당 상품의 메트릭 정보를 찾을 수 없습니다.");
58+
}
59+
Brand brand = brandMap.get(product.getBrandId());
60+
if (brand == null) {
61+
throw new CoreException(ErrorType.NOT_FOUND, "해당 상품의 브랜드 정보를 찾을 수 없습니다.");
62+
}
63+
Supply supply = supplyMap.get(product.getId());
64+
if (supply == null) {
65+
throw new CoreException(ErrorType.NOT_FOUND, "해당 상품의 재고 정보를 찾을 수 없습니다.");
66+
}
67+
68+
return new ProductInfo(
69+
product.getId(),
70+
product.getName(),
71+
brand.getName(),
72+
product.getPrice().amount(),
73+
metrics.getLikeCount(),
74+
supply.getStock().quantity()
75+
);
76+
});
77+
}
78+
79+
public Page<ProductInfo> getProductsByLikeCount(Pageable pageable) {
80+
Page<ProductMetrics> metricsPage = productMetricsService.getMetrics(pageable);
81+
List<Long> productIds = metricsPage.map(ProductMetrics::getProductId).toList();
82+
Map<Long, Product> productMap = productService.getProductMapByIds(productIds);
83+
Set<Long> brandIds = productMap.values().stream().map(Product::getBrandId).collect(Collectors.toSet());
84+
Map<Long, Brand> brandMap = brandService.getBrandMapByBrandIds(brandIds);
85+
Map<Long, Supply> supplyMap = supplyService.getSupplyMapByProductIds(productIds);
86+
87+
return metricsPage.map(metrics -> {
88+
Product product = productMap.get(metrics.getProductId());
89+
if (product == null) {
90+
throw new CoreException(ErrorType.NOT_FOUND, "해당 상품 정보를 찾을 수 없습니다.");
91+
}
4292
Brand brand = brandMap.get(product.getBrandId());
93+
if (brand == null) {
94+
throw new CoreException(ErrorType.NOT_FOUND, "해당 상품의 브랜드 정보를 찾을 수 없습니다.");
95+
}
4396
Supply supply = supplyMap.get(product.getId());
97+
if (supply == null) {
98+
throw new CoreException(ErrorType.NOT_FOUND, "해당 상품의 재고 정보를 찾을 수 없습니다.");
99+
}
44100

45101
return new ProductInfo(
46102
product.getId(),
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.loopers.domain.metrics.product;
22

3+
import org.springframework.data.domain.Page;
4+
import org.springframework.data.domain.Pageable;
5+
36
import java.util.Collection;
4-
import java.util.List;
57
import java.util.Optional;
68

79
public interface ProductMetricsRepository {
810
Optional<ProductMetrics> findByProductId(Long productId);
911

1012
Collection<ProductMetrics> findByProductIds(Collection<Long> productIds);
13+
14+
Page<ProductMetrics> findAll(Pageable pageable);
1115
}

apps/commerce-api/src/main/java/com/loopers/domain/metrics/product/ProductMetricsService.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.loopers.support.error.CoreException;
44
import com.loopers.support.error.ErrorType;
55
import lombok.RequiredArgsConstructor;
6+
import org.springframework.data.domain.Page;
7+
import org.springframework.data.domain.Pageable;
68
import org.springframework.stereotype.Component;
79

810
import java.util.Collection;
@@ -24,4 +26,14 @@ public Map<Long, ProductMetrics> getMetricsMapByProductIds(Collection<Long> prod
2426
.stream()
2527
.collect(Collectors.toMap(ProductMetrics::getProductId, metrics -> metrics));
2628
}
29+
30+
// pageable like_count 요건에 따라 정렬된 상위 N개 상품 메트릭 조회
31+
public Page<ProductMetrics> getMetrics(Pageable pageable) {
32+
// 현재는 like_count, desc만 가지므로, 예외처리 필요
33+
String sortString = pageable.getSort().toString();
34+
if (!sortString.equals("likeCount: DESC")) {
35+
throw new CoreException(ErrorType.BAD_REQUEST, "지원하지 않는 정렬 방식입니다.");
36+
}
37+
return productMetricsRepository.findAll(pageable);
38+
}
2739
}

apps/commerce-api/src/main/java/com/loopers/domain/product/ProductService.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ public Page<Product> getProducts(Pageable pageable) {
3535
int size = pageable.getPageSize();
3636
String sortStr = pageable.getSort().toString().split(":")[0];
3737
Sort sort = Sort.by(Sort.Direction.DESC, "createdAt");
38+
3839
if (StringUtils.startsWith(sortStr, "price_asc")) {
3940
sort = Sort.by(Sort.Direction.ASC, "price");
40-
} else if (StringUtils.equals(sortStr, "like_desc")) {
41-
sort = Sort.by(Sort.Direction.DESC, "like_count");
4241
}
4342
return productRepository.findAll(PageRequest.of(page, size, sort));
4443
}

apps/commerce-api/src/main/java/com/loopers/infrastructure/metrics/product/ProductMetricsRepositoryImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.loopers.domain.metrics.product.ProductMetrics;
44
import com.loopers.domain.metrics.product.ProductMetricsRepository;
55
import lombok.RequiredArgsConstructor;
6+
import org.springframework.data.domain.Page;
7+
import org.springframework.data.domain.Pageable;
68
import org.springframework.stereotype.Component;
79

810
import java.util.Collection;
@@ -22,4 +24,9 @@ public Optional<ProductMetrics> findByProductId(Long productId) {
2224
public Collection<ProductMetrics> findByProductIds(Collection<Long> productIds) {
2325
return jpaRepository.findAllById(productIds);
2426
}
27+
28+
@Override
29+
public Page<ProductMetrics> findAll(Pageable pageable) {
30+
return jpaRepository.findAll(pageable);
31+
}
2532
}

apps/commerce-api/src/main/java/com/loopers/interfaces/api/product/ProductV1Controller.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,7 @@ public class ProductV1Controller implements ProductV1ApiSpec {
2424
@RequestMapping(method = RequestMethod.GET)
2525
@Override
2626
public ApiResponse<ProductV1Dto.ProductsPageResponse> getProductList(@PageableDefault(size = 20) Pageable pageable) {
27-
int page = pageable.getPageNumber();
28-
int size = pageable.getPageSize();
29-
String sortStr = pageable.getSort().toString().split(":")[0];
30-
Sort sort = Sort.by(Sort.Direction.DESC, "createdAt");
31-
if (StringUtils.equals(sortStr, "price_asc")) {
32-
sort = Sort.by(Sort.Direction.ASC, "price");
33-
} else if (StringUtils.equals(sortStr, "like_desc")) {
34-
sort = Sort.by(Sort.Direction.DESC, "like_count");
35-
}
36-
37-
Page<ProductInfo> products = productFacade.getProductList(PageRequest.of(page, size, sort));
27+
Page<ProductInfo> products = productFacade.getProductList(pageable);
3828
ProductV1Dto.ProductsPageResponse response = ProductV1Dto.ProductsPageResponse.from(products);
3929
return ApiResponse.success(response);
4030
}

0 commit comments

Comments
 (0)