Skip to content

fix: 주간 랭킹 데이터 조회 방식 수정#393

Merged
sanchaehwa merged 1 commit intomainfrom
fix/loadrank
Dec 4, 2025
Merged

fix: 주간 랭킹 데이터 조회 방식 수정#393
sanchaehwa merged 1 commit intomainfrom
fix/loadrank

Conversation

@sanchaehwa
Copy link
Member

@sanchaehwa sanchaehwa commented Dec 4, 2025

#️⃣ 연관된 이슈

ex) close #Issue number

📝 작업 내용

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)

📷 스크린샷

이미지

💬 리뷰 요구사항(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 명칭

📌 PR 진행 시 참고사항

  • 리뷰어는 좋은 코드 방향을 제시하되, 수정을 강요하지 않습니다.
  • 좋은 코드를 발견하면 칭찬과 격려를 아끼지 않습니다.
  • 리뷰는 Reviewer로 지정된 시점 기준으로 3일 이내에 진행해 주세요.
  • Comment 작성 시 아래 Prefix를 사용해 주세요:
    • P1: 꼭 반영해 주세요 (Request Changes) – 이슈나 취약점 관련
    • P2: 반영을 고려해 주세요 (Comment) – 개선 의견
    • P3: 단순 제안 (Chore)

Summary by CodeRabbit

  • Bug Fixes

    • Improved weekly ranking update logic to modify existing rankings in-place rather than recreating them entirely.
  • Refactor

    • Updated ranking retrieval to consistently fetch the top 8 entries per week.
    • Adjusted ranking update behavior to only refresh existing member rankings, excluding new entries.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

Walkthrough

The pull request refactors the WeeklyRanking entity and service to replace delete-and-recreate ranking updates with in-place updates. The entity introduces separate mutation methods for point/certification and rank. The repository adds a new findTop8ByWeekStart() method and changes the return type of findByWeekStart() from Tuple to WeeklyRanking. The service now loads existing rankings, updates them, and persists the collection, while always fetching the top 8 entries.

Changes

Cohort / File(s) Summary
Entity mutation methods
src/main/java/com/example/green/domain/dashboard/rankingmodule/entity/WeeklyRanking.java
Removed setRank(int) method. Added updatePointAndCertification(BigDecimal totalPoint, int certificationCount) and updateRank(int rank) methods, separating point/certification updates from rank updates.
Repository interface and implementation
src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepository.java, WeeklyRankingRepositoryCustom.java, WeeklyRankingRepositoryImpl.java
Changed findByWeekStart() return type from List<Tuple> to List<WeeklyRanking>. Removed deleteByWeekStart(LocalDate) method. Added findTop8ByWeekStart(LocalDate weekStart) query method to retrieve top 8 rankings by week, ordered by rank ascending.
Service logic refactor
src/main/java/com/example/green/domain/dashboard/rankingmodule/service/WeeklyRankingService.java
Changed updateWeeklyRanks() from delete-then-create pattern to loading existing rankings, updating point/certification in-place, and persisting updates. Changed getAllRankData() to always fetch top 8 entries (hard-coded) instead of using dynamic topN parameter. No existing rankings are created for members without prior records.
Test removal
src/test/java/com/example/green/domain/dashboard/ranking/service/WeeklyRankingServiceTest.java
Removed top-N weekly ranking test method and associated TopMemberPointResponse import.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Service refactor logic: Verify correctness of in-place update strategy and that ranking recalculation operates on the updated collection.
  • findTop8ByWeekStart query: Confirm ordering and limiting logic is properly implemented in the repository method.
  • Behavioral change: Verify that no longer creating rankings for members without existing records is intentional and doesn't break downstream functionality.
  • Repository return type change: Ensure all callers of findByWeekStart() handle List<WeeklyRanking> instead of List<Tuple> correctly.

Possibly related PRs

Suggested labels

dev:fix

Suggested reviewers

  • yunjeooong

Poem

🐰 Old rankings deleted, now we update with grace,
Eight at the top, each in its rightful place,
Point and rank mutations, split clean and fair,
The service hops along without a care! 🌿

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: 주간 랭킹 데이터 조회 방식 수정' directly describes the main objective of the changeset—modifying how weekly ranking data is retrieved. The changes involve refactoring the ranking query logic, repository methods, and service layer to fetch top 8 rankings instead of dynamic parameters, which aligns with the 'fix' label and the stated purpose of revising the data retrieval approach.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/loadrank

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Dec 4, 2025

Unit Test Coverage Report

Total Project Coverage 37.61%
File Coverage [11.78%]
WeeklyRankingService.java 21.45%
WeeklyRanking.java 0%
WeeklyRankingRepositoryImpl.java 0%

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/example/green/domain/dashboard/rankingmodule/service/WeeklyRankingService.java (1)

44-44: Unused parameter: weekEnd.

The weekEnd parameter is declared but never used in the method body. If it's intended for creating new entries, ensure it's used; otherwise, remove it from the signature.

🧹 Nitpick comments (2)
src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepositoryCustom.java (1)

18-19: Consider reusing findTopNByWeekStart instead of adding a hardcoded variant.

The new findTop8ByWeekStart duplicates findTopNByWeekStart(weekStart, 8). If the top-8 limit is a business constant, consider defining it once and calling the parameterized method.

src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepositoryImpl.java (1)

102-113: Remove unnecessary @Param annotation.

The @Param annotation is used for Spring Data JPA @Query methods to bind named parameters. In a QueryDSL implementation using JPAQueryFactory, it has no effect and adds confusion.

 @Override
-public List<WeeklyRanking> findTop8ByWeekStart(@Param("weekStart") LocalDate weekStart) {
+public List<WeeklyRanking> findTop8ByWeekStart(LocalDate weekStart) {

     QWeeklyRanking weeklyRanking = QWeeklyRanking.weeklyRanking;

     return queryFactory
         .selectFrom(weeklyRanking)
         .where(weeklyRanking.weekStart.eq(weekStart))
         .orderBy(weeklyRanking.rank.asc())
-        .limit(8) // TOP 8
+        .limit(8)
         .fetch();
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f9b78d and 8f9ddbb.

📒 Files selected for processing (6)
  • src/main/java/com/example/green/domain/dashboard/rankingmodule/entity/WeeklyRanking.java (1 hunks)
  • src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepository.java (1 hunks)
  • src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepositoryCustom.java (1 hunks)
  • src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepositoryImpl.java (2 hunks)
  • src/main/java/com/example/green/domain/dashboard/rankingmodule/service/WeeklyRankingService.java (1 hunks)
  • src/test/java/com/example/green/domain/dashboard/ranking/service/WeeklyRankingServiceTest.java (0 hunks)
💤 Files with no reviewable changes (1)
  • src/test/java/com/example/green/domain/dashboard/ranking/service/WeeklyRankingServiceTest.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: check
🔇 Additional comments (3)
src/main/java/com/example/green/domain/dashboard/rankingmodule/repository/WeeklyRankingRepository.java (1)

11-11: LGTM!

The return type change from List<Tuple> to List<WeeklyRanking> is appropriate and aligns with the entity-based update approach introduced in this PR.

src/main/java/com/example/green/domain/dashboard/rankingmodule/entity/WeeklyRanking.java (1)

61-68: LGTM!

The explicit update methods (updatePointAndCertification and updateRank) provide a cleaner mutation API compared to setters, making intent clear and supporting the in-place update pattern.

src/main/java/com/example/green/domain/dashboard/rankingmodule/service/WeeklyRankingService.java (1)

98-112: Ranking logic is correct for handling ties.

The tie-breaking logic correctly assigns the same rank to members with identical points and certification counts, while incrementing the counter for subsequent entries.

Comment on lines +75 to +90
for (Member member : allMembers) {

BigDecimal point = memberPoints.getOrDefault(member.getId(), BigDecimal.ZERO);

int certificationCount = certifiedCounts.getOrDefault(member.getId(), 0);

String profileImageUrl = (member.getProfile() != null) ?
member.getProfile().getProfileImageUrl() : null;

WeeklyRanking existing = existingMap.get(member.getId());

if (existing != null) {
existing.updatePointAndCertification(point, certificationCount);
updatedRanks.add(existing);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

New members will never appear in rankings.

The current logic only updates existing WeeklyRanking entries. Members without a pre-existing entry for weekStart are silently skipped (lines 86-89). This means:

  • New members can never enter the rankings
  • The initial population of rankings is not handled

If this is intentional (e.g., initial entries are created elsewhere), please clarify. Otherwise, you need to create new entries for members not in existingMap.

 if (existing != null) {
     existing.updatePointAndCertification(point, certificationCount);
     updatedRanks.add(existing);
+} else {
+    WeeklyRanking newRanking = WeeklyRanking.builder()
+        .memberId(member.getId())
+        .memberName(member.getName())
+        .profileImageUrl(profileImageUrl)
+        .totalPoint(point)
+        .certificationCount(certificationCount)
+        .rank(0) // will be set below
+        .weekStart(weekStart)
+        .weekEnd(weekEnd)
+        .build();
+    updatedRanks.add(newRanking);
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
src/main/java/com/example/green/domain/dashboard/rankingmodule/service/WeeklyRankingService.java
around lines 75 to 90, the loop only updates existing WeeklyRanking objects and
skips members missing from existingMap, preventing new members from appearing in
rankings; modify the loop so that when existingMap.get(member.getId()) is null
you create a new WeeklyRanking for the current weekStart (populate member
id/reference, point, certificationCount and any required default fields), add it
to updatedRanks (and to whatever repository/collection will be persisted), and
ensure any necessary constructors or factory methods are used to set initial
rank state consistently with existing entries.

Comment on lines 117 to +120
public List<TopMemberPointResponse> getAllRankData(LocalDate weekStart, int topN) {

// 상위 N명 랭킹 엔티티 조회
List<WeeklyRanking> topMembersFromDb = weeklyRankingRepository.findTopNByWeekStart(weekStart,
topN);

if (topMembersFromDb.isEmpty()) {
return new ArrayList<>();
}
List<WeeklyRanking> topMembersFromDb = weeklyRankingRepository.findTop8ByWeekStart(weekStart);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

The topN parameter is ignored.

The method signature accepts topN but always calls findTop8ByWeekStart, ignoring the parameter. This is misleading to callers.

Either use the parameter:

-List<WeeklyRanking> topMembersFromDb = weeklyRankingRepository.findTop8ByWeekStart(weekStart);
+List<WeeklyRanking> topMembersFromDb = weeklyRankingRepository.findTopNByWeekStart(weekStart, topN);

Or remove it from the signature if top-8 is always the requirement:

-public List<TopMemberPointResponse> getAllRankData(LocalDate weekStart, int topN) {
+public List<TopMemberPointResponse> getAllRankData(LocalDate weekStart) {
🤖 Prompt for AI Agents
In
src/main/java/com/example/green/domain/dashboard/rankingmodule/service/WeeklyRankingService.java
around lines 117-120, the method getAllRankData(LocalDate weekStart, int topN)
ignores the topN parameter and always calls
weeklyRankingRepository.findTop8ByWeekStart(weekStart); change this so the
method uses the topN value (e.g., call a repository method that accepts a limit
such as findTopNByWeekStart(weekStart, topN) or use a pageable/limit query) or
if the business requirement is fixed to 8, remove the topN parameter from the
signature and update callers accordingly; ensure repository and tests are
updated to match the chosen approach.

@sanchaehwa sanchaehwa merged commit d5a72ff into main Dec 4, 2025
2 checks passed
@sanchaehwa sanchaehwa deleted the fix/loadrank branch December 4, 2025 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant