Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Member feature #43

Merged
merged 3 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import hanium.englishfairytale.common.util.ImageFileUtility;
import hanium.englishfairytale.exception.RuntimeIOException;
import hanium.englishfairytale.exception.code.ErrorCode;
import hanium.englishfairytale.tale.application.dto.TaleImageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -18,13 +17,13 @@ public class FileManageService {
private final FileStore fileStore;

@Transactional
public TaleImageInfo uploadTaleImage(MultipartFile image) {
public ImageInfo uploadImage(MultipartFile image) {
try {
String originalName = image.getOriginalFilename();
String storedName = ImageFileUtility.createObjectNameByUUID(originalName);
String imageUrl = fileStore.upload(storedName, image.getInputStream(), ImageFileUtility.createObjectMetadata(image));

return new TaleImageInfo(originalName, storedName, imageUrl);
return new ImageInfo(originalName, storedName, imageUrl);
} catch (IOException e) {
throw new RuntimeIOException(e, ErrorCode.IMAGE_PROCESSING_IO);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package hanium.englishfairytale.tale.application.dto;
package hanium.englishfairytale.common.files;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class TaleImageInfo {
public class ImageInfo {
String originalFileName;
String storedName;
String imageUrl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ public enum ErrorCode {
EXCEED_KEYWORD_LIMIT(TaleCode.KEYWORD_COUNT_LIMIT.getCode(), BAD_REQUEST, "입력 키워드 개수 초과"),
DUPLICATED_KEYWORD(TaleCode.KEYWORD_DUPLICATED.getCode(), BAD_REQUEST, "중복된 키워드가 있는 경우"),
IMAGE_PROCESSING_IO(TaleCode.IMAGE_IO.getCode(), BAD_REQUEST, "이미지 처리 중 문제가 발생한 경우"),
IMAGE_NON_EXITED(TaleCode.NON_EXISTED_IMAGE.getCode(), NOT_ACCEPTABLE, "삭제할 이미지가 존재하지 않는 경우"),
TALE_IMAGE_NON_EXISTED(TaleCode.NON_EXISTED_IMAGE.getCode(), NOT_ACCEPTABLE, "삭제할 이미지가 존재하지 않는 경우"),

// Member
MEMBER_NOT_FOUND(MemberCode.NOT_FOUND.getCode(), NOT_FOUND, "존재하지 않는 회원"),
EXISTED_MEMBER(MemberCode.MEMBER_EXISTED.getCode(), CONFLICT, "이미 회원가입 되어있을 경우"),
DUPLICATED_NICKNAME(MemberCode.NICKNAME_DUPLICATED.getCode(), CONFLICT, "동일한 닉네임이 존재하는 경우"),
MEMBER_IMAGE_NON_EXISTED(MemberCode.NON_EXISTED_IMAGE.getCode(), CONFLICT, "삭제할 이미지가 존재하지 않는 경우")
;

private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum MemberCode {
NOT_FOUND("M-001"),
MEMBER_EXISTED("M-002"),
NICKNAME_DUPLICATED("M-003"),
NON_EXISTED_IMAGE("M-004"),
;

private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,101 @@
package hanium.englishfairytale.member.application;

import hanium.englishfairytale.common.files.FileManageService;
import hanium.englishfairytale.exception.BusinessException;
import hanium.englishfairytale.exception.NotFoundException;
import hanium.englishfairytale.exception.code.ErrorCode;
import hanium.englishfairytale.member.application.dto.MemberCreateCommand;
import hanium.englishfairytale.member.application.dto.CreateMemberResponse;
import hanium.englishfairytale.member.application.dto.MemberImageUpdateCommand;
import hanium.englishfairytale.member.application.dto.MemberUpdatePasswordCommand;
import hanium.englishfairytale.member.domain.ImageRepository;
import hanium.englishfairytale.member.domain.Member;
import hanium.englishfairytale.member.domain.MemberImage;
import hanium.englishfairytale.member.domain.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
public class MemberCommandService {

private final MemberRepository memberRepository;
private final ImageRepository imageRepository;
private final FileManageService fileManageService;

@Transactional
public CreateMemberResponse register(MemberCreateCommand memberCreateCommand) {
return new CreateMemberResponse(createAndSaveMember(memberCreateCommand));
public Long register(MemberCreateCommand memberCreateCommand) {
verifyExistedMember(memberCreateCommand);
return createAndSaveMember(memberCreateCommand);
}

private Long createAndSaveMember(MemberCreateCommand memberCreateCommand) {
verifyExistedMember(memberCreateCommand);
verifyDuplicatedNickname(memberCreateCommand);
return memberRepository.save(createMember(memberCreateCommand));
@Transactional
public void updateNickname(Long memberId, String nickname) {
Member member = findMember(memberId);
member.updateNickname(nickname);
}

@Transactional
public void updatePassword(MemberUpdatePasswordCommand updatePasswordCommand) {
Member member = findMember(updatePasswordCommand.getMemberId());
member.updatePassword(updatePasswordCommand.getPassword());
}

@Transactional
public void updateMemberImage(MemberImageUpdateCommand imageUpdateCommand) {
Member member = findMember(imageUpdateCommand.getMemberId());
member.updateMemberImage(createAndSaveMemberImage(imageUpdateCommand.getImage()));
}

@Transactional
public void deleteMemberImage(Long memberId) {
Member member = findMember(memberId);
Long imageId = findImageId(member);
deleteImage(member, imageId);
}

private void deleteImage(Member member, Long imageId) {
member.makeImageNull();
imageRepository.delete(imageId);
}

private Long findImageId(Member member) {
verifyImageIsEmpty(member);
return member.getImageId();
}

private void verifyImageIsEmpty(Member member) {
member.checkImageEmpty();
}

private Member findMember(Long id) {
return memberRepository.findMemberById(id)
.orElseThrow(() -> new NotFoundException(ErrorCode.MEMBER_NOT_FOUND));
}

private void verifyDuplicatedNickname(MemberCreateCommand memberCreateCommand) {
if (memberRepository.findByNickname(memberCreateCommand.getNickname()).isPresent()) {
throw new BusinessException(ErrorCode.DUPLICATED_NICKNAME);
private Long createAndSaveMember(MemberCreateCommand memberCreateCommand) {
Member member = createMember(memberCreateCommand);
if (!checkImageEmpty(memberCreateCommand)) {
member.putImage(createAndSaveMemberImage(memberCreateCommand.getImage()));
}
return saveMember(member);
}

private boolean checkImageEmpty(MemberCreateCommand memberCreateCommand) {
return memberCreateCommand.getImage().isEmpty();
}

private Long saveMember(Member member) {
return memberRepository.save(member);
}

private MemberImage createAndSaveMemberImage(MultipartFile file) {
return new MemberImage(fileManageService.uploadImage(file));
}

private void verifyExistedMember(MemberCreateCommand memberCreateCommand) {
if (memberRepository.findByPhoneNumber(memberCreateCommand.getPhoneNumber()).isPresent()) {
if (memberRepository.findMemberByPhoneNumber(memberCreateCommand.getPhoneNumber()).isPresent()) {
throw new BusinessException(ErrorCode.EXISTED_MEMBER);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
package hanium.englishfairytale.member.application;

import hanium.englishfairytale.tale.application.dto.TalesInfo;
import hanium.englishfairytale.tale.domain.Keyword;
import hanium.englishfairytale.tale.domain.TaleKeyword;
import hanium.englishfairytale.tale.domain.TaleRepository;
import hanium.englishfairytale.exception.BusinessException;
import hanium.englishfairytale.exception.NotFoundException;
import hanium.englishfairytale.exception.code.ErrorCode;
import hanium.englishfairytale.member.application.dto.MemberDetailInfo;
import hanium.englishfairytale.member.application.dto.MemberInfo;
import hanium.englishfairytale.member.domain.Member;
import hanium.englishfairytale.member.domain.MemberRepository;
import hanium.englishfairytale.member.infra.MemberQueryDao;
import hanium.englishfairytale.tale.infra.TaleQueryDao;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class MemberQueryService {

private final TaleRepository taleRepository;
private final MemberRepository memberRepository;
private final MemberQueryDao memberQueryDao;
private final TaleQueryDao taleQueryDao;

@Transactional
public void verifyNickname(String nickname) {
verifyNicknameDuplicated(nickname);
}

@Transactional(readOnly = true)
public List<TalesInfo> findMainTalesInfo(Long memberId) {
@Transactional
public MemberInfo findMemberInfo(Long memberId) {
return new MemberInfo(findMember(memberId), countTales(memberId));
}

// memberId -> Tale 조회 -> 최신순, Tale+Member+Image+TaleKeywords 나옴.
// 각 TaleKeyword 의 id값 -> Keywords 조회 -> 위에서 찾은 TaleKeyword 의 id 값을 넣는다. ->
@Transactional
public MemberDetailInfo findMemberDetailInfo(Long memberId) {
return new MemberDetailInfo(findMember(memberId));
}

private Member findMember(Long memberId) {
return memberQueryDao.findMemberAndImage(memberId)
.orElseThrow(() -> new NotFoundException(ErrorCode.MEMBER_NOT_FOUND));
}

return null;
private Long countTales(Long memberId) {
return taleQueryDao.countTales(memberId);
}

private List<Keyword> getKeywordsFromTaleKeyword(List<TaleKeyword> taleKeywords) {
return taleKeywords.stream()
.map(TaleKeyword::getKeyword)
.collect(Collectors.toList());
private void verifyNicknameDuplicated(String nickName) {
if (memberRepository.findByMemberNickname(nickName).isPresent()) {
throw new BusinessException(ErrorCode.DUPLICATED_NICKNAME);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.Builder;
import lombok.Getter;
import org.springframework.web.multipart.MultipartFile;

@Builder
@Getter
Expand All @@ -11,4 +12,6 @@ public class MemberCreateCommand {
private String nickname;
private String email;
private String password;
private MultipartFile image;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package hanium.englishfairytale.member.application.dto;

import hanium.englishfairytale.member.domain.Member;
import lombok.Getter;

@Getter
public class MemberDetailInfo {
String nickname;
String email;
String phoneNumber;
String imageUrl;

public MemberDetailInfo(Member member) {
this.nickname = member.getNickname();
this.email = member.getEmail();
this.phoneNumber = member.getPhoneNumber();
this.imageUrl = member.getImage() == null ? null : member.getImage().getUrl();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hanium.englishfairytale.member.application.dto;

import lombok.Builder;
import lombok.Getter;
import org.springframework.web.multipart.MultipartFile;

@Builder
@Getter
public class MemberImageUpdateCommand {
private Long memberId;
private MultipartFile image;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package hanium.englishfairytale.member.application.dto;

import hanium.englishfairytale.member.domain.Member;
import lombok.Getter;

@Getter
public class MemberInfo {
String nickname;
String imageUrl;
Long taleCounts;

public MemberInfo(Member member, Long taleCounts) {
this.nickname = member.getNickname();
this.imageUrl = member.getImage() == null ? null : member.getImage().getUrl();
this.taleCounts = taleCounts;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package hanium.englishfairytale.member.application.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CreateMemberResponse {
private Long memberId;
@AllArgsConstructor
@Builder
public class MemberUpdatePasswordCommand {
Long memberId;
String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package hanium.englishfairytale.member.domain;

public interface ImageRepository {

void delete(Long memberImageId);
}
35 changes: 34 additions & 1 deletion src/main/java/hanium/englishfairytale/member/domain/Member.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package hanium.englishfairytale.member.domain;

import hanium.englishfairytale.exception.BusinessException;
import hanium.englishfairytale.exception.code.ErrorCode;
import hanium.englishfairytale.tale.domain.Tale;
import lombok.AccessLevel;
import lombok.Builder;
Expand Down Expand Up @@ -34,7 +36,7 @@ public class Member {
@Column(name = "created_date")
private LocalDateTime createdTime;

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<Tale> tales = new ArrayList<>();

@Builder
Expand All @@ -45,6 +47,7 @@ public Member(String name, String phoneNumber, String nickname, String email, St
this.email = email;
this.password = password;
this.createdTime = LocalDateTime.now();
this.image = new Image();
this.tales = new ArrayList<>();
}

Expand All @@ -54,4 +57,34 @@ public void addTale(Tale newTale) {
public void putImage(MemberImage memberImage) {
image.putMemberImage(memberImage);
}

public void updateNickname(String nickname) {
this.nickname = nickname;
}
public void updatePassword(String password) {
this.password = password;
}

public void updateMemberImage(MemberImage memberImage) {
if (image == null) {
this.image = new Image();
this.image.putMemberImage(memberImage);
} else {
image.putMemberImage(memberImage);
}
}

public void checkImageEmpty() {
if (image == null) {
throw new BusinessException(ErrorCode.MEMBER_IMAGE_NON_EXISTED);
}
}

public Long getImageId() {
return this.image.getMemberImage().getId();
}

public void makeImageNull() {
this.image = null;
}
}
Loading