33import com .loopers .application .product .ProductInfo ;
44import com .loopers .application .product .ProductService ;
55import com .loopers .application .ranking .RankingService .RankingItem ;
6+ import com .loopers .domain .rank .MonthlyProductRank ;
7+ import com .loopers .domain .rank .WeeklyProductRank ;
8+ import com .loopers .infrastructure .rank .MonthlyRankJpaRepository ;
9+ import com .loopers .infrastructure .rank .WeeklyRankJpaRepository ;
610import java .math .BigDecimal ;
711import java .util .ArrayList ;
812import java .util .List ;
913import java .util .Map ;
1014import java .util .stream .Collectors ;
1115import lombok .RequiredArgsConstructor ;
1216import lombok .extern .slf4j .Slf4j ;
17+ import org .springframework .data .domain .PageRequest ;
1318import org .springframework .stereotype .Service ;
1419
1520/**
16- * 랭킹 + 상품 정보 조합 Facade
21+ * Facade for combining ranking data with product information.
22+ *
23+ * <p>This service provides unified access to daily, weekly, and monthly rankings
24+ * by merging ranking data with detailed product information.
1725 */
1826@ Slf4j
1927@ Service
@@ -22,33 +30,117 @@ public class RankingFacade {
2230
2331 private final RankingService rankingService ;
2432 private final ProductService productService ;
33+ private final WeeklyRankJpaRepository weeklyRankJpaRepository ;
34+ private final MonthlyRankJpaRepository monthlyRankJpaRepository ;
2535
2636 /**
27- * 일간 랭킹 페이지 조회 (상품 정보 포함)
37+ * Retrieves daily rankings with product information.
38+ *
39+ * @param date the target date in yyyyMMdd format
40+ * @param page the page number (1-based)
41+ * @param size the page size
42+ * @return list of rankings with product details
2843 */
2944 public List <RankingProductInfo > getDailyRanking (String date , int page , int size ) {
30- // 1. Redis ZSET에서 랭킹 조회
3145 List <RankingItem > rankingItems = rankingService .getDailyRanking (date , page , size );
3246
3347 if (rankingItems .isEmpty ()) {
3448 return List .of ();
3549 }
3650
37- // 2. Product 정보 조회 (Batch)
51+ return combineWithProductInfo (rankingItems );
52+ }
53+
54+ /**
55+ * Retrieves today's rankings.
56+ *
57+ * @param page the page number (1-based)
58+ * @param size the page size
59+ * @return list of rankings with product details
60+ */
61+ public List <RankingProductInfo > getTodayRanking (int page , int size ) {
62+ String today = java .time .LocalDate .now ().format (java .time .format .DateTimeFormatter .ofPattern ("yyyyMMdd" ));
63+ return getDailyRanking (today , page , size );
64+ }
65+
66+ /**
67+ * Retrieves weekly rankings with product information.
68+ *
69+ * @param yearWeek the target week in ISO format (e.g., "2025-W01")
70+ * @param page the page number (1-based)
71+ * @param size the page size
72+ * @return list of rankings with product details
73+ */
74+ public List <RankingProductInfo > getWeeklyRanking (String yearWeek , int page , int size ) {
75+ PageRequest pageRequest = PageRequest .of (page - 1 , size );
76+ List <WeeklyProductRank > weeklyRanks = weeklyRankJpaRepository .findByYearWeekOrderByRankPositionAsc (
77+ yearWeek , pageRequest
78+ );
79+
80+ if (weeklyRanks .isEmpty ()) {
81+ return List .of ();
82+ }
83+
84+ return combineWithProductInfo (
85+ weeklyRanks .stream ()
86+ .map (rank -> new RankingItem (
87+ rank .getRankPosition (),
88+ rank .getProductId (),
89+ rank .getTotalScore ()
90+ ))
91+ .toList ()
92+ );
93+ }
94+
95+ /**
96+ * Retrieves monthly rankings with product information.
97+ *
98+ * @param yearMonth the target month (e.g., "2025-01")
99+ * @param page the page number (1-based)
100+ * @param size the page size
101+ * @return list of rankings with product details
102+ */
103+ public List <RankingProductInfo > getMonthlyRanking (String yearMonth , int page , int size ) {
104+ PageRequest pageRequest = PageRequest .of (page - 1 , size );
105+ List <MonthlyProductRank > monthlyRanks = monthlyRankJpaRepository .findByYearMonthOrderByRankPositionAsc (
106+ yearMonth , pageRequest
107+ );
108+
109+ if (monthlyRanks .isEmpty ()) {
110+ return List .of ();
111+ }
112+
113+ return combineWithProductInfo (
114+ monthlyRanks .stream ()
115+ .map (rank -> new RankingItem (
116+ rank .getRankPosition (),
117+ rank .getProductId (),
118+ rank .getTotalScore ()
119+ ))
120+ .toList ()
121+ );
122+ }
123+
124+ /**
125+ * Combines ranking items with product information.
126+ *
127+ * @param rankingItems the list of ranking items
128+ * @return list of rankings with product details
129+ */
130+ private List <RankingProductInfo > combineWithProductInfo (List <RankingItem > rankingItems ) {
38131 List <Long > productIds = rankingItems .stream ()
39132 .map (RankingItem ::getProductId )
40133 .toList ();
41134
42135 Map <Long , ProductInfo > productMap = productService .findByIds (productIds ).stream ()
43136 .collect (Collectors .toMap (ProductInfo ::id , p -> p ));
44137
45- // 3. 랭킹 + 상품 정보 조합
46138 List <RankingProductInfo > results = new ArrayList <>();
47139 for (RankingItem item : rankingItems ) {
48140 ProductInfo product = productMap .get (item .getProductId ());
49141
50142 if (product == null ) {
51- log .warn ("랭킹에 있지만 상품 정보 없음 - productId: {}" , item .getProductId ());
143+ log .warn ("Product not found for ranking: productId= {}" , item .getProductId ());
52144 continue ;
53145 }
54146
@@ -68,26 +160,18 @@ public List<RankingProductInfo> getDailyRanking(String date, int page, int size)
68160 }
69161
70162 /**
71- * 오늘 랭킹 페이지 조회
72- */
73- public List <RankingProductInfo > getTodayRanking (int page , int size ) {
74- String today = java .time .LocalDate .now ().format (java .time .format .DateTimeFormatter .ofPattern ("yyyyMMdd" ));
75- return getDailyRanking (today , page , size );
76- }
77-
78- /**
79- * 랭킹 + 상품 정보 DTO
163+ * DTO for ranking combined with product information.
80164 */
81165 @ lombok .Getter
82166 @ lombok .Builder
83167 public static class RankingProductInfo {
84- private int rank ; // 순위
85- private Double score ; // 점수
86- private Long productId ; // 상품 ID
87- private String productName ; // 상품명
88- private String brandName ; // 브랜드명
89- private BigDecimal price ; // 가격
90- private Integer stock ; // 재고
91- private Long likeCount ; // 좋아요 수
168+ private int rank ;
169+ private Double score ;
170+ private Long productId ;
171+ private String productName ;
172+ private String brandName ;
173+ private BigDecimal price ;
174+ private Integer stock ;
175+ private Long likeCount ;
92176 }
93177}
0 commit comments