From 1ce806331fd66a1ff297dd9efb24ec460135735f Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 14:32:49 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20User=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=EC=97=90=20JPA=20Auditing=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/back/domain/user/entity/User.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/back/domain/user/entity/User.java b/src/main/java/com/back/domain/user/entity/User.java index d1d64476..3e0c21a0 100644 --- a/src/main/java/com/back/domain/user/entity/User.java +++ b/src/main/java/com/back/domain/user/entity/User.java @@ -4,6 +4,8 @@ import lombok.*; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; import java.time.LocalDateTime; import java.util.ArrayList; @@ -33,8 +35,12 @@ public class User { private Double abvDegree; // 알콜도수(회원 등급) + @CreatedDate // JPA Auditing 적용 + @Column(nullable = false, updatable = false) private LocalDateTime createdAt; // 생성 날짜 + @LastModifiedDate // JPA Auditing 적용 + @Column(nullable = false) private LocalDateTime updatedAt; // 수정 날짜 @Builder.Default From 2364cb4945e81136530d9cdbea0f56e2a21bf215 Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 15:23:27 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20DTO=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/profile/dto/ProfileResponseDto.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/com/back/domain/profile/dto/ProfileResponseDto.java diff --git a/src/main/java/com/back/domain/profile/dto/ProfileResponseDto.java b/src/main/java/com/back/domain/profile/dto/ProfileResponseDto.java new file mode 100644 index 00000000..f42277f1 --- /dev/null +++ b/src/main/java/com/back/domain/profile/dto/ProfileResponseDto.java @@ -0,0 +1,18 @@ +package com.back.domain.profile.dto; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ProfileResponseDto { + private Long id; + private String nickname; + private String email; + + // 서버에 저장된 실제 값(0~100) + private Double abvDegree; // 83.2 + // 표현용(서버에서 계산) + private Integer abvLevel; // 1~6 + private String abvLabel; // "83.2%" +} From 7eb0faa964d591f52e4f978f74f547562468364f Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 15:24:21 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20ABV=20=EB=A0=88=EB=B2=A8=20?= =?UTF-8?q?=EB=B0=8F=20=ED=8D=BC=EC=84=BC=ED=8A=B8=20=EB=9D=BC=EB=B2=A8?= =?UTF-8?q?=EB=A7=81=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/user/support/AbvView.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/com/back/domain/user/support/AbvView.java diff --git a/src/main/java/com/back/domain/user/support/AbvView.java b/src/main/java/com/back/domain/user/support/AbvView.java new file mode 100644 index 00000000..72d26e8f --- /dev/null +++ b/src/main/java/com/back/domain/user/support/AbvView.java @@ -0,0 +1,28 @@ +package com.back.domain.user.support; + +public final class AbvView { + + private AbvView(){} + + // 0~100%를 6단계로 매핑 + public static int levelOf(Double percent) { + if (percent == null) return 1; + + double x = Math.max(0, Math.min(100, percent)); + int p = (int) x; + + if (p <= 10) return 1; // 0~10 + if (p <= 25) return 2; // 11~25 + if (p <= 45) return 3; // 26~45 + if (p <= 65) return 4; // 46~65 + if (p <= 85) return 5; // 66~85 + return 6; // 86~100 + } + + // 화면용 "23.5%" 라벨 + public static String percentLabel(Double percent) { + if (percent == null) return "0%"; + double x = Math.max(0.0, Math.min(100.0, percent)); + return (x % 1.0 == 0.0) ? String.format("%.0f%%", x) : String.format("%.1f%%", x); + } +} From d3b59b1550e73f7b57bb19079f4f93f93b52b28a Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 15:25:52 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=ED=99=95=EC=9D=B8=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/back/domain/user/repository/UserRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/back/domain/user/repository/UserRepository.java b/src/main/java/com/back/domain/user/repository/UserRepository.java index ce4bcc8a..040d5ef1 100644 --- a/src/main/java/com/back/domain/user/repository/UserRepository.java +++ b/src/main/java/com/back/domain/user/repository/UserRepository.java @@ -6,5 +6,6 @@ @Repository public interface UserRepository extends JpaRepository { + boolean existsByNicknameAndIdNot(String nickname, Long id); } From 5b9a8778a0e5c97c1194bd35f16328b117993529 Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 15:45:22 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile/service/ProfileService.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/java/com/back/domain/profile/service/ProfileService.java diff --git a/src/main/java/com/back/domain/profile/service/ProfileService.java b/src/main/java/com/back/domain/profile/service/ProfileService.java new file mode 100644 index 00000000..5fe694d2 --- /dev/null +++ b/src/main/java/com/back/domain/profile/service/ProfileService.java @@ -0,0 +1,34 @@ +package com.back.domain.profile.service; + +import com.back.domain.profile.dto.ProfileResponseDto; +import com.back.domain.user.entity.User; +import com.back.domain.user.repository.UserRepository; +import com.back.domain.user.support.AbvView; +import com.back.global.exception.ServiceException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class ProfileService { + + private final UserRepository userRepository; + + @Transactional(readOnly = true) + public ProfileResponseDto getProfile(Long id) { + User user = userRepository.findById(id).orElseThrow(() -> new ServiceException(404, "사용자를 찾을 수 없습니다.")); + + Double percent = user.getAbvDegree(); + int level = AbvView.levelOf(percent); + String label = AbvView.percentLabel(percent); + + return ProfileResponseDto.builder() + .id(user.getId()) + .nickname(user.getNickname()) + .abvDegree(percent) + .abvLevel(level) + .abvLabel(label) + .build(); + } +} From 835799c5a1160f96b4e0cac1467aea0985cb9d5f Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 16:07:27 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=20=ED=95=84=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/back/domain/user/entity/User.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/back/domain/user/entity/User.java b/src/main/java/com/back/domain/user/entity/User.java index 3e0c21a0..036d95d2 100644 --- a/src/main/java/com/back/domain/user/entity/User.java +++ b/src/main/java/com/back/domain/user/entity/User.java @@ -47,8 +47,6 @@ public class User { @Column(nullable = false, length = 20) private String role = "USER"; - private String profileImgUrl; - public boolean isAdmin() { return "ADMIN".equalsIgnoreCase(role); } From 5abc38f6a64f99133a1905fcf4cba190e4b179a0 Mon Sep 17 00:00:00 2001 From: meohin Date: Thu, 18 Sep 2025 16:08:14 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=A1=B0=ED=9A=8C=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile/controller/ProfileController.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/com/back/domain/profile/controller/ProfileController.java diff --git a/src/main/java/com/back/domain/profile/controller/ProfileController.java b/src/main/java/com/back/domain/profile/controller/ProfileController.java new file mode 100644 index 00000000..2bd8e66f --- /dev/null +++ b/src/main/java/com/back/domain/profile/controller/ProfileController.java @@ -0,0 +1,26 @@ +package com.back.domain.profile.controller; + +import com.back.domain.profile.dto.ProfileResponseDto; +import com.back.domain.profile.service.ProfileService; +import com.back.domain.user.service.UserService; +import com.back.global.rsData.RsData; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/me/profile") +@RequiredArgsConstructor +public class ProfileController { + + private final UserService userService; + private final ProfileService profileService; + + @GetMapping + public RsData getProfile(@AuthenticationPrincipal(expression = "id") Long userId) { + ProfileResponseDto body = profileService.getProfile(userId); + return RsData.successOf(body); // code=200, message="success" + } +}