diff --git a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java index c449f15..132b597 100644 --- a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java +++ b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java @@ -328,26 +328,5 @@ public ResponseEntity> updateProfileImage( memberService.updateProfileImage(userDetails.getUsername(), profileImage); return ApiResponse.success_only(SuccessStatus.UPDATE_PROFILE_IMAGE_SUCCESS); } - - /* - * - * 약관동의 API - * - * */ - @Operation( - summary = "이용약관동의 API", - description = "이용약관 동의 여부를 저장합니다." - ) - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "닉네임 중복 체크 성공") - }) - @PostMapping("/agree-terms") - public ResponseEntity> agreeToTerms( - @AuthenticationPrincipal UserDetails userDetails, - @RequestBody AgreeTermsRequestDTO agreeTermsRequestDTO) { - - memberService.agreeToTerms(userDetails.getUsername(), agreeTermsRequestDTO); - return ApiResponse.success_only(SuccessStatus.TERMS_AGREE_SUCCESS); - } } diff --git a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java index 84ada27..37ceca2 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java @@ -5,10 +5,8 @@ import com.moongeul.backend.api.member.dto.*; import com.moongeul.backend.api.member.entity.*; import com.moongeul.backend.api.member.jwt.dto.JwtTokenDTO; -import com.moongeul.backend.api.member.repository.AgreeRepository; import com.moongeul.backend.api.member.repository.FollowRepository; import com.moongeul.backend.api.member.repository.MemberRepository; -import com.moongeul.backend.api.member.repository.TermsRepository; import com.moongeul.backend.api.member.util.NicknameGenerator; import com.moongeul.backend.api.post.dto.CategoryPostListResponseDTO; import com.moongeul.backend.api.post.dto.PostDTO; @@ -51,8 +49,6 @@ public class MemberService { private final GoogleOAuthService googleOAuthService; private final KakaoOAuthService kakaoOAuthService; private final NicknameGenerator nicknameGenerator; - private final TermsRepository termsRepository; - private final AgreeRepository agreeRepository; private final FileUploadService fileUploadService; // 인가코드 받아 JWT로 교환 및 회원가입/로그인 처리 @@ -441,51 +437,6 @@ private void validatePrivacyAccess(Member currentMember, Member targetMember) { } } - /* - * - * 약관동의 API - * - * */ - @Transactional - public void agreeToTerms(String email, AgreeTermsRequestDTO agreeTermsRequestDTO){ - - Member member = getMemberByEmail(email); - - // 예외처리: 필수 동의 여부 검증 - if (!agreeTermsRequestDTO.isServiceTermsAgree() || !agreeTermsRequestDTO.isPrivatePolicyAgree()) { - throw new BadRequestException(ErrorStatus.DISAGREE_REQUIRED_TERM.getMessage()); - } - - // 1. 약관 타입과 DTO의 동의 여부 매핑 - Map agreementData = Map.of( - TermsType.SERVICE_TERMS_AGREE, agreeTermsRequestDTO.isServiceTermsAgree(), - TermsType.PRIVACY_POLICY_AGREE, agreeTermsRequestDTO.isPrivatePolicyAgree(), - TermsType.MARKETING_AGREE, agreeTermsRequestDTO.isMarketingAgree() - ); - - agreementData.forEach((type, isAgreed) -> { - // 1. 해당 타입의 약관 마스터 정보 조회 - Terms terms = termsRepository.findByTermsType(type) - .orElseThrow(() -> new NotFoundException(ErrorStatus.TERMS_NOTFOUND_EXCEPTION.getMessage())); - - // 2. 기존 동의 내역이 있는지 조회 - agreeRepository.findByMemberAndTerms(member, terms) - .ifPresentOrElse( - // 이미 데이터가 있다면? -> 동의 여부 필드만 수정 (Dirty Checking 발생) - existingAgree -> existingAgree.updateAgreement(isAgreed), - // 데이터가 없다면? -> 새로 생성해서 저장 - () -> { - Agree newAgree = Agree.builder() - .member(member) - .terms(terms) - .isAgreed(isAgreed) - .build(); - agreeRepository.save(newAgree); - } - ); - }); - } - // 회원 조회 메서드 private Member getMemberByEmail(String email) { return memberRepository.findByEmail(email) diff --git a/src/main/java/com/moongeul/backend/api/setting/controller/SettingController.java b/src/main/java/com/moongeul/backend/api/setting/controller/SettingController.java index 9fcc1d7..100a86a 100644 --- a/src/main/java/com/moongeul/backend/api/setting/controller/SettingController.java +++ b/src/main/java/com/moongeul/backend/api/setting/controller/SettingController.java @@ -1,7 +1,9 @@ package com.moongeul.backend.api.setting.controller; +import com.moongeul.backend.api.setting.dto.AgreeTermsRequestDTO; import com.moongeul.backend.api.setting.dto.PrivacyLevelResponseDTO; import com.moongeul.backend.api.setting.dto.PrivacyLevelUpdateRequestDTO; +import com.moongeul.backend.api.setting.service.AgreeTermsSettingService; import com.moongeul.backend.api.setting.service.PrivacySettingService; import com.moongeul.backend.common.response.ApiResponse; import com.moongeul.backend.common.response.SuccessStatus; @@ -13,19 +15,16 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Tag(name = "Setting", description = "설정 관련 API 입니다.") @RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/setting") +@RequestMapping("/api/v2/setting") public class SettingController { private final PrivacySettingService privacySettingService; + private final AgreeTermsSettingService agreeTermsSettingService; @Operation( summary = "계정 공개 범위 조회 API", @@ -68,4 +67,20 @@ public ResponseEntity> updatePrivacyLevel( PrivacyLevelResponseDTO response = privacySettingService.updatePrivacyLevel(userDetails.getUsername(), request); return ApiResponse.success(SuccessStatus.UPDATE_PRIVACY_LEVEL_SUCCESS, response); } + + @Operation( + summary = "이용약관동의 API", + description = "이용약관 동의 여부를 저장합니다." + ) + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "닉네임 중복 체크 성공") + }) + @PostMapping("/agree-terms") + public ResponseEntity> agreeToTerms( + @AuthenticationPrincipal UserDetails userDetails, + @RequestBody AgreeTermsRequestDTO agreeTermsRequestDTO) { + + agreeTermsSettingService.agreeToTerms(userDetails.getUsername(), agreeTermsRequestDTO); + return ApiResponse.success_only(SuccessStatus.TERMS_AGREE_SUCCESS); + } } diff --git a/src/main/java/com/moongeul/backend/api/member/dto/AgreeTermsRequestDTO.java b/src/main/java/com/moongeul/backend/api/setting/dto/AgreeTermsRequestDTO.java similarity index 77% rename from src/main/java/com/moongeul/backend/api/member/dto/AgreeTermsRequestDTO.java rename to src/main/java/com/moongeul/backend/api/setting/dto/AgreeTermsRequestDTO.java index e3ef795..0adb147 100644 --- a/src/main/java/com/moongeul/backend/api/member/dto/AgreeTermsRequestDTO.java +++ b/src/main/java/com/moongeul/backend/api/setting/dto/AgreeTermsRequestDTO.java @@ -1,6 +1,5 @@ -package com.moongeul.backend.api.member.dto; +package com.moongeul.backend.api.setting.dto; -import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/moongeul/backend/api/member/entity/Agree.java b/src/main/java/com/moongeul/backend/api/setting/entity/Agree.java similarity index 90% rename from src/main/java/com/moongeul/backend/api/member/entity/Agree.java rename to src/main/java/com/moongeul/backend/api/setting/entity/Agree.java index f238761..1ccd848 100644 --- a/src/main/java/com/moongeul/backend/api/member/entity/Agree.java +++ b/src/main/java/com/moongeul/backend/api/setting/entity/Agree.java @@ -1,5 +1,6 @@ -package com.moongeul.backend.api.member.entity; +package com.moongeul.backend.api.setting.entity; +import com.moongeul.backend.api.member.entity.Member; import com.moongeul.backend.common.entity.BaseTimeEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/moongeul/backend/api/member/entity/Terms.java b/src/main/java/com/moongeul/backend/api/setting/entity/Terms.java similarity index 93% rename from src/main/java/com/moongeul/backend/api/member/entity/Terms.java rename to src/main/java/com/moongeul/backend/api/setting/entity/Terms.java index 7b1040c..8c2e46a 100644 --- a/src/main/java/com/moongeul/backend/api/member/entity/Terms.java +++ b/src/main/java/com/moongeul/backend/api/setting/entity/Terms.java @@ -1,4 +1,4 @@ -package com.moongeul.backend.api.member.entity; +package com.moongeul.backend.api.setting.entity; import jakarta.persistence.*; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/moongeul/backend/api/member/entity/TermsType.java b/src/main/java/com/moongeul/backend/api/setting/entity/TermsType.java similarity index 87% rename from src/main/java/com/moongeul/backend/api/member/entity/TermsType.java rename to src/main/java/com/moongeul/backend/api/setting/entity/TermsType.java index bab54d4..6b5f8dc 100644 --- a/src/main/java/com/moongeul/backend/api/member/entity/TermsType.java +++ b/src/main/java/com/moongeul/backend/api/setting/entity/TermsType.java @@ -1,4 +1,4 @@ -package com.moongeul.backend.api.member.entity; +package com.moongeul.backend.api.setting.entity; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/moongeul/backend/api/member/repository/AgreeRepository.java b/src/main/java/com/moongeul/backend/api/setting/repository/AgreeRepository.java similarity index 64% rename from src/main/java/com/moongeul/backend/api/member/repository/AgreeRepository.java rename to src/main/java/com/moongeul/backend/api/setting/repository/AgreeRepository.java index 439a5d5..7e2472c 100644 --- a/src/main/java/com/moongeul/backend/api/member/repository/AgreeRepository.java +++ b/src/main/java/com/moongeul/backend/api/setting/repository/AgreeRepository.java @@ -1,8 +1,8 @@ -package com.moongeul.backend.api.member.repository; +package com.moongeul.backend.api.setting.repository; -import com.moongeul.backend.api.member.entity.Agree; +import com.moongeul.backend.api.setting.entity.Agree; import com.moongeul.backend.api.member.entity.Member; -import com.moongeul.backend.api.member.entity.Terms; +import com.moongeul.backend.api.setting.entity.Terms; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; diff --git a/src/main/java/com/moongeul/backend/api/member/repository/TermsRepository.java b/src/main/java/com/moongeul/backend/api/setting/repository/TermsRepository.java similarity index 56% rename from src/main/java/com/moongeul/backend/api/member/repository/TermsRepository.java rename to src/main/java/com/moongeul/backend/api/setting/repository/TermsRepository.java index 296b753..27d8e4c 100644 --- a/src/main/java/com/moongeul/backend/api/member/repository/TermsRepository.java +++ b/src/main/java/com/moongeul/backend/api/setting/repository/TermsRepository.java @@ -1,7 +1,7 @@ -package com.moongeul.backend.api.member.repository; +package com.moongeul.backend.api.setting.repository; -import com.moongeul.backend.api.member.entity.Terms; -import com.moongeul.backend.api.member.entity.TermsType; +import com.moongeul.backend.api.setting.entity.Terms; +import com.moongeul.backend.api.setting.entity.TermsType; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; diff --git a/src/main/java/com/moongeul/backend/api/setting/service/AgreeTermsSettingService.java b/src/main/java/com/moongeul/backend/api/setting/service/AgreeTermsSettingService.java new file mode 100644 index 0000000..08ec4fa --- /dev/null +++ b/src/main/java/com/moongeul/backend/api/setting/service/AgreeTermsSettingService.java @@ -0,0 +1,75 @@ +package com.moongeul.backend.api.setting.service; + +import com.moongeul.backend.api.member.repository.MemberRepository; +import com.moongeul.backend.api.setting.repository.AgreeRepository; +import com.moongeul.backend.api.setting.repository.TermsRepository; +import com.moongeul.backend.api.setting.dto.AgreeTermsRequestDTO; +import com.moongeul.backend.api.setting.entity.Agree; +import com.moongeul.backend.api.member.entity.Member; +import com.moongeul.backend.api.setting.entity.Terms; +import com.moongeul.backend.api.setting.entity.TermsType; +import com.moongeul.backend.common.exception.BadRequestException; +import com.moongeul.backend.common.exception.NotFoundException; +import com.moongeul.backend.common.response.ErrorStatus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Map; + +@Service +@Slf4j +@RequiredArgsConstructor +public class AgreeTermsSettingService { + + private final MemberRepository memberRepository; + private final TermsRepository termsRepository; + private final AgreeRepository agreeRepository; + + /* 약관동의 API */ + @Transactional + public void agreeToTerms(String email, AgreeTermsRequestDTO agreeTermsRequestDTO){ + + Member member = getMemberByEmail(email); + + // 예외처리: 필수 동의 여부 검증 + if (!agreeTermsRequestDTO.isServiceTermsAgree() || !agreeTermsRequestDTO.isPrivatePolicyAgree()) { + throw new BadRequestException(ErrorStatus.DISAGREE_REQUIRED_TERM.getMessage()); + } + + // 1. 약관 타입과 DTO의 동의 여부 매핑 + Map agreementData = Map.of( + TermsType.SERVICE_TERMS_AGREE, agreeTermsRequestDTO.isServiceTermsAgree(), + TermsType.PRIVACY_POLICY_AGREE, agreeTermsRequestDTO.isPrivatePolicyAgree(), + TermsType.MARKETING_AGREE, agreeTermsRequestDTO.isMarketingAgree() + ); + + agreementData.forEach((type, isAgreed) -> { + // 1. 해당 타입의 약관 마스터 정보 조회 + Terms terms = termsRepository.findByTermsType(type) + .orElseThrow(() -> new NotFoundException(ErrorStatus.TERMS_NOTFOUND_EXCEPTION.getMessage())); + + // 2. 기존 동의 내역이 있는지 조회 + agreeRepository.findByMemberAndTerms(member, terms) + .ifPresentOrElse( + // 이미 데이터가 있다면? -> 동의 여부 필드만 수정 (Dirty Checking 발생) + existingAgree -> existingAgree.updateAgreement(isAgreed), + // 데이터가 없다면? -> 새로 생성해서 저장 + () -> { + Agree newAgree = Agree.builder() + .member(member) + .terms(terms) + .isAgreed(isAgreed) + .build(); + agreeRepository.save(newAgree); + } + ); + }); + } + + private Member getMemberByEmail(String email) { + return memberRepository.findByEmail(email) + .orElseThrow(() -> new NotFoundException(ErrorStatus.USER_NOTFOUND_EXCEPTION.getMessage())); + } +} diff --git a/src/main/java/com/moongeul/backend/api/setting/service/PrivacySettingService.java b/src/main/java/com/moongeul/backend/api/setting/service/PrivacySettingService.java index e0b8777..526a76d 100644 --- a/src/main/java/com/moongeul/backend/api/setting/service/PrivacySettingService.java +++ b/src/main/java/com/moongeul/backend/api/setting/service/PrivacySettingService.java @@ -1,7 +1,6 @@ package com.moongeul.backend.api.setting.service; -import com.moongeul.backend.api.member.entity.Member; -import com.moongeul.backend.api.member.entity.PrivacyLevel; +import com.moongeul.backend.api.member.entity.*; import com.moongeul.backend.api.member.repository.MemberRepository; import com.moongeul.backend.api.setting.dto.PrivacyLevelResponseDTO; import com.moongeul.backend.api.setting.dto.PrivacyLevelUpdateRequestDTO;