From bc4f627ae536d22d0c8c86ef5abcf0fcb35e5976 Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 10:21:23 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feature:=20=EB=B3=B4=ED=98=B8=EC=9E=90,=20?= =?UTF-8?q?=EB=85=B8=EC=9D=B8=20=EC=86=8C=EC=85=9C=EA=B3=BC=20=ED=82=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/service/ActivityService.java | 160 ++++++------------ .../global/api_payload/SuccessCode.java | 5 +- .../service/ApiService.java} | 4 +- .../global/service/CoordinateService.java | 65 +++++++ .../silverbridgeX_user/global/util/UUID.java | 18 ++ .../user/controller/TokenController.java | 37 +++- .../user/converter/UserConverter.java | 8 +- .../silverbridgeX_user/user/domain/User.java | 11 ++ .../user/domain/UserRole.java | 6 + .../user/dto/UserRequestDto.java | 13 +- .../user/repository/UserRepository.java | 2 +- .../user/service/UserService.java | 53 +++++- 12 files changed, 248 insertions(+), 134 deletions(-) rename src/main/java/com/example/silverbridgeX_user/{activity/service/ActivityApiService.java => global/service/ApiService.java} (95%) create mode 100644 src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java create mode 100644 src/main/java/com/example/silverbridgeX_user/global/util/UUID.java create mode 100644 src/main/java/com/example/silverbridgeX_user/user/domain/UserRole.java diff --git a/src/main/java/com/example/silverbridgeX_user/activity/service/ActivityService.java b/src/main/java/com/example/silverbridgeX_user/activity/service/ActivityService.java index aa407e7..6708ff4 100644 --- a/src/main/java/com/example/silverbridgeX_user/activity/service/ActivityService.java +++ b/src/main/java/com/example/silverbridgeX_user/activity/service/ActivityService.java @@ -6,16 +6,14 @@ import com.example.silverbridgeX_user.activity.dto.ActivityResponseDto.TourSpotItemDto; import com.example.silverbridgeX_user.activity.repository.ActivityNativeRepository; import com.example.silverbridgeX_user.activity.repository.ActivityRepository; -import com.example.silverbridgeX_user.global.api_payload.ErrorCode; -import com.example.silverbridgeX_user.global.exception.GeneralException; +import com.example.silverbridgeX_user.global.service.ApiService; +import com.example.silverbridgeX_user.global.service.CoordinateService; import com.example.silverbridgeX_user.global.util.EmbeddingClient; import com.example.silverbridgeX_user.user.repository.UserRepository; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.transaction.Transactional; import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.time.LocalDate; import java.util.ArrayList; @@ -27,7 +25,6 @@ import org.neo4j.driver.Driver; import org.neo4j.driver.Session; import org.neo4j.driver.Values; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Slf4j @@ -37,7 +34,8 @@ public class ActivityService { private final ActivityRepository activityRepository; private final EmbeddingClient embeddingClient; private final ActivityNativeRepository activityNativeRepository; - private final ActivityApiService activityApiService; + private final CoordinateService coordinateService; + private final ApiService apiService; private final UserRepository userRepository; private final Driver driver; @@ -45,7 +43,6 @@ public class ActivityService { String festivalApiUrl = "http://api.data.go.kr/openapi/tn_pubr_public_cltur_fstvl_api"; String tourSpotApiUrl = "http://api.data.go.kr/openapi/tn_pubr_public_trrsrt_api"; - String addressToCoordinateApiurl = "https://api.vworld.kr/req/address?service=address&format=json&request=getCoord&refine=false"; public void fetchAndSaveFestivalData() { ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); @@ -53,9 +50,9 @@ public void fetchAndSaveFestivalData() { int page = 1; while (true) { try { - String urlStr = activityApiService.buildUrl(festivalApiUrl, page); - String json = activityApiService.getJsonFromUrl(urlStr); - JsonNode items = activityApiService.parseItems(json); + String urlStr = apiService.buildUrl(festivalApiUrl, page); + String json = apiService.getJsonFromUrl(urlStr); + JsonNode items = apiService.parseItems(json); if (items == null || !items.isArray() || items.isEmpty()) { log.info("page {} 응답 없음. 중단.", page); @@ -111,15 +108,61 @@ public void fetchAndSaveFestivalData() { } } + public void fetchAndSaveCoordinate() throws Exception { + List activities = activityRepository.findAll(); + System.out.println(activities.size()); + + for (Activity activity : activities) { + + try { + if (activity.getLatitude().startsWith("\"")) { + coordinateService.change(activity); + } + + if (!activity.getLongitude().isEmpty() || !activity.getLatitude().isEmpty()) { + continue; + } + + String urlStr = null; + + if (activity.getStreetAddress() != null) { + urlStr = coordinateService.buildCoordinateUrl("ROAD", activity.getStreetAddress()); + } else if (activity.getLotNumberAddress() != null) { + urlStr = coordinateService.buildCoordinateUrl("PARCEL", activity.getLotNumberAddress()); + } + + if (urlStr == null) { + continue; + } + + String json = apiService.getJsonFromUrl(urlStr); + log.info(json); + JsonNode point = apiService.parsePoint(json); + + if (!point.isMissingNode()) { + String x = String.valueOf(point.get("x")); + String y = String.valueOf(point.get("y")); + + activity.updateCoordinate(x, y); + activityRepository.save(activity); + } + } catch (IOException | ParseException e) { + throw new RuntimeException(e); + } + + } + + } + public void fetchAndSaveTourSpotData() { ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); int page = 1; while (true) { try { - String urlStr = activityApiService.buildUrl(tourSpotApiUrl, page); - String json = activityApiService.getJsonFromUrl(urlStr); - JsonNode items = activityApiService.parseItems(json); + String urlStr = apiService.buildUrl(tourSpotApiUrl, page); + String json = apiService.getJsonFromUrl(urlStr); + JsonNode items = apiService.parseItems(json); if (items == null || !items.isArray() || items.isEmpty()) { log.info("page {} 응답 없음. 중단.", page); @@ -169,97 +212,6 @@ public void fetchAndSaveTourSpotData() { } } - public void fetchAndSaveCoordinate() throws Exception { - List activities = activityRepository.findAll(); - System.out.println(activities.size()); - - for (Activity activity : activities) { - - try { - if (activity.getLatitude().startsWith("\"")) { - change(activity); - } - - if (!activity.getLongitude().isEmpty() || !activity.getLatitude().isEmpty()) { - continue; - } - - String urlStr = null; - - if (activity.getStreetAddress() != null) { - urlStr = buildCoordinateUrl("ROAD", activity.getStreetAddress()); - } else if (activity.getLotNumberAddress() != null) { - urlStr = buildCoordinateUrl("PARCEL", activity.getLotNumberAddress()); - } - - if (urlStr == null) { - continue; - } - - String json = activityApiService.getJsonFromUrl(urlStr); - log.info(json); - JsonNode point = activityApiService.parsePoint(json); - - if (!point.isMissingNode()) { - String x = String.valueOf(point.get("x")); - String y = String.valueOf(point.get("y")); - - activity.updateCoordinate(x, y); - activityRepository.save(activity); - } - } catch (IOException | ParseException e) { - throw new RuntimeException(e); - } - - } - - } - - @Value("${geocoder.api.key}") - private String key; - - private String buildCoordinateUrl(String type, String address) throws Exception { - StringBuilder urlBuilder = new StringBuilder(addressToCoordinateApiurl); - urlBuilder.append("&key=" + key); - urlBuilder.append("&type=" + type); // PARCEL : 지번주소, ROAD : 도로명주소 - urlBuilder.append("&address=" + URLEncoder.encode(address, StandardCharsets.UTF_8)); - return urlBuilder.toString(); - } - - private void change(Activity activity) { - String latitude = activity.getLatitude(); - String longitude = activity.getLongitude(); - - boolean updated = false; - - if (latitude != null && latitude.contains("\"")) { - latitude = latitude.replace("\"", ""); // 모든 " 제거 - activity.updateLatitude(latitude); - updated = true; - } - - if (longitude != null && longitude.contains("\"")) { - longitude = longitude.replace("\"", ""); - activity.updateLongitude(longitude); - updated = true; - } - - if (updated) { - activityRepository.save(activity); - System.out.println("좌표 문자열 정제 완료: " + activity.getId()); - } - } - - // 해당 API에서 제공하지 않는 주소들에 대한 2차 검증 로직 - public void test() throws Exception { - Activity activity = activityRepository.findById(Long.valueOf(102)) - .orElseThrow(() -> GeneralException.of(ErrorCode.ACTIVITY_NOT_FOUND)); - String urlStr = buildCoordinateUrl("PARCEL", activity.getLotNumberAddress()); - String json = activityApiService.getJsonFromUrl(urlStr); - System.out.println(json); - - } - public void insertActivitiesNeo4j() { List activities = activityRepository.findAll(); diff --git a/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java b/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java index c580150..f679acf 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java +++ b/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java @@ -13,7 +13,8 @@ public enum SuccessCode implements BaseCode { CREATED(HttpStatus.CREATED, "COMMON_201", "Created"), // User - USER_LOGIN_SUCCESS(HttpStatus.CREATED, "USER_2011", "회원가입& 로그인이 완료되었습니다."), + USER_SOCIAL_LOGIN_SUCCESS(HttpStatus.CREATED, "USER_2011", "소셜 회원가입 혹은 로그인이 완료되었습니다."), + USER_KEY_LOGIN_SUCCESS(HttpStatus.CREATED, "USER_2012", "KEY 로그인이 완료되었습니다."), USER_LOGOUT_SUCCESS(HttpStatus.OK, "USER_2001", "로그아웃 되었습니다."), USER_REISSUE_SUCCESS(HttpStatus.OK, "USER_2002", "토큰 재발급이 완료되었습니다."), USER_DELETE_SUCCESS(HttpStatus.OK, "USER_2003", "회원탈퇴가 완료되었습니다."), @@ -21,7 +22,7 @@ public enum SuccessCode implements BaseCode { USER_INFO_UPDATE_SUCCESS(HttpStatus.OK, "USER_2005", "회원 정보 수정이 완료 되었습니다."), USER_INFO_VIEW_SUCCESS(HttpStatus.OK, "USER_2006", "회원 정보 조회가 완료 되었습니다."), USER_PROFILE_IMAGE_UPDATE_SUCCESS(HttpStatus.OK, "USER_2007", "프로필 사진 이미지 업로드가 완료 되었습니다."), - USER_MYPAGE_VIEW_SUCCESS(HttpStatus.OK, "USER_2010", "마이페이지 정보 조회가 완료되었습니다."), + USER_MYPAGE_VIEW_SUCCESS(HttpStatus.OK, "USER_2008", "마이페이지 정보 조회가 완료되었습니다."), // Recommend Activity RECOMMEND_ACTIVITY_VIEW_LIST_SUCCESS(HttpStatus.OK, "ACTIVITY_2001", "추천하는 활동 리스를 반환 완료했습니다."), diff --git a/src/main/java/com/example/silverbridgeX_user/activity/service/ActivityApiService.java b/src/main/java/com/example/silverbridgeX_user/global/service/ApiService.java similarity index 95% rename from src/main/java/com/example/silverbridgeX_user/activity/service/ActivityApiService.java rename to src/main/java/com/example/silverbridgeX_user/global/service/ApiService.java index 8e81a5b..08da73f 100644 --- a/src/main/java/com/example/silverbridgeX_user/activity/service/ActivityApiService.java +++ b/src/main/java/com/example/silverbridgeX_user/global/service/ApiService.java @@ -1,4 +1,4 @@ -package com.example.silverbridgeX_user.activity.service; +package com.example.silverbridgeX_user.global.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -12,7 +12,7 @@ import org.springframework.stereotype.Service; @Service -public class ActivityApiService { +public class ApiService { private final ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java b/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java new file mode 100644 index 0000000..5375f6d --- /dev/null +++ b/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java @@ -0,0 +1,65 @@ +package com.example.silverbridgeX_user.global.service; + +import com.example.silverbridgeX_user.activity.domain.Activity; +import com.example.silverbridgeX_user.activity.repository.ActivityRepository; +import com.example.silverbridgeX_user.global.api_payload.ErrorCode; +import com.example.silverbridgeX_user.global.exception.GeneralException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import lombok.NoArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@NoArgsConstructor(force = true) +public class CoordinateService { + private final ActivityRepository activityRepository; + private final ApiService apiService; + + public String addressToCoordinateApiurl = "https://api.vworld.kr/req/address?service=address&format=json&request=getCoord&refine=false"; + + @Value("${geocoder.api.key}") + private String key; + + public String buildCoordinateUrl(String type, String address) { + StringBuilder urlBuilder = new StringBuilder(addressToCoordinateApiurl); + urlBuilder.append("&key=" + key); + urlBuilder.append("&type=" + type); // PARCEL : 지번주소, ROAD : 도로명주소 + urlBuilder.append("&address=" + URLEncoder.encode(address, StandardCharsets.UTF_8)); + return urlBuilder.toString(); + } + + public void change(Activity activity) { + String latitude = activity.getLatitude(); + String longitude = activity.getLongitude(); + + boolean updated = false; + + if (latitude != null && latitude.contains("\"")) { + latitude = latitude.replace("\"", ""); // 모든 " 제거 + activity.updateLatitude(latitude); + updated = true; + } + + if (longitude != null && longitude.contains("\"")) { + longitude = longitude.replace("\"", ""); + activity.updateLongitude(longitude); + updated = true; + } + + if (updated) { + activityRepository.save(activity); + System.out.println("좌표 문자열 정제 완료: " + activity.getId()); + } + } + + // 해당 API에서 제공하지 않는 주소들에 대한 2차 검증 로직 + public void test() throws Exception { + Activity activity = activityRepository.findById(Long.valueOf(102)) + .orElseThrow(() -> GeneralException.of(ErrorCode.ACTIVITY_NOT_FOUND)); + String urlStr = buildCoordinateUrl("PARCEL", activity.getLotNumberAddress()); + String json = apiService.getJsonFromUrl(urlStr); + System.out.println(json); + + } +} diff --git a/src/main/java/com/example/silverbridgeX_user/global/util/UUID.java b/src/main/java/com/example/silverbridgeX_user/global/util/UUID.java new file mode 100644 index 0000000..a745c99 --- /dev/null +++ b/src/main/java/com/example/silverbridgeX_user/global/util/UUID.java @@ -0,0 +1,18 @@ +package com.example.silverbridgeX_user.global.util; + +import java.security.SecureRandom; + +public class UUID { + + private static final String BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private static final SecureRandom random = new SecureRandom(); + + public static String generate() { + StringBuilder sb = new StringBuilder(6); + for (int i = 0; i < 6; i++) { + sb.append(BASE62.charAt(random.nextInt(BASE62.length()))); + } + return sb.toString(); + } + +} diff --git a/src/main/java/com/example/silverbridgeX_user/user/controller/TokenController.java b/src/main/java/com/example/silverbridgeX_user/user/controller/TokenController.java index 4247f16..b0da1e3 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/controller/TokenController.java +++ b/src/main/java/com/example/silverbridgeX_user/user/controller/TokenController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -25,14 +26,14 @@ public class TokenController { private final UserService userService; - @Operation(summary = "토큰 반환", description = "프론트에게 유저 정보 받아 토큰 반환하는 메서드입니다.") + @Operation(summary = "토큰 반환", description = "노인/보호자 소셜 로그인 후, 프론트에게 유저 정보 받아 토큰 반환하는 메서드입니다.") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2011", description = "회원가입 & 로그인 성공"), }) - @PostMapping("/generate") + @PostMapping("/generate/social") public ApiResponse tokenToFront( - @RequestBody UserRequestDto.UserReqDto userReqDto // email, username, nickname - ) { + @RequestBody UserRequestDto.UserReqDto userReqDto + ) throws Exception { Boolean isMember = userService.checkMemberByEmail(userReqDto.getEmail()); String accessToken = ""; @@ -41,23 +42,41 @@ public ApiResponse tokenToFront( String signIn = "wasUser"; if (isMember) { - User user = userService.findByUserName(userReqDto.getEmail()); + User user = userService.findByEmail(userReqDto.getEmail()); - JwtDto jwt = userService.jwtMakeSave(userReqDto.getEmail()); + JwtDto jwt = userService.jwtMakeSave(user.getUsername()); accessToken = jwt.getAccessToken(); refreshToken = jwt.getRefreshToken(); } else { - User newUser = userService.createUser(userReqDto); + User user = userService.createUser(userReqDto); - JwtDto jwt = userService.jwtMakeSave(userReqDto.getEmail()); + JwtDto jwt = userService.jwtMakeSave(user.getUsername()); accessToken = jwt.getAccessToken(); refreshToken = jwt.getRefreshToken(); signIn = "newUser"; } - return ApiResponse.onSuccess(SuccessCode.USER_LOGIN_SUCCESS, + return ApiResponse.onSuccess(SuccessCode.USER_SOCIAL_LOGIN_SUCCESS, UserConverter.jwtDto(accessToken, refreshToken, signIn)); } + + @Operation(summary = "토큰 반환", description = "노인의 key 로그인 후, 프론트에게 유저 정보 받아 토큰 반환하는 메서드입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2012", description = "회원가입 & 로그인 성공"), + }) + @PostMapping("/generate/key") + public ApiResponse tokenToFront( + @RequestParam String key + ) { + User user = userService.findByUserName(key); + + JwtDto jwt = userService.jwtMakeSave(user.getUsername()); + String accessToken = jwt.getAccessToken(); + String refreshToken = jwt.getRefreshToken(); + + return ApiResponse.onSuccess(SuccessCode.USER_KEY_LOGIN_SUCCESS, + UserConverter.jwtDto(accessToken, refreshToken, "wasUser")); + } } diff --git a/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java b/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java index 9a050b9..3b10654 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java +++ b/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java @@ -5,16 +5,17 @@ import com.example.silverbridgeX_user.user.dto.UserRequestDto; public class UserConverter { - public static User saveUser(UserRequestDto.UserReqDto userReqDto) { + public static User saveUser(UserRequestDto.UserReqDto userReqDto, String key) { return User.builder() + .role(userReqDto.getRole()) .email(userReqDto.getEmail()) - .username(userReqDto.getEmail()) + .username(key) .nickname(userReqDto.getNickname()) + .streetAddress(userReqDto.getStreetAddress()) .build(); } - public static JwtDto jwtDto(String access, String refresh, String signIn) { return JwtDto.builder() .accessToken(access) @@ -23,4 +24,5 @@ public static JwtDto jwtDto(String access, String refresh, String signIn) { .build(); } + } diff --git a/src/main/java/com/example/silverbridgeX_user/user/domain/User.java b/src/main/java/com/example/silverbridgeX_user/user/domain/User.java index fec31a4..76e9202 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/domain/User.java +++ b/src/main/java/com/example/silverbridgeX_user/user/domain/User.java @@ -5,6 +5,8 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -39,6 +41,10 @@ public class User extends BaseEntity { @Column(nullable = false) private String nickname; + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private UserRole role; + private String sex; private String birth; @@ -82,6 +88,11 @@ public void updateNickname(String nickname) { public void updatePreferredKeywords(List keywords) { this.preferredKeywords = keywords; } + + public void updateCoordinate(String longitude, String latitude) { + this.longitude = longitude; + this.latitude = latitude; + } } diff --git a/src/main/java/com/example/silverbridgeX_user/user/domain/UserRole.java b/src/main/java/com/example/silverbridgeX_user/user/domain/UserRole.java new file mode 100644 index 0000000..79cfec2 --- /dev/null +++ b/src/main/java/com/example/silverbridgeX_user/user/domain/UserRole.java @@ -0,0 +1,6 @@ +package com.example.silverbridgeX_user.user.domain; + +public enum UserRole { + OLDER, + PROTECTOR +} diff --git a/src/main/java/com/example/silverbridgeX_user/user/dto/UserRequestDto.java b/src/main/java/com/example/silverbridgeX_user/user/dto/UserRequestDto.java index f5224a4..f544b1a 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/dto/UserRequestDto.java +++ b/src/main/java/com/example/silverbridgeX_user/user/dto/UserRequestDto.java @@ -1,5 +1,6 @@ package com.example.silverbridgeX_user.user.dto; +import com.example.silverbridgeX_user.user.domain.UserRole; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; import lombok.AllArgsConstructor; @@ -16,6 +17,8 @@ public class UserRequestDto { @AllArgsConstructor @NoArgsConstructor public static class UserReqDto { + @Schema(description = "역할(OLDER/PROTECTOR)") + private UserRole role; @Schema(description = "이메일") private String email; @@ -23,6 +26,9 @@ public static class UserReqDto { @Schema(description = "닉네임") private String nickname; + @Schema(description = "도로명 주소") + private String streetAddress; + } @Schema(description = "UserNicknameReqDto") @@ -44,17 +50,10 @@ public static class UserNicknameReqDto { @AllArgsConstructor @NoArgsConstructor public static class UserAddressReqDto { - @Schema(description = "수령자 이름") - private String recipientName; - - @Schema(description = "전화번호") - private String phoneNumber; @Schema(description = "도로명 주소") private String streetAddress; - @Schema(description = "상세 주소") - private String detailedAddress; } @Schema(description = "UserPreferenceDto") diff --git a/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java b/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java index aec249c..21179b1 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java +++ b/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java @@ -25,7 +25,7 @@ public interface UserRepository extends JpaRepository { // 5. 닉네임이 사용중인지 판단하는 기능 boolean existsByNickname(String nickname); - + @Modifying @Transactional @Query(value = "UPDATE member SET preferred_embedding = CAST(:embedding AS vector) WHERE id = :userId", nativeQuery = true) diff --git a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java index ada5a3c..19aac60 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java +++ b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java @@ -2,15 +2,21 @@ import com.example.silverbridgeX_user.global.api_payload.ErrorCode; import com.example.silverbridgeX_user.global.exception.GeneralException; +import com.example.silverbridgeX_user.global.service.ApiService; +import com.example.silverbridgeX_user.global.service.CoordinateService; +import com.example.silverbridgeX_user.global.util.UUID; import com.example.silverbridgeX_user.user.converter.UserConverter; import com.example.silverbridgeX_user.user.domain.RefreshToken; import com.example.silverbridgeX_user.user.domain.User; +import com.example.silverbridgeX_user.user.domain.UserRole; import com.example.silverbridgeX_user.user.dto.JwtDto; import com.example.silverbridgeX_user.user.dto.UserRequestDto; import com.example.silverbridgeX_user.user.dto.UserRequestDto.UserPreferenceDto; +import com.example.silverbridgeX_user.user.dto.UserRequestDto.UserReqDto; import com.example.silverbridgeX_user.user.jwt.JwtTokenUtils; import com.example.silverbridgeX_user.user.repository.RefreshTokenRepository; import com.example.silverbridgeX_user.user.repository.UserRepository; +import com.fasterxml.jackson.databind.JsonNode; import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; import jakarta.transaction.Transactional; @@ -34,13 +40,20 @@ public class UserService { private final UserRepository userRepository; private final RefreshTokenRepository refreshTokenRepository; private final JpaUserDetailsManager manager; + private final CoordinateService coordinateService; private final JwtTokenUtils jwtTokenUtils; private final RestTemplate restTemplate; + private final ApiService apiService; private final Driver driver; @Value("${chat.server.url}") private String chatServerUrl; + + @Value("${geocoder.api.key}") + private String key; private String PREF_URL; + public String addressToCoordinateApiUrl = "https://api.vworld.kr/req/address?service=address&format=json&request=getCoord&refine=false"; + @PostConstruct public void init() { @@ -53,21 +66,49 @@ public User findByUserName(String userName) { .orElseThrow(() -> new GeneralException(ErrorCode.USER_NOT_FOUND_BY_USERNAME)); } + @Transactional + public User findByEmail(String email) { + return userRepository.findByEmail(email) + .orElseThrow(() -> new GeneralException(ErrorCode.USER_NOT_FOUND_BY_EMAIL)); + } + @Transactional public Boolean checkMemberByEmail(String email) { return userRepository.existsByEmail(email); } @Transactional - public User createUser(UserRequestDto.UserReqDto userReqDto) { - // User 엔티티 만들기 - User newUser = UserConverter.saveUser(userReqDto); + public User createUser(UserReqDto userReqDto) throws Exception { + + String uniqueKey; + do { + uniqueKey = UUID.generate(); + } while (userRepository.existsByUsername(uniqueKey)); + + User newUser = UserConverter.saveUser(userReqDto, uniqueKey); userRepository.save(newUser); - // Neo4j 사용자 노드 만들기 - insertUserNodeIfNotExists(newUser.getId()); + if (userReqDto.getRole().equals(UserRole.OLDER)) { + + insertUserNodeIfNotExists(newUser.getId()); + + String urlStr = coordinateService.buildCoordinateUrl("ROAD", userReqDto.getStreetAddress()); + String json = apiService.getJsonFromUrl(urlStr); + log.info(json); + JsonNode point = apiService.parsePoint(json); + if (!point.isMissingNode()) { + String x = String.valueOf(point.get("x")); + String y = String.valueOf(point.get("y")); + x = x.replace("\"", ""); + y = y.replace("\"", ""); + + newUser.updateCoordinate(x, y); + userRepository.save(newUser); + } + } + + manager.loadUserByUsername(newUser.getUsername()); // 저장된 사용자 정보를 다시 로드하여 동기화 시도 - manager.loadUserByUsername(userReqDto.getEmail()); // 저장된 사용자 정보를 다시 로드하여 동기화 시도 return newUser; } From c009d9944a99a8ffd131d19a8e93a583ed4e62f2 Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 16:58:25 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feature:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20(=EC=A1=B0=ED=9A=8C,=20=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/api_payload/ErrorCode.java | 7 +-- .../global/api_payload/SuccessCode.java | 8 ++- .../global/converter/CoordinateConverter.java | 14 +++++ .../global/dto/CoordinateDto.java | 20 +++++++ .../global/service/CoordinateService.java | 17 ++++++ .../user/controller/UserController.java | 52 +++++++++++++++++-- .../user/converter/UserConverter.java | 20 +++++++ .../silverbridgeX_user/user/domain/User.java | 4 ++ .../user/dto/UserResponseDto.java | 34 ++++++++++-- .../user/service/UserService.java | 50 +++++++++++------- 10 files changed, 190 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/example/silverbridgeX_user/global/converter/CoordinateConverter.java create mode 100644 src/main/java/com/example/silverbridgeX_user/global/dto/CoordinateDto.java diff --git a/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java b/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java index d97b30b..8198c80 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java +++ b/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java @@ -11,16 +11,13 @@ public enum ErrorCode implements BaseCode { // Common BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON_400", "잘못된 요청입니다."), INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON_500", "서버 에러, 서버 개발자에게 문의하세요."), - INVALID_PARAMETER(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON_5002", "잘못된 DAY Parameter 가 들어왔습니다. "), // User USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_4041", "존재하지 않는 회원입니다."), USER_NOT_FOUND_BY_EMAIL(HttpStatus.NOT_FOUND, "USER_4042", "존재하지 않는 회원입니다.-EMAIL"), USER_NOT_FOUND_BY_USERNAME(HttpStatus.NOT_FOUND, "USER_4043", "존재하지 않는 회원입니다.-USERNAME"), - ALREADY_USED_NICKNAME(HttpStatus.FORBIDDEN, "USER_4031", "이미 사용중인 닉네임입니다."), - USER_ADDRESS_NULL(HttpStatus.BAD_REQUEST, "USER_4001", "주소값이 비었거나 NULL입니다."), - INVALID_PHONE_NUMBER_FORMAT(HttpStatus.BAD_REQUEST, "USER_4002", "전화번호 형식은 연속된 숫자 11개여야 합니다."), - SMS_CODE_NOT_VERIFIED(HttpStatus.BAD_REQUEST, "USER_4003", "전화번호 인증 코드가 틀렸습니다"), + USER_NOT_OLDER(HttpStatus.FORBIDDEN, "USER_4031", "해당 유저가 노인이 아니랍니다."), + USER_NOT_PROTECTOR(HttpStatus.FORBIDDEN, "USER_4032", "해당 유저가 보호자가 아닙니다."), // Jwt WRONG_REFRESH_TOKEN(HttpStatus.NOT_FOUND, "JWT_4041", "일치하는 리프레시 토큰이 없습니다."), diff --git a/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java b/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java index f679acf..a8286d3 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java +++ b/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java @@ -18,11 +18,9 @@ public enum SuccessCode implements BaseCode { USER_LOGOUT_SUCCESS(HttpStatus.OK, "USER_2001", "로그아웃 되었습니다."), USER_REISSUE_SUCCESS(HttpStatus.OK, "USER_2002", "토큰 재발급이 완료되었습니다."), USER_DELETE_SUCCESS(HttpStatus.OK, "USER_2003", "회원탈퇴가 완료되었습니다."), - USER_NICKNAME_SUCCESS(HttpStatus.OK, "USER_2004", "닉네임 생성/수정이 완료되었습니다."), - USER_INFO_UPDATE_SUCCESS(HttpStatus.OK, "USER_2005", "회원 정보 수정이 완료 되었습니다."), - USER_INFO_VIEW_SUCCESS(HttpStatus.OK, "USER_2006", "회원 정보 조회가 완료 되었습니다."), - USER_PROFILE_IMAGE_UPDATE_SUCCESS(HttpStatus.OK, "USER_2007", "프로필 사진 이미지 업로드가 완료 되었습니다."), - USER_MYPAGE_VIEW_SUCCESS(HttpStatus.OK, "USER_2008", "마이페이지 정보 조회가 완료되었습니다."), + USER_NICKNAME_UPDATE_SUCCESS(HttpStatus.OK, "USER_2004", "닉네임 수정이 완료되었습니다."), + USER_ADDRESS_UPDATE_SUCCESS(HttpStatus.OK, "USER_2005", "주소지 수정이 완료되었습니다."), + USER_MYPAGE_VIEW_SUCCESS(HttpStatus.OK, "USER_2006", "마이페이지 정보 조회가 완료되었습니다."), // Recommend Activity RECOMMEND_ACTIVITY_VIEW_LIST_SUCCESS(HttpStatus.OK, "ACTIVITY_2001", "추천하는 활동 리스를 반환 완료했습니다."), diff --git a/src/main/java/com/example/silverbridgeX_user/global/converter/CoordinateConverter.java b/src/main/java/com/example/silverbridgeX_user/global/converter/CoordinateConverter.java new file mode 100644 index 0000000..f11848b --- /dev/null +++ b/src/main/java/com/example/silverbridgeX_user/global/converter/CoordinateConverter.java @@ -0,0 +1,14 @@ +package com.example.silverbridgeX_user.global.converter; + +import com.example.silverbridgeX_user.global.dto.CoordinateDto.simpleCoordinateDto; + +public class CoordinateConverter { + + public static simpleCoordinateDto simpleCoordinateDto(String x, String y) { + + return simpleCoordinateDto.builder() + .x(x) + .y(y) + .build(); + } +} diff --git a/src/main/java/com/example/silverbridgeX_user/global/dto/CoordinateDto.java b/src/main/java/com/example/silverbridgeX_user/global/dto/CoordinateDto.java new file mode 100644 index 0000000..0e68319 --- /dev/null +++ b/src/main/java/com/example/silverbridgeX_user/global/dto/CoordinateDto.java @@ -0,0 +1,20 @@ +package com.example.silverbridgeX_user.global.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +public class CoordinateDto { + + @Getter + @Setter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class simpleCoordinateDto { + private String x; + private String y; + } +} diff --git a/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java b/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java index 5375f6d..f0dd85c 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java +++ b/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java @@ -3,7 +3,10 @@ import com.example.silverbridgeX_user.activity.domain.Activity; import com.example.silverbridgeX_user.activity.repository.ActivityRepository; import com.example.silverbridgeX_user.global.api_payload.ErrorCode; +import com.example.silverbridgeX_user.global.converter.CoordinateConverter; +import com.example.silverbridgeX_user.global.dto.CoordinateDto; import com.example.silverbridgeX_user.global.exception.GeneralException; +import com.fasterxml.jackson.databind.JsonNode; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import lombok.NoArgsConstructor; @@ -21,6 +24,20 @@ public class CoordinateService { @Value("${geocoder.api.key}") private String key; + public CoordinateDto.simpleCoordinateDto getCoordinateByAddress(String type, String address) throws Exception { + String urlStr = buildCoordinateUrl(type, address); + assert apiService != null; + String json = apiService.getJsonFromUrl(urlStr); + JsonNode point = apiService.parsePoint(json); + + String x = String.valueOf(point.get("x")); + String y = String.valueOf(point.get("y")); + x = x.replace("\"", ""); + y = y.replace("\"", ""); + + return CoordinateConverter.simpleCoordinateDto(x, y); + } + public String buildCoordinateUrl(String type, String address) { StringBuilder urlBuilder = new StringBuilder(addressToCoordinateApiurl); urlBuilder.append("&key=" + key); diff --git a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java index 1f71ecd..a2c5c46 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java +++ b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java @@ -2,9 +2,13 @@ import com.example.silverbridgeX_user.global.api_payload.ApiResponse; import com.example.silverbridgeX_user.global.api_payload.SuccessCode; +import com.example.silverbridgeX_user.user.converter.UserConverter; import com.example.silverbridgeX_user.user.domain.User; import com.example.silverbridgeX_user.user.dto.JwtDto; +import com.example.silverbridgeX_user.user.dto.UserRequestDto.UserAddressReqDto; import com.example.silverbridgeX_user.user.dto.UserRequestDto.UserNicknameReqDto; +import com.example.silverbridgeX_user.user.dto.UserResponseDto.OlderMyPageResDto; +import com.example.silverbridgeX_user.user.dto.UserResponseDto.ProtectorMyPageResDto; import com.example.silverbridgeX_user.user.jwt.CustomUserDetails; import com.example.silverbridgeX_user.user.service.UserService; import io.swagger.v3.oas.annotations.Operation; @@ -59,9 +63,9 @@ public ApiResponse deleteUser(Authentication auth) { return ApiResponse.onSuccess(SuccessCode.USER_DELETE_SUCCESS, "user entity 삭제 완료"); } - @Operation(summary = "닉네임 입력, 수정", description = "중복 안되는 닉네임을 입력받는 메서드입니다.") + @Operation(summary = "닉네임 수정", description = "닉네임을 변경하는 메서드입니다.") @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2004", description = "닉네임 생성이 완료되었습니다.") + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2004", description = "닉네임 변경이 완료되었습니다.") }) @PostMapping(value = "/nickname/update") public ApiResponse nickname( @@ -70,6 +74,48 @@ public ApiResponse nickname( ) { User user = userService.findByUserName(customUserDetails.getUsername()); userService.saveNickname(nicknameReqDto, user); - return ApiResponse.onSuccess(SuccessCode.USER_NICKNAME_SUCCESS, true); + return ApiResponse.onSuccess(SuccessCode.USER_NICKNAME_UPDATE_SUCCESS, true); } + + @Operation(summary = "주소 수정", description = "주소를 변경하는 메서드입니다.") + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2005", description = "주소지 변경이 완료되었습니다.") + }) + @PostMapping(value = "/address/update") + public ApiResponse address( + @RequestBody UserAddressReqDto addressReqDto, + @AuthenticationPrincipal CustomUserDetails customUserDetails + ) throws Exception { + User user = userService.findByUserName(customUserDetails.getUsername()); + userService.saveAddress(addressReqDto, user); + return ApiResponse.onSuccess(SuccessCode.USER_ADDRESS_UPDATE_SUCCESS, true); + } + + @Operation(summary = "노인 마이페이지 조회", description = "노인 마이페이지를 조회하는 메서드입니다.") + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2006", description = "노인 마이페이지 정보 조회가 완료되었습니다.") + }) + @PostMapping(value = "/mypage/older") + public ApiResponse mypageOlder( + @AuthenticationPrincipal CustomUserDetails customUserDetails + ) { + User user = userService.findByUserName(customUserDetails.getUsername()); + userService.validateOlder(user); + return ApiResponse.onSuccess(SuccessCode.USER_MYPAGE_VIEW_SUCCESS, UserConverter.olderMyPageResDto(user)); + } + + @Operation(summary = "보호자 마이페이지 조회", description = "보호자 마이페이지를 조회하는 메서드입니다.") + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2006", description = "노인 마이페이지 정보 조회가 완료되었습니다.") + }) + @PostMapping(value = "/mypage/protector") + public ApiResponse mypageProtector( + @AuthenticationPrincipal CustomUserDetails customUserDetails + ) { + User user = userService.findByUserName(customUserDetails.getUsername()); + userService.validateProtector(user); + + return ApiResponse.onSuccess(SuccessCode.USER_MYPAGE_VIEW_SUCCESS, UserConverter.protectorMyPageResDto(user)); + } + } diff --git a/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java b/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java index 3b10654..d4755aa 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java +++ b/src/main/java/com/example/silverbridgeX_user/user/converter/UserConverter.java @@ -3,6 +3,8 @@ import com.example.silverbridgeX_user.user.domain.User; import com.example.silverbridgeX_user.user.dto.JwtDto; import com.example.silverbridgeX_user.user.dto.UserRequestDto; +import com.example.silverbridgeX_user.user.dto.UserResponseDto.OlderMyPageResDto; +import com.example.silverbridgeX_user.user.dto.UserResponseDto.ProtectorMyPageResDto; public class UserConverter { public static User saveUser(UserRequestDto.UserReqDto userReqDto, String key) { @@ -24,5 +26,23 @@ public static JwtDto jwtDto(String access, String refresh, String signIn) { .build(); } + public static OlderMyPageResDto olderMyPageResDto(User user) { + return OlderMyPageResDto.builder() + .key(user.getUsername()) + .nickname(user.getNickname()) + .address(user.getStreetAddress()) + .email(user.getEmail()) + .build(); + } + + public static ProtectorMyPageResDto protectorMyPageResDto(User user) { + return ProtectorMyPageResDto.builder() + .key(user.getUsername()) + .nickname(user.getNickname()) + .address(user.getStreetAddress()) + .email(user.getEmail()) + .build(); + } + } diff --git a/src/main/java/com/example/silverbridgeX_user/user/domain/User.java b/src/main/java/com/example/silverbridgeX_user/user/domain/User.java index 76e9202..ba7ab04 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/domain/User.java +++ b/src/main/java/com/example/silverbridgeX_user/user/domain/User.java @@ -85,6 +85,10 @@ public void updateNickname(String nickname) { this.nickname = nickname; } + public void updateAddress(String address) { + this.streetAddress = address; + } + public void updatePreferredKeywords(List keywords) { this.preferredKeywords = keywords; } diff --git a/src/main/java/com/example/silverbridgeX_user/user/dto/UserResponseDto.java b/src/main/java/com/example/silverbridgeX_user/user/dto/UserResponseDto.java index c11f4c8..1fadca5 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/dto/UserResponseDto.java +++ b/src/main/java/com/example/silverbridgeX_user/user/dto/UserResponseDto.java @@ -10,18 +10,44 @@ @NoArgsConstructor public class UserResponseDto { - @Schema(description = "UserMyPageResDto") + @Schema(description = "OlderMyPageResDto") @Getter @Setter @Builder @AllArgsConstructor @NoArgsConstructor - public static class UserMyPageResDto { + public static class OlderMyPageResDto { @Schema(description = "닉네임") private String nickname; - @Schema(description = "프로필 이미지") - private String profileImage; + @Schema(description = "key") + private String key; + + @Schema(description = "address") + private String address; + + @Schema(description = "email") + private String email; + } + + @Schema(description = "ProtectorMyPageResDto") + @Getter + @Setter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class ProtectorMyPageResDto { + @Schema(description = "닉네임") + private String nickname; + + @Schema(description = "key") + private String key; + + @Schema(description = "address") + private String address; + + @Schema(description = "email") + private String email; } } diff --git a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java index 19aac60..b16429c 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java +++ b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java @@ -1,6 +1,7 @@ package com.example.silverbridgeX_user.user.service; import com.example.silverbridgeX_user.global.api_payload.ErrorCode; +import com.example.silverbridgeX_user.global.dto.CoordinateDto; import com.example.silverbridgeX_user.global.exception.GeneralException; import com.example.silverbridgeX_user.global.service.ApiService; import com.example.silverbridgeX_user.global.service.CoordinateService; @@ -16,7 +17,6 @@ import com.example.silverbridgeX_user.user.jwt.JwtTokenUtils; import com.example.silverbridgeX_user.user.repository.RefreshTokenRepository; import com.example.silverbridgeX_user.user.repository.UserRepository; -import com.fasterxml.jackson.databind.JsonNode; import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; import jakarta.transaction.Transactional; @@ -92,23 +92,14 @@ public User createUser(UserReqDto userReqDto) throws Exception { insertUserNodeIfNotExists(newUser.getId()); - String urlStr = coordinateService.buildCoordinateUrl("ROAD", userReqDto.getStreetAddress()); - String json = apiService.getJsonFromUrl(urlStr); - log.info(json); - JsonNode point = apiService.parsePoint(json); - if (!point.isMissingNode()) { - String x = String.valueOf(point.get("x")); - String y = String.valueOf(point.get("y")); - x = x.replace("\"", ""); - y = y.replace("\"", ""); - - newUser.updateCoordinate(x, y); - userRepository.save(newUser); - } + CoordinateDto.simpleCoordinateDto coordinateDto = + coordinateService.getCoordinateByAddress("ROAD", userReqDto.getStreetAddress()); + + newUser.updateCoordinate(coordinateDto.getX(), coordinateDto.getY()); + userRepository.save(newUser); } manager.loadUserByUsername(newUser.getUsername()); // 저장된 사용자 정보를 다시 로드하여 동기화 시도 - return newUser; } @@ -223,11 +214,18 @@ public void insertUserNodeIfNotExists(Long userId) { @Transactional public void saveNickname(UserRequestDto.UserNicknameReqDto nicknameReqDto, User user) { String nickname = nicknameReqDto.getNickname(); - - if (userRepository.existsByNickname(nickname)) { - throw GeneralException.of(ErrorCode.ALREADY_USED_NICKNAME); - } user.updateNickname(nickname); + userRepository.save(user); + } + + @Transactional + public void saveAddress(UserRequestDto.UserAddressReqDto addressReqDto, User user) throws Exception { + String address = addressReqDto.getStreetAddress(); + user.updateAddress(address); + + CoordinateDto.simpleCoordinateDto coordinateDto = coordinateService.getCoordinateByAddress("ROAD", address); + user.updateCoordinate(coordinateDto.getX(), coordinateDto.getY()); + userRepository.save(user); } public void updatePreferredKeywords() { @@ -251,4 +249,18 @@ public void updatePreferredKeywords() { }); } } + + public void validateOlder(User user) { + if (!user.getRole().equals(UserRole.OLDER)) { + log.info(String.valueOf(user.getRole())); + throw new GeneralException(ErrorCode.USER_NOT_OLDER); + } + } + + public void validateProtector(User user) { + if (!user.getRole().equals(UserRole.PROTECTOR)) { + log.info(String.valueOf(user.getRole())); + throw new GeneralException(ErrorCode.USER_NOT_PROTECTOR); + } + } } From b578791fe42c32c01fd5efa7f55ec21118b80d47 Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 17:02:51 +0900 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20api=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=99=EC=82=AC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../silverbridgeX_user/user/controller/UserController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java index a2c5c46..c6ee46d 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java +++ b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java @@ -57,7 +57,7 @@ public ApiResponse reissue( @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2003", description = "회원탈퇴가 완료되었습니다."), }) - @DeleteMapping("/delete") + @DeleteMapping("/me") public ApiResponse deleteUser(Authentication auth) { userService.deleteUser(auth.getName()); return ApiResponse.onSuccess(SuccessCode.USER_DELETE_SUCCESS, "user entity 삭제 완료"); @@ -67,7 +67,7 @@ public ApiResponse deleteUser(Authentication auth) { @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2004", description = "닉네임 변경이 완료되었습니다.") }) - @PostMapping(value = "/nickname/update") + @PostMapping(value = "/nickname") public ApiResponse nickname( @RequestBody UserNicknameReqDto nicknameReqDto, @AuthenticationPrincipal CustomUserDetails customUserDetails @@ -81,7 +81,7 @@ public ApiResponse nickname( @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2005", description = "주소지 변경이 완료되었습니다.") }) - @PostMapping(value = "/address/update") + @PostMapping(value = "/address") public ApiResponse address( @RequestBody UserAddressReqDto addressReqDto, @AuthenticationPrincipal CustomUserDetails customUserDetails From f63df2dce554fed087f71029f4c03c68a6826e7b Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 17:27:12 +0900 Subject: [PATCH 4/7] =?UTF-8?q?refactor:=20role=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=EB=90=A8=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EB=85=B8=EC=9D=B8?= =?UTF-8?q?=EB=A7=8C=20=EC=B6=94=EC=B2=9C=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20?= =?UTF-8?q?=EC=9E=91=EB=8F=99=EC=8B=9C=ED=82=A4=EA=B2=8C=EB=81=94=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecommendActivity/service/RecommendActivityService.java | 5 ++++- .../activity/repository/ActivityRepository.java | 4 ---- .../silverbridgeX_user/user/repository/UserRepository.java | 6 +++++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/silverbridgeX_user/RecommendActivity/service/RecommendActivityService.java b/src/main/java/com/example/silverbridgeX_user/RecommendActivity/service/RecommendActivityService.java index ef47c35..efe5357 100644 --- a/src/main/java/com/example/silverbridgeX_user/RecommendActivity/service/RecommendActivityService.java +++ b/src/main/java/com/example/silverbridgeX_user/RecommendActivity/service/RecommendActivityService.java @@ -12,6 +12,8 @@ import com.example.silverbridgeX_user.global.api_payload.ErrorCode; import com.example.silverbridgeX_user.global.exception.GeneralException; import com.example.silverbridgeX_user.user.domain.User; +import com.example.silverbridgeX_user.user.domain.UserRole; +import com.example.silverbridgeX_user.user.repository.UserRepository; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.LinkedHashSet; @@ -27,6 +29,7 @@ @Service @RequiredArgsConstructor public class RecommendActivityService { + private final UserRepository userRepository; private final ActivityLogRepository activityLogRepository; private final ActivityRepository activityRepository; private final RecommendActivityRepository recommendActivityRepository; @@ -155,7 +158,7 @@ public void insertSimilarEdges(List> rows) { public void generateAllUsersRecommendation() { // 0) 모든 사용자 조회 (PostgreSQL) - List users = activityRepository.findAllUsers(); + List users = userRepository.findAllUsersByRole(UserRole.OLDER); try (Session session = neo4jDriver.session()) { diff --git a/src/main/java/com/example/silverbridgeX_user/activity/repository/ActivityRepository.java b/src/main/java/com/example/silverbridgeX_user/activity/repository/ActivityRepository.java index ff97c2e..e9fc6e8 100644 --- a/src/main/java/com/example/silverbridgeX_user/activity/repository/ActivityRepository.java +++ b/src/main/java/com/example/silverbridgeX_user/activity/repository/ActivityRepository.java @@ -1,7 +1,6 @@ package com.example.silverbridgeX_user.activity.repository; import com.example.silverbridgeX_user.activity.domain.Activity; -import com.example.silverbridgeX_user.user.domain.User; import java.util.Collection; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; @@ -18,7 +17,4 @@ ORDER BY random() """, nativeQuery = true) List pickRandom(int limit, Collection excluded); - @Query("select u from User u") - List findAllUsers(); - } diff --git a/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java b/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java index 21179b1..79bb94d 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java +++ b/src/main/java/com/example/silverbridgeX_user/user/repository/UserRepository.java @@ -1,6 +1,8 @@ package com.example.silverbridgeX_user.user.repository; import com.example.silverbridgeX_user.user.domain.User; +import com.example.silverbridgeX_user.user.domain.UserRole; +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -25,7 +27,9 @@ public interface UserRepository extends JpaRepository { // 5. 닉네임이 사용중인지 판단하는 기능 boolean existsByNickname(String nickname); - + + List findAllUsersByRole(UserRole role); + @Modifying @Transactional @Query(value = "UPDATE member SET preferred_embedding = CAST(:embedding AS vector) WHERE id = :userId", nativeQuery = true) From 277a00cb3c8a9a30933165a612176dadbf464df5 Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 23:42:14 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feature:=20=EB=85=B8=EC=9D=B8=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D,=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/api_payload/ErrorCode.java | 2 +- .../global/api_payload/SuccessCode.java | 2 + .../global/service/CoordinateService.java | 6 ++- .../user/controller/UserController.java | 39 ++++++++++++++++++- .../silverbridgeX_user/user/domain/User.java | 15 +++++++ .../user/service/UserService.java | 36 ++++++++++++++--- 6 files changed, 89 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java b/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java index 8198c80..5431981 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java +++ b/src/main/java/com/example/silverbridgeX_user/global/api_payload/ErrorCode.java @@ -15,7 +15,7 @@ public enum ErrorCode implements BaseCode { // User USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_4041", "존재하지 않는 회원입니다."), USER_NOT_FOUND_BY_EMAIL(HttpStatus.NOT_FOUND, "USER_4042", "존재하지 않는 회원입니다.-EMAIL"), - USER_NOT_FOUND_BY_USERNAME(HttpStatus.NOT_FOUND, "USER_4043", "존재하지 않는 회원입니다.-USERNAME"), + USER_NOT_FOUND_BY_USERNAME(HttpStatus.NOT_FOUND, "USER_4043", "존재하지 않는 회원입니다.-USERNAME & KEY"), USER_NOT_OLDER(HttpStatus.FORBIDDEN, "USER_4031", "해당 유저가 노인이 아니랍니다."), USER_NOT_PROTECTOR(HttpStatus.FORBIDDEN, "USER_4032", "해당 유저가 보호자가 아닙니다."), diff --git a/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java b/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java index a8286d3..8c2f508 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java +++ b/src/main/java/com/example/silverbridgeX_user/global/api_payload/SuccessCode.java @@ -21,6 +21,8 @@ public enum SuccessCode implements BaseCode { USER_NICKNAME_UPDATE_SUCCESS(HttpStatus.OK, "USER_2004", "닉네임 수정이 완료되었습니다."), USER_ADDRESS_UPDATE_SUCCESS(HttpStatus.OK, "USER_2005", "주소지 수정이 완료되었습니다."), USER_MYPAGE_VIEW_SUCCESS(HttpStatus.OK, "USER_2006", "마이페이지 정보 조회가 완료되었습니다."), + USER_PROTECTOR_CONNECT_OLDER_SUCCESS(HttpStatus.OK, "USER_2007", "보호자의 노인 연결이 완료되었습니다."), + USER_PROTECTOR_REGISTER_OLDER_SUCCESS(HttpStatus.OK, "USER_2008", "보호자의 노인 등록이 완료되었습니다."), // Recommend Activity RECOMMEND_ACTIVITY_VIEW_LIST_SUCCESS(HttpStatus.OK, "ACTIVITY_2001", "추천하는 활동 리스를 반환 완료했습니다."), diff --git a/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java b/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java index f0dd85c..f3e3600 100644 --- a/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java +++ b/src/main/java/com/example/silverbridgeX_user/global/service/CoordinateService.java @@ -9,12 +9,14 @@ import com.fasterxml.jackson.databind.JsonNode; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +@Slf4j @Service -@NoArgsConstructor(force = true) +@RequiredArgsConstructor public class CoordinateService { private final ActivityRepository activityRepository; private final ApiService apiService; diff --git a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java index c6ee46d..6fba66f 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java +++ b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java @@ -5,6 +5,7 @@ import com.example.silverbridgeX_user.user.converter.UserConverter; import com.example.silverbridgeX_user.user.domain.User; import com.example.silverbridgeX_user.user.dto.JwtDto; +import com.example.silverbridgeX_user.user.dto.UserRequestDto; import com.example.silverbridgeX_user.user.dto.UserRequestDto.UserAddressReqDto; import com.example.silverbridgeX_user.user.dto.UserRequestDto.UserNicknameReqDto; import com.example.silverbridgeX_user.user.dto.UserResponseDto.OlderMyPageResDto; @@ -19,9 +20,11 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Tag(name = "회원", description = "회원 관련 api 입니다.") @@ -95,7 +98,7 @@ public ApiResponse address( @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2006", description = "노인 마이페이지 정보 조회가 완료되었습니다.") }) - @PostMapping(value = "/mypage/older") + @GetMapping(value = "/mypage/older") public ApiResponse mypageOlder( @AuthenticationPrincipal CustomUserDetails customUserDetails ) { @@ -108,7 +111,7 @@ public ApiResponse mypageOlder( @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2006", description = "노인 마이페이지 정보 조회가 완료되었습니다.") }) - @PostMapping(value = "/mypage/protector") + @GetMapping(value = "/mypage/protector") public ApiResponse mypageProtector( @AuthenticationPrincipal CustomUserDetails customUserDetails ) { @@ -118,4 +121,36 @@ public ApiResponse mypageProtector( return ApiResponse.onSuccess(SuccessCode.USER_MYPAGE_VIEW_SUCCESS, UserConverter.protectorMyPageResDto(user)); } + @Operation(summary = "보호자의 노인 연결", description = "보호자가 관리할 노인을 연결하는 메서드입니다.") + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2007", description = "보호자의 노인 연결이 완료되었습니다.") + }) + @PostMapping(value = "/connection") + public ApiResponse connectOlder( + @AuthenticationPrincipal CustomUserDetails customUserDetails, + @RequestParam("olderKey") String olderKey + ) { + User protector = userService.findByUserName(customUserDetails.getUsername()); + userService.connectOlder(protector, olderKey); + + return ApiResponse.onSuccess(SuccessCode.USER_PROTECTOR_CONNECT_OLDER_SUCCESS, true); + } + + @Operation(summary = "보호자의 노인 등록", description = "보호자가 관리할 노인을 등록하는 메서드입니다.") + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2008", description = "보호자의 노인 등록이 완료되었습니다.") + }) + @PostMapping(value = "/register") + public ApiResponse registerOlder( + @AuthenticationPrincipal CustomUserDetails customUserDetails, + @RequestBody UserRequestDto.UserReqDto userReqDto + ) throws Exception { + User protector = userService.findByUserName(customUserDetails.getUsername()); + + User older = userService.createUser(userReqDto); + userService.registerOlder(protector, older); + + return ApiResponse.onSuccess(SuccessCode.USER_PROTECTOR_REGISTER_OLDER_SUCCESS, true); + } + } diff --git a/src/main/java/com/example/silverbridgeX_user/user/domain/User.java b/src/main/java/com/example/silverbridgeX_user/user/domain/User.java index ba7ab04..979ecab 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/domain/User.java +++ b/src/main/java/com/example/silverbridgeX_user/user/domain/User.java @@ -10,8 +10,12 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; +import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -45,6 +49,13 @@ public class User extends BaseEntity { @Enumerated(EnumType.STRING) private UserRole role; + @ManyToOne + @JoinColumn(name = "protector_id") + private User protector; + + @OneToMany(mappedBy = "protector", cascade = CascadeType.ALL) + private List olders = new ArrayList<>(); + private String sex; private String birth; @@ -97,6 +108,10 @@ public void updateCoordinate(String longitude, String latitude) { this.longitude = longitude; this.latitude = latitude; } + + public void updateProtector(User protector) { + this.protector = protector; // null 가능 + } } diff --git a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java index b16429c..4892d9d 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java +++ b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java @@ -3,7 +3,6 @@ import com.example.silverbridgeX_user.global.api_payload.ErrorCode; import com.example.silverbridgeX_user.global.dto.CoordinateDto; import com.example.silverbridgeX_user.global.exception.GeneralException; -import com.example.silverbridgeX_user.global.service.ApiService; import com.example.silverbridgeX_user.global.service.CoordinateService; import com.example.silverbridgeX_user.global.util.UUID; import com.example.silverbridgeX_user.user.converter.UserConverter; @@ -43,17 +42,12 @@ public class UserService { private final CoordinateService coordinateService; private final JwtTokenUtils jwtTokenUtils; private final RestTemplate restTemplate; - private final ApiService apiService; private final Driver driver; @Value("${chat.server.url}") private String chatServerUrl; - @Value("${geocoder.api.key}") - private String key; private String PREF_URL; - public String addressToCoordinateApiUrl = "https://api.vworld.kr/req/address?service=address&format=json&request=getCoord&refine=false"; - @PostConstruct public void init() { @@ -180,6 +174,13 @@ public void deleteUser(String username) { refreshTokenRepository.deleteByUsername(username); log.info("DB에서 리프레시 토큰 삭제 완료"); } + + if (user.getRole().equals(UserRole.PROTECTOR)) { + for (User older : user.getOlders()) { + older.updateProtector(null); // FK 끊기 + } + } + userRepository.delete(user); log.info("{} 회원 탈퇴 완료", username); } @@ -228,6 +229,7 @@ public void saveAddress(UserRequestDto.UserAddressReqDto addressReqDto, User use userRepository.save(user); } + @Transactional public void updatePreferredKeywords() { ResponseEntity response = restTemplate.getForEntity(PREF_URL, UserPreferenceDto[].class); @@ -263,4 +265,26 @@ public void validateProtector(User user) { throw new GeneralException(ErrorCode.USER_NOT_PROTECTOR); } } + + @Transactional + public void connectOlder(User protector, String key) { + User older = userRepository.findByUsername(key) + .orElseThrow(() -> new GeneralException(ErrorCode.USER_NOT_FOUND_BY_USERNAME)); + + validateProtector(protector); + validateOlder(older); + + older.updateProtector(protector); + userRepository.save(older); + } + + @Transactional + public void registerOlder(User protector, User older) { + validateProtector(protector); + validateOlder(older); + + older.updateProtector(protector); + userRepository.save(older); + } + } From 60e85473ae1198464e81187782383a78a5c293df Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 23:50:00 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20restful=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 8 ++++---- .../silverbridgeX_user/user/service/UserService.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java index 6fba66f..eb457a6 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java +++ b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java @@ -125,13 +125,13 @@ public ApiResponse mypageProtector( @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2007", description = "보호자의 노인 연결이 완료되었습니다.") }) - @PostMapping(value = "/connection") - public ApiResponse connectOlder( + @PostMapping(value = "/protectors/older-links") + public ApiResponse assignOlder( @AuthenticationPrincipal CustomUserDetails customUserDetails, @RequestParam("olderKey") String olderKey ) { User protector = userService.findByUserName(customUserDetails.getUsername()); - userService.connectOlder(protector, olderKey); + userService.assignOlder(protector, olderKey); return ApiResponse.onSuccess(SuccessCode.USER_PROTECTOR_CONNECT_OLDER_SUCCESS, true); } @@ -140,7 +140,7 @@ public ApiResponse connectOlder( @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2008", description = "보호자의 노인 등록이 완료되었습니다.") }) - @PostMapping(value = "/register") + @PostMapping(value = "/protectors/olders") public ApiResponse registerOlder( @AuthenticationPrincipal CustomUserDetails customUserDetails, @RequestBody UserRequestDto.UserReqDto userReqDto diff --git a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java index 4892d9d..8aaa24e 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java +++ b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java @@ -267,7 +267,7 @@ public void validateProtector(User user) { } @Transactional - public void connectOlder(User protector, String key) { + public void assignOlder(User protector, String key) { User older = userRepository.findByUsername(key) .orElseThrow(() -> new GeneralException(ErrorCode.USER_NOT_FOUND_BY_USERNAME)); From 3873f7622d344ce12e174f76efdbab77050d66ef Mon Sep 17 00:00:00 2001 From: persi Date: Sat, 14 Jun 2025 23:59:37 +0900 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=EB=85=B8=EC=9D=B8=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=EC=8B=9C=20=EC=83=9D=EC=84=B1=EB=90=9C=20=EB=85=B8?= =?UTF-8?q?=EC=9D=B8=20KEY=EA=B0=92=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../silverbridgeX_user/user/controller/UserController.java | 6 +++--- .../silverbridgeX_user/user/service/UserService.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java index eb457a6..1ac0b2a 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java +++ b/src/main/java/com/example/silverbridgeX_user/user/controller/UserController.java @@ -141,16 +141,16 @@ public ApiResponse assignOlder( @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER_2008", description = "보호자의 노인 등록이 완료되었습니다.") }) @PostMapping(value = "/protectors/olders") - public ApiResponse registerOlder( + public ApiResponse registerOlder( @AuthenticationPrincipal CustomUserDetails customUserDetails, @RequestBody UserRequestDto.UserReqDto userReqDto ) throws Exception { User protector = userService.findByUserName(customUserDetails.getUsername()); User older = userService.createUser(userReqDto); - userService.registerOlder(protector, older); + String key = userService.registerOlder(protector, older); - return ApiResponse.onSuccess(SuccessCode.USER_PROTECTOR_REGISTER_OLDER_SUCCESS, true); + return ApiResponse.onSuccess(SuccessCode.USER_PROTECTOR_REGISTER_OLDER_SUCCESS, key); } } diff --git a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java index 8aaa24e..8c750b1 100644 --- a/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java +++ b/src/main/java/com/example/silverbridgeX_user/user/service/UserService.java @@ -279,12 +279,13 @@ public void assignOlder(User protector, String key) { } @Transactional - public void registerOlder(User protector, User older) { + public String registerOlder(User protector, User older) { validateProtector(protector); validateOlder(older); older.updateProtector(protector); userRepository.save(older); + return older.getUsername(); } }