From 78678cb850e89748733f1c4a45d9b6e5eca4f42d Mon Sep 17 00:00:00 2001 From: Arachneee Date: Thu, 26 Sep 2024 14:20:36 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=ED=96=89=EC=82=AC=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EC=A0=84=EC=B2=B4=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haengdong/application/MemberService.java | 108 +++------------- .../request/MembersUpdateAppRequest.java | 8 ++ .../haengdong/domain/member/Members.java | 65 ++++++++++ .../haengdong/domain/member/MembersTest.java | 118 ++++++++++++++++++ 4 files changed, 211 insertions(+), 88 deletions(-) create mode 100644 server/src/main/java/server/haengdong/domain/member/Members.java create mode 100644 server/src/test/java/server/haengdong/domain/member/MembersTest.java diff --git a/server/src/main/java/server/haengdong/application/MemberService.java b/server/src/main/java/server/haengdong/application/MemberService.java index 9da74972a..cf79ba8d3 100644 --- a/server/src/main/java/server/haengdong/application/MemberService.java +++ b/server/src/main/java/server/haengdong/application/MemberService.java @@ -1,17 +1,12 @@ package server.haengdong.application; -import static java.util.stream.Collectors.toMap; - -import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import server.haengdong.application.request.MemberSaveAppRequest; -import server.haengdong.application.request.MemberUpdateAppRequest; import server.haengdong.application.request.MembersSaveAppRequest; import server.haengdong.application.request.MembersUpdateAppRequest; import server.haengdong.application.response.MemberAppResponse; @@ -22,6 +17,7 @@ import server.haengdong.domain.bill.BillRepository; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.member.Members; import server.haengdong.domain.member.Member; import server.haengdong.domain.member.MemberRepository; import server.haengdong.exception.HaengdongErrorCode; @@ -54,6 +50,16 @@ public MembersSaveAppResponse saveMembers(String token, MembersSaveAppRequest re return MembersSaveAppResponse.of(savedMembers); } + private void validateMemberSave(List memberNames, Event event) { + if (memberNames.size() != Set.copyOf(memberNames).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE, memberNames); + } + if (memberRepository.findAllByEvent(event).stream() + .anyMatch(member -> memberNames.contains(member.getName()))) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST); + } + } + public List getCurrentMembers(String token) { Event event = getEvent(token); @@ -65,16 +71,6 @@ public List getCurrentMembers(String token) { .toList(); } - private void validateMemberSave(List memberNames, Event event) { - if (memberNamesDuplicated(memberNames)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE, memberNames); - } - if (memberRepository.findAllByEvent(event).stream() - .anyMatch(member -> memberNames.contains(member.getName()))) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST); - } - } - public MembersDepositAppResponse findAllMembers(String token) { Event event = getEvent(token); @@ -86,80 +82,11 @@ public MembersDepositAppResponse findAllMembers(String token) { @Transactional public void updateMembers(String token, MembersUpdateAppRequest request) { Event event = getEvent(token); - validateMemberUpdate(request); - - List updatedMembers = request.members().stream() - .map(memberRequest -> memberRequest.toMember(event)) - .toList(); - List eventMembers = memberRepository.findAllByEvent(event); - - validateUpdatedMembersExist(eventMembers, updatedMembers); - validateUpdatedNamesUnique(eventMembers, updatedMembers); - memberRepository.saveAll(updatedMembers); - } - - private Event getEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } + Members requestMembers = new Members(request.toMembers(event)); + Members members = new Members(memberRepository.findAllByEvent(event)); - private void validateMemberUpdate(MembersUpdateAppRequest request) { - validateChangedNameUnique(request.members()); - validateMemberUnique(request.members()); - } - - private void validateChangedNameUnique(List members) { - List memberNames = members.stream() - .map(MemberUpdateAppRequest::name) - .toList(); - if (memberNamesDuplicated(memberNames)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); - } - } - - private boolean memberNamesDuplicated(List memberNames) { - return memberNames.size() != Set.copyOf(memberNames).size(); - } - - private void validateMemberUnique(List members) { - List memberIds = members.stream() - .map(MemberUpdateAppRequest::id) - .distinct() - .toList(); - if (members.size() != memberIds.size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); - } - } - - private void validateUpdatedMembersExist(List eventMembers, List updatedMembers) { - if (updatedMembers.size() != eventMembers.size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_UPDATE_MISMATCH); - } - Set members = new HashSet<>(eventMembers); - - if (!members.containsAll(updatedMembers)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_UPDATE_MISMATCH); - } - } - - private void validateUpdatedNamesUnique(List eventMembers, List updatedMembers) { - Map eventMemberNames = eventMembers.stream() - .collect(toMap(Member::getId, Member::getName)); - Set existNames = new HashSet<>(eventMemberNames.values()); - - boolean memberNameDuplicated = updatedMembers.stream() - .filter(updatedMember -> isMemberNameUpdated(eventMemberNames, updatedMember)) - .map(Member::getName) - .anyMatch(existNames::contains); - - if (memberNameDuplicated) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); - } - } - - private boolean isMemberNameUpdated(Map eventMemberNames, Member updatedMember) { - String prevMemberName = eventMemberNames.get(updatedMember.getId()); - return !updatedMember.hasName(prevMemberName); + members.validateUpdateAble(requestMembers); + memberRepository.saveAll(requestMembers.getMembers()); } @Transactional @@ -180,4 +107,9 @@ private void deleteMember(String token, Member member) { billDetailRepository.deleteAllByMember(member); memberRepository.delete(member); } + + private Event getEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } } diff --git a/server/src/main/java/server/haengdong/application/request/MembersUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MembersUpdateAppRequest.java index a8ce8b893..aa3253504 100644 --- a/server/src/main/java/server/haengdong/application/request/MembersUpdateAppRequest.java +++ b/server/src/main/java/server/haengdong/application/request/MembersUpdateAppRequest.java @@ -1,6 +1,14 @@ package server.haengdong.application.request; import java.util.List; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.member.Member; public record MembersUpdateAppRequest(List members) { + + public List toMembers(Event event) { + return members.stream() + .map(memberRequest -> memberRequest.toMember(event)) + .toList(); + } } diff --git a/server/src/main/java/server/haengdong/domain/member/Members.java b/server/src/main/java/server/haengdong/domain/member/Members.java new file mode 100644 index 000000000..e0aab7c27 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/member/Members.java @@ -0,0 +1,65 @@ +package server.haengdong.domain.member; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +public class Members { + + private final Set members; + + public Members(List members) { + validateNameUnique(members); + validateMemberUnique(members); + this.members = new HashSet<>(members); + } + + private void validateNameUnique(List members) { + List memberNames = members.stream() + .map(Member::getName) + .toList(); + if (memberNames.size() != Set.copyOf(memberNames).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); + } + } + + private void validateMemberUnique(List members) { + if (members.size() != Set.copyOf(members).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); + } + } + + public void validateUpdateAble(Members requestMembers) { + validateUpdatedMembersExist(requestMembers); + validateUpdatedNamesUnique(requestMembers); + } + + private void validateUpdatedMembersExist(Members requestMembers) { + if (!this.members.equals(requestMembers.members)) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_UPDATE_MISMATCH); + } + } + + private void validateUpdatedNamesUnique(Members requestMembers) { + boolean duplicated = requestMembers.members.stream() + .anyMatch(this::isMemberNameUpdated); + + if (duplicated) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); + } + } + + private boolean isMemberNameUpdated(Member updatedMember) { + return this.members.stream() + .filter(member -> !member.getId().equals(updatedMember.getId())) + .anyMatch(member -> member.hasName(updatedMember.getName())); + } + + public List getMembers() { + return members.stream().toList(); + } +} + + diff --git a/server/src/test/java/server/haengdong/domain/member/MembersTest.java b/server/src/test/java/server/haengdong/domain/member/MembersTest.java new file mode 100644 index 000000000..7a0b5c5a3 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/member/MembersTest.java @@ -0,0 +1,118 @@ +package server.haengdong.domain.member; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; + +class MembersTest { + + @DisplayName("이벤트 이름들은 중복될 수 없다.") + @Test + void validateNameUnique() { + Event event = new Event("행동대장 회식", "1234", "1231415jaksdf"); + List members = List.of( + new Member(1L, event, "고구마", false), + new Member(2L, event, "감자", false), + new Member(3L, event, "감자", false) + ); + + assertThatThrownBy(() -> new Members(members)) + .isInstanceOf(HaengdongException.class) + .hasMessage("중복된 참여 인원 이름 변경 요청이 존재합니다."); + } + + @DisplayName("이벤트 회원들은 중복될 수 없다.") + @Test + void validateMemberUnique() { + Event event = new Event("행동대장 회식", "1234", "1231415jaksdf"); + Member member1 = new Member(1L, event, "고구마", false); + Member member2 = new Member(2L, event, "감자", false); + List members = List.of(member1, member2, member2); + + + assertThatThrownBy(() -> new Members(members)) + .isInstanceOf(HaengdongException.class) + .hasMessage("중복된 참여 인원 이름 변경 요청이 존재합니다."); + } + + @DisplayName("이벤트 이름들로 이벤트 참여자들을 생성한다.") + @Test + void create() { + Event event = new Event("행동대장 회식", "1234", "1231415jaksdf"); + Member member1 = new Member(1L, event, "고구마", false); + Member member2 = new Member(2L, event, "감자", false); + Member member3 = new Member(3L, event, "당근", false); + List members = List.of(member1, member2, member3); + + Members eventMembers = new Members(members); + assertThat(eventMembers.getMembers()).hasSize(3) + .containsExactlyInAnyOrder(member1, member2, member3); + } + + @DisplayName("이벤트의 참여자들 전체가 존재하지 않으면 업데이트할 수 없다.") + @Test + void validateUpdatedMembersExist() { + Event event = new Event("행동대장 회식", "1234", "1231415jaksdf"); + Member member1 = new Member(1L, event, "고구마", false); + Member member2 = new Member(2L, event, "감자", false); + Member member3 = new Member(3L, event, "당근", false); + Member member4 = new Member(4L, event, "양파", false); + Members members = new Members(List.of(member1, member2, member3, member4)); + + Member updateMember1 = new Member(1L, event, "토다리", false); + Member updateMember2 = new Member(2L, event, "쿠키", false); + Member updateMember3 = new Member(3L, event, "백호", false); + Members updatedMembers = new Members(List.of(updateMember1, updateMember2, updateMember3)); + + assertThatThrownBy(() -> members.validateUpdateAble(updatedMembers)) + .isInstanceOf(HaengdongException.class) + .hasMessage("업데이트 요청된 참여자 ID 목록과 기존 행사 참여자 ID 목록이 일치하지 않습니다."); + } + + @DisplayName("업데이트할 이름 중에 기존 이벤트의 참여자들의 이름과 중복되면 업데이트할 수 없다.") + @Test + void validateUpdatedNamesUnique() { + Event event = new Event("행동대장 회식", "1234", "1231415jaksdf"); + Member member1 = new Member(1L, event, "고구마", false); + Member member2 = new Member(2L, event, "감자", false); + Member member3 = new Member(3L, event, "당근", false); + Member member4 = new Member(4L, event, "양파", false); + Members members = new Members(List.of(member1, member2, member3, member4)); + + Member updateMember1 = new Member(1L, event, "토다리", false); + Member updateMember2 = new Member(2L, event, "쿠키", false); + Member updateMember3 = new Member(3L, event, "백호", false); + Member updateMember4 = new Member(4L, event, "감자", false); + Members updatedMembers = new Members(List.of(updateMember1, updateMember2, updateMember3, updateMember4)); + + assertThatThrownBy(() -> members.validateUpdateAble(updatedMembers)) + .isInstanceOf(HaengdongException.class) + .hasMessage("중복된 행사 참여 인원 이름이 존재합니다."); + } + + @DisplayName("이벤트의 참여자들 전체를 업데이트 검증한다.") + @Test + void validateUpdateAble() { + Event event = new Event("행동대장 회식", "1234", "1231415jaksdf"); + Member member1 = new Member(1L, event, "고구마", false); + Member member2 = new Member(2L, event, "감자", false); + Member member3 = new Member(3L, event, "당근", false); + Member member4 = new Member(4L, event, "양파", false); + Members members = new Members(List.of(member1, member2, member3, member4)); + + Member updateMember1 = new Member(1L, event, "토다리", false); + Member updateMember2 = new Member(2L, event, "쿠키", false); + Member updateMember3 = new Member(3L, event, "백호", false); + Member updateMember4 = new Member(4L, event, "망쵸", false); + Members updatedMembers = new Members(List.of(updateMember1, updateMember2, updateMember3, updateMember4)); + + assertThatCode(() -> members.validateUpdateAble(updatedMembers)) + .doesNotThrowAnyException(); + } +}