Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import konkuk.thip.comment.adapter.in.web.request.CommentCreateRequest;
import konkuk.thip.comment.adapter.in.web.request.CommentIsLikeRequest;
import konkuk.thip.comment.adapter.in.web.response.CommentDeleteResponse;
import konkuk.thip.comment.adapter.in.web.response.CommentIdResponse;
import konkuk.thip.comment.adapter.in.web.response.CommentCreateResponse;
import konkuk.thip.comment.adapter.in.web.response.CommentIsLikeResponse;
import konkuk.thip.comment.application.port.in.CommentCreateUseCase;
import konkuk.thip.comment.application.port.in.CommentDeleteUseCase;
Expand Down Expand Up @@ -42,11 +42,11 @@ public class CommentCommandController {
)
@ExceptionDescription(COMMENT_CREATE)
@PostMapping("/comments/{postId}")
public BaseResponse<CommentIdResponse> createComment(
public BaseResponse<CommentCreateResponse> createComment(
@RequestBody @Valid final CommentCreateRequest request,
@Parameter(description = "댓글을 작성하려는 게시물 ID", example = "1") @PathVariable("postId") final Long postId,
@Parameter(hidden = true) @UserId final Long userId) {
return BaseResponse.ok(CommentIdResponse.of(commentCreateUseCase.createComment(request.toCommand(userId,postId))));
return BaseResponse.ok(commentCreateUseCase.createComment(request.toCommand(userId,postId)));
}

@Operation(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package konkuk.thip.comment.adapter.in.web.response;

import java.util.List;

public record CommentCreateResponse(
Long commentId,
Long creatorId,
String creatorProfileImageUrl,
String creatorNickname,
String aliasName,
String aliasColor,
String postDate, // 댓글 작성 시각 (~ 전 형식)
String content,
int likeCount,
boolean isLike,
boolean isDeleted, // 삭제된 댓글인지 아닌지
boolean isWriter,
List<ReplyCommentCreateDto> replyList
) {
public record ReplyCommentCreateDto(
Long commentId,
String parentCommentCreatorNickname,
Long creatorId,
String creatorProfileImageUrl,
String creatorNickname,
String aliasName,
String aliasColor,
String postDate, // 댓글 작성 시각 (~ 전 형식)
String content,
int likeCount,
boolean isLike,
boolean isWriter
) {}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,14 @@ public List<CommentQueryDto> findAllActiveChildCommentsOldestFirst(Long rootComm
public Map<Long, List<CommentQueryDto>> findAllActiveChildCommentsOldestFirst(Set<Long> rootCommentIds) {
return commentJpaRepository.findAllActiveChildCommentsByCreatedAtAsc(rootCommentIds);
}

@Override
public CommentQueryDto findRootCommentById(Long rootCommentId) {
return commentJpaRepository.findRootCommentId(rootCommentId);
}

@Override
public CommentQueryDto findChildCommentById(Long rootCommentId, Long replyCommentId) {
return commentJpaRepository.findChildCommentId(rootCommentId, replyCommentId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ public interface CommentQueryRepository {
List<CommentQueryDto> findAllActiveChildCommentsByCreatedAtAsc(Long rootCommentId);

Map<Long, List<CommentQueryDto>> findAllActiveChildCommentsByCreatedAtAsc(Set<Long> rootCommentIds);

CommentQueryDto findRootCommentId(Long commentId);

CommentQueryDto findChildCommentId(Long rootCommentId, Long commentId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,66 @@ public Map<Long, List<CommentQueryDto>> findAllActiveChildCommentsByCreatedAtAsc

return resultMap;
}

@Override
public CommentQueryDto findRootCommentId(Long rootCommentId) {

QCommentQueryDto proj = new QCommentQueryDto(
comment.commentId,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
comment.status.eq(StatusType.INACTIVE)
);

return queryFactory
.select(proj)
.from(comment)
.join(comment.userJpaEntity, commentCreator)
.join(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(
comment.commentId.eq(rootCommentId),
comment.status.eq(StatusType.ACTIVE)
)
.fetchOne();
}
Comment thread
hd0rable marked this conversation as resolved.

@Override
public CommentQueryDto findChildCommentId(Long rootCommentId, Long replyCommentId) {

QCommentQueryDto proj = new QCommentQueryDto(
comment.commentId,
comment.parent.commentId,
parentCommentCreator.nickname,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
comment.status.eq(StatusType.INACTIVE)
);

return queryFactory
.select(proj)
.from(comment)
.join(comment.parent, parentComment)
.join(parentComment.userJpaEntity, parentCommentCreator)
.join(comment.userJpaEntity, commentCreator)
.join(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(
comment.parent.commentId.eq(rootCommentId),
parentComment.status.eq(StatusType.ACTIVE),
comment.status.eq(StatusType.ACTIVE),
comment.commentId.eq(replyCommentId)
)
.fetchOne();
}
Comment thread
hd0rable marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package konkuk.thip.comment.application.mapper;

import konkuk.thip.comment.adapter.in.web.response.CommentCreateResponse;
import konkuk.thip.comment.adapter.in.web.response.CommentForSinglePostResponse;
import konkuk.thip.comment.application.port.out.dto.CommentQueryDto;
import konkuk.thip.common.util.DateUtil;
Expand Down Expand Up @@ -27,6 +28,15 @@ public interface CommentQueryMapper {
@Mapping(target = "isWriter", source = "root.creatorId", qualifiedByName = "isWriter")
CommentForSinglePostResponse.RootCommentDto toRoot(CommentQueryDto root, @Context Set<Long> likedCommentIds, @Context Long userId);

// 댓글/답글 생성시 루트 댓글 매핑
@Mapping(target = "replyList", expression = "java(new java.util.ArrayList<>())")
@Mapping(target = "isDeleted", constant = "false")
@Mapping(target = "isLike", expression = "java(isLike)")
@Mapping(target = "postDate", expression = "java(DateUtil.formatBeforeTime(root.createdAt()))")
@Mapping(target = "aliasName", source = "root.alias")
@Mapping(target = "isWriter", source = "root.creatorId", qualifiedByName = "isWriter")
CommentCreateResponse toRoot(CommentQueryDto root, boolean isLike, @Context Long userId);

/**
* 개별 답글 매핑
*/
Expand All @@ -36,6 +46,13 @@ public interface CommentQueryMapper {
@Mapping(target = "isWriter", source = "child.creatorId", qualifiedByName = "isWriter")
CommentForSinglePostResponse.RootCommentDto.ReplyDto toReply(CommentQueryDto child, @Context Set<Long> likedCommentIds, @Context Long userId);

// 답글 생성시 답글 매핑
@Mapping(target = "isLike", constant = "false")
@Mapping(target = "postDate", expression = "java(DateUtil.formatBeforeTime(child.createdAt()))")
@Mapping(target = "aliasName", source = "child.alias")
@Mapping(target = "isWriter", source = "child.creatorId", qualifiedByName = "isWriter")
CommentCreateResponse.ReplyCommentCreateDto toReply(CommentQueryDto child, @Context Long userId);

/**
* 답글 리스트 헬퍼
*/
Expand All @@ -61,6 +78,16 @@ default CommentForSinglePostResponse.RootCommentDto toRootCommentResponseWithChi
return rootDto;
}

default CommentCreateResponse toRootCommentResponseWithChildren(
CommentQueryDto root, CommentQueryDto children, boolean isLikedParentComment, @Context Long userId) {
CommentCreateResponse.ReplyCommentCreateDto replyDto = toReply(children,userId);

CommentCreateResponse rootDto = toRoot(root, isLikedParentComment, userId);
rootDto.replyList().add(replyDto);
return rootDto;
}


@Named("isWriter")
default boolean isWriter(Long creatorId, @Context Long userId) {
return creatorId != null && creatorId.equals(userId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package konkuk.thip.comment.application.port.in;

import konkuk.thip.comment.adapter.in.web.response.CommentCreateResponse;
import konkuk.thip.comment.application.port.in.dto.CommentCreateCommand;

public interface CommentCreateUseCase {
Long createComment(CommentCreateCommand command);
CommentCreateResponse createComment(CommentCreateCommand command);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ public interface CommentQueryPort {
List<CommentQueryDto> findAllActiveChildCommentsOldestFirst(Long rootCommentId);

Map<Long, List<CommentQueryDto>> findAllActiveChildCommentsOldestFirst(Set<Long> rootCommentIds);

CommentQueryDto findRootCommentById(Long rootCommentId);

CommentQueryDto findChildCommentById(Long rootCommentId , Long replyCommentId);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package konkuk.thip.comment.application.service;

import konkuk.thip.comment.adapter.in.web.response.CommentCreateResponse;
import konkuk.thip.comment.application.mapper.CommentQueryMapper;
import konkuk.thip.comment.application.port.in.CommentCreateUseCase;
import konkuk.thip.comment.application.port.in.dto.CommentCreateCommand;
import konkuk.thip.comment.application.port.out.CommentCommandPort;
import konkuk.thip.comment.application.port.out.CommentLikeQueryPort;
import konkuk.thip.comment.application.port.out.CommentQueryPort;
import konkuk.thip.comment.application.port.out.dto.CommentQueryDto;
import konkuk.thip.comment.application.service.validator.CommentAuthorizationValidator;
import konkuk.thip.comment.domain.Comment;
import konkuk.thip.common.exception.InvalidStateException;
Expand All @@ -21,13 +26,17 @@
public class CommentCreateService implements CommentCreateUseCase {

private final CommentCommandPort commentCommandPort;
private final CommentQueryPort commentQueryPort;
private final CommentLikeQueryPort commentLikeQueryPort;
private final CommentQueryMapper commentQueryMapper;


private final PostHandler postHandler;
private final CommentAuthorizationValidator commentAuthorizationValidator;

@Override
@Transactional
public Long createComment(CommentCreateCommand command) {
public CommentCreateResponse createComment(CommentCreateCommand command) {

// 1. 댓글/답글 생성 선행검증 및 작성하려는 게시글 타입 검증
Comment.validateCommentCreate(command.isReplyRequest(), command.parentId());
Expand All @@ -42,7 +51,7 @@ public Long createComment(CommentCreateCommand command) {
// TODO 기록 및 투표: 모임방의 내 게시글에 대한 댓글, 내 댓글에 대한 답글 알림 전송

// 3. 댓글 생성
Long commentId = createCommentDomain(command);
Long savedCommentId = createCommentDomain(command);

//TODO 게시물의 댓글 수 증가/감소 동시성 제어 로직 추가해야됨

Expand All @@ -52,7 +61,20 @@ public Long createComment(CommentCreateCommand command) {
// 4-2 Jpa엔티티 게시물 댓글 수 증가
postHandler.updatePost(type, post);

return commentId;
// 5. 매퍼로 DTO 변환 후 반환
if (command.isReplyRequest()) {
// 부모 댓글 조회
CommentQueryDto parentCommentDto = commentQueryPort.findRootCommentById(command.parentId());
// 사용자 부모 댓글 좋아요 여부 조회
boolean isLikedParentComment = commentLikeQueryPort.isLikedCommentByUser(command.userId(),parentCommentDto.commentId());

CommentQueryDto savedReplyCommentDto = commentQueryPort.findChildCommentById(command.parentId(), savedCommentId);
return commentQueryMapper.toRootCommentResponseWithChildren(parentCommentDto, savedReplyCommentDto,isLikedParentComment,command.userId());
} else {
CommentQueryDto savedCommentDto = commentQueryPort.findRootCommentById(savedCommentId);
return commentQueryMapper.toRoot(savedCommentDto, false, command.userId());
}
Comment thread
hd0rable marked this conversation as resolved.
Comment on lines +64 to +76
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM


}

private Long createCommentDomain(CommentCreateCommand command) {
Expand Down