diff --git a/backend/ongi/src/main/java/ongi/step/controller/StepController.java b/backend/ongi/src/main/java/ongi/step/controller/StepController.java index 8676c38..09b5539 100644 --- a/backend/ongi/src/main/java/ongi/step/controller/StepController.java +++ b/backend/ongi/src/main/java/ongi/step/controller/StepController.java @@ -2,8 +2,10 @@ import jakarta.annotation.Nullable; import java.time.LocalDate; +import java.util.List; import lombok.RequiredArgsConstructor; import ongi.security.CustomUserDetails; +import ongi.step.dto.FamilyStepRankResponse; import ongi.step.dto.FamilyStepResponse; import ongi.step.dto.StepUpsertRequest; import ongi.step.service.StepService; @@ -38,4 +40,11 @@ public ResponseEntity getFamilySteps( FamilyStepResponse response = stepService.getFamilySteps(userDetails.getUser(), date); return ResponseEntity.ok(response); } + + @GetMapping("/rank") + public ResponseEntity> getFamilyStepsRank( + @AuthenticationPrincipal CustomUserDetails userDetails){ + List responses = stepService.getFamilyStepRank(userDetails.getUser(), LocalDate.now()); + return ResponseEntity.ok(responses); + } } diff --git a/backend/ongi/src/main/java/ongi/step/dto/FamilyStepRankResponse.java b/backend/ongi/src/main/java/ongi/step/dto/FamilyStepRankResponse.java new file mode 100644 index 0000000..e8401c7 --- /dev/null +++ b/backend/ongi/src/main/java/ongi/step/dto/FamilyStepRankResponse.java @@ -0,0 +1,9 @@ +package ongi.step.dto; + +public record FamilyStepRankResponse( + String familyName, + Integer averageSteps, + Boolean isOurFamily +) { + +} diff --git a/backend/ongi/src/main/java/ongi/step/dto/FamilyStepRankingResponse.java b/backend/ongi/src/main/java/ongi/step/dto/FamilyStepRankingResponse.java deleted file mode 100644 index c3d94a3..0000000 --- a/backend/ongi/src/main/java/ongi/step/dto/FamilyStepRankingResponse.java +++ /dev/null @@ -1,5 +0,0 @@ -package ongi.step.dto; - -public class FamilyStepRankingResponse { - -} diff --git a/backend/ongi/src/main/java/ongi/step/repository/StepRepository.java b/backend/ongi/src/main/java/ongi/step/repository/StepRepository.java index 51b77d8..669f776 100644 --- a/backend/ongi/src/main/java/ongi/step/repository/StepRepository.java +++ b/backend/ongi/src/main/java/ongi/step/repository/StepRepository.java @@ -20,11 +20,31 @@ public interface StepRepository extends JpaRepository { Optional findByCreatedByAndDate(User user, LocalDate date); @Query("SELECT IFNULL(SUM(s.steps), 0) FROM Step s WHERE s.family = :family AND s.date = :date") - Integer getTotalStepsByFamilyAndDate(@Param("family") Family family, @Param("date") LocalDate date); - - List findByFamilyAndDateBetween(Family family, LocalDate startDate, LocalDate endDate); - - List getTotalStepsByDateBetween(LocalDate startDate, LocalDate endDate); - - List findByFamily(Family family); + Integer getTotalStepsByFamilyAndDate(@Param("family") Family family, + @Param("date") LocalDate date); + + @Query(""" + select + f.code as familyCode, + f.name as familyName, + coalesce(sum(s.steps), 0) as totalSteps, + count(distinct m) as memberCount + from Family f + left join f.members m + left join Step s + on s.family = f + and s.date between :start and :end + group by f.code, f.name + """) + List findStepsAndSizeBetween( + @Param("start") LocalDate start, + @Param("end") LocalDate end + ); + + interface FamilyStepsAndSizeView { + String getFamilyCode(); + String getFamilyName(); + Long getTotalSteps(); + Long getMemberCount(); + } } diff --git a/backend/ongi/src/main/java/ongi/step/service/StepService.java b/backend/ongi/src/main/java/ongi/step/service/StepService.java index 9ee9ab5..1c99344 100644 --- a/backend/ongi/src/main/java/ongi/step/service/StepService.java +++ b/backend/ongi/src/main/java/ongi/step/service/StepService.java @@ -1,12 +1,13 @@ package ongi.step.service; import java.time.temporal.TemporalAdjusters; +import java.util.Comparator; import java.util.Optional; import lombok.RequiredArgsConstructor; import ongi.exception.EntityNotFoundException; import ongi.family.entity.Family; import ongi.family.repository.FamilyRepository; -import ongi.step.dto.FamilyStepRankingResponse; +import ongi.step.dto.FamilyStepRankResponse; import ongi.step.dto.FamilyStepResponse; import ongi.step.dto.FamilyStepResponse.MemberStepInfo; import ongi.step.dto.StepUpsertRequest; @@ -50,6 +51,7 @@ public void upsertStep(User user, StepUpsertRequest request) { } } + @Transactional public FamilyStepResponse getFamilySteps(User user, LocalDate date) { Family family = familyRepository.findByMembersContains(user.getUuid()) .orElseThrow(() -> new EntityNotFoundException("가족을 찾을 수 없습니다.")); @@ -57,14 +59,13 @@ public FamilyStepResponse getFamilySteps(User user, LocalDate date) { List familySteps = stepRepository.findByFamilyAndDate(family, date); Integer totalSteps = stepRepository.getTotalStepsByFamilyAndDate(family, date); - List memberSteps = family.getMembers().stream().map(uuid -> new MemberStepInfo(uuid, userRepository.findByUuid(uuid).get().getName(), - familySteps.stream() - .filter(step -> step.getCreatedBy().getUuid().equals(uuid)) - .findFirst() - .map(Step::getSteps) - .orElse(0))).toList(); + familySteps.stream() + .filter(step -> step.getCreatedBy().getUuid().equals(uuid)) + .findFirst() + .map(Step::getSteps) + .orElse(0))).toList(); return new FamilyStepResponse( totalSteps, @@ -73,26 +74,25 @@ public FamilyStepResponse getFamilySteps(User user, LocalDate date) { ); } - - /// TODO /// - public List getFamilyStepRanking(User user, LocalDate date) { - Family family = familyRepository.findByMembersContains(user.getUuid()) + @Transactional + public List getFamilyStepRank(User user, LocalDate date) { + Family ourFamily = familyRepository.findByMembersContains(user.getUuid()) .orElseThrow(() -> new EntityNotFoundException("가족을 찾을 수 없습니다.")); - // TODO - return null; - } - - private int get7DaysAverageSteps(Family family) { - LocalDate today = LocalDate.now(); - List familySteps = stepRepository.findByFamilyAndDateBetween(family, today, - getThisWeekMonday(today)); - - int totalSteps = familySteps.stream() - .mapToInt(Step::getSteps) - .sum(); - - return totalSteps / family.getMembers().size(); + return stepRepository.findStepsAndSizeBetween(getThisWeekMonday(date), date).stream() + .map(v -> { + long cnt = v.getMemberCount(); + long total = v.getTotalSteps() ; + int perMemberWeeklyTotal = (cnt == 0) ? 0 : (int)Math.round((double) total / cnt); + + return new FamilyStepRankResponse( + v.getFamilyName(), + perMemberWeeklyTotal, + v.getFamilyCode().equals(ourFamily.getCode()) + ); + }) + .sorted(Comparator.comparingInt(FamilyStepRankResponse::averageSteps).reversed()) + .toList(); } public LocalDate getThisWeekMonday(LocalDate date) {