Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
import com.loopers.domain.brand.BrandRepository;
import com.loopers.domain.product.Product;
import com.loopers.domain.product.ProductRepository;
import com.loopers.domain.ranking.MonthlyRankingRepository;
import com.loopers.domain.ranking.RankingPeriod;
import com.loopers.domain.ranking.RankingRepository;
import com.loopers.domain.ranking.WeeklyRankingRepository;
import com.loopers.support.page.PageResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -22,20 +27,22 @@
public class RankingFacade {

private final RankingRepository rankingRepository;
private final WeeklyRankingRepository weeklyRankingRepository;
private final MonthlyRankingRepository monthlyRankingRepository;
private final ProductRepository productRepository;
private final BrandRepository brandRepository;
private final ProductAssembler productAssembler;

@Transactional(readOnly = true)
public PageResponse<RankingInfo> getPage(LocalDate date, int page, int size) {
public PageResponse<RankingInfo> getPage(LocalDate date, RankingPeriod period, int page, int size) {
long offset = (long) (page - 1) * size;
List<Long> productIds = rankingRepository.findProductIdsByRank(date, offset, (long) size);
List<Long> productIds = resolveProductIds(date, period, offset, (long) size);

if (productIds.isEmpty()) {
return new PageResponse<>(List.of(), page, size, 0);
}

long count = rankingRepository.countByDate(date);
long count = resolveCount(date, period);
Comment on lines +37 to +45
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

period/date 인자의 null 방어를 명시해야 한다.

period가 null이면 switch (period)에서 NullPointerException이 발생하고 ApiControllerAdvice 경로가 아닌 일반 500으로 응답되어 오류 포맷이 어긋난다. Controller에서 기본값 DAILY를 보장한다고 하지만, 내부 호출자(스케줄러·테스트 등)를 고려해 퍼사드 진입부에서 Objects.requireNonNull 또는 CoreException으로 명시적으로 처리하는 편이 안전하다. date 역시 null 시 TemporalAdjusters에서 NPE가 발생한다.

추가 테스트: getPage(null, null, 1, 20) 호출 시 기대한 예외 타입이 던져지는지 단위 테스트를 보강한다.

🛡️ 수정안
     `@Transactional`(readOnly = true)
     public PageResponse<RankingInfo> getPage(LocalDate date, RankingPeriod period, int page, int size) {
+        Objects.requireNonNull(date, "date");
+        Objects.requireNonNull(period, "period");
         long offset = (long) (page - 1) * size;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/commerce-api/src/main/java/com/loopers/application/ranking/RankingFacade.java`
around lines 37 - 45, In getPage(LocalDate date, RankingPeriod period, int page,
int size) add explicit null checks for period and date (e.g.,
Objects.requireNonNull or throw a CoreException with a clear error code/message)
before any use (the switch(period) and any TemporalAdjusters calls) so NPEs are
avoided and errors follow ApiControllerAdvice handling; update
resolveProductIds/resolveCount callers if needed to accept the validated values;
and add a unit test asserting getPage(null, null, 1, 20) throws the expected
exception type and message.

int totalPages = (int) Math.ceil((double) count / size);

List<Product> products = productRepository.findAllByIdIn(productIds);
Expand All @@ -55,4 +62,23 @@ public PageResponse<RankingInfo> getPage(LocalDate date, int page, int size) {

return new PageResponse<>(rankingInfos, page, size, totalPages);
}

private List<Long> resolveProductIds(LocalDate date, RankingPeriod period, long offset, long limit) {
return switch (period) {
case DAILY -> rankingRepository.findProductIdsByRank(date, offset, limit);
case WEEKLY -> weeklyRankingRepository.findProductIdsByBaseDate(
date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)), offset, limit);
case MONTHLY -> monthlyRankingRepository.findProductIdsByBaseDate(
date.withDayOfMonth(1), offset, limit);
};
}

private long resolveCount(LocalDate date, RankingPeriod period) {
return switch (period) {
case DAILY -> rankingRepository.countByDate(date);
case WEEKLY -> weeklyRankingRepository.countByBaseDate(
date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)));
case MONTHLY -> monthlyRankingRepository.countByBaseDate(date.withDayOfMonth(1));
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.loopers.domain.ranking;

import java.time.LocalDate;
import java.util.List;

public interface MonthlyRankingRepository {

List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit);

long countByBaseDate(LocalDate baseDate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.loopers.domain.ranking;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.ZonedDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "mv_product_rank_monthly")
public class MvProductRankMonthly {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "product_id", nullable = false)
private Long productId;

@Column(name = "`rank`", nullable = false)
private int rank;

@Column(name = "score", nullable = false)
private double score;

@Column(name = "total_like", nullable = false)
private long totalLike;

@Column(name = "total_order", nullable = false)
private long totalOrder;

@Column(name = "total_view", nullable = false)
private long totalView;

@Column(name = "total_sales", nullable = false)
private long totalSales;

@Column(name = "base_date", nullable = false)
private LocalDate baseDate;

@Column(name = "created_at", nullable = false, updatable = false)
private ZonedDateTime createdAt;

private MvProductRankMonthly(Long productId, int rank, double score,
long totalLike, long totalOrder, long totalView,
long totalSales, LocalDate baseDate) {
this.productId = productId;
this.rank = rank;
this.score = score;
this.totalLike = totalLike;
this.totalOrder = totalOrder;
this.totalView = totalView;
this.totalSales = totalSales;
this.baseDate = baseDate;
}

public static MvProductRankMonthly of(Long productId, int rank, double score,
long totalLike, long totalOrder, long totalView,
long totalSales, LocalDate baseDate) {
return new MvProductRankMonthly(productId, rank, score, totalLike, totalOrder, totalView, totalSales, baseDate);
}

@PrePersist
private void prePersist() {
this.createdAt = ZonedDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.loopers.domain.ranking;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.ZonedDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "mv_product_rank_weekly")
public class MvProductRankWeekly {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "product_id", nullable = false)
private Long productId;

@Column(name = "`rank`", nullable = false)
private int rank;

@Column(name = "score", nullable = false)
private double score;

@Column(name = "total_like", nullable = false)
private long totalLike;

@Column(name = "total_order", nullable = false)
private long totalOrder;

@Column(name = "total_view", nullable = false)
private long totalView;

@Column(name = "total_sales", nullable = false)
private long totalSales;

@Column(name = "base_date", nullable = false)
private LocalDate baseDate;

@Column(name = "created_at", nullable = false, updatable = false)
private ZonedDateTime createdAt;

private MvProductRankWeekly(Long productId, int rank, double score,
long totalLike, long totalOrder, long totalView,
long totalSales, LocalDate baseDate) {
this.productId = productId;
this.rank = rank;
this.score = score;
this.totalLike = totalLike;
this.totalOrder = totalOrder;
this.totalView = totalView;
this.totalSales = totalSales;
this.baseDate = baseDate;
}

public static MvProductRankWeekly of(Long productId, int rank, double score,
long totalLike, long totalOrder, long totalView,
long totalSales, LocalDate baseDate) {
return new MvProductRankWeekly(productId, rank, score, totalLike, totalOrder, totalView, totalSales, baseDate);
}

@PrePersist
private void prePersist() {
this.createdAt = ZonedDateTime.now();
}
Comment on lines +45 to +70
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

createdAt의 타임존을 명시적으로 고정하는 편이 운영 혼선을 줄인다.

ZonedDateTime.now()는 JVM의 기본 타임존에 의존한다. API/배치 서버의 타임존이 달라지거나 컨테이너 이미지 변경으로 UTCAsia/Seoul이 섞이면 동일 baseDate의 행에 대해 created_at만 시차가 들어간 값이 쓰여 장애 분석 로그에서 혼란을 준다. 가능한 ZonedDateTime.now(ZoneId.of("Asia/Seoul")) 또는 ZoneOffset.UTC로 고정하거나, 프로젝트에 BaseEntity/Auditing이 있다면 그쪽 규약을 따르는 것이 좋다.

또한 동일한 타임스탬프 규약이 MvProductRankMonthly에도 반복되므로, 공통 @MappedSuperclass로 뽑으면 규약을 한 곳에서 강제할 수 있다(아래 중복 관련 코멘트 참조).

추가 테스트: 엔티티 저장 후 created_at이 기대 타임존으로 저장되는지 검증하는 통합 테스트를 JpaWeeklyRankingRepositoryTest에 추가한다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/commerce-api/src/main/java/com/loopers/domain/ranking/MvProductRankWeekly.java`
around lines 45 - 70, The createdAt assignment in MvProductRankWeekly currently
uses ZonedDateTime.now() (see createdAt field and prePersist()), which relies on
the JVM default TZ; change prePersist() to set createdAt with an explicit zone
(e.g., ZonedDateTime.now(ZoneId.of("Asia/Seoul")) or
ZonedDateTime.now(ZoneOffset.UTC)) or refactor both MvProductRankWeekly and
MvProductRankMonthly to inherit a single `@MappedSuperclass/BaseEntity` or project
Auditing convention that centralizes createdAt handling; after changing, add an
integration test in JpaWeeklyRankingRepositoryTest to assert that the persisted
created_at uses the chosen timezone/offset.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.loopers.domain.ranking;

public enum RankingPeriod {
DAILY,
WEEKLY,
MONTHLY
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.loopers.domain.ranking;

import java.time.LocalDate;
import java.util.List;

public interface WeeklyRankingRepository {

List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit);

long countByBaseDate(LocalDate baseDate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.loopers.infrastructure.ranking;

import com.loopers.domain.ranking.MonthlyRankingRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.util.List;

@RequiredArgsConstructor
@Repository
public class JpaMonthlyRankingRepository implements MonthlyRankingRepository {

private final MonthlyRankingJpaRepository jpaRepository;

@Override
public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
int pageNumber = (int) (offset / limit);
PageRequest pageRequest = PageRequest.of(pageNumber, (int) limit);
return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
}
Comment on lines +18 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd JpaWeeklyRankingRepository.java | xargs -I{} sed -n '1,80p' {}

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 1007


🏁 Script executed:

rg "offset\s*/\s*limit|PageRequest\.of" --type java -B 2 -A 2

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 14089


🏁 Script executed:

fd "Repository" --extension java | xargs grep -l "offset.*limit\|limit.*offset" 2>/dev/null

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 943


🏁 Script executed:

cat apps/commerce-api/src/test/java/com/loopers/infrastructure/ranking/JpaMonthlyRankingRepositoryTest.java

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 4146


🏁 Script executed:

cat apps/commerce-api/src/test/java/com/loopers/infrastructure/ranking/JpaWeeklyRankingRepositoryTest.java

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 4127


limit=0 입력 시 ArithmeticException 발생, 비배수 offset 계산 오류 위험

pageNumber = (int) (offset / limit)limit == 0일 때 0으로 나누기 예외를 발생시켜 500 에러가 된다. 또한 파사드에서 항상 배수 형태로 입력된다는 가정 하에 작동하지만, 인프라 계층만 보면 이는 전제일 뿐이므로 경계 방어가 필요하다. JpaWeeklyRankingRepository도 동일한 패턴을 가지고 있다.

수정: limit <= 0 검증 및 offset % limit != 0 확인, Math.toIntExact() 사용으로 오버플로우 방지. 현재 테스트는 offset=2, limit=2 같은 안전한 경우만 검증하므로, limit=0 및 비배수 offset 입력 시 동작을 명세하는 단위 테스트를 추가해야 한다.

♻️ 제안 수정
-    `@Override`
-    public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
-        int pageNumber = (int) (offset / limit);
-        PageRequest pageRequest = PageRequest.of(pageNumber, (int) limit);
-        return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
-    }
+    `@Override`
+    public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
+        if (limit <= 0) {
+            return List.of();
+        }
+        if (offset % limit != 0) {
+            throw new IllegalArgumentException(
+                    "offset(" + offset + ") must be a multiple of limit(" + limit + ")");
+        }
+        int pageNumber = Math.toIntExact(offset / limit);
+        PageRequest pageRequest = PageRequest.of(pageNumber, Math.toIntExact(limit));
+        return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
int pageNumber = (int) (offset / limit);
PageRequest pageRequest = PageRequest.of(pageNumber, (int) limit);
return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
}
public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
if (limit <= 0) {
return List.of();
}
if (offset % limit != 0) {
throw new IllegalArgumentException(
"offset(" + offset + ") must be a multiple of limit(" + limit + ")");
}
int pageNumber = Math.toIntExact(offset / limit);
PageRequest pageRequest = PageRequest.of(pageNumber, Math.toIntExact(limit));
return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/commerce-api/src/main/java/com/loopers/infrastructure/ranking/JpaMonthlyRankingRepository.java`
around lines 18 - 22, In findProductIdsByBaseDate (and mirror the same fix in
JpaWeeklyRankingRepository) add defensive validation: if limit <= 0 throw an
IllegalArgumentException (or similar), and if offset % limit != 0 throw an
IllegalArgumentException to explicitly reject non-multiple offsets; compute
pageNumber using Math.toIntExact(offset / limit) and build
PageRequest.of(pageNumber, Math.toIntExact(limit)) to avoid silent
truncation/overflow; finally add unit tests that assert behavior for limit=0 and
for non-multiple offset values (e.g., offset=3, limit=2) to codify the expected
exceptions.


@Override
public long countByBaseDate(LocalDate baseDate) {
return jpaRepository.countByBaseDate(baseDate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.loopers.infrastructure.ranking;

import com.loopers.domain.ranking.WeeklyRankingRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.util.List;

@RequiredArgsConstructor
@Repository
public class JpaWeeklyRankingRepository implements WeeklyRankingRepository {

private final WeeklyRankingJpaRepository jpaRepository;

@Override
public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
int pageNumber = (int) (offset / limit);
PageRequest pageRequest = PageRequest.of(pageNumber, (int) limit);
return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
}
Comment on lines +18 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

offset/limitPageRequest 변환이 정렬되지 않은 offset에서 부정확하다.

pageNumber = (int) (offset / limit)offsetlimit의 배수일 때만 정확하다. 현재 호출처(RankingFacade.getPage)는 offset=(page-1)*size로 항상 정렬되어 있어 우연히 동작하나, 계약상 offset은 임의 값을 허용한다. 향후 커서/스킵 방식 호출이 생기면 페이지 경계를 잘라먹어 랭킹이 누락되는 장애로 이어질 수 있다. 또한 limit <= 0에 대한 방어가 없어 ArithmeticException(division by zero) 또는 IllegalArgumentException(PageRequest.ofsize>=1을 요구)로 500이 발생한다. 운영 관점에서 사용자가 size=0을 주면 500을 뱉게 되므로 입력 검증이 필요하다.

🛠 제안 수정안
 `@Override`
 public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
-    int pageNumber = (int) (offset / limit);
-    PageRequest pageRequest = PageRequest.of(pageNumber, (int) limit);
-    return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
+    if (limit <= 0) {
+        return List.of();
+    }
+    if (offset % limit != 0) {
+        throw new IllegalArgumentException("offset must be a multiple of limit: offset=" + offset + ", limit=" + limit);
+    }
+    int pageNumber = Math.toIntExact(offset / limit);
+    PageRequest pageRequest = PageRequest.of(pageNumber, Math.toIntExact(limit));
+    return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
 }

추가 테스트: offset=3, limit=2(비정렬) 케이스, limit=0 케이스, offset=Integer.MAX_VALUE+1L(오버플로우) 케이스.

참고로 MonthlyRankingRepository 구현체도 동일한 변환 로직을 가질 가능성이 높으니 일관 수정이 필요하다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
int pageNumber = (int) (offset / limit);
PageRequest pageRequest = PageRequest.of(pageNumber, (int) limit);
return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
}
public List<Long> findProductIdsByBaseDate(LocalDate baseDate, long offset, long limit) {
if (limit <= 0) {
return List.of();
}
if (offset % limit != 0) {
throw new IllegalArgumentException("offset must be a multiple of limit: offset=" + offset + ", limit=" + limit);
}
int pageNumber = Math.toIntExact(offset / limit);
PageRequest pageRequest = PageRequest.of(pageNumber, Math.toIntExact(limit));
return jpaRepository.findProductIdsByBaseDate(baseDate, pageRequest);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/commerce-api/src/main/java/com/loopers/infrastructure/ranking/JpaWeeklyRankingRepository.java`
around lines 18 - 22, The conversion from offset/limit in
JpaWeeklyRankingRepository.findProductIdsByBaseDate is unsafe: validate that
limit > 0 (throw IllegalArgumentException or return empty) to avoid division by
zero/invalid PageRequest, compute the page number using floor division to handle
non-multiple offsets (use Math.floorDiv(offset, limit)) and clamp the result to
an int (e.g. (int)Math.min(Integer.MAX_VALUE, Math.floorDiv(offset, limit)))
before calling PageRequest.of, and apply the same defensive change to the
corresponding MonthlyRankingRepository implementation; add unit tests for
offset=3,limit=2, limit=0 and extreme overflow offsets.


@Override
public long countByBaseDate(LocalDate baseDate) {
return jpaRepository.countByBaseDate(baseDate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.loopers.infrastructure.ranking;

import com.loopers.domain.ranking.MvProductRankMonthly;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.time.LocalDate;
import java.util.List;

public interface MonthlyRankingJpaRepository extends JpaRepository<MvProductRankMonthly, Long> {

@Query("SELECT m.productId FROM MvProductRankMonthly m WHERE m.baseDate = :baseDate ORDER BY m.rank ASC")
List<Long> findProductIdsByBaseDate(@Param("baseDate") LocalDate baseDate, Pageable pageable);

long countByBaseDate(LocalDate baseDate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.loopers.infrastructure.ranking;

import com.loopers.domain.ranking.MvProductRankWeekly;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.time.LocalDate;
import java.util.List;

public interface WeeklyRankingJpaRepository extends JpaRepository<MvProductRankWeekly, Long> {

@Query("SELECT w.productId FROM MvProductRankWeekly w WHERE w.baseDate = :baseDate ORDER BY w.rank ASC")
List<Long> findProductIdsByBaseDate(@Param("baseDate") LocalDate baseDate, Pageable pageable);

long countByBaseDate(LocalDate baseDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.loopers.application.ranking.RankingFacade;
import com.loopers.application.ranking.RankingInfo;
import com.loopers.domain.ranking.RankingPeriod;
import com.loopers.interfaces.api.ApiResponse;
import com.loopers.support.page.PageResponse;
import lombok.RequiredArgsConstructor;
Expand All @@ -22,11 +23,12 @@ public class RankingController {
@GetMapping("/api/v1/rankings")
public ApiResponse<PageResponse<RankingDto.Response>> getRankings(
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyyMMdd") LocalDate date,
@RequestParam(defaultValue = "DAILY") RankingPeriod period,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size
) {
LocalDate targetDate = date != null ? date : LocalDate.now(ZoneOffset.UTC);
PageResponse<RankingInfo> infos = rankingFacade.getPage(targetDate, page, size);
PageResponse<RankingInfo> infos = rankingFacade.getPage(targetDate, period, page, size);
return ApiResponse.success(infos.map(RankingDto.Response::from));
}
}
Loading