From b2fad09c4769965f03ecea9c59bdf9d9fa6bafac Mon Sep 17 00:00:00 2001 From: TaeHyeon Kim Date: Fri, 1 Dec 2023 17:34:52 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=ED=9A=8C=EC=9B=90=20=EC=9E=91=EC=84=B1=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C?= =?UTF-8?q?,=20=EC=B9=B4=ED=8E=98=20=EB=B3=84=EB=A1=9C=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A7=81=EB=90=98=EB=8F=84=EB=A1=9D=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#136)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 엔티티 영역에서 mapId 가 같은 카페일 경우 동일 카페로 간주하도록 구현 * feat: 자신이 댓글 쓴 카페 목록 조회 시, 카페 별로 grouping 되도록 구현 * test: 기능 구현으로 인해 테스트 변경 * feat: 카페 mapId 에 따른 페이지네이션 처리 구현 * fix: 범위 벗어나는 toIndex 수정 * fix: 범위 잘못된 toIndex 수정 * feat: equals override 메서드 instanceof 이용하도록 구현 --------- Co-authored-by: 김태현 --- .../java/mocacong/server/domain/Cafe.java | 17 ++++++++++ .../dto/response/MyCommentCafeResponse.java | 13 +++++++- .../mocacong/server/service/CafeService.java | 31 ++++++++++++++----- .../acceptance/MemberAcceptanceTest.java | 5 ++- .../java/mocacong/server/domain/CafeTest.java | 10 ++++++ .../server/service/CafeServiceTest.java | 10 +++--- 6 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/main/java/mocacong/server/domain/Cafe.java b/src/main/java/mocacong/server/domain/Cafe.java index 62bf598d..fe72aa86 100644 --- a/src/main/java/mocacong/server/domain/Cafe.java +++ b/src/main/java/mocacong/server/domain/Cafe.java @@ -107,4 +107,21 @@ public void addScore(Score score) { public void addReview(Review review) { this.reviews.add(review); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Cafe)) { + return false; + } + Cafe cafe = (Cafe) o; + return Objects.equals(mapId, cafe.mapId); + } + + @Override + public int hashCode() { + return Objects.hash(mapId); + } } diff --git a/src/main/java/mocacong/server/dto/response/MyCommentCafeResponse.java b/src/main/java/mocacong/server/dto/response/MyCommentCafeResponse.java index 84aeabd4..4fd731d8 100644 --- a/src/main/java/mocacong/server/dto/response/MyCommentCafeResponse.java +++ b/src/main/java/mocacong/server/dto/response/MyCommentCafeResponse.java @@ -1,6 +1,10 @@ package mocacong.server.dto.response; +import java.util.List; +import java.util.stream.Collectors; import lombok.*; +import mocacong.server.domain.Cafe; +import mocacong.server.domain.Comment; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -11,5 +15,12 @@ public class MyCommentCafeResponse { private String mapId; private String name; private String studyType; - private String comment; + private List comments; + + public static MyCommentCafeResponse of(Cafe cafe, List comments) { + List contents = comments.stream() + .map(Comment::getContent) + .collect(Collectors.toList()); + return new MyCommentCafeResponse(cafe.getMapId(), cafe.getName(), cafe.getStudyType(), contents); + } } diff --git a/src/main/java/mocacong/server/service/CafeService.java b/src/main/java/mocacong/server/service/CafeService.java index 2c1db50e..9433a9a6 100644 --- a/src/main/java/mocacong/server/service/CafeService.java +++ b/src/main/java/mocacong/server/service/CafeService.java @@ -169,17 +169,32 @@ public MyReviewCafesResponse findMyReviewCafes(Long memberId, Integer page, int public MyCommentCafesResponse findMyCommentCafes(Long memberId, int page, int count) { Member member = memberRepository.findById(memberId) .orElseThrow(NotFoundMemberException::new); - Slice comments = commentRepository.findByMemberId(member.getId(), PageRequest.of(page, count)); + List comments = commentRepository.findAllByMemberId(member.getId()); List responses = comments.stream() - .map(comment -> new MyCommentCafeResponse( - comment.getCafe().getMapId(), - comment.getCafe().getName(), - comment.getCafe().getStudyType(), - comment.getContent() - )) + .collect(Collectors.groupingByConcurrent(Comment::getCafe)) + .entrySet() + .stream() + .map(commentsGroupingByCafe -> + MyCommentCafeResponse.of(commentsGroupingByCafe.getKey(), commentsGroupingByCafe.getValue())) .collect(Collectors.toList()); - return new MyCommentCafesResponse(comments.isLast(), responses); + + int toIndex = Math.min((page + 1) * count, responses.size()); + int fromIndex = Math.min(toIndex, page * count); + + return new MyCommentCafesResponse(findIsEnd(page, count, responses), responses.subList(fromIndex, toIndex)); + } + + /* + * TODO (23.11.11.) + * comments 를 Slice 로 받아온 후 grouping 할 경우 페이지네이션 시 count 보다 적은 데이터 수가 반환될 수 있음. + * 따라서 comments 전체를 받아온 후, mapId로 grouping 해야 한 후 페이지네이션해야 하므로 isLast 여부를 jpa Slice 로 구할 수 없음. + * + * 또한, 현재 mapId가 동일한 카페의 댓글 전체를 리스트로 반환하므로 API 스펙 협의 및 로직 개선 필요. + */ + private boolean findIsEnd(int page, int count, List responses) { + int lastDataIndex = (page + 1) * count - 1; + return responses.size() - 1 <= lastDataIndex; } @CacheEvict(key = "#mapId", value = "cafePreviewCache") diff --git a/src/test/java/mocacong/server/acceptance/MemberAcceptanceTest.java b/src/test/java/mocacong/server/acceptance/MemberAcceptanceTest.java index e9b38695..34feef91 100644 --- a/src/test/java/mocacong/server/acceptance/MemberAcceptanceTest.java +++ b/src/test/java/mocacong/server/acceptance/MemberAcceptanceTest.java @@ -397,7 +397,10 @@ void findMyCommentCafes() { .extract() .as(MyCommentCafesResponse.class); - assertThat(response.getCafes()).hasSize(3); + assertAll( + ()->assertThat(response.getCafes()).hasSize(2), + ()->assertThat(response.getCafes().get(0).getComments()).containsExactlyInAnyOrder("댓글3") + ); } @Test diff --git a/src/test/java/mocacong/server/domain/CafeTest.java b/src/test/java/mocacong/server/domain/CafeTest.java index f0b6029a..fb27c11f 100644 --- a/src/test/java/mocacong/server/domain/CafeTest.java +++ b/src/test/java/mocacong/server/domain/CafeTest.java @@ -8,6 +8,16 @@ class CafeTest { + @Test + @DisplayName("카페 mapId가 같으면 동일 카페로 간주한다") + void equals() { + String cafeMapId = "12345"; + Cafe cafe1 = new Cafe(cafeMapId, "케이카페"); + Cafe cafe2 = new Cafe(cafeMapId, "이름만다른케이카페"); + + assertThat(cafe1.equals(cafe2)).isTrue(); + } + @Test @DisplayName("카페에 평점을 기여한 사람이 없으면 0점을 반환한다") void findScoreWithNoReviews() { diff --git a/src/test/java/mocacong/server/service/CafeServiceTest.java b/src/test/java/mocacong/server/service/CafeServiceTest.java index 2016e7c2..8263bad3 100644 --- a/src/test/java/mocacong/server/service/CafeServiceTest.java +++ b/src/test/java/mocacong/server/service/CafeServiceTest.java @@ -487,14 +487,14 @@ void findMyCommentCafes() { commentRepository.save(new Comment(cafe2, member1, "댓글3")); commentRepository.save(new Comment(cafe2, member2, "댓글4")); - MyCommentCafesResponse actual = cafeService.findMyCommentCafes(member1.getId(), 0, 5); + MyCommentCafesResponse actual = cafeService.findMyCommentCafes(member1.getId(), 0, 3); assertAll( () -> assertThat(actual.getIsEnd()).isTrue(), - () -> assertThat(actual.getCafes()).hasSize(3), - () -> assertThat(actual.getCafes().get(0).getComment()).isEqualTo("댓글1"), - () -> assertThat(actual.getCafes().get(1).getComment()).isEqualTo("댓글2"), - () -> assertThat(actual.getCafes().get(2).getComment()).isEqualTo("댓글3") + // 댓글 수는 3개지만, 카페 종류가 2종류이므로 response size는 2개 + () -> assertThat(actual.getCafes()).hasSize(2), + () -> assertThat(actual.getCafes().get(0).getComments()).containsExactlyInAnyOrder("댓글1", "댓글2"), + () -> assertThat(actual.getCafes().get(1).getComments()).containsExactlyInAnyOrder("댓글3") ); }