From dd0179a66360f45e9bbb1ca11d5c7550b6549878 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Sat, 16 Mar 2024 17:18:18 +0900 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20HTTP=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EA=B0=80=20GET=EC=9D=B8=20=EB=8C=93=EA=B8=80=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=AA=A8=EB=93=A0=20URL=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/balancetalk/global/config/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/balancetalk/global/config/SecurityConfig.java b/src/main/java/balancetalk/global/config/SecurityConfig.java index c006ffe8d..e2588616a 100644 --- a/src/main/java/balancetalk/global/config/SecurityConfig.java +++ b/src/main/java/balancetalk/global/config/SecurityConfig.java @@ -32,7 +32,7 @@ public class SecurityConfig { // swagger "/swagger-ui/**", "/v3/api-docs/**", "/members/duplicate", - "/posts", "/posts/{postId}", "/posts/{postId}/vote", "/posts/{postId}/comments", + "/posts", "/posts/{postId}", "/posts/{postId}/vote", "/posts/{postId}/comments/**", "/notices", "/notices/{noticeId}" }; From c1473fc4894664c4f0eb445b048f6a41b6f68e2b Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Sat, 16 Mar 2024 17:18:48 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=EC=9D=B8=EA=B8=B0=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=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 26 +++++++++++++++++++ .../comment/domain/CommentRepository.java | 14 ++++++++++ .../presentation/CommentController.java | 8 ++++++ .../member/domain/MemberRepository.java | 6 +++++ 4 files changed, 54 insertions(+) diff --git a/src/main/java/balancetalk/module/comment/application/CommentService.java b/src/main/java/balancetalk/module/comment/application/CommentService.java index 6505ef8d2..980770f34 100644 --- a/src/main/java/balancetalk/module/comment/application/CommentService.java +++ b/src/main/java/balancetalk/module/comment/application/CommentService.java @@ -16,9 +16,12 @@ import balancetalk.module.post.domain.PostRepository; import balancetalk.module.vote.domain.Vote; import balancetalk.module.vote.domain.VoteRepository; +import java.util.ArrayList; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +35,9 @@ @RequiredArgsConstructor public class CommentService { + private static final int BEST_COMMENTS_SIZE = 3; + private static final int MIN_COUNT_FOR_BEST_COMMENT = 15; + private final CommentRepository commentRepository; private final MemberRepository memberRepository; private final PostRepository postRepository; @@ -180,4 +186,24 @@ public void cancelLikeComment(Long commentId) { commentLikeRepository.deleteByMemberAndComment(member, comment); } + + @Transactional(readOnly = true) + public List findBestComments(Long postId) { + Post post = validatePostId(postId); + List options = post.getOptions(); + + List responses = new ArrayList<>(); + for (BalanceOption option : options) { + List memberIdsBySelectedOptionId = + memberRepository.findMemberIdsBySelectedOptionId(option.getId()); + + List bestComments = commentRepository.findBestCommentsByPostId(postId, + memberIdsBySelectedOptionId, MIN_COUNT_FOR_BEST_COMMENT, PageRequest.of(0, BEST_COMMENTS_SIZE)); + + responses.addAll(bestComments.stream() + .map(comment -> CommentResponse.fromEntity(comment, option.getId())).toList()); + } + + return responses; + } } diff --git a/src/main/java/balancetalk/module/comment/domain/CommentRepository.java b/src/main/java/balancetalk/module/comment/domain/CommentRepository.java index 51d0fba38..2757fc451 100644 --- a/src/main/java/balancetalk/module/comment/domain/CommentRepository.java +++ b/src/main/java/balancetalk/module/comment/domain/CommentRepository.java @@ -1,9 +1,23 @@ package balancetalk.module.comment.domain; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface CommentRepository extends JpaRepository { Page findAllByPostId(Long postId, Pageable pageable); + + @Query("select c " + + "from Comment c left join c.likes l " + + "where c.post.id = :postId and c.member.id in :memberIds " + + "group by c.id " + + "having count(l) >= :minCountForBest " + + "order by count(l) desc") + List findBestCommentsByPostId(@Param("postId") Long postId, + @Param("memberIds") List memberIds, + @Param("minCountForBest") int minCountForBest, + Pageable pageable); } diff --git a/src/main/java/balancetalk/module/comment/presentation/CommentController.java b/src/main/java/balancetalk/module/comment/presentation/CommentController.java index e02813f86..d4917bd3d 100644 --- a/src/main/java/balancetalk/module/comment/presentation/CommentController.java +++ b/src/main/java/balancetalk/module/comment/presentation/CommentController.java @@ -6,6 +6,7 @@ import balancetalk.module.comment.dto.ReplyCreateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -35,6 +36,13 @@ public Page findAllCommentsByPostId(@PathVariable Long postId, return commentService.findAllComments(postId, pageable); } + @ResponseStatus(HttpStatus.OK) + @GetMapping("/best") + @Operation(summary = "인기 댓글 조회", description = "추천 수가 가장 많은 댓글을 각 선택지별로 3개씩 조회한다.") + public List findBestComments(@PathVariable Long postId) { + return commentService.findBestComments(postId); + } + @ResponseStatus(HttpStatus.OK) @PutMapping("/{commentId}") @Operation(summary = "댓글 수정", description = "comment-id에 해당하는 댓글 내용을 수정한다.") diff --git a/src/main/java/balancetalk/module/member/domain/MemberRepository.java b/src/main/java/balancetalk/module/member/domain/MemberRepository.java index adc3ed057..619204fd4 100644 --- a/src/main/java/balancetalk/module/member/domain/MemberRepository.java +++ b/src/main/java/balancetalk/module/member/domain/MemberRepository.java @@ -1,10 +1,16 @@ package balancetalk.module.member.domain; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; +import org.springframework.data.jpa.repository.Query; + public interface MemberRepository extends JpaRepository { Optional findByEmail(String username); boolean existsByNickname(String nickname); boolean existsByEmail(String email); void deleteByEmail(String email); + + @Query("select m.id from Member m JOIN m.votes v WHERE v.balanceOption.id = :balanceOptionId") + List findMemberIdsBySelectedOptionId(Long balanceOptionId); } From 03c2fda1476f79b6f292518ce21f4386dc9f3649 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Sat, 16 Mar 2024 20:10:39 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EB=B9=84=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B3=BC=20=ED=9A=8C=EC=9B=90=20=EA=B0=81=EA=B0=81=EC=9D=98=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=EB=B6=84,=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20DTO=EC=97=90=20myLike=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 28 ++++++++++++++----- .../module/comment/domain/CommentLike.java | 2 ++ .../comment/domain/CommentRepository.java | 3 +- .../module/comment/dto/CommentResponse.java | 6 +++- .../presentation/CommentController.java | 10 ++++--- .../module/member/domain/Member.java | 5 ++++ 6 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/main/java/balancetalk/module/comment/application/CommentService.java b/src/main/java/balancetalk/module/comment/application/CommentService.java index 980770f34..f26fc1226 100644 --- a/src/main/java/balancetalk/module/comment/application/CommentService.java +++ b/src/main/java/balancetalk/module/comment/application/CommentService.java @@ -2,6 +2,7 @@ import balancetalk.global.exception.BalanceTalkException; import balancetalk.global.exception.ErrorCode; +import balancetalk.global.utils.SecurityUtils; import balancetalk.module.comment.domain.Comment; import balancetalk.module.comment.domain.CommentLike; import balancetalk.module.comment.domain.CommentLikeRepository; @@ -59,7 +60,7 @@ public Comment createComment(CommentRequest request, Long postId) { } @Transactional(readOnly = true) - public Page findAllComments(Long postId, Pageable pageable) { + public Page findAllComments(Long postId, String token, Pageable pageable) { validatePostId(postId); Page comments = commentRepository.findAllByPostId(postId, pageable); @@ -71,7 +72,12 @@ public Page findAllComments(Long postId, Pageable pageable) { Long balanceOptionId = voteForComment.map(Vote::getBalanceOption).map(BalanceOption::getId) .orElseThrow(() -> new BalanceTalkException(NOT_FOUND_BALANCE_OPTION)); - return CommentResponse.fromEntity(comment, balanceOptionId); + if (token == null) { + return CommentResponse.fromEntity(comment, balanceOptionId, false); + } else { + Member member = getCurrentMember(memberRepository); + return CommentResponse.fromEntity(comment, balanceOptionId, member.hasLikedComment(comment)); + } }); } @@ -188,7 +194,7 @@ public void cancelLikeComment(Long commentId) { } @Transactional(readOnly = true) - public List findBestComments(Long postId) { + public List findBestComments(Long postId, String token) { Post post = validatePostId(postId); List options = post.getOptions(); @@ -198,10 +204,18 @@ public List findBestComments(Long postId) { memberRepository.findMemberIdsBySelectedOptionId(option.getId()); List bestComments = commentRepository.findBestCommentsByPostId(postId, - memberIdsBySelectedOptionId, MIN_COUNT_FOR_BEST_COMMENT, PageRequest.of(0, BEST_COMMENTS_SIZE)); - - responses.addAll(bestComments.stream() - .map(comment -> CommentResponse.fromEntity(comment, option.getId())).toList()); + memberIdsBySelectedOptionId, 2, PageRequest.of(0, BEST_COMMENTS_SIZE)); + + if (token == null) { + responses.addAll(bestComments.stream() + .map(comment -> CommentResponse.fromEntity(comment, option.getId(), false)).toList()); + } else { + Member member = getCurrentMember(memberRepository); + responses.addAll(bestComments.stream() + .map(comment -> + CommentResponse.fromEntity(comment, option.getId(), member.hasLikedComment(comment))) + .toList()); + } } return responses; diff --git a/src/main/java/balancetalk/module/comment/domain/CommentLike.java b/src/main/java/balancetalk/module/comment/domain/CommentLike.java index b926218b9..a6aecabd2 100644 --- a/src/main/java/balancetalk/module/comment/domain/CommentLike.java +++ b/src/main/java/balancetalk/module/comment/domain/CommentLike.java @@ -5,9 +5,11 @@ import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.Getter; import lombok.NoArgsConstructor; @Entity +@Getter @Builder @AllArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/balancetalk/module/comment/domain/CommentRepository.java b/src/main/java/balancetalk/module/comment/domain/CommentRepository.java index 2757fc451..eeb27e070 100644 --- a/src/main/java/balancetalk/module/comment/domain/CommentRepository.java +++ b/src/main/java/balancetalk/module/comment/domain/CommentRepository.java @@ -10,8 +10,7 @@ public interface CommentRepository extends JpaRepository { Page findAllByPostId(Long postId, Pageable pageable); - @Query("select c " - + "from Comment c left join c.likes l " + @Query("select c from Comment c left join c.likes l " + "where c.post.id = :postId and c.member.id in :memberIds " + "group by c.id " + "having count(l) >= :minCountForBest " diff --git a/src/main/java/balancetalk/module/comment/dto/CommentResponse.java b/src/main/java/balancetalk/module/comment/dto/CommentResponse.java index ef19e2d2f..d3174fb91 100644 --- a/src/main/java/balancetalk/module/comment/dto/CommentResponse.java +++ b/src/main/java/balancetalk/module/comment/dto/CommentResponse.java @@ -31,13 +31,16 @@ public class CommentResponse { @Schema(description = "댓글 추천 수", example = "24") private int likesCount; + @Schema(description = "추천 여부", example = "true") + private boolean myLike; + @Schema(description = "댓글 생성 날짜") private LocalDateTime createdAt; @Schema(description = "댓글 수정 날짜") private LocalDateTime lastModifiedAt; - public static CommentResponse fromEntity(Comment comment, Long balanceOptionId) { + public static CommentResponse fromEntity(Comment comment, Long balanceOptionId, boolean myLike) { return CommentResponse.builder() .id(comment.getId()) .content(comment.getContent()) @@ -45,6 +48,7 @@ public static CommentResponse fromEntity(Comment comment, Long balanceOptionId) .postId(comment.getPost().getId()) .selectedOptionId(balanceOptionId) .likesCount(comment.getLikes().size()) + .myLike(myLike) .createdAt(comment.getCreatedAt()) .lastModifiedAt(comment.getLastModifiedAt()) .build(); diff --git a/src/main/java/balancetalk/module/comment/presentation/CommentController.java b/src/main/java/balancetalk/module/comment/presentation/CommentController.java index d4917bd3d..736993cf4 100644 --- a/src/main/java/balancetalk/module/comment/presentation/CommentController.java +++ b/src/main/java/balancetalk/module/comment/presentation/CommentController.java @@ -32,15 +32,17 @@ public String createComment(@PathVariable Long postId, @RequestBody CommentReque @ResponseStatus(HttpStatus.OK) @GetMapping @Operation(summary = "댓글 목록 조회", description = "post-id에 해당하는 게시글에 있는 모든 댓글을 조회한다.") - public Page findAllCommentsByPostId(@PathVariable Long postId, Pageable pageable) { - return commentService.findAllComments(postId, pageable); + public Page findAllCommentsByPostId(@PathVariable Long postId, Pageable pageable, + @RequestHeader(value = "Authorization", required = false) String token) { + return commentService.findAllComments(postId, token, pageable); } @ResponseStatus(HttpStatus.OK) @GetMapping("/best") @Operation(summary = "인기 댓글 조회", description = "추천 수가 가장 많은 댓글을 각 선택지별로 3개씩 조회한다.") - public List findBestComments(@PathVariable Long postId) { - return commentService.findBestComments(postId); + public List findBestComments(@PathVariable Long postId, + @RequestHeader(value = "Authorization", required = false) String token) { + return commentService.findBestComments(postId, token); } @ResponseStatus(HttpStatus.OK) diff --git a/src/main/java/balancetalk/module/member/domain/Member.java b/src/main/java/balancetalk/module/member/domain/Member.java index 1c8162277..3f6b61e75 100644 --- a/src/main/java/balancetalk/module/member/domain/Member.java +++ b/src/main/java/balancetalk/module/member/domain/Member.java @@ -140,4 +140,9 @@ public boolean hasLiked(Post post) { return postLikes.stream() .anyMatch(like -> like.getPost().equals(post)); } + + public boolean hasLikedComment(Comment comment) { + return commentLikes.stream() + .anyMatch(like -> like.getComment().equals(comment)); + } } From bea124b8829e93ae4ac89c9637960b1aa6a88e30 Mon Sep 17 00:00:00 2001 From: Hanjaemo Date: Sat, 16 Mar 2024 23:36:56 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor:=20api=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8D=98=20=EB=A7=A4=EC=A7=81=20=EB=84=98=EB=B2=84?= =?UTF-8?q?=EB=A5=BC=20=EC=83=81=EC=88=98=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../balancetalk/module/comment/application/CommentService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/balancetalk/module/comment/application/CommentService.java b/src/main/java/balancetalk/module/comment/application/CommentService.java index f26fc1226..bb82ab685 100644 --- a/src/main/java/balancetalk/module/comment/application/CommentService.java +++ b/src/main/java/balancetalk/module/comment/application/CommentService.java @@ -2,7 +2,6 @@ import balancetalk.global.exception.BalanceTalkException; import balancetalk.global.exception.ErrorCode; -import balancetalk.global.utils.SecurityUtils; import balancetalk.module.comment.domain.Comment; import balancetalk.module.comment.domain.CommentLike; import balancetalk.module.comment.domain.CommentLikeRepository; @@ -204,7 +203,7 @@ public List findBestComments(Long postId, String token) { memberRepository.findMemberIdsBySelectedOptionId(option.getId()); List bestComments = commentRepository.findBestCommentsByPostId(postId, - memberIdsBySelectedOptionId, 2, PageRequest.of(0, BEST_COMMENTS_SIZE)); + memberIdsBySelectedOptionId, MIN_COUNT_FOR_BEST_COMMENT, PageRequest.of(0, BEST_COMMENTS_SIZE)); if (token == null) { responses.addAll(bestComments.stream()