Skip to content

Commit

Permalink
공지사항 댓글 & 답글 CRUD (#91)
Browse files Browse the repository at this point in the history
* Feat[#90] : comment CRUD

* Refactor[#90] : Patch url 수정

---------

Co-authored-by: Menhez Team <[email protected]>
  • Loading branch information
JaeyoungChoi98 and Menhez Team committed May 24, 2024
1 parent 244938b commit 1acc011
Show file tree
Hide file tree
Showing 11 changed files with 387 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.sideteam.groupsaver.domain.club.controller;

import com.sideteam.groupsaver.domain.club.dto.request.CommentRequest;
import com.sideteam.groupsaver.domain.club.dto.response.CommentResponse;
import com.sideteam.groupsaver.domain.club.service.CommentService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/clubs/noti/comment")
public class CommentController {
private final CommentService commentService;

@GetMapping
public ResponseEntity<List<CommentResponse>> getComments(@RequestBody CommentRequest request) {
return ResponseEntity.ok(commentService.getComments(request));
}

@PostMapping
public ResponseEntity<String> createComment(@RequestBody CommentRequest request) {
commentService.createComment(request);
return ResponseEntity.ok("OK");
}

@PostMapping("/reply")
public ResponseEntity<String> createReply(@RequestBody CommentRequest request) {
commentService.createReply(request);
return ResponseEntity.ok("OK");
}

@PatchMapping
public ResponseEntity<String> updateComment(@RequestBody CommentRequest request) {
commentService.update(request);
return ResponseEntity.ok("OK");
}

@DeleteMapping
public ResponseEntity<String> deleteComment(@RequestBody CommentRequest request) {
commentService.delete(request);
return ResponseEntity.ok("OK");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.sideteam.groupsaver.domain.club.domain;

import com.sideteam.groupsaver.domain.common.BaseEntity;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PublicNotiComment extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String text;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "publicNotification_Id")
private PublicNotification publicNotification;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "publicNotiComment_Id")
private PublicNotiComment publicNotiComment;
@OneToMany(mappedBy = "publicNotiComment", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<PublicNotiComment> replyList = new ArrayList<>();

@Builder
public PublicNotiComment(String text, PublicNotification publicNotification, PublicNotiComment publicNotiComment) {
this.text = text;
this.publicNotification = publicNotification;
this.publicNotiComment = publicNotiComment;
}

public static PublicNotiComment of(String text, PublicNotification publicNotification, PublicNotiComment publicNotiComment) {
return PublicNotiComment.builder()
.text(text)
.publicNotification(publicNotification)
.publicNotiComment(publicNotiComment)
.build();
}

public void updateText(String text) {
this.text = text;
}

public void addReply(PublicNotiComment reply) {
this.replyList.add(reply);
}

public void deleteText() {
this.text = "삭제된 댓글입니다";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand All @@ -20,6 +23,8 @@ public class PublicNotification extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "club_id")
private Club club;
@OneToMany(mappedBy = "publicNotification", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<PublicNotiComment> commentList = new ArrayList<>();

@Builder
public PublicNotification(String title, String body, boolean fix, Club club) {
Expand All @@ -45,4 +50,8 @@ public void updateFix() {
this.fix = false;
}
}

public void addComment(PublicNotiComment publicNotiComment) {
this.commentList.add(publicNotiComment);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sideteam.groupsaver.domain.club.domain;

import com.sideteam.groupsaver.domain.club.dto.response.CommentResponse;
import lombok.Builder;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

import java.util.List;

@RedisHash(value = "club_noti_comment")
@Getter
public class RedisComment {
@Id
private long publicNotificationId;
private List<CommentResponse> commentResponses;

@Builder
private RedisComment(long publicNotificationId, List<CommentResponse> commentResponses) {
this.publicNotificationId = publicNotificationId;
this.commentResponses = commentResponses;
}

public static RedisComment of(long publicNotificationId, List<CommentResponse> commentResponses) {
return RedisComment.builder()
.publicNotificationId(publicNotificationId)
.commentResponses(commentResponses)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.sideteam.groupsaver.domain.club.dto.request;

import lombok.Getter;

@Getter
public class CommentRequest {
private long publicId;
private long commentId;
private String text;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.sideteam.groupsaver.domain.club.dto.response;

import com.sideteam.groupsaver.domain.club.domain.PublicNotiComment;
import com.sideteam.groupsaver.global.util.ProjectTimeFormat;
import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Getter
public class CommentResponse {
private long commentId;
private long memberId;
private String profileUrl;
private String nickname;
private String text;
private LocalDateTime time;
private boolean me;
private List<CommentResponse> replyList = new ArrayList<>();

@Builder
private CommentResponse(long commentId, long memberId, String profileUrl, String nickname, String text, LocalDateTime time, boolean me) {
this.commentId = commentId;
this.memberId = memberId;
this.profileUrl = profileUrl;
this.nickname = nickname;
this.text = text;
this.time = time;
this.me = me;
}

public static CommentResponse of(long commentId, long memberId,String profileUrl, String nickname, String text, LocalDateTime time) {
return CommentResponse.builder()
.commentId(commentId)
.memberId(memberId)
.profileUrl(profileUrl)
.nickname(nickname)
.text(text)
.time(time)
.me(false)
.build();
}

public void update(PublicNotiComment comment) {
this.profileUrl = comment.getCreator().getProfileUrl();
this.nickname = comment.getCreator().getNickname();
this.text = comment.getText();
this.time = LocalDateTime.ofInstant(comment.getUpdateAt(), ProjectTimeFormat.SERVER_ZONE_ID);
}

public void isMe(boolean isMe) {
this.me = isMe;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.sideteam.groupsaver.domain.club.repository;

import com.sideteam.groupsaver.domain.club.domain.PublicNotiComment;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PublicNotiCommentRepository extends JpaRepository<PublicNotiComment, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.sideteam.groupsaver.domain.club.repository;

import com.sideteam.groupsaver.domain.club.domain.RedisComment;
import org.springframework.data.repository.CrudRepository;

public interface RedisCommentRepository extends CrudRepository<RedisComment, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.sideteam.groupsaver.domain.club.service;

import com.sideteam.groupsaver.domain.club.domain.PublicNotiComment;
import com.sideteam.groupsaver.domain.club.domain.PublicNotification;
import com.sideteam.groupsaver.domain.club.dto.request.CommentRequest;
import com.sideteam.groupsaver.domain.club.dto.response.CommentResponse;
import com.sideteam.groupsaver.domain.club.repository.PublicNotiCommentRepository;
import com.sideteam.groupsaver.domain.club.repository.PublicNotificationRepository;
import com.sideteam.groupsaver.domain.club.repository.RedisCommentRepository;
import com.sideteam.groupsaver.global.auth.userdetails.GetAuthUserUtils;
import com.sideteam.groupsaver.global.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.sideteam.groupsaver.global.exception.member.MemberErrorCode.DO_NOT_HAVE_PERMISSION;

@Service
@RequiredArgsConstructor
@Transactional
public class CommentService {
private final PublicNotificationRepository publicNotificationRepository;
private final PublicNotiCommentRepository commentRepository;
private final RedisCommentRepository redisCommentRepository;
private final RedisCommentService redisCommentService;

public void createComment(CommentRequest request) {
PublicNotification publicNotification = publicNotificationRepository.findById(request.getPublicId()).orElseThrow(IllegalArgumentException::new);
PublicNotiComment comment = PublicNotiComment.of(request.getText(), publicNotification, null);
publicNotification.addComment(comment);
commentRepository.save(comment);
redisCommentService.createRedisComments(comment);
}

public void update(CommentRequest request) {
PublicNotiComment comment = commentRepository.findById(request.getCommentId()).orElseThrow(IllegalArgumentException::new);
checkIsMe(comment.getCreator().getId());
comment.updateText(request.getText());
redisCommentService.updateComment(comment);
}

public void delete(CommentRequest request) {
PublicNotiComment comment = commentRepository.findById(request.getCommentId()).orElseThrow(IllegalArgumentException::new);
checkIsMe(comment.getCreator().getId());
comment.deleteText();
redisCommentService.updateComment(comment);
}

private void checkIsMe(long memberId) {
if(!Objects.equals(memberId, GetAuthUserUtils.getAuthUserId())) {
throw new BusinessException(DO_NOT_HAVE_PERMISSION, DO_NOT_HAVE_PERMISSION.getDetail());
}
}

@Transactional(readOnly = true)
public List<CommentResponse> getComments(CommentRequest request) {
return redisCommentRepository.findById(request.getPublicId()).orElseThrow(IllegalArgumentException::new)
.getCommentResponses()
.stream()
.map(this::isMe)
.collect(Collectors.toList());
}

private CommentResponse isMe(CommentResponse response) {
long currentMember = GetAuthUserUtils.getAuthUserId();
response.isMe(response.getMemberId() == currentMember);
response.getReplyList().forEach(reply -> reply.isMe(reply.getMemberId() == currentMember));
return response;
}

public void createReply(CommentRequest request) {
PublicNotiComment comment = commentRepository.findById(request.getCommentId()).orElseThrow(IllegalArgumentException::new);
PublicNotiComment reply = PublicNotiComment.of(request.getText(), comment.getPublicNotification(), comment);
comment.addReply(reply);
comment.getPublicNotification().addComment(reply);
commentRepository.save(reply);
redisCommentService.createReply(reply);
}
}
Loading

0 comments on commit 1acc011

Please sign in to comment.