diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/api/AiInternalController.java b/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/api/AiInternalController.java index 8d481f1..eb8ca2b 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/api/AiInternalController.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/api/AiInternalController.java @@ -30,7 +30,7 @@ @Slf4j @RestController @RequiredArgsConstructor -@RequestMapping("/internal-api/model") +@RequestMapping("${service-api.ai}") public class AiInternalController { private final AiInternalService aiInternalService; private final MemberRepository memberRepository; @@ -75,7 +75,6 @@ public ResponseEntity> saveRecommendations(@RequestBody Map< recommendationService.save(dto); return ApiResponse.success(HttpStatus.OK, "예측 결과를 성공적으로 저장했습니다."); } catch (CustomException e) { - log.error("커스텀 예외 발생: {}", e.getMessage(), e); return ResponseEntity .status(e.getHttpStatus()) .body(ApiResponse.fail(e)); @@ -115,35 +114,4 @@ private Map encryptPredictionData(List d return null; } } - - // TODO : 암/복호화 API 연결 이후 아래 코드 삭제 -// @PostMapping("/prediction") -// public ResponseEntity> sendAllUsersPredictionData() { -// try { -// List members = memberRepository.findAllByIsDeletedFalse(); -// -// List allDtos = members.stream() -// .filter(member -> member.getCloset() != null) -// .map(aiInternalService::makePredictRequest) -// .collect(Collectors.toList()); -// -// return ResponseEntity.ok(allDtos); -// } catch (Exception e) { -// log.error(e.getMessage()); -// } -// return null; -// } -// -// @PostMapping("/recommendation") -// public ResponseEntity> saveRecommendations(@RequestBody ModelClothingRecommendationDto dto) { -// recommendationService.save(dto); -// return ApiResponse.success(HttpStatus.OK, "예측 결과를 성공적으로 저장했습니다."); -// } -// -// @PostMapping("/history") -// public ResponseEntity>> getSimilarHistory(@RequestBody HistoryRequestDto dto) { -// dto.validate(); -// List result = recordCalendarService.getMemberHistory(dto); -// return ApiResponse.success(HttpStatus.OK, result); -// } } diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/schedular/ModelSchedular.java b/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/schedular/ModelSchedular.java index 7a0e024..f02eec4 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/schedular/ModelSchedular.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/schedular/ModelSchedular.java @@ -40,51 +40,6 @@ public class ModelSchedular { @Value("${ai.server.url}") private String aiServerUrl; - /** - * 매일 새벽 5시에 모델 서버로 예측에 필요한 데이터를 평문 형태로 전송합니다. - */ -// @Transactional -// @Scheduled(cron = "0 0 5 * * *") -// public void pushPredictionDataToAiServer() { -// try { -// List members = memberRepository.findAllByIsDeletedFalse(); -// -// List allDtos = members.stream() -// .filter(member -> member.getCloset() != null) -// .map(member -> { -// try { -// return aiInternalService.makePredictRequest(member); -// } catch (Exception e) { -// log.error("멤버 {} 예측 데이터 생성 실패: {}", member.getId(), e.getMessage()); -// return null; -// } -// }) -// .filter(Objects::nonNull) -// .collect(Collectors.toList()); -// -// if (allDtos.isEmpty()) { -// log.info("AI 서버로 전송할 데이터가 없습니다."); -// return; -// } -// -// HttpHeaders headers = new HttpHeaders(); -// headers.setContentType(MediaType.APPLICATION_JSON); -// -// HttpEntity> requestEntity = new HttpEntity<>(allDtos, headers); -// ResponseEntity response = restTemplate.postForEntity(aiServerUrl, requestEntity, String.class); -// -// if (response.getStatusCode().is2xxSuccessful()) { -// log.info("AI 서버에 예측 데이터 전송 완료. 응답: {}", response.getStatusCode()); -// } else { -// log.warn("AI 서버 응답 실패. 상태코드: {}, 응답본문: {}", response.getStatusCode(), response.getBody()); -// } -// -// } catch (Exception e) { -// log.error("AI 서버 전송 실패", e); -// } -// } - - /** * 매일 새벽 5시에 모델 서버로 예측에 필요한 데이터를 암호화된 형태로 전송합니다. */ @@ -113,7 +68,6 @@ public void pushPredictionAESDataToAiServer() { } Map encrypted = encryptPredictionData(allDtos); - HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity> requestEntity = new HttpEntity<>(encrypted, headers); diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/service/RecommendationService.java b/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/service/RecommendationService.java index 60fa746..d7e2ef2 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/service/RecommendationService.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/ai_model/service/RecommendationService.java @@ -65,7 +65,6 @@ private RecommendPredictDto makeResultForPredict(Closet closet, ClothingRecommen throw new CustomException(ErrorCode.UNKNOWN_ERROR, "예측 데이터를 변환하는 중 오류가 발생하였습니다: " + e.getMessage()); } } - // TODO : AI 학습 이후 사용자가 대량으로 의상을 삭제해서 추천할 의상이 없어져버리는 경우에 대한 고민이 필요해보임. private List makeOuterList(Closet closet, List outers) { if (outers.isEmpty()) return new ArrayList<>(); diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/closet/api/ClothController.java b/src/main/java/com/howWeather/howWeather_backend/domain/closet/api/ClothController.java index 0a39203..36c439e 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/closet/api/ClothController.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/closet/api/ClothController.java @@ -1,6 +1,6 @@ package com.howWeather.howWeather_backend.domain.closet.api; -import com.howWeather.howWeather_backend.domain.closet.service.ClothService; +import com.howWeather.howWeather_backend.domain.closet.service.ClothImageService; import com.howWeather.howWeather_backend.domain.member.entity.Member; import com.howWeather.howWeather_backend.global.Response.ApiResponse; import com.howWeather.howWeather_backend.global.jwt.CheckAuthenticatedUser; @@ -16,14 +16,14 @@ @RequiredArgsConstructor @RequestMapping("/api/cloth") public class ClothController { - private final ClothService clothService; + private final ClothImageService clothImageService; @GetMapping("/upper-image/{clothType}") @CheckAuthenticatedUser public ResponseEntity> upperImage(@RequestHeader("Authorization") String accessTokenHeader, @AuthenticationPrincipal Member member, @PathVariable("clothType") int clothType) { - String url = clothService.getUpperImage(clothType); + String url = clothImageService.getUpperImage(clothType); return ApiResponse.success(HttpStatus.OK, url); } @@ -32,7 +32,7 @@ public ResponseEntity> upperImage(@RequestHeader("Authorizat public ResponseEntity> outerImage(@RequestHeader("Authorization") String accessTokenHeader, @AuthenticationPrincipal Member member, @PathVariable("clothType") int clothType) { - String url = clothService.getOuterImage(clothType); + String url = clothImageService.getOuterImage(clothType); return ApiResponse.success(HttpStatus.OK, url); } } diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClosetService.java b/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClosetService.java index 880fa9f..f814feb 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClosetService.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClosetService.java @@ -35,8 +35,6 @@ public class ClosetService { private static final Long MAX_UPPER_ID = 9L; private static final String UPPER = "uppers"; private static final String OUTER = "outers"; - private final List layerFlexibleUpper = new ArrayList<>(List.of(9L)); // 아우터로 할 수 있는 상의 - private final List layerFlexibleOuter = new ArrayList<>(List.of(3L)); // 상의로 할 수 있는 아우터 @Transactional @@ -71,14 +69,11 @@ private void addUpperClothes(Closet closet, List uppers) { for (ClothRegisterDto c : uppers) { validateClothDto(c, UPPER); - boolean isLayerFlexible = layerFlexibleUpper.contains(c.getClothType()); - Upper newUpper = Upper.builder() .upperType(c.getClothType()) .color(c.getColor()) .thickness(c.getThickness()) .isActive(true) - .isLayerFlexible(isLayerFlexible) .build(); boolean isDuplicate = closet.getUpperList().stream() @@ -94,14 +89,11 @@ private void addOuterClothes(Closet closet, List outers) { for (ClothRegisterDto c : outers) { validateClothDto(c, OUTER); - boolean isLayerFlexible = layerFlexibleOuter.contains(c.getClothType()); - Outer newOuter = Outer.builder() .outerType(c.getClothType()) .color(c.getColor()) .thickness(c.getThickness()) .isActive(true) - .isLayerFlexible(isLayerFlexible) .build(); boolean isDuplicate = closet.getOuterList().stream() @@ -205,7 +197,6 @@ public ClothListDto getUppers(Member member) { } catch (Exception e) { throw new CustomException(ErrorCode.UNKNOWN_ERROR, "아우터 조회 중 서버 오류가 발생했습니다."); } - } @Transactional(readOnly = true) @@ -219,34 +210,6 @@ public ClothListDto getOuters(Member member) { } } - @Transactional(readOnly = true) - public ClothListDto findLayerFlexibleOuters(Member member) { // 상의가 될 수 있는 아우터 - Closet closet = getCloset(member); - - return findLayerFlexibleClothes( - OUTER, - closet.getOuterList(), - layerFlexibleOuter, - Outer::isActive, - Outer::getOuterType, - this::mapOuterToDto - ); - } - - @Transactional(readOnly = true) - public ClothListDto findLayerFlexibleUppers(Member member) { // 아우터가 될 수 있는 상의 - Closet closet = getCloset(member); - - return findLayerFlexibleClothes( - UPPER, - closet.getUpperList(), - layerFlexibleUpper, - Upper::isActive, - Upper::getUpperType, - this::mapUpperToDto - ); - } - @Transactional public void updateUpper(Long clothId, UpdateClothDto updateDto, Member member) { try { diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClothService.java b/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClothImageService.java similarity index 96% rename from src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClothService.java rename to src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClothImageService.java index fff756c..29851d0 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClothService.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/closet/service/ClothImageService.java @@ -11,7 +11,7 @@ @Service @Slf4j @AllArgsConstructor -public class ClothService { +public class ClothImageService { private final ClothRepository clothRepository; @Transactional(readOnly = true) diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/member/api/MyAccountController.java b/src/main/java/com/howWeather/howWeather_backend/domain/member/api/MyAccountController.java index dded81b..b1ea425 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/member/api/MyAccountController.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/member/api/MyAccountController.java @@ -5,8 +5,7 @@ import com.howWeather.howWeather_backend.domain.member.dto.ProfileDto; import com.howWeather.howWeather_backend.domain.member.dto.RegionDto; import com.howWeather.howWeather_backend.domain.member.entity.Member; -import com.howWeather.howWeather_backend.domain.member.repository.MemberRepository; -import com.howWeather.howWeather_backend.domain.member.service.AuthService; +import com.howWeather.howWeather_backend.domain.member.service.MyAccountService; import com.howWeather.howWeather_backend.global.Response.ApiResponse; import com.howWeather.howWeather_backend.global.jwt.CheckAuthenticatedUser; import lombok.RequiredArgsConstructor; @@ -23,13 +22,13 @@ @RequiredArgsConstructor @RequestMapping("/api/mypage") public class MyAccountController { - private final AuthService authService; + private final MyAccountService myAccountService; @GetMapping("/profile") @CheckAuthenticatedUser public ResponseEntity getProfile(@RequestHeader("Authorization") String accessTokenHeader, @AuthenticationPrincipal Member member) { - ProfileDto profile = authService.getProfile(member); + ProfileDto profile = myAccountService.getProfile(member); return ResponseEntity.ok(profile); } @@ -38,7 +37,7 @@ public ResponseEntity getProfile(@RequestHeader("Authorization") Str public ResponseEntity> updateGender(@RequestHeader("Authorization") String accessTokenHeader, @RequestBody ProfileChangeIntDto profileChangeDto, @AuthenticationPrincipal Member member) { - authService.updateGender(member, profileChangeDto); + myAccountService.updateGender(member, profileChangeDto); return ApiResponse.success(HttpStatus.OK, "성별을 성공적으로 수정하였습니다."); } @@ -47,7 +46,7 @@ public ResponseEntity> updateGender(@RequestHeader("Authoriz public ResponseEntity> updateAgeGroup(@RequestHeader("Authorization") String accessTokenHeader, @RequestBody ProfileChangeIntDto profileChangeDto, @AuthenticationPrincipal Member member) { - authService.updateAgeGroup(member, profileChangeDto); + myAccountService.updateAgeGroup(member, profileChangeDto); return ApiResponse.success(HttpStatus.OK, "연령대를 성공적으로 수정하였습니다."); } @@ -56,7 +55,7 @@ public ResponseEntity> updateAgeGroup(@RequestHeader("Author public ResponseEntity> updateNickname(@RequestHeader("Authorization") String accessTokenHeader, @Valid @RequestBody NicknameDto nicknameDto, @AuthenticationPrincipal Member member) { - authService.updateNickname(member,nicknameDto); + myAccountService.updateNickname(member,nicknameDto); return ApiResponse.success(HttpStatus.OK, "닉네임을 성공적으로 수정하였습니다."); } @@ -65,7 +64,7 @@ public ResponseEntity> updateNickname(@RequestHeader("Author public ResponseEntity> updateConstitution(@RequestHeader("Authorization") String accessTokenHeader, @Valid @RequestBody ProfileChangeIntDto profileChangeDto, @AuthenticationPrincipal Member member) { - authService.updateConstitution(member, profileChangeDto); + myAccountService.updateConstitution(member, profileChangeDto); return ApiResponse.success(HttpStatus.OK, "체질을 성공적으로 수정하였습니다."); } @@ -73,7 +72,7 @@ public ResponseEntity> updateConstitution(@RequestHeader("Au @CheckAuthenticatedUser public ResponseEntity> getLocation(@RequestHeader("Authorization") String accessTokenHeader, @AuthenticationPrincipal Member member) { - String location = authService.getLoccation(member); + String location = myAccountService.getLoccation(member); return ApiResponse.success(HttpStatus.OK, location); } @@ -82,7 +81,7 @@ public ResponseEntity> getLocation(@RequestHeader("Authoriza public ResponseEntity> updateLocation(@RequestHeader("Authorization") String accessTokenHeader, @Valid @RequestBody RegionDto regionDto, @AuthenticationPrincipal Member member) { - authService.updateLocation(member, regionDto); + myAccountService.updateLocation(member, regionDto); return ApiResponse.success(HttpStatus.OK, "지역을 성공적으로 수정하였습니다."); } } diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/member/service/AuthService.java b/src/main/java/com/howWeather/howWeather_backend/domain/member/service/AuthService.java index d2aa3ba..cf09836 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/member/service/AuthService.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/member/service/AuthService.java @@ -7,8 +7,6 @@ import com.howWeather.howWeather_backend.domain.member.entity.Member; import com.howWeather.howWeather_backend.domain.member.repository.MemberRepository; import com.howWeather.howWeather_backend.domain.closet.repository.ClosetRepository; -import com.howWeather.howWeather_backend.domain.weather.entity.Region; -import com.howWeather.howWeather_backend.domain.weather.repository.RegionRepository; import com.howWeather.howWeather_backend.global.exception.CustomException; import com.howWeather.howWeather_backend.global.exception.ErrorCode; import com.howWeather.howWeather_backend.global.exception.LoginException; @@ -31,7 +29,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalTime; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; @@ -51,7 +48,6 @@ public class AuthService { private final FcmAlarmPreferenceService fcmAlarmPreferenceService; private final CustomOAuth2UserService customOAuth2UserService; private final OAuth2AuthorizedClientService authorizedClientService; - private final RegionRepository regionRepository; @Transactional public void signup(SignupRequestDto signupRequestDto) { @@ -169,27 +165,6 @@ private void blacklistToken(String token, String tokenType) { } } - @Transactional(readOnly = true) - public ProfileDto getProfile(Member member) { - try { - return ProfileDto.builder() - .loginId(member.getLoginId()) - .email(member.getEmail()) - .ageGroup(member.getAgeGroup()) - .nickname(member.getNickname()) - .bodyType(member.getBodyType()) - .constitution(member.getConstitution()) - .gender(member.getGender()) - .build(); - - } catch (CustomException e) { - throw e; - } catch (Exception e) { - log.error("프로필 조회 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "프로필 조회 중 오류가 발생했습니다."); - } - } - @Transactional public void changePasswordAndLogout(Member member, PasswordChangeDto dto, String accessToken, String refreshToken) { changePassword(member, dto); @@ -236,136 +211,6 @@ private void validateOldPassword(Member member, String oldPassword) { } } - @Transactional - public void updateGender(Member member, ProfileChangeIntDto profileChangeDto) { - try { - validateIntData(profileChangeDto.getData(), 1, 2); - if (profileChangeDto.getData() != null) { - Member persistedMember = memberRepository.findById(member.getId()) - .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); - persistedMember.changeGender(profileChangeDto.getData()); - } - } catch (CustomException e) { - throw e; - } catch (Exception e) { - log.error("성별 수정 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "성별 수정 중 오류가 발생했습니다."); - } - } - - @Transactional - public void updateAgeGroup(Member member, ProfileChangeIntDto profileChangeDto) { - try { - validateIntData(profileChangeDto.getData(), 1, 3); - if (profileChangeDto.getData() != null) { - Member persistedMember = memberRepository.findById(member.getId()) - .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); - persistedMember.changeAgeGroup(profileChangeDto.getData()); - } - } catch (CustomException e) { - throw e; - } catch (Exception e) { - log.error("연령대 수정 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "연령대 수정 중 오류가 발생했습니다."); - } - } - - @Transactional - public void updateNickname(Member member, NicknameDto nicknameDto) { - try { - if (nicknameDto.getData() != null) { - Member persistedMember = memberRepository.findById(member.getId()) - .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); - persistedMember.changeNickname(nicknameDto.getData()); - } - } catch (CustomException e) { - throw e; - } catch (Exception e) { - log.error("닉네임 수정 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "닉네임 수정 중 오류가 발생했습니다."); - } - } - - @Transactional - public void updateConstitution(Member member, ProfileChangeIntDto profileChangeDto) { - try { - validateIntData(profileChangeDto.getData(), 1, 3); - if (profileChangeDto.getData() != null) { - Member persistedMember = memberRepository.findById(member.getId()) - .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); - persistedMember.changeConstitution(profileChangeDto.getData()); - } - } catch (CustomException e) { - throw e; - } catch (Exception e) { - log.error("체질 수정 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "체질 수정 중 오류가 발생했습니다."); - } - } - - @Transactional(readOnly = true) - public String getLoccation(Member member) { - try { - String region = member.getRegionName(); - - if (region == null || region.trim().isEmpty()) - return "서울특별시 용산구"; - - return region; - - } catch (CustomException e) { - throw e; - }catch (Exception e) { - log.error("지역 조회 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "지역 조회 중 오류가 발생했습니다."); - } - } - - @Transactional - public void updateLocation(Member member, RegionDto regionDto) { - try { - LocalTime now = LocalTime.now(); - if (!now.isBefore(LocalTime.of(4, 00)) && now.isBefore(LocalTime.of(7, 0))) { - throw new CustomException(ErrorCode.TIME_RESTRICTED_FOR_REGION_CHANGE); - } - validateRegion(regionDto.getRegionName()); - - Member persistedMember = memberRepository.findById(member.getId()) - .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); - - String oldRegionName = persistedMember.getRegionName(); - String newRegionName = regionDto.getRegionName(); - - if (oldRegionName == null || !newRegionName.equals(oldRegionName)) { - if (oldRegionName != null) { - regionRepository.findByName(oldRegionName).ifPresent(Region::decrementCurrentUserCount); - } - - Region newRegion = regionRepository.findByName(newRegionName) - .orElseThrow(() -> new CustomException(ErrorCode.REGION_NOT_FOUND)); - newRegion.incrementCurrentUserCount(); - persistedMember.changeRegion(newRegionName); - } - } catch (CustomException e) { - throw e; - } catch (Exception e) { - log.error("지역 수정 중 에러 발생: {}", e.getMessage(), e); - throw new CustomException(ErrorCode.UNKNOWN_ERROR, "지역 수정 중 오류가 발생했습니다."); - } - } - - private void validateRegion(String regionName) { - if (regionName == null || regionName.isEmpty() || !regionRepository.existsByName(regionName)) { - throw new CustomException(ErrorCode.REGION_NOT_FOUND); - } - } - - private void validateIntData(Integer data, int s, int e) { - if (data < s || data > e) { - throw new CustomException(ErrorCode.INVALID_INPUT, "유효하지 않은 입력값입니다."); - } - } - @Transactional public void withdraw(Member member, String jwtAccessToken, String refreshToken, String socialAccessToken) { try { @@ -427,7 +272,7 @@ public String resetPassword(String identifier) { memberRepository.flush(); mailService.sendTemporaryPassword(member.getEmail(), tempPassword); return member.getEmail(); - } catch (CustomException e) { + } catch (CustomException e) { throw e; } catch (Exception e) { log.error("비밀번호 초기화 중 에러 발생: {}", e.getMessage(), e); diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/member/service/MyAccountService.java b/src/main/java/com/howWeather/howWeather_backend/domain/member/service/MyAccountService.java new file mode 100644 index 0000000..6783ac3 --- /dev/null +++ b/src/main/java/com/howWeather/howWeather_backend/domain/member/service/MyAccountService.java @@ -0,0 +1,177 @@ +package com.howWeather.howWeather_backend.domain.member.service; + +import com.howWeather.howWeather_backend.domain.member.dto.NicknameDto; +import com.howWeather.howWeather_backend.domain.member.dto.ProfileChangeIntDto; +import com.howWeather.howWeather_backend.domain.member.dto.ProfileDto; +import com.howWeather.howWeather_backend.domain.member.dto.RegionDto; +import com.howWeather.howWeather_backend.domain.member.entity.Member; +import com.howWeather.howWeather_backend.domain.member.repository.MemberRepository; +import com.howWeather.howWeather_backend.domain.weather.entity.Region; +import com.howWeather.howWeather_backend.domain.weather.repository.RegionRepository; +import com.howWeather.howWeather_backend.global.exception.CustomException; +import com.howWeather.howWeather_backend.global.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalTime; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MyAccountService { + private final MemberRepository memberRepository; + private final RegionRepository regionRepository; + + @Transactional(readOnly = true) + public ProfileDto getProfile(Member member) { + try { + return ProfileDto.builder() + .loginId(member.getLoginId()) + .email(member.getEmail()) + .ageGroup(member.getAgeGroup()) + .nickname(member.getNickname()) + .bodyType(member.getBodyType()) + .constitution(member.getConstitution()) + .gender(member.getGender()) + .build(); + + } catch (CustomException e) { + throw e; + } catch (Exception e) { + log.error("프로필 조회 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "프로필 조회 중 오류가 발생했습니다."); + } + } + + @Transactional + public void updateGender(Member member, ProfileChangeIntDto profileChangeDto) { + try { + validateIntData(profileChangeDto.getData(), 1, 2); + if (profileChangeDto.getData() != null) { + Member persistedMember = memberRepository.findById(member.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); + persistedMember.changeGender(profileChangeDto.getData()); + } + } catch (CustomException e) { + throw e; + } catch (Exception e) { + log.error("성별 수정 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "성별 수정 중 오류가 발생했습니다."); + } + } + + @Transactional + public void updateAgeGroup(Member member, ProfileChangeIntDto profileChangeDto) { + try { + validateIntData(profileChangeDto.getData(), 1, 3); + if (profileChangeDto.getData() != null) { + Member persistedMember = memberRepository.findById(member.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); + persistedMember.changeAgeGroup(profileChangeDto.getData()); + } + } catch (CustomException e) { + throw e; + } catch (Exception e) { + log.error("연령대 수정 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "연령대 수정 중 오류가 발생했습니다."); + } + } + + @Transactional + public void updateNickname(Member member, NicknameDto nicknameDto) { + try { + if (nicknameDto.getData() != null) { + Member persistedMember = memberRepository.findById(member.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); + persistedMember.changeNickname(nicknameDto.getData()); + } + } catch (CustomException e) { + throw e; + } catch (Exception e) { + log.error("닉네임 수정 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "닉네임 수정 중 오류가 발생했습니다."); + } + } + + @Transactional + public void updateConstitution(Member member, ProfileChangeIntDto profileChangeDto) { + try { + validateIntData(profileChangeDto.getData(), 1, 3); + if (profileChangeDto.getData() != null) { + Member persistedMember = memberRepository.findById(member.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); + persistedMember.changeConstitution(profileChangeDto.getData()); + } + } catch (CustomException e) { + throw e; + } catch (Exception e) { + log.error("체질 수정 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "체질 수정 중 오류가 발생했습니다."); + } + } + + private void validateIntData(Integer data, int start, int end) { + if (data < start || data > end) { + throw new CustomException(ErrorCode.INVALID_INPUT, "유효하지 않은 입력값입니다."); + } + } + + @Transactional(readOnly = true) + public String getLoccation(Member member) { + try { + String region = member.getRegionName(); + + if (region == null || region.trim().isEmpty()) + return "서울특별시 용산구"; + + return region; + + } catch (CustomException e) { + throw e; + }catch (Exception e) { + log.error("지역 조회 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "지역 조회 중 오류가 발생했습니다."); + } + } + + @Transactional + public void updateLocation(Member member, RegionDto regionDto) { + try { + LocalTime now = LocalTime.now(); + if (!now.isBefore(LocalTime.of(4, 00)) && now.isBefore(LocalTime.of(7, 0))) { + throw new CustomException(ErrorCode.TIME_RESTRICTED_FOR_REGION_CHANGE); + } + validateRegion(regionDto.getRegionName()); + + Member persistedMember = memberRepository.findById(member.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.ID_NOT_FOUND, "회원 정보를 찾을 수 없습니다.")); + + String oldRegionName = persistedMember.getRegionName(); + String newRegionName = regionDto.getRegionName(); + + if (oldRegionName == null || !newRegionName.equals(oldRegionName)) { + if (oldRegionName != null) { + regionRepository.findByName(oldRegionName).ifPresent(Region::decrementCurrentUserCount); + } + + Region newRegion = regionRepository.findByName(newRegionName) + .orElseThrow(() -> new CustomException(ErrorCode.REGION_NOT_FOUND)); + newRegion.incrementCurrentUserCount(); + persistedMember.changeRegion(newRegionName); + } + } catch (CustomException e) { + throw e; + } catch (Exception e) { + log.error("지역 수정 중 에러 발생: {}", e.getMessage(), e); + throw new CustomException(ErrorCode.UNKNOWN_ERROR, "지역 수정 중 오류가 발생했습니다."); + } + } + + private void validateRegion(String regionName) { + if (regionName == null || regionName.isEmpty() || !regionRepository.existsByName(regionName)) { + throw new CustomException(ErrorCode.REGION_NOT_FOUND); + } + } +} diff --git a/src/main/java/com/howWeather/howWeather_backend/domain/weather/scheduler/WeatherScheduler.java b/src/main/java/com/howWeather/howWeather_backend/domain/weather/scheduler/WeatherScheduler.java index ba760f1..0171921 100644 --- a/src/main/java/com/howWeather/howWeather_backend/domain/weather/scheduler/WeatherScheduler.java +++ b/src/main/java/com/howWeather/howWeather_backend/domain/weather/scheduler/WeatherScheduler.java @@ -1,6 +1,5 @@ package com.howWeather.howWeather_backend.domain.weather.scheduler; -import com.howWeather.howWeather_backend.domain.ai_model.repository.ClothingRecommendationRepository; import com.howWeather.howWeather_backend.domain.weather.repository.WeatherForecastRepository; import com.howWeather.howWeather_backend.domain.weather.service.WeatherService; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/howWeather/howWeather_backend/global/cipher/AesTestController.java b/src/main/java/com/howWeather/howWeather_backend/global/cipher/AesTestController.java index d462d15..03f96e7 100644 --- a/src/main/java/com/howWeather/howWeather_backend/global/cipher/AesTestController.java +++ b/src/main/java/com/howWeather/howWeather_backend/global/cipher/AesTestController.java @@ -13,10 +13,9 @@ import java.util.Map; @RestController -@RequestMapping("/api/aes-test") +@RequestMapping("${service-api.aes}") @RequiredArgsConstructor public class AesTestController { - private final AESCipher aesCipher; private final ObjectMapper objectMapper; diff --git a/src/main/java/com/howWeather/howWeather_backend/global/custom/InvalidPrefix.java b/src/main/java/com/howWeather/howWeather_backend/global/custom/InvalidPrefix.java index 85eda24..f238e1b 100644 --- a/src/main/java/com/howWeather/howWeather_backend/global/custom/InvalidPrefix.java +++ b/src/main/java/com/howWeather/howWeather_backend/global/custom/InvalidPrefix.java @@ -13,5 +13,5 @@ String message() default "아이디는 'Google_', 'Kakao_' 등의 접두사로 시작할 수 없습니다."; Class[] groups() default {}; Class[] payload() default {}; - String[] prefixes(); // 금지할 접두사 목록 + String[] prefixes(); } diff --git a/src/main/java/com/howWeather/howWeather_backend/global/exception/LoginException.java b/src/main/java/com/howWeather/howWeather_backend/global/exception/LoginException.java index 0b44aee..af433ae 100644 --- a/src/main/java/com/howWeather/howWeather_backend/global/exception/LoginException.java +++ b/src/main/java/com/howWeather/howWeather_backend/global/exception/LoginException.java @@ -1,7 +1,5 @@ package com.howWeather.howWeather_backend.global.exception; -import lombok.Getter; - public class LoginException extends CustomException { public LoginException(ErrorCode errorCode, String message) { super(errorCode, message); diff --git a/src/main/java/com/howWeather/howWeather_backend/global/jwt/JwtTokenProvider.java b/src/main/java/com/howWeather/howWeather_backend/global/jwt/JwtTokenProvider.java index ee5dbc1..17b6475 100644 --- a/src/main/java/com/howWeather/howWeather_backend/global/jwt/JwtTokenProvider.java +++ b/src/main/java/com/howWeather/howWeather_backend/global/jwt/JwtTokenProvider.java @@ -109,17 +109,6 @@ public JwtToken reissueAccessToken(String refreshToken) { .build(); } -// public Authentication getAuthentication(String token) { -// Claims claims = parseClaims(token); -// String loginId = claims.getSubject(); -// -// UserDetails userDetails = customUserDetailsService.loadUserByUsername(loginId); -// -// System.out.println("userDetails = " + userDetails); -// return new UsernamePasswordAuthenticationToken(userDetails, token, userDetails.getAuthorities()); -// } - - public Authentication getAuthentication(String token) { Claims claims = parseClaims(token); if (claims == null || claims.getSubject() == null) { diff --git a/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshToken.java b/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshToken.java deleted file mode 100644 index 266fc9e..0000000 --- a/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshToken.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.howWeather.howWeather_backend.global.jwt; - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import lombok.*; - -@Builder(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Data -@Entity -@NoArgsConstructor -public class RefreshToken { - @Id - private String username; - private String refreshToken; -} diff --git a/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshTokenRepository.java b/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshTokenRepository.java deleted file mode 100644 index fb237ba..0000000 --- a/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshTokenRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.howWeather.howWeather_backend.global.jwt; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface RefreshTokenRepository extends JpaRepository { -} \ No newline at end of file diff --git a/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshTokenService.java b/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshTokenService.java deleted file mode 100644 index 1931404..0000000 --- a/src/main/java/com/howWeather/howWeather_backend/global/jwt/RefreshTokenService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.howWeather.howWeather_backend.global.jwt; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@Component -@RequiredArgsConstructor -public class RefreshTokenService { - private final RefreshTokenRepository refreshTokenRepository; - - public void saveRefreshToken(String username, String refreshToken) { - RefreshToken savedRefreshToken = new RefreshToken(username, refreshToken); - refreshTokenRepository.save(savedRefreshToken); - } -} \ No newline at end of file