Skip to content

Commit

Permalink
Merge pull request #53 from inhooo00/feature/myPage
Browse files Browse the repository at this point in the history
Feat(#48): 마이페이지 구현
  • Loading branch information
inhooo00 authored Aug 3, 2024
2 parents f194021 + 7e8e4d9 commit 6f4f7df
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ private Member createMember(UserInfo userInfo, SocialType provider) {
.role(Role.ROLE_USER)
.firstLogin(true)
.nickname(nickname)
.introduction("자기 소개를 입력해 주세요.")
.build()
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package shop.kkeujeok.kkeujeokbackend.member.api;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import shop.kkeujeok.kkeujeokbackend.global.annotation.CurrentUserEmail;
import shop.kkeujeok.kkeujeokbackend.global.template.RspTemplate;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.request.MyPageUpdateReqDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response.MyPageInfoResDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.application.MyPageService;

@RestController
@RequestMapping("/api/members")
public class MemberController {

private final MyPageService myPageService;

public MemberController(MyPageService myPageService) {
this.myPageService = myPageService;
}

@GetMapping("/mypage")
public RspTemplate<MyPageInfoResDto> myProfileInfo(@CurrentUserEmail String email) {
MyPageInfoResDto memberResDto = myPageService.findMyProfileByEmail(email);
return new RspTemplate<>(HttpStatus.OK, "내 프로필 정보", memberResDto);
}

@PatchMapping("/mypage")
public RspTemplate<MyPageInfoResDto> update(@CurrentUserEmail String email,
@RequestBody MyPageUpdateReqDto myPageUpdateReqDto) {
return new RspTemplate<>(HttpStatus.OK, "내 프로필 정보 수정", myPageService.update(email,myPageUpdateReqDto));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.NoArgsConstructor;
import shop.kkeujeok.kkeujeokbackend.global.entity.BaseEntity;
import shop.kkeujeok.kkeujeokbackend.global.entity.Status;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.request.MyPageUpdateReqDto;

@Entity
@Getter
Expand All @@ -32,8 +33,10 @@ public class Member extends BaseEntity {

private String nickname;

private String introduction;

@Builder
private Member(Status status, Role role, String email, String name, String picture, SocialType socialType, boolean firstLogin, String nickname) {
private Member(Status status, Role role, String email, String name, String picture, SocialType socialType, boolean firstLogin, String nickname, String introduction) {
this.status = status;
this.role = role;
this.email = email;
Expand All @@ -42,5 +45,19 @@ private Member(Status status, Role role, String email, String name, String pictu
this.socialType = socialType;
this.firstLogin = firstLogin;
this.nickname = nickname;
this.introduction = introduction;
}

public void update(String nickname, String introduction) {
if(isUpdateRequired(nickname, introduction)) {
this.nickname = nickname;
this.introduction = introduction;
}
}

private boolean isUpdateRequired(String updateNickname, String updateIntroduction) {
return !this.nickname.equals(updateNickname) ||
!this.introduction.equals(updateIntroduction);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member, Long>, JpaSpecificationExecutor<Member> {

Optional<Member> findByEmail(String email);
boolean existsByNickname(String nickname);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.request;

public record MyPageUpdateReqDto(
String nickname,
String introduction
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response;

import lombok.Builder;
import shop.kkeujeok.kkeujeokbackend.member.domain.Member;
import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType;

@Builder
public record MyPageInfoResDto(
String picture,
String email,
String name,
String nickName,
SocialType socialType,
String introduction

) {
public static MyPageInfoResDto From(Member member) {
return MyPageInfoResDto.builder()
.picture(member.getPicture())
.email(member.getEmail())
.name(member.getName())
.nickName(member.getNickname())
.socialType(member.getSocialType())
.introduction(member.getIntroduction())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package shop.kkeujeok.kkeujeokbackend.member.mypage.application;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.kkeujeok.kkeujeokbackend.auth.exception.EmailNotFoundException;
import shop.kkeujeok.kkeujeokbackend.member.domain.Member;
import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.request.MyPageUpdateReqDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response.MyPageInfoResDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.exception.ExistsNicknameException;

@Service
@Transactional(readOnly = true)
public class MyPageService {
private final MemberRepository memberRepository;

public MyPageService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}

// 프로필 정보 조회
public MyPageInfoResDto findMyProfileByEmail(String email) {
Member member = memberRepository.findByEmail(email).orElseThrow();

return MyPageInfoResDto.From(member);
}

// 프로필 정보 수정
@Transactional
public MyPageInfoResDto update(String email, MyPageUpdateReqDto myPageUpdateReqDto) {
Member member = memberRepository.findByEmail(email).orElseThrow(EmailNotFoundException::new);

if (isNicknameChanged(member, myPageUpdateReqDto.nickname()) && isNicknameDuplicate(myPageUpdateReqDto.nickname())) {
throw new ExistsNicknameException();
}

member.update(myPageUpdateReqDto.nickname(), myPageUpdateReqDto.introduction());

return MyPageInfoResDto.From(member);
}

private boolean isNicknameChanged(Member member, String newNickname) {
return !normalizeNickname(member.getNickname()).equals(normalizeNickname(newNickname));
}

private boolean isNicknameDuplicate(String nickname) {
return memberRepository.existsByNickname(normalizeNickname(nickname));
}

private String normalizeNickname(String nickname) {
return nickname.replaceAll("\\s+", "");
}

// 팀 대시보드 정보 조회

// 챌린지 정보 조회

// 알림 조회
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package shop.kkeujeok.kkeujeokbackend.member.mypage.exception;

import shop.kkeujeok.kkeujeokbackend.global.error.exception.InvalidGroupException;

public class ExistsNicknameException extends InvalidGroupException {
public ExistsNicknameException(String message) {
super(message);
}

public ExistsNicknameException() {
this("이미 사용중인 닉네임 입니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package shop.kkeujeok.kkeujeokbackend.member.mypage.application;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import shop.kkeujeok.kkeujeokbackend.member.domain.Member;
import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType;
import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.request.MyPageUpdateReqDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response.MyPageInfoResDto;

import java.util.Optional;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@ExtendWith(MockitoExtension.class)
public class MyPageServiceTest {

@Mock
private MemberRepository memberRepository;

@InjectMocks
private MyPageService myPageService;

private MyPageUpdateReqDto myPageUpdateReqDto;
private MyPageInfoResDto myPageInfoResDto;
private Member member;

@BeforeEach
void setUp() {
myPageUpdateReqDto = new MyPageUpdateReqDto("nickname", "introduction");
myPageInfoResDto = new MyPageInfoResDto("picture", "email", "name", "nickname", SocialType.GOOGLE, "introduction");
member = Member.builder()
.email("email")
.name("name")
.nickname("nickname")
.socialType(SocialType.GOOGLE)
.introduction("introduction")
.picture("picture")
.build();
}

@DisplayName("프로필을 조회합니다.")
@Test
void 프로필을_조회합니다() {
// Given
when(memberRepository.findByEmail(anyString())).thenReturn(Optional.of(member));

// When
MyPageInfoResDto result = myPageService.findMyProfileByEmail("email");

// Then
assertEquals(myPageInfoResDto.email(), result.email());
assertEquals(myPageInfoResDto.name(), result.name());
assertEquals(myPageInfoResDto.nickName(), result.nickName());
assertEquals(myPageInfoResDto.socialType(), result.socialType());
assertEquals(myPageInfoResDto.introduction(), result.introduction());
assertEquals(myPageInfoResDto.picture(), result.picture());
}

// 프로필 정보 수정
@DisplayName("프로필 정보를 수정합니다.")
@Test
void 프로필_정보를_수정합니다() {
// Given
when(memberRepository.findByEmail(anyString())).thenReturn(Optional.of(member));
MyPageUpdateReqDto newMyPageUpdateReqDto = new MyPageUpdateReqDto("newNickname", "newIntroduction");
// When
MyPageInfoResDto result = myPageService.update("email", newMyPageUpdateReqDto);

// Then
assertEquals("newNickname", result.nickName());
assertEquals("newIntroduction", result.introduction());

verify(memberRepository, times(1)).findByEmail("email");
}

// 팀 대시보드 정보 조회

// 챌린지 정보 조회

// 알림 조회
}

0 comments on commit 6f4f7df

Please sign in to comment.