Skip to content

Commit d9f23f0

Browse files
committed
feat: RankingFacade 클래스 추가 및 랭킹 조회 기능 구현
1 parent 6c51a58 commit d9f23f0

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package com.loopers.application.ranking;
2+
3+
import com.loopers.domain.product.Product;
4+
import com.loopers.domain.product.ProductRepository;
5+
import com.loopers.domain.ranking.RankingEntry;
6+
import com.loopers.domain.ranking.RankingInfo;
7+
import com.loopers.domain.ranking.RankingService;
8+
import lombok.RequiredArgsConstructor;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.stereotype.Component;
11+
import org.springframework.transaction.annotation.Transactional;
12+
13+
import java.time.Clock;
14+
import java.time.LocalDate;
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.stream.Collectors;
19+
20+
@Slf4j
21+
@Component
22+
@RequiredArgsConstructor
23+
public class RankingFacade {
24+
25+
private final RankingService rankingService;
26+
private final ProductRepository productRepository;
27+
private final Clock clock;
28+
29+
/**
30+
* 랭킹 페이지 조회
31+
*/
32+
@Transactional(readOnly = true)
33+
public RankingPageInfo getRankingPage(RankingCommand command) {
34+
List<RankingEntry> entries = rankingService.getRankingPage(
35+
command.date(),
36+
command.page(),
37+
command.size()
38+
);
39+
40+
if (entries.isEmpty()) {
41+
return RankingPageInfo.empty(command.date(), command.page(), command.size());
42+
}
43+
44+
// 상품 정보 조회
45+
List<Long> productIds = entries.stream()
46+
.map(RankingEntry::productId)
47+
.collect(Collectors.toList());
48+
49+
Map<Long, Product> productMap = productRepository.findAllByIds(productIds).stream()
50+
.collect(Collectors.toMap(Product::getId, p -> p));
51+
52+
// 랭킹 정보 조합
53+
List<RankingInfo> rankings = new ArrayList<>();
54+
long startRank = (long) command.page() * command.size() + 1;
55+
56+
for (int i = 0; i < entries.size(); i++) {
57+
RankingEntry entry = entries.get(i);
58+
Product product = productMap.get(entry.productId());
59+
60+
if (product != null) {
61+
rankings.add(RankingInfo.of(
62+
product.getId(),
63+
product.getName(),
64+
product.getPriceValue(),
65+
product.getBrand().getName(),
66+
startRank + i,
67+
entry.score()
68+
));
69+
}
70+
}
71+
72+
Long totalCount = rankingService.getRankingSize(command.date());
73+
74+
return RankingPageInfo.of(
75+
rankings,
76+
command.date(),
77+
command.page(),
78+
command.size(),
79+
totalCount
80+
);
81+
}
82+
83+
/**
84+
* Top-N 랭킹 조회
85+
*/
86+
@Transactional(readOnly = true)
87+
public List<RankingInfo> getTopN(LocalDate date, int n) {
88+
List<RankingEntry> entries = rankingService.getTopNWithScores(date, n);
89+
90+
if (entries.isEmpty()) {
91+
return List.of();
92+
}
93+
94+
List<Long> productIds = entries.stream()
95+
.map(RankingEntry::productId)
96+
.collect(Collectors.toList());
97+
98+
Map<Long, Product> productMap = productRepository.findAllByIds(productIds).stream()
99+
.collect(Collectors.toMap(Product::getId, p -> p));
100+
101+
List<RankingInfo> rankings = new ArrayList<>();
102+
for (int i = 0; i < entries.size(); i++) {
103+
RankingEntry entry = entries.get(i);
104+
Product product = productMap.get(entry.productId());
105+
106+
if (product != null) {
107+
rankings.add(RankingInfo.of(
108+
product.getId(),
109+
product.getName(),
110+
product.getPriceValue(),
111+
product.getBrand().getName(),
112+
(long) (i + 1),
113+
entry.score()
114+
));
115+
}
116+
}
117+
118+
return rankings;
119+
}
120+
121+
/**
122+
* 특정 상품의 순위 조회
123+
*/
124+
public Long getProductRank(Long productId, LocalDate date) {
125+
return rankingService.getRank(productId, date);
126+
}
127+
128+
/**
129+
* 특정 상품의 순위 조회 (오늘 기준)
130+
*/
131+
public Long getProductRankToday(Long productId) {
132+
return rankingService.getRank(productId, LocalDate.now(clock));
133+
}
134+
}

0 commit comments

Comments
 (0)