From a4d99341a5e0ca35d5e37fce457645a6d5cb083a Mon Sep 17 00:00:00 2001 From: Ji Ho June <129824629+ho0010@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:56:59 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat:=20debate=EC=97=90=20user=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/itpick/backend/dto/debate/PostDebateRequest.java | 3 +++ src/main/java/store/itpick/backend/model/Debate.java | 4 ++++ src/main/java/store/itpick/backend/model/User.java | 3 +++ .../java/store/itpick/backend/service/DebateService.java | 6 +++++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/store/itpick/backend/dto/debate/PostDebateRequest.java b/src/main/java/store/itpick/backend/dto/debate/PostDebateRequest.java index 8cf2c0a..095040d 100644 --- a/src/main/java/store/itpick/backend/dto/debate/PostDebateRequest.java +++ b/src/main/java/store/itpick/backend/dto/debate/PostDebateRequest.java @@ -15,6 +15,9 @@ @Builder public class PostDebateRequest { + @NotNull(message = "user ID는 필수입니다.") + private Long userId; + @NotNull(message = "keyword ID는 필수입니다.") private Long keywordId; diff --git a/src/main/java/store/itpick/backend/model/Debate.java b/src/main/java/store/itpick/backend/model/Debate.java index 3cb2857..ab7ff34 100644 --- a/src/main/java/store/itpick/backend/model/Debate.java +++ b/src/main/java/store/itpick/backend/model/Debate.java @@ -50,4 +50,8 @@ public class Debate { @ManyToOne @JoinColumn(name = "keyword_id", nullable = false) private Keyword keyword; + + @ManyToOne + @JoinColumn(name = "user_id",nullable = false) + private User user; } diff --git a/src/main/java/store/itpick/backend/model/User.java b/src/main/java/store/itpick/backend/model/User.java index adb0ca9..995fac5 100644 --- a/src/main/java/store/itpick/backend/model/User.java +++ b/src/main/java/store/itpick/backend/model/User.java @@ -66,4 +66,7 @@ public class User { @OneToMany(mappedBy = "user") private List userVoteChoices; + + @OneToMany(mappedBy = "user") + private List debates; } diff --git a/src/main/java/store/itpick/backend/service/DebateService.java b/src/main/java/store/itpick/backend/service/DebateService.java index efa2e51..15a9081 100644 --- a/src/main/java/store/itpick/backend/service/DebateService.java +++ b/src/main/java/store/itpick/backend/service/DebateService.java @@ -6,6 +6,7 @@ import org.springframework.stereotype.Service; import store.itpick.backend.common.exception.DebateException; import store.itpick.backend.common.exception.AuthException; +import store.itpick.backend.common.exception.UserException; import store.itpick.backend.dto.debate.*; import store.itpick.backend.dto.vote.PostVoteRequest; import store.itpick.backend.jwt.JwtProvider; @@ -34,10 +35,13 @@ public class DebateService { @Transactional public PostDebateResponse createDebate(PostDebateRequest postDebateRequest) { + User user = userRepository.findById(postDebateRequest.getUserId()) + .orElseThrow(() -> new UserException(USER_NOT_FOUND)); + Keyword keyword = keywordRepository.findById(postDebateRequest.getKeywordId()) .orElseThrow(() -> new DebateException(KEYWORD_NOT_FOUND)); - Debate debate = Debate.builder().title(postDebateRequest.getTitle()).content(postDebateRequest.getContent()).hits(0L).onTrend(false).status("active").createAt(Timestamp.valueOf(LocalDateTime.now())).updateAt(Timestamp.valueOf(LocalDateTime.now())).keyword(keyword).build(); + Debate debate = Debate.builder().title(postDebateRequest.getTitle()).content(postDebateRequest.getContent()).hits(0L).onTrend(false).status("active").createAt(Timestamp.valueOf(LocalDateTime.now())).updateAt(Timestamp.valueOf(LocalDateTime.now())).keyword(keyword).user(user).build(); debate = debateRepository.save(debate); From fd517a8deec479f1e4c91b7c4d7bb675a00afa98 Mon Sep 17 00:00:00 2001 From: Ji Ho June <129824629+ho0010@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:39:18 +0900 Subject: [PATCH 2/3] Feat: getDebate API --- .../backend/controller/DebateController.java | 11 +++ .../backend/dto/debate/GetDebateRequest.java | 20 +++++ .../backend/dto/debate/GetDebateResponse.java | 56 ++++++++++++++ .../store/itpick/backend/jwt/JwtProvider.java | 2 + .../repository/CommentHeartRepository.java | 1 + .../backend/repository/CommentRepository.java | 4 + .../repository/VoteOptionRepository.java | 3 + .../itpick/backend/service/DebateService.java | 76 +++++++++++++++++++ 8 files changed, 173 insertions(+) create mode 100644 src/main/java/store/itpick/backend/dto/debate/GetDebateRequest.java create mode 100644 src/main/java/store/itpick/backend/dto/debate/GetDebateResponse.java diff --git a/src/main/java/store/itpick/backend/controller/DebateController.java b/src/main/java/store/itpick/backend/controller/DebateController.java index fc723b8..568b5d1 100644 --- a/src/main/java/store/itpick/backend/controller/DebateController.java +++ b/src/main/java/store/itpick/backend/controller/DebateController.java @@ -78,4 +78,15 @@ public BaseResponse deleteUserVoteChoice(@Valid @RequestBody DeleteUserV voteService.deleteUserVoteChoice(deleteUserVoteChoiceRequest); return new BaseResponse<>(HttpStatus.OK); } + + @GetMapping("/details") + public BaseResponse getDebate( + @RequestParam Long debateId, + @RequestHeader("Authorization") String token) { + + String jwtToken = token.substring(7); + + GetDebateResponse debateResponse = debateService.getDebate(debateId, jwtToken); + return new BaseResponse<>(debateResponse); + } } diff --git a/src/main/java/store/itpick/backend/dto/debate/GetDebateRequest.java b/src/main/java/store/itpick/backend/dto/debate/GetDebateRequest.java new file mode 100644 index 0000000..a816568 --- /dev/null +++ b/src/main/java/store/itpick/backend/dto/debate/GetDebateRequest.java @@ -0,0 +1,20 @@ +package store.itpick.backend.dto.debate; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class GetDebateRequest { + + @NotNull(message = "User ID는 필수입니다.") + private Long userId; + + @NotNull(message = "Debate ID는 필수입니다.") + private Long debateId; +} \ No newline at end of file diff --git a/src/main/java/store/itpick/backend/dto/debate/GetDebateResponse.java b/src/main/java/store/itpick/backend/dto/debate/GetDebateResponse.java new file mode 100644 index 0000000..e1e9970 --- /dev/null +++ b/src/main/java/store/itpick/backend/dto/debate/GetDebateResponse.java @@ -0,0 +1,56 @@ +package store.itpick.backend.dto.debate; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.sql.Timestamp; +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GetDebateResponse { + + private Long debateId; + private String title; + private String content; + private Long hits; + private boolean onTrend; + private String status; + private Timestamp createAt; + private Timestamp updateAt; + private String keyword; + private String userNickname; + private String userImgUrl; + private List voteOptions; + private List comments; + private boolean userVoted; + private String userVoteOptionText; + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class VoteOptionResponse { + private String optionText; + private String imgUrl; + private long voteCount; + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class CommentResponse { + private Long commentId; + private String commentText; + private String userNickname; + private String userImgUrl; + private Timestamp createAt; + private long commentHeartCount; + private boolean userHearted; + } +} diff --git a/src/main/java/store/itpick/backend/jwt/JwtProvider.java b/src/main/java/store/itpick/backend/jwt/JwtProvider.java index 7b0dac3..b46ac29 100644 --- a/src/main/java/store/itpick/backend/jwt/JwtProvider.java +++ b/src/main/java/store/itpick/backend/jwt/JwtProvider.java @@ -120,4 +120,6 @@ public Long getUserIdFromToken(String token){ return claims.get("userId", Long.class); } + + } diff --git a/src/main/java/store/itpick/backend/repository/CommentHeartRepository.java b/src/main/java/store/itpick/backend/repository/CommentHeartRepository.java index 03b54e7..5d598d4 100644 --- a/src/main/java/store/itpick/backend/repository/CommentHeartRepository.java +++ b/src/main/java/store/itpick/backend/repository/CommentHeartRepository.java @@ -11,4 +11,5 @@ @Repository public interface CommentHeartRepository extends JpaRepository { CommentHeart findByUserAndComment(User user, Comment comment); + boolean existsByCommentAndUser_userId(Comment comment, Long userId); } \ No newline at end of file diff --git a/src/main/java/store/itpick/backend/repository/CommentRepository.java b/src/main/java/store/itpick/backend/repository/CommentRepository.java index b088c8b..d2b732f 100644 --- a/src/main/java/store/itpick/backend/repository/CommentRepository.java +++ b/src/main/java/store/itpick/backend/repository/CommentRepository.java @@ -3,7 +3,11 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import store.itpick.backend.model.Comment; +import store.itpick.backend.model.Debate; + +import java.util.List; @Repository public interface CommentRepository extends JpaRepository { + List findByDebate(Debate debate); } diff --git a/src/main/java/store/itpick/backend/repository/VoteOptionRepository.java b/src/main/java/store/itpick/backend/repository/VoteOptionRepository.java index 76e38d8..be4b374 100644 --- a/src/main/java/store/itpick/backend/repository/VoteOptionRepository.java +++ b/src/main/java/store/itpick/backend/repository/VoteOptionRepository.java @@ -5,6 +5,9 @@ import store.itpick.backend.model.Vote; import store.itpick.backend.model.VoteOption; +import java.util.List; + public interface VoteOptionRepository extends JpaRepository { + List findByVote(Vote vote); } diff --git a/src/main/java/store/itpick/backend/service/DebateService.java b/src/main/java/store/itpick/backend/service/DebateService.java index 15a9081..ab2c971 100644 --- a/src/main/java/store/itpick/backend/service/DebateService.java +++ b/src/main/java/store/itpick/backend/service/DebateService.java @@ -7,6 +7,8 @@ import store.itpick.backend.common.exception.DebateException; import store.itpick.backend.common.exception.AuthException; import store.itpick.backend.common.exception.UserException; +import store.itpick.backend.common.exception.jwt.unauthorized.JwtInvalidTokenException; +import store.itpick.backend.common.exception.jwt.unauthorized.JwtUnauthorizedTokenException; import store.itpick.backend.dto.debate.*; import store.itpick.backend.dto.vote.PostVoteRequest; import store.itpick.backend.jwt.JwtProvider; @@ -30,7 +32,10 @@ public class DebateService { private final CommentRepository commentRepository; private final CommentHeartRepository commentHeartRepository; private final UserRepository userRepository; + private final UserVoteChoiceRepository userVoteChoiceRepository; + private final VoteOptionRepository voteOptionRepository; private final VoteService voteService; + private final JwtProvider jwtProvider; @Transactional public PostDebateResponse createDebate(PostDebateRequest postDebateRequest) { @@ -120,4 +125,75 @@ public PostCommentHeartResponse creatCommentHeart(PostCommentHeartRequest postCo return new PostCommentHeartResponse(commentHeart.getCommentHeartId()); } } + + @Transactional + public GetDebateResponse getDebate(Long debateId, String token) { + + if (jwtProvider.isExpiredToken(token)) { + throw new JwtUnauthorizedTokenException(INVALID_TOKEN); + } + + Long userId = jwtProvider.getUserIdFromToken(token); + + Debate debate = debateRepository.findById(debateId) + .orElseThrow(() -> new DebateException(DEBATE_NOT_FOUND)); + + User user = debate.getUser(); + + boolean userVoted = false; + String userVoteOptionText = null; + + for (VoteOption voteOption : debate.getVote().getVoteOptions()) { + UserVoteChoice userVoteChoice = userVoteChoiceRepository.findByVoteOptionAndUser(voteOption, user); + if (userVoteChoice != null) { + userVoted = true; + userVoteOptionText = voteOption.getOptionText(); + break; + } + } + + List voteOptions = voteOptionRepository.findByVote(debate.getVote()).stream() + .map(option -> GetDebateResponse.VoteOptionResponse.builder() + .optionText(option.getOptionText()) + .imgUrl(option.getImgUrl()) + .voteCount(option.getUserVoteChoices().size()) + .build()) + .toList(); + + List comments = commentRepository.findByDebate(debate).stream() + .map(comment -> { + boolean userHearted = commentHeartRepository.existsByCommentAndUser_userId(comment, userId); + + return GetDebateResponse.CommentResponse.builder() + .commentId(comment.getCommentId()) + .commentText(comment.getComment()) + .userNickname(comment.getUser().getNickname()) + .userImgUrl(comment.getUser().getImageUrl()) + .createAt(comment.getCreateAt()) + .commentHeartCount(comment.getCommentHearts().size()) + .userHearted(userHearted) + .build(); + }) + .toList(); + + + return GetDebateResponse.builder() + .debateId(debate.getDebateId()) + .title(debate.getTitle()) + .content(debate.getContent()) + .hits(debate.getHits()) + .onTrend(debate.isOnTrend()) + .status(debate.getStatus()) + .createAt(debate.getCreateAt()) + .updateAt(debate.getUpdateAt()) + .keyword(debate.getKeyword().getKeyword()) + .userNickname(debate.getUser().getNickname()) + .userImgUrl(debate.getUser().getImageUrl()) + .voteOptions(voteOptions) + .comments(comments) + .userVoted(userVoted) + .userVoteOptionText(userVoteOptionText) + .build(); + } + } From 2202b93d2a7ccd77ecb1c4c32550e2b16f617641 Mon Sep 17 00:00:00 2001 From: Ji Ho June <129824629+ho0010@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:36:32 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Feat:=20getDebate=20API=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/status/BaseExceptionResponseStatus.java | 2 ++ .../store/itpick/backend/controller/DebateController.java | 8 +++++++- .../java/store/itpick/backend/service/DebateService.java | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/store/itpick/backend/common/response/status/BaseExceptionResponseStatus.java b/src/main/java/store/itpick/backend/common/response/status/BaseExceptionResponseStatus.java index 209c158..f789f88 100644 --- a/src/main/java/store/itpick/backend/common/response/status/BaseExceptionResponseStatus.java +++ b/src/main/java/store/itpick/backend/common/response/status/BaseExceptionResponseStatus.java @@ -71,6 +71,8 @@ public enum BaseExceptionResponseStatus implements ResponseStatus { INVALID_COMMENT_HEART_VALUE(6004,HttpStatus.BAD_REQUEST.value(), "댓글 좋아요 생성 요청에서 잘못된 값이 존재합니다."), COMMENT_NOT_FOUND(6005,HttpStatus.BAD_REQUEST.value(), "해당 댓글이 존재하지 않습니다."), KEYWORD_NOT_FOUND(6006,HttpStatus.BAD_REQUEST.value(), "해당 키워드가 존재하지 않습니다."), + INVALID_GET_DEBATE_VALUE(6007,HttpStatus.BAD_REQUEST.value(), "토론 상세 정보 요청에서 잘못된 값이 존재합니다."), + /** diff --git a/src/main/java/store/itpick/backend/controller/DebateController.java b/src/main/java/store/itpick/backend/controller/DebateController.java index 568b5d1..c1b3b0f 100644 --- a/src/main/java/store/itpick/backend/controller/DebateController.java +++ b/src/main/java/store/itpick/backend/controller/DebateController.java @@ -82,11 +82,17 @@ public BaseResponse deleteUserVoteChoice(@Valid @RequestBody DeleteUserV @GetMapping("/details") public BaseResponse getDebate( @RequestParam Long debateId, - @RequestHeader("Authorization") String token) { + @RequestHeader("Authorization") String token,BindingResult bindingResult) { String jwtToken = token.substring(7); + + if (bindingResult.hasErrors()) { + throw new DebateException(INVALID_GET_DEBATE_VALUE, getErrorMessages(bindingResult)); + } + GetDebateResponse debateResponse = debateService.getDebate(debateId, jwtToken); + return new BaseResponse<>(debateResponse); } } diff --git a/src/main/java/store/itpick/backend/service/DebateService.java b/src/main/java/store/itpick/backend/service/DebateService.java index ab2c971..8b85185 100644 --- a/src/main/java/store/itpick/backend/service/DebateService.java +++ b/src/main/java/store/itpick/backend/service/DebateService.java @@ -132,7 +132,7 @@ public GetDebateResponse getDebate(Long debateId, String token) { if (jwtProvider.isExpiredToken(token)) { throw new JwtUnauthorizedTokenException(INVALID_TOKEN); } - + Long userId = jwtProvider.getUserIdFromToken(token); Debate debate = debateRepository.findById(debateId)