Skip to content

Commit d95ef9e

Browse files
committed
fix : conflict merge
2 parents 1ae6022 + d538e97 commit d95ef9e

File tree

8 files changed

+166
-3
lines changed

8 files changed

+166
-3
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ dependencies {
3131
implementation("io.github.cdimascio:java-dotenv:5.2.2")
3232
implementation("org.springframework.boot:spring-boot-starter-security")
3333
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
34-
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0")
34+
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0")
3535
implementation("io.jsonwebtoken:jjwt-api:0.12.3")
3636
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3")
3737
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3")
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.back.domain.profile.controller;
2+
3+
import com.back.domain.profile.dto.ProfileResponseDto;
4+
import com.back.domain.profile.dto.ProfileUpdateRequestDto;
5+
import com.back.domain.profile.service.ProfileService;
6+
import com.back.domain.user.service.UserService;
7+
import com.back.global.rsData.RsData;
8+
import jakarta.validation.Valid;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
11+
import org.springframework.web.bind.annotation.*;
12+
13+
@RestController
14+
@RequestMapping("/me/profile")
15+
@RequiredArgsConstructor
16+
public class ProfileController {
17+
18+
private final UserService userService;
19+
private final ProfileService profileService;
20+
21+
@GetMapping
22+
public RsData<ProfileResponseDto> getProfile(@AuthenticationPrincipal(expression = "id") Long userId) {
23+
ProfileResponseDto body = profileService.getProfile(userId);
24+
return RsData.successOf(body); // code=200, message="success"
25+
}
26+
27+
@PutMapping
28+
public RsData<ProfileResponseDto> updateProfile(@AuthenticationPrincipal(expression = "id") Long userId, @Valid @RequestBody ProfileUpdateRequestDto profileUpdateRequestDto) {
29+
ProfileResponseDto body = profileService.updateProfile(userId, profileUpdateRequestDto);
30+
return RsData.successOf(body); // code=200
31+
}
32+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.back.domain.profile.dto;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
6+
@Getter
7+
@Builder
8+
public class ProfileResponseDto {
9+
private Long id;
10+
private String nickname;
11+
private String email;
12+
13+
// 서버에 저장된 실제 값(0~100)
14+
private Double abvDegree; // 83.2
15+
// 표현용(서버에서 계산)
16+
private Integer abvLevel; // 1~6
17+
private String abvLabel; // "83.2%"
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.back.domain.profile.dto;
2+
3+
import jakarta.validation.constraints.Email;
4+
import jakarta.validation.constraints.Size;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
8+
@Getter
9+
@Setter
10+
public class ProfileUpdateRequestDto {
11+
12+
@Size(min = 1, max = 10, message = "닉네임은 1~10자")
13+
private String nickname;
14+
15+
@Email(message = "이메일 형식이 아닙니다")
16+
private String email;
17+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.back.domain.profile.service;
2+
3+
import com.back.domain.profile.dto.ProfileResponseDto;
4+
import com.back.domain.profile.dto.ProfileUpdateRequestDto;
5+
import com.back.domain.user.entity.User;
6+
import com.back.domain.user.repository.UserRepository;
7+
import com.back.domain.user.support.AbvView;
8+
import com.back.global.exception.ServiceException;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
import org.springframework.transaction.annotation.Transactional;
12+
13+
@Service
14+
@RequiredArgsConstructor
15+
public class ProfileService {
16+
17+
private final UserRepository userRepository;
18+
19+
@Transactional(readOnly = true)
20+
public ProfileResponseDto getProfile(Long id) {
21+
User user = userRepository.findById(id).orElseThrow(() -> new ServiceException(404, "사용자를 찾을 수 없습니다."));
22+
23+
Double percent = user.getAbvDegree();
24+
int level = AbvView.levelOf(percent);
25+
String label = AbvView.percentLabel(percent);
26+
27+
return ProfileResponseDto.builder()
28+
.id(user.getId())
29+
.nickname(user.getNickname())
30+
.abvDegree(percent)
31+
.abvLevel(level)
32+
.abvLabel(label)
33+
.build();
34+
}
35+
36+
@Transactional
37+
public ProfileResponseDto updateProfile(Long id, ProfileUpdateRequestDto profileUpdateRequestDto) {
38+
User user = userRepository.findById(id).orElseThrow(() -> new ServiceException(404, "사용자를 찾을 수 없습니다."));
39+
40+
if (profileUpdateRequestDto.getNickname() != null) {
41+
String nickname = profileUpdateRequestDto.getNickname().trim();
42+
if (nickname.isEmpty() || nickname.length() > 10) {
43+
throw new ServiceException(400, "닉네임은 1~10자");
44+
}
45+
46+
if (userRepository.existsByNicknameAndIdNot(nickname, id)) {
47+
throw new ServiceException(409, "이미 사용중인 닉네임");
48+
}
49+
50+
user.setNickname(nickname);
51+
}
52+
53+
if (profileUpdateRequestDto.getEmail() != null) {
54+
String email = profileUpdateRequestDto.getEmail().trim();
55+
user.setEmail(email.isEmpty() ? null : email);
56+
}
57+
58+
userRepository.save(user);
59+
60+
return getProfile(id);
61+
}
62+
}

src/main/java/com/back/domain/user/entity/User.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import lombok.*;
55
import org.springframework.security.core.GrantedAuthority;
66
import org.springframework.security.core.authority.SimpleGrantedAuthority;
7+
import org.springframework.data.annotation.CreatedDate;
8+
import org.springframework.data.annotation.LastModifiedDate;
79

810
import java.time.LocalDateTime;
911
import java.util.ArrayList;
@@ -40,16 +42,18 @@ public class User {
4042

4143
private Double abvDegree; // 알콜도수(회원 등급)
4244

45+
@CreatedDate // JPA Auditing 적용
46+
@Column(nullable = false, updatable = false)
4347
private LocalDateTime createdAt; // 생성 날짜
4448

49+
@LastModifiedDate // JPA Auditing 적용
50+
@Column(nullable = false)
4551
private LocalDateTime updatedAt; // 수정 날짜
4652

4753
@Builder.Default
4854
@Column(nullable = false, length = 20)
4955
private String role = "USER";
5056

51-
private String profileImgUrl;
52-
5357
public boolean isAdmin() {
5458
return "ADMIN".equalsIgnoreCase(role);
5559
}

src/main/java/com/back/domain/user/repository/UserRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
@Repository
1010
public interface UserRepository extends JpaRepository<User, Long> {
11+
1112
Optional<User> findByOauthId(String oauthId);
1213
Optional<User> findByEmail(String email);
1314
Optional<User> findByNickname(String nickname);
15+
boolean existsByNicknameAndIdNot(String nickname, Long id);
1416
}
1517

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.back.domain.user.support;
2+
3+
public final class AbvView {
4+
5+
private AbvView(){}
6+
7+
// 0~100%를 6단계로 매핑
8+
public static int levelOf(Double percent) {
9+
if (percent == null) return 1;
10+
11+
double x = Math.max(0, Math.min(100, percent));
12+
int p = (int) x;
13+
14+
if (p <= 10) return 1; // 0~10
15+
if (p <= 25) return 2; // 11~25
16+
if (p <= 45) return 3; // 26~45
17+
if (p <= 65) return 4; // 46~65
18+
if (p <= 85) return 5; // 66~85
19+
return 6; // 86~100
20+
}
21+
22+
// 화면용 "23.5%" 라벨
23+
public static String percentLabel(Double percent) {
24+
if (percent == null) return "0%";
25+
double x = Math.max(0.0, Math.min(100.0, percent));
26+
return (x % 1.0 == 0.0) ? String.format("%.0f%%", x) : String.format("%.1f%%", x);
27+
}
28+
}

0 commit comments

Comments
 (0)