From 6a3fb57af6679021bc92ec61ad1fbf811cc2ca91 Mon Sep 17 00:00:00 2001 From: toychip Date: Sat, 10 Feb 2024 19:00:58 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EC=A7=81=ED=9B=84=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84,=20=EA=B4=80=EC=8B=AC=EC=82=AC,=20=EB=8B=89=EB=84=A4?= =?UTF-8?q?=EC=9E=84=20=EC=82=BD=EC=9E=85=20=EB=A1=9C=EC=A7=81=20(#51)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존 소셜로그인 - originName으로 변경, 관심사 Member(1) : Interest(N)로 매핑, 기존 값 수정 Editor 사용 --- .../comment/dto/response/CommentResponse.java | 2 +- .../dto/response/HoneyTipSingleResponse.java | 2 +- .../main/dto/response/TitleResponse.java | 4 +- .../ttoklip/domain/member/domain/Member.java | 37 +++++++++- .../domain/member/editor/MemberEditor.java | 56 ++++++++++++++++ .../repository/MemberOAuthRepository.java | 2 +- .../domain/privacy/ProfileController.java | 29 ++++++++ .../domain/privacy/domain/Interest.java | 43 ++++++++++++ .../{profile => privacy}/domain/Profile.java | 2 +- .../privacy/dto/PrivacyCreateRequest.java | 42 ++++++++++++ .../repository/InterestRepository.java | 7 ++ .../repository/ProfileRepository.java | 4 +- .../privacy/service/ProfileService.java | 67 +++++++++++++++++++ .../profile/service/ProfileService.java | 21 ------ .../dto/response/QuestionSingleResponse.java | 2 +- .../ttoklip/global/exception/ErrorType.java | 4 ++ .../handler/CustomOAuthSuccessHandler.java | 4 +- .../service/CustomOAuth2UserService.java | 8 +-- 18 files changed, 298 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/api/ttoklip/domain/member/editor/MemberEditor.java create mode 100644 src/main/java/com/api/ttoklip/domain/privacy/ProfileController.java create mode 100644 src/main/java/com/api/ttoklip/domain/privacy/domain/Interest.java rename src/main/java/com/api/ttoklip/domain/{profile => privacy}/domain/Profile.java (95%) create mode 100644 src/main/java/com/api/ttoklip/domain/privacy/dto/PrivacyCreateRequest.java create mode 100644 src/main/java/com/api/ttoklip/domain/privacy/repository/InterestRepository.java rename src/main/java/com/api/ttoklip/domain/{profile => privacy}/repository/ProfileRepository.java (57%) create mode 100644 src/main/java/com/api/ttoklip/domain/privacy/service/ProfileService.java delete mode 100644 src/main/java/com/api/ttoklip/domain/profile/service/ProfileService.java diff --git a/src/main/java/com/api/ttoklip/domain/common/comment/dto/response/CommentResponse.java b/src/main/java/com/api/ttoklip/domain/common/comment/dto/response/CommentResponse.java index 0b079916..e1f2c14c 100644 --- a/src/main/java/com/api/ttoklip/domain/common/comment/dto/response/CommentResponse.java +++ b/src/main/java/com/api/ttoklip/domain/common/comment/dto/response/CommentResponse.java @@ -47,7 +47,7 @@ private static CommentResponse getCommentResponse(final Comment questionComment, .commentId(questionComment.getId()) .commentContent(questionComment.getContent()) .parentId(parentCommentId) - .writer(questionComment.getMember().getName()) + .writer(questionComment.getMember().getOriginName()) .writtenTime(formatCreatedDate) .build(); } diff --git a/src/main/java/com/api/ttoklip/domain/honeytip/post/dto/response/HoneyTipSingleResponse.java b/src/main/java/com/api/ttoklip/domain/honeytip/post/dto/response/HoneyTipSingleResponse.java index 3b1ba3ca..467f30a6 100644 --- a/src/main/java/com/api/ttoklip/domain/honeytip/post/dto/response/HoneyTipSingleResponse.java +++ b/src/main/java/com/api/ttoklip/domain/honeytip/post/dto/response/HoneyTipSingleResponse.java @@ -67,7 +67,7 @@ public static HoneyTipSingleResponse of(final HoneyTip honeyTip, final List interests = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "member", fetch = FetchType.LAZY, orphanRemoval = true) private List reports = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private List comments = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private List honeyTips = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private List questions = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private List honeyTipLikes = new ArrayList<>(); + public MemberEditorBuilder toEditor() { + return MemberEditor.builder() + .independentYear(independentYear) + .independentMonth(independentMonth) +// .street() + .nickname(nickname); + } + + public void insertPrivacy(MemberEditor memberEditor) { + System.out.println("Member.insertPrivacy"); + independentYear = memberEditor.getIndependentYear(); + independentMonth = memberEditor.getIndependentMonth(); + nickname = memberEditor.getNickname(); + System.out.println("independentYear = " + independentYear); + System.out.println("independentMonth = " + independentMonth); + + } } \ No newline at end of file diff --git a/src/main/java/com/api/ttoklip/domain/member/editor/MemberEditor.java b/src/main/java/com/api/ttoklip/domain/member/editor/MemberEditor.java new file mode 100644 index 00000000..6021c9bf --- /dev/null +++ b/src/main/java/com/api/ttoklip/domain/member/editor/MemberEditor.java @@ -0,0 +1,56 @@ +package com.api.ttoklip.domain.member.editor; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.util.StringUtils; + +@Getter +@RequiredArgsConstructor +public class MemberEditor { + private final String nickname; + private final String street; + private final int independentYear; + private final int independentMonth; + + public static MemberEditorBuilder builder() { + return new MemberEditorBuilder(); + } + + public static class MemberEditorBuilder { + private String nickname; + private String street; + private int independentYear; + private int independentMonth; + + MemberEditorBuilder(){ + } + + public MemberEditorBuilder nickname(final String nickname) { + if (StringUtils.hasText(nickname)) { + this.nickname = nickname; + } + return this; + } + + public MemberEditorBuilder street(final String street) { + if (StringUtils.hasText(street)) { + this.street = street; + } + return this; + } + + public MemberEditorBuilder independentYear(final int independentYear) { + this.independentYear = independentYear; + return this; + } + + public MemberEditorBuilder independentMonth(final int independentMonth) { + this.independentMonth = independentMonth; + return this; + } + + public MemberEditor build() { + return new MemberEditor(nickname, street, independentYear, independentMonth); + } + } +} diff --git a/src/main/java/com/api/ttoklip/domain/member/repository/MemberOAuthRepository.java b/src/main/java/com/api/ttoklip/domain/member/repository/MemberOAuthRepository.java index 5235f593..ff968f94 100644 --- a/src/main/java/com/api/ttoklip/domain/member/repository/MemberOAuthRepository.java +++ b/src/main/java/com/api/ttoklip/domain/member/repository/MemberOAuthRepository.java @@ -2,7 +2,7 @@ import com.api.ttoklip.domain.member.domain.Member; import com.api.ttoklip.domain.member.domain.QMember; -import com.api.ttoklip.domain.profile.domain.QProfile; +import com.api.ttoklip.domain.privacy.domain.QProfile; import com.api.ttoklip.global.exception.ApiException; import com.api.ttoklip.global.exception.ErrorType; import com.querydsl.jpa.impl.JPAQueryFactory; diff --git a/src/main/java/com/api/ttoklip/domain/privacy/ProfileController.java b/src/main/java/com/api/ttoklip/domain/privacy/ProfileController.java new file mode 100644 index 00000000..2b7fd547 --- /dev/null +++ b/src/main/java/com/api/ttoklip/domain/privacy/ProfileController.java @@ -0,0 +1,29 @@ +package com.api.ttoklip.domain.privacy; + +import com.api.ttoklip.domain.privacy.dto.PrivacyCreateRequest; +import com.api.ttoklip.domain.privacy.service.ProfileService; +import com.api.ttoklip.global.success.Message; +import com.api.ttoklip.global.success.SuccessResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +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.RestController; + +@Tag(name = "AFTER AUTH LOGIN API", description = "꿀팁공유해요 소셜 로그인 후 회원가입 API입니다.") +@RestController +@RequestMapping("/api/v1/privacy") +@RequiredArgsConstructor +public class ProfileController { + + private final ProfileService profileService; + + @PostMapping("/insert") + public SuccessResponse register(@RequestBody @Validated final PrivacyCreateRequest request) { + profileService.insert(request); + + return new SuccessResponse<>(1000L); + } +} diff --git a/src/main/java/com/api/ttoklip/domain/privacy/domain/Interest.java b/src/main/java/com/api/ttoklip/domain/privacy/domain/Interest.java new file mode 100644 index 00000000..60d36941 --- /dev/null +++ b/src/main/java/com/api/ttoklip/domain/privacy/domain/Interest.java @@ -0,0 +1,43 @@ +package com.api.ttoklip.domain.privacy.domain; + +import com.api.ttoklip.domain.common.Category; +import com.api.ttoklip.domain.member.domain.Member; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class Interest { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Enumerated(EnumType.STRING) + private Category category; + + public static Interest of(final Member member, final Category category) { + return Interest.builder() + .member(member) + .category(category) + .build(); + } +} diff --git a/src/main/java/com/api/ttoklip/domain/profile/domain/Profile.java b/src/main/java/com/api/ttoklip/domain/privacy/domain/Profile.java similarity index 95% rename from src/main/java/com/api/ttoklip/domain/profile/domain/Profile.java rename to src/main/java/com/api/ttoklip/domain/privacy/domain/Profile.java index 8b4aab71..bf4e88f2 100644 --- a/src/main/java/com/api/ttoklip/domain/profile/domain/Profile.java +++ b/src/main/java/com/api/ttoklip/domain/privacy/domain/Profile.java @@ -1,4 +1,4 @@ -package com.api.ttoklip.domain.profile.domain; +package com.api.ttoklip.domain.privacy.domain; import com.api.ttoklip.domain.member.domain.Member; import jakarta.persistence.Entity; diff --git a/src/main/java/com/api/ttoklip/domain/privacy/dto/PrivacyCreateRequest.java b/src/main/java/com/api/ttoklip/domain/privacy/dto/PrivacyCreateRequest.java new file mode 100644 index 00000000..84c29745 --- /dev/null +++ b/src/main/java/com/api/ttoklip/domain/privacy/dto/PrivacyCreateRequest.java @@ -0,0 +1,42 @@ +package com.api.ttoklip.domain.privacy.dto; + +import com.api.ttoklip.domain.common.Category; +import com.api.ttoklip.global.exception.ApiException; +import com.api.ttoklip.global.exception.ErrorType; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class PrivacyCreateRequest { + + private String street; + 직 + private String nickname; + private List categories; + + @Min(0) + @Max(99) + private int independentYear; + + @Min(0) + @Max(11) + private int independentMonth; + + public List getCategories() { + validCategorySize(); + return categories.stream() + .map(Category::findCategoryByValue) + .toList(); + } + + private void validCategorySize() { + if (categories.size() > 3) { + throw new ApiException(ErrorType.INVALID_CATEGORIES_SIZE); + } + } + +} diff --git a/src/main/java/com/api/ttoklip/domain/privacy/repository/InterestRepository.java b/src/main/java/com/api/ttoklip/domain/privacy/repository/InterestRepository.java new file mode 100644 index 00000000..92910330 --- /dev/null +++ b/src/main/java/com/api/ttoklip/domain/privacy/repository/InterestRepository.java @@ -0,0 +1,7 @@ +package com.api.ttoklip.domain.privacy.repository; + +import com.api.ttoklip.domain.privacy.domain.Interest; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface InterestRepository extends JpaRepository { +} diff --git a/src/main/java/com/api/ttoklip/domain/profile/repository/ProfileRepository.java b/src/main/java/com/api/ttoklip/domain/privacy/repository/ProfileRepository.java similarity index 57% rename from src/main/java/com/api/ttoklip/domain/profile/repository/ProfileRepository.java rename to src/main/java/com/api/ttoklip/domain/privacy/repository/ProfileRepository.java index 4d6f8241..f6d81fd4 100644 --- a/src/main/java/com/api/ttoklip/domain/profile/repository/ProfileRepository.java +++ b/src/main/java/com/api/ttoklip/domain/privacy/repository/ProfileRepository.java @@ -1,6 +1,6 @@ -package com.api.ttoklip.domain.profile.repository; +package com.api.ttoklip.domain.privacy.repository; -import com.api.ttoklip.domain.profile.domain.Profile; +import com.api.ttoklip.domain.privacy.domain.Profile; import org.springframework.data.jpa.repository.JpaRepository; public interface ProfileRepository extends JpaRepository { diff --git a/src/main/java/com/api/ttoklip/domain/privacy/service/ProfileService.java b/src/main/java/com/api/ttoklip/domain/privacy/service/ProfileService.java new file mode 100644 index 00000000..3d0f7618 --- /dev/null +++ b/src/main/java/com/api/ttoklip/domain/privacy/service/ProfileService.java @@ -0,0 +1,67 @@ +package com.api.ttoklip.domain.privacy.service; + +import static com.api.ttoklip.global.util.SecurityUtil.getCurrentMember; + +import com.api.ttoklip.domain.common.Category; +import com.api.ttoklip.domain.member.domain.Member; +import com.api.ttoklip.domain.member.editor.MemberEditor; +import com.api.ttoklip.domain.member.editor.MemberEditor.MemberEditorBuilder; +import com.api.ttoklip.domain.member.repository.MemberRepository; +import com.api.ttoklip.domain.member.service.MemberService; +import com.api.ttoklip.domain.privacy.domain.Interest; +import com.api.ttoklip.domain.privacy.domain.Profile; +import com.api.ttoklip.domain.privacy.dto.PrivacyCreateRequest; +import com.api.ttoklip.domain.privacy.repository.InterestRepository; +import com.api.ttoklip.domain.privacy.repository.ProfileRepository; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class ProfileService { + + private final ProfileRepository profileRepository; + private final InterestRepository interestRepository; + private final MemberService memberService; + + // 회원가입시 자동으로 프로필 이미지 기입 + @Transactional + public Long register(final Profile profile) { + profileRepository.save(profile); + return profile.getId(); + } + + // 회원 가입 후 입력 받을 닉네임, 우리동네 설정, 나의 동릭 경험, 관심 카테고리 선택 + @Transactional + public void insert(final PrivacyCreateRequest request) { + Member currentMember = memberService.findByIdWithProfile(getCurrentMember().getId()); + MemberEditor editor = getEditor(currentMember, request); + currentMember.insertPrivacy(editor); + registerInterest(request, currentMember); + } + + private MemberEditor getEditor(final Member currentMember, final PrivacyCreateRequest request) { + int independentYear = request.getIndependentYear(); + int independentMonth = request.getIndependentMonth(); + String nickname = request.getNickname(); // ToDo 추후에 닉네임 중복되는지 검사하는 로직 처리 + // String street = request.getStreet(); // ToDo 추후에 Embeded로 주소 처리 + MemberEditorBuilder editorBuilder = currentMember.toEditor(); + return editorBuilder + .independentYear(independentYear) + .independentMonth(independentMonth) + .nickname(nickname) + .build(); + } + + private void registerInterest(final PrivacyCreateRequest request, final Member currentMember) { + List requestCategories = request.getCategories(); + List interests = requestCategories + .stream() + .map(category -> Interest.of(currentMember, category)) + .toList(); + interestRepository.saveAll(interests); + } +} diff --git a/src/main/java/com/api/ttoklip/domain/profile/service/ProfileService.java b/src/main/java/com/api/ttoklip/domain/profile/service/ProfileService.java deleted file mode 100644 index 2171ad66..00000000 --- a/src/main/java/com/api/ttoklip/domain/profile/service/ProfileService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.api.ttoklip.domain.profile.service; - -import com.api.ttoklip.domain.profile.domain.Profile; -import com.api.ttoklip.domain.profile.repository.ProfileRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class ProfileService { - - private final ProfileRepository profileRepository; - - @Transactional - public Long register(final Profile profile) { - profileRepository.save(profile); - return profile.getId(); - } -} diff --git a/src/main/java/com/api/ttoklip/domain/question/post/dto/response/QuestionSingleResponse.java b/src/main/java/com/api/ttoklip/domain/question/post/dto/response/QuestionSingleResponse.java index acdbf959..5c84c05d 100644 --- a/src/main/java/com/api/ttoklip/domain/question/post/dto/response/QuestionSingleResponse.java +++ b/src/main/java/com/api/ttoklip/domain/question/post/dto/response/QuestionSingleResponse.java @@ -62,7 +62,7 @@ public static QuestionSingleResponse of(final Question question, final List