Skip to content

Commit

Permalink
Merge pull request #169 from woowacourse-teams/feature/#151
Browse files Browse the repository at this point in the history
모임 댓글 기능 구현
  • Loading branch information
ay-eonii authored Aug 1, 2024
2 parents 7982f13 + 11e4ad9 commit d4ce086
Show file tree
Hide file tree
Showing 15 changed files with 397 additions and 7 deletions.
60 changes: 57 additions & 3 deletions backend/src/main/java/mouda/backend/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,88 @@
package mouda.backend.comment.domain;

import java.time.LocalDateTime;

import org.springframework.http.HttpStatus;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import mouda.backend.comment.exception.CommentErrorMessage;
import mouda.backend.comment.exception.CommentException;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.domain.Moim;

@Entity
@Getter
@NoArgsConstructor
public class Comment {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String content;

@ManyToOne
@JoinColumn(name = "moim_id")
@JoinColumn(nullable = false)
private Moim moim;

@ManyToOne
@JoinColumn(name = "member_id")
@JoinColumn(nullable = false)
private Member member;

@Column(nullable = false)
private LocalDateTime createdAt;

private Long parentId;

@Builder
public Comment(String content, Moim moim, Member member, LocalDateTime createdAt, Long parentId) {
validateContent(content);
validateMoim(moim);
validateMember(member);
this.content = content;
this.moim = moim;
this.member = member;
this.createdAt = createdAt;
this.parentId = parentId;
}

private void validateContent(String content) {
if (content == null || content.isBlank()) {
throw new CommentException(HttpStatus.BAD_REQUEST, CommentErrorMessage.CONTENT_NOT_FOUND);
}
}

private void validateMoim(Moim moim) {
if (moim == null) {
throw new CommentException(HttpStatus.NOT_FOUND, CommentErrorMessage.MOIM_NOT_FOUND);
}
}

private void validateMember(Member member) {
if (member == null) {
throw new CommentException(HttpStatus.NOT_FOUND, CommentErrorMessage.MEMBER_NOT_FOUND);
}
}

public boolean isParent() {
return parentId == null;
}

public boolean isChild() {
return parentId != null;
}

public String getAuthorNickname() {
return member.getNickname();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mouda.backend.comment.dto.request;

import java.time.LocalDateTime;

import jakarta.validation.constraints.NotNull;
import mouda.backend.comment.domain.Comment;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.domain.Moim;

public record CommentCreateRequest(
Long parentId,

@NotNull
String content
) {
public Comment toEntity(Moim moim, Member member) {
return Comment.builder()
.content(content)
.moim(moim)
.member(member)
.createdAt(LocalDateTime.now())
.parentId(parentId)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package mouda.backend.comment.dto.response;

import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Builder;
import mouda.backend.comment.domain.Comment;

@Builder
public record ChildCommentResponse(
Long commentId,

String nickname,

String content,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
LocalDateTime dateTime
) {
public static ChildCommentResponse toResponse(Comment comment) {
return ChildCommentResponse.builder()
.commentId(comment.getId())
.nickname(comment.getAuthorNickname())
.content(comment.getContent())
.dateTime(comment.getCreatedAt())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package mouda.backend.comment.dto.response;

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

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Builder;
import mouda.backend.comment.domain.Comment;

@Builder
public record CommentResponse(
Long commentId,

String nickname,

String content,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
LocalDateTime dateTime,

List<ChildCommentResponse> children
) {
public static CommentResponse toResponse(Comment parentComment, List<Comment> childComments) {
List<ChildCommentResponse> children = childComments.stream()
.map(ChildCommentResponse::toResponse)
.toList();

return CommentResponse.builder()
.commentId(parentComment.getId())
.nickname(parentComment.getAuthorNickname())
.content(parentComment.getContent())
.dateTime(parentComment.getCreatedAt())
.children(children)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package mouda.backend.comment.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum CommentErrorMessage {

CONTENT_NOT_FOUND("댓글 내용이 존재하지 않습니다."),
MEMBER_NOT_FOUND("작성자가 존재하지 않습니다."),
PARENT_NOT_FOUND("부모 댓글이 존재하지 않습니다."),
MOIM_NOT_FOUND("모임이 존재하지 않습니다.");

private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mouda.backend.comment.exception;

import org.springframework.http.HttpStatus;

import mouda.backend.exception.MoudaException;

public class CommentException extends MoudaException {

public CommentException(HttpStatus httpStatus, CommentErrorMessage commentErrorMessage) {
super(httpStatus, commentErrorMessage.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mouda.backend.comment.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import mouda.backend.comment.domain.Comment;

public interface CommentRepository extends JpaRepository<Comment, Long> {

List<Comment> findAllByMoimIdOrderByCreatedAt(long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import mouda.backend.comment.dto.request.CommentCreateRequest;
import mouda.backend.common.RestResponse;
import mouda.backend.config.argumentresolver.LoginMember;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.domain.Moim;
import mouda.backend.moim.dto.request.MoimCreateRequest;
import mouda.backend.moim.dto.request.MoimJoinRequest;
Expand Down Expand Up @@ -65,4 +68,16 @@ public ResponseEntity<Void> deleteMoim(@PathVariable Long moimId) {

return ResponseEntity.ok().build();
}

@Override
@PostMapping("/{moimId}")
public ResponseEntity<Void> createComment(
@LoginMember Member member,
@PathVariable Long moimId,
@RequestBody CommentCreateRequest commentCreateRequest
) {
moimService.createComment(member, moimId, commentCreateRequest);

return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import mouda.backend.comment.dto.request.CommentCreateRequest;
import mouda.backend.common.RestResponse;
import mouda.backend.config.argumentresolver.LoginMember;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.dto.request.MoimCreateRequest;
import mouda.backend.moim.dto.request.MoimJoinRequest;
import mouda.backend.moim.dto.response.MoimDetailsFindResponse;
Expand Down Expand Up @@ -44,4 +47,11 @@ public interface MoimSwagger {
@ApiResponse(responseCode = "200", description = "모임 삭제 성공!"),
})
ResponseEntity<Void> deleteMoim(@PathVariable Long moimId);

@Operation(summary = "댓글 작성", description = "해당하는 id의 모임에 댓글을 생성한다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "댓글 생성 성공!")
})
ResponseEntity<Void> createComment(@LoginMember Member member, @PathVariable Long moimId,
@RequestBody CommentCreateRequest commentCreateRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;

import lombok.Builder;
import mouda.backend.comment.dto.response.CommentResponse;
import mouda.backend.moim.domain.Moim;

@Builder
Expand All @@ -17,10 +18,12 @@ public record MoimDetailsFindResponse(
int maxPeople,
String authorNickname,
String description,
List<String> participants
List<String> participants,
List<CommentResponse> comments
) {

public static MoimDetailsFindResponse toResponse(Moim moim, List<String> participants) {
public static MoimDetailsFindResponse toResponse(Moim moim, List<String> participants,
List<CommentResponse> comments) {
return MoimDetailsFindResponse.builder()
.title(moim.getTitle())
.date(moim.getDate())
Expand All @@ -30,6 +33,7 @@ public static MoimDetailsFindResponse toResponse(Moim moim, List<String> partici
.maxPeople(moim.getMaxPeople())
.description(moim.getDescription())
.participants(participants)
.comments(comments)
.build();
}
}
44 changes: 42 additions & 2 deletions backend/src/main/java/mouda/backend/moim/service/MoimService.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package mouda.backend.moim.service;

import static java.util.stream.Collectors.*;

import java.util.List;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import mouda.backend.comment.domain.Comment;
import mouda.backend.comment.dto.request.CommentCreateRequest;
import mouda.backend.comment.dto.response.CommentResponse;
import mouda.backend.comment.exception.CommentErrorMessage;
import mouda.backend.comment.exception.CommentException;
import mouda.backend.comment.repository.CommentRepository;
import mouda.backend.member.domain.Member;
import mouda.backend.member.repository.MemberRepository;
import mouda.backend.moim.domain.Moim;
Expand All @@ -28,8 +37,12 @@ public class MoimService {

private final MemberRepository memberRepository;

private final CommentRepository commentRepository;

public Moim createMoim(MoimCreateRequest moimCreateRequest) {
Member author = new Member(moimCreateRequest.authorNickname());
Member author = Member.builder()
.nickname(moimCreateRequest.authorNickname())
.build();
Moim moim = moimRepository.save(moimCreateRequest.toEntity());
author.joinMoim(moim);
memberRepository.save(author);
Expand Down Expand Up @@ -59,7 +72,21 @@ public MoimDetailsFindResponse findMoimDetails(long id) {
.map(Member::getNickname)
.toList();

return MoimDetailsFindResponse.toResponse(moim, participants);
List<Comment> comments = commentRepository.findAllByMoimIdOrderByCreatedAt(id);
List<CommentResponse> commentResponses = toCommentResponse(comments);

return MoimDetailsFindResponse.toResponse(moim, participants, commentResponses);
}

private List<CommentResponse> toCommentResponse(List<Comment> comments) {
Map<Long, List<Comment>> children = comments.stream()
.filter(Comment::isChild)
.collect(groupingBy(Comment::getParentId));

return comments.stream()
.filter(Comment::isParent)
.map(comment -> CommentResponse.toResponse(comment, children.getOrDefault(comment.getId(), List.of())))
.toList();
}

public void joinMoim(MoimJoinRequest moimJoinRequest) {
Expand All @@ -84,4 +111,17 @@ public void deleteMoim(long id) {

moimRepository.delete(moim);
}

public void createComment(Member member, Long moimId, CommentCreateRequest commentCreateRequest) {
Moim moim = moimRepository.findById(moimId).orElseThrow(
() -> new MoimException(HttpStatus.NOT_FOUND, MoimErrorMessage.NOT_FOUND)
);

Long parentId = commentCreateRequest.parentId();
if (parentId != null && !commentRepository.existsById(parentId)) {
throw new CommentException(HttpStatus.BAD_REQUEST, CommentErrorMessage.PARENT_NOT_FOUND);
}

commentRepository.save(commentCreateRequest.toEntity(moim, member));
}
}
Loading

0 comments on commit d4ce086

Please sign in to comment.