diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserController.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserController.java index f7847db..f3bec5b 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserController.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserController.java @@ -17,12 +17,13 @@ @RequiredArgsConstructor @RestController public class UserController { + private final UserService userService; @Operation(summary = "내 정보 조회", description = "내 정보를 조회한다.") @GetMapping("/api/user") public ApiResponse getUserInfo( - @AuthenticationPrincipal JwtUser jwtUser + @AuthenticationPrincipal JwtUser jwtUser ) { var userModel = userService.getUserModel(jwtUser.getId()); return ApiResponse.success(UserRes.UserMyInfo.from(userModel)); @@ -31,8 +32,8 @@ public ApiResponse getUserInfo( @Operation(summary = "내 정보 수정", description = "내 정보를 수정한다.") @PutMapping("/api/user") public ApiResponse updateUser( - @Valid @RequestBody UserReq.Update request, - @AuthenticationPrincipal JwtUser jwtUser + @Valid @RequestBody UserReq.Update request, + @AuthenticationPrincipal JwtUser jwtUser ) { var command = request.toCommand(); userService.updateUser(jwtUser.getId(), command); @@ -42,16 +43,16 @@ public ApiResponse updateUser( @Operation(summary = "스트릭 조회", description = "스트릭을 조회한다.") @GetMapping("/api/user/streak") public ApiResponse getStreak( - @AuthenticationPrincipal JwtUser jwtUser, - UserReq.GetStreak request + @AuthenticationPrincipal JwtUser jwtUser, + UserReq.GetStreak request ) { - if(request.startDate().isAfter(request.endDate())){ + if (request.startDate().isAfter(request.endDate())) { throw new IllegalArgumentException("시작일은 종료일보다 이전이어야 합니다."); } var userModelStreak = userService.getUserStreak( - jwtUser.getId(), - request.startDate(), - request.endDate() + jwtUser.getId(), + request.startDate(), + request.endDate() ); return ApiResponse.success(UserRes.Streak.from(userModelStreak)); } @@ -59,12 +60,22 @@ public ApiResponse getStreak( @Operation(summary = "유저 랭킹 페이징", description = "전체 유저 랭킹을 조회 페이징") @GetMapping("/api/users/ranking") public ApiResponse> getUsersRanking( - @Valid PagingRequest request + @Valid PagingRequest request ) { var userModelPage = userService.getUserPagingByRanking(request.toPageable()); var response = PagingResponse.from(userModelPage, UserRes.User::from); return ApiResponse.success(response); } + @Operation(summary = "내 랭킹 조회", description = "유저 랭킹을 조회한다.") + @GetMapping("/api/users/my-ranking") + public ApiResponse getMyRanking( + @AuthenticationPrincipal JwtUser jwtUser + ) { + var userModelRanking = userService.getMyRanking(jwtUser.getId()); + var response = UserRes.MyRankingInfo.from(userModelRanking); + return ApiResponse.success(response); + } + } diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserRes.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserRes.java index 5438ba1..9d53452 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserRes.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/controller/UserRes.java @@ -9,84 +9,114 @@ import java.util.List; public class UserRes { + @Builder public record UserMyInfo( - Long id, - String nickname, - String profileImageUrl, - String email, - TierInfo tierInfo, - Role role + Long id, + String nickname, + String profileImageUrl, + String email, + TierInfo tierInfo, + Role role ) { + public static UserMyInfo from(UserModel.Main userMain) { var tierInfo = TierInfo.from(userMain.exp()); return UserMyInfo.builder() - .id(userMain.id()) - .nickname(userMain.nickname()) - .profileImageUrl(userMain.profileImageUrl()) - .email(userMain.email()) - .tierInfo(tierInfo) - .role(userMain.role()) - .build(); + .id(userMain.id()) + .nickname(userMain.nickname()) + .profileImageUrl(userMain.profileImageUrl()) + .email(userMain.email()) + .tierInfo(tierInfo) + .role(userMain.role()) + .build(); } } @Builder public record User( - Long id, - String nickname, - String profileImageUrl, - TierInfo tierInfo + Long id, + String nickname, + String profileImageUrl, + TierInfo tierInfo ) { + public static User from(UserModel.Main userMain) { var tierInfo = TierInfo.from(userMain.exp()); return User.builder() - .id(userMain.id()) - .nickname(userMain.nickname()) - .profileImageUrl(userMain.profileImageUrl()) - .tierInfo(tierInfo) - .build(); + .id(userMain.id()) + .nickname(userMain.nickname()) + .profileImageUrl(userMain.profileImageUrl()) + .tierInfo(tierInfo) + .build(); } } @Builder public record TierInfo( - String tier, - Integer totalExp, - Integer currentExp + String tier, + Integer totalExp, + Integer currentExp ) { + public static TierInfo from(Integer exp) { var tier = TierSystem.getTier(exp); return TierInfo.builder() - .tier(tier.getKorean()) - .totalExp(tier.getEndExp() - tier.getStartExp()) // 티어 시작 경험치부터 끝 경험치까지 - .currentExp(exp - tier.getStartExp()) // 현재 경험치 - 티어 시작 경험치 - .build(); + .tier(tier.getKorean()) + .totalExp(tier.getEndExp() - tier.getStartExp()) // 티어 시작 경험치부터 끝 경험치까지 + .currentExp(exp - tier.getStartExp()) // 현재 경험치 - 티어 시작 경험치 + .build(); } } @Builder public record Streak( - /** 여기서 Model의 DayCount를 사용해도 되는지 */ - List dayCounts + /** 여기서 Model의 DayCount를 사용해도 되는지 */ + List dayCounts ) { - public static Streak from(UserModel.Streak streak){ + + public static Streak from(UserModel.Streak streak) { return Streak.builder() - .dayCounts(streak.dayCounts()) - .build(); + .dayCounts(streak.dayCounts()) + .build(); } } /** - * 하루에 대한 스트릭 카운트 - * 0인 것도 보낸다. + * 하루에 대한 스트릭 카운트 0인 것도 보낸다. */ @Builder public record DayCount( - LocalDate date, - Integer count + LocalDate date, + Integer count + ) { + + } + + @Builder + public record MyRankingInfo( + Long id, + String nickname, + String profileImageUrl, + String email, + TierInfo tierInfo, + Role role, + Integer rank ) { + + public static MyRankingInfo from(UserModel.MyRanking myRanking) { + var tierInfo = TierInfo.from(myRanking.exp()); + return MyRankingInfo.builder() + .id(myRanking.id()) + .nickname(myRanking.nickname()) + .profileImageUrl(myRanking.profileImageUrl()) + .email(myRanking.email()) + .tierInfo(tierInfo) + .rank(myRanking.rank()) + .role(myRanking.role()) + .build(); + } } } diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserModel.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserModel.java index 0e9a85d..3b3161f 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserModel.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserModel.java @@ -10,40 +10,46 @@ import java.util.stream.Collectors; -public class UserModel{ +public class UserModel { + @Builder public record Main( - Long id, - String email, - String nickname, - String profileImageUrl, - Integer exp, - Role role, - LocalDateTime createdAt + Long id, + String email, + String nickname, + String profileImageUrl, + Integer exp, + Role role, + LocalDateTime createdAt ) { + public static Main from(User user) { return Main.builder() - .id(user.getId()) - .email(user.getEmail()) - .nickname(user.getNickname()) - .profileImageUrl(user.getProfileImageUrl()) - .exp(user.getExp()) - .role(user.getRole()) - .createdAt(user.getCreatedAt()) - .build(); + .id(user.getId()) + .email(user.getEmail()) + .nickname(user.getNickname()) + .profileImageUrl(user.getProfileImageUrl()) + .exp(user.getExp()) + .role(user.getRole()) + .createdAt(user.getCreatedAt()) + .build(); } } @Builder public record Streak( - List dayCounts + List dayCounts ) { - /** 여기서 count 0인걸 포함하는 기능을 쓰는게 맞는지 */ - public static Streak from(Map streakCounts, LocalDate startDate, LocalDate endDate) { + + /** + * 여기서 count 0인걸 포함하는 기능을 쓰는게 맞는지 + */ + public static Streak from(Map streakCounts, LocalDate startDate, + LocalDate endDate) { List resultList = startDate.datesUntil(endDate.plusDays(1)) - // 날짜가 존재하면 map(date)로 count를 가져오고, 없으면 0을 저장한다. - .map(date -> new DayCount(date, streakCounts.getOrDefault(date, 0))) - .collect(Collectors.toList()); + // 날짜가 존재하면 map(date)로 count를 가져오고, 없으면 0을 저장한다. + .map(date -> new DayCount(date, streakCounts.getOrDefault(date, 0))) + .collect(Collectors.toList()); return new Streak(resultList); } @@ -55,25 +61,51 @@ public String toString() { } else { for (int i = 0; i < dayCounts.size(); i++) { sb.append(dayCounts.get(i).toString()); - if (i < dayCounts.size() - 1) + if (i < dayCounts.size() - 1) { sb.append("\n"); + } } } return sb.toString(); } } + @Builder public record DayCount( - LocalDate date, - Integer count + LocalDate date, + Integer count ) { @Override public String toString() { return "DayCount{" + - "date=" + date + - ", count=" + count + '}'; + "date=" + date + + ", count=" + count + '}'; + } + } + + @Builder + public record MyRanking( + Long id, + String email, + String nickname, + String profileImageUrl, + Role role, + Integer exp, + Integer rank + ) { + + public static MyRanking from(User user, Integer rank) { + return MyRanking.builder() + .id(user.getId()) + .email(user.getEmail()) + .nickname(user.getNickname()) + .profileImageUrl(user.getProfileImageUrl()) + .role(user.getRole()) + .exp(user.getExp()) + .rank(rank) + .build(); } } diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserService.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserService.java index 9d28f63..e1299eb 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserService.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/UserService.java @@ -17,6 +17,7 @@ @RequiredArgsConstructor @Service public class UserService { + private final UserReader userReader; private final UserChallengeReader userChallengeReader; @@ -30,8 +31,8 @@ public UserModel.Main getUserModel(Long id) { public List getManagerAndAdmin() { List users = userReader.getManagerAndAdmin(); return users.stream() - .map(UserModel.Main::from) - .toList(); + .map(UserModel.Main::from) + .toList(); } /** @@ -46,15 +47,23 @@ public void updateUser(Long id, UserCommand.Update userUpdate) { @Transactional(readOnly = true) public Page getUserPagingByRanking(Pageable pageable) { - Page users = userReader.getUserPagingByRanking(pageable); + Page users = userReader.getUserPagingByRanking(pageable); return users.map(UserModel.Main::from); } @Transactional(readOnly = true) - public UserModel.Streak getUserStreak(Long id, LocalDate startDate, LocalDate endDate){ - List userStreaks = userChallengeReader.countAllByUserIdAndDate(id, startDate, endDate); + public UserModel.Streak getUserStreak(Long id, LocalDate startDate, LocalDate endDate) { + List userStreaks = userChallengeReader.countAllByUserIdAndDate(id, startDate, + endDate); Map map = userStreaks.stream() - .collect(Collectors.toMap(DayCountType::getDate, DayCountType::getCount)); + .collect(Collectors.toMap(DayCountType::getDate, DayCountType::getCount)); return UserModel.Streak.from(map, startDate, endDate); } + + @Transactional(readOnly = true) + public UserModel.MyRanking getMyRanking(Long id) { + User user = userReader.getById(id); + Integer rank = userReader.getRanking(user.getExp()); + return UserModel.MyRanking.from(user, rank); + } } diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/port/UserReader.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/port/UserReader.java index 276b622..4dd9fd5 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/port/UserReader.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/domain/port/UserReader.java @@ -9,6 +9,7 @@ import java.util.Optional; public interface UserReader { + User getById(Long id); boolean existsByEmail(String email); @@ -20,4 +21,6 @@ public interface UserReader { Page getUserPagingByRanking(Pageable pageable); List getManagerAndAdmin(); + + Integer getRanking(Integer exp); } diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserReaderImpl.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserReaderImpl.java index 34e660f..64abb7f 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserReaderImpl.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserReaderImpl.java @@ -18,6 +18,7 @@ @Component @RequiredArgsConstructor public class UserReaderImpl implements UserReader { + private final UserRepository userRepository; private final JPAQueryFactory queryFactory; @@ -44,14 +45,14 @@ public Optional findByAuthToken(String authToken) { @Override public Page getUserPagingByRanking(Pageable pageable) { Long totalCount = queryFactory - .select(QUser.user.count()) - .from(QUser.user) - .fetchOne(); + .select(QUser.user.count()) + .from(QUser.user) + .fetchOne(); List users = queryFactory.selectFrom(QUser.user) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(QUser.user.exp.desc()) - .fetch(); + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(QUser.user.exp.desc()) + .fetch(); return new PageImpl<>(users, pageable, totalCount == null ? 0 : totalCount); } @@ -60,4 +61,9 @@ public Page getUserPagingByRanking(Pageable pageable) { public List getManagerAndAdmin() { return userRepository.findByRoleIn(List.of(Role.MANAGER, Role.ADMIN)); } + + @Override + public Integer getRanking(Integer exp) { + return userRepository.countByExpGreaterThan(exp) + 1; + } } diff --git a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserRepository.java b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserRepository.java index 310a94e..bc1b486 100644 --- a/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserRepository.java +++ b/zzansuni-api-server/app/src/main/java/org/haedal/zzansuni/user/infrastructure/UserRepository.java @@ -8,10 +8,14 @@ import java.util.Optional; public interface UserRepository extends JpaRepository { + Optional findByAuthToken(String authToken); + boolean existsByEmail(String email); Optional findByEmail(String email); List findByRoleIn(List roles); + + Integer countByExpGreaterThan(Integer exp); }