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 @@ -2,7 +2,8 @@
== 픽픽픽 답글 작성 API(POST: /devdevdev/api/v1/picks/{pickId}/comments/{pickOriginParentCommentId}/{pickParentCommentId})

* 픽픽픽 답글을 작성한다.
* 회원만 픽픽픽 답글을 작성 할 수 있다.
** 회원인 경우 토큰을 `Authorization` 헤더에 포함시켜야 한다.
** 익명 회원인 경우 `Anonymous-Member-Id` 헤더에 익명 회원 아이디를 포함시켜야 한다.
* #픽픽픽 댓글이 삭제 상태# 이면 답글을 작성 할 수 없다.
* 최초 댓글에 대한 답글을 작성할 경우 `pickCommentOriginParentId` 값과 `pickParentCommentId` 값이 동일하다.

Expand Down Expand Up @@ -40,7 +41,7 @@ include::{snippets}/register-pick-comment-reply/response-fields.adoc[]
* `픽픽픽 댓글이 없습니다.`: 픽픽픽 댓글이 존재하지 않는 경우
* `삭제된 픽픽픽 댓글에는 답글을 작성할 수 없습니다.`: 픽픽픽 댓글이 삭제된 경우
* `승인 상태가 아닌 픽픽픽에는 답글을 작성할 수 없습니다.`: 픽픽픽이 승인 상태가 아닌 경우
* `익명 회원은 사용할 수 없는 기능 입니다.`: 익명 회원인 경우
* `회원을 찾을 수 없습니다.`: 회원이 존재하지 않는 경우
* `익명 사용자가 아닙니다. 잘못된 메소드 호출 입니다.`: 회원이 익명 회원 메소드를 호출한 경우

include::{snippets}/register-pick-comment-reply-bind-exception/response-body.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType;
import com.dreamypatisiel.devdevdev.domain.policy.PickBestCommentsPolicy;
import com.dreamypatisiel.devdevdev.domain.policy.PickPopularScorePolicy;
import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentRecommendRepository;
import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentRepository;
import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentSort;
Expand All @@ -13,7 +14,6 @@
import com.dreamypatisiel.devdevdev.openai.embeddings.EmbeddingsService;
import com.dreamypatisiel.devdevdev.web.dto.SliceCustom;
import com.dreamypatisiel.devdevdev.web.dto.request.pick.ModifyPickCommentRequest;
import com.dreamypatisiel.devdevdev.web.dto.request.pick.RegisterPickRepliedCommentRequest;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentRecommendResponse;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentResponse;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentsResponse;
Expand All @@ -33,9 +33,10 @@ public class GuestPickCommentService extends PickCommonService implements PickCo
public GuestPickCommentService(EmbeddingsService embeddingsService,
PickBestCommentsPolicy pickBestCommentsPolicy,
PickRepository pickRepository,
PickPopularScorePolicy pickPopularScorePolicy,
PickCommentRepository pickCommentRepository,
PickCommentRecommendRepository pickCommentRecommendRepository) {
super(embeddingsService, pickBestCommentsPolicy, pickRepository, pickCommentRepository,
super(embeddingsService, pickBestCommentsPolicy, pickPopularScorePolicy, pickRepository, pickCommentRepository,
pickCommentRecommendRepository);
}

Expand All @@ -47,7 +48,7 @@ public PickCommentResponse registerPickComment(Long pickId, PickCommentDto pickC

@Override
public PickCommentResponse registerPickRepliedComment(Long pickParentCommentId, Long pickCommentOriginParentId,
Long pickId, RegisterPickRepliedCommentRequest pickSubCommentRequest,
Long pickId, PickCommentDto pickCommentDto,
Authentication authentication) {

throw new AccessDeniedException(INVALID_ANONYMOUS_CAN_NOT_USE_THIS_FUNCTION_MESSAGE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import com.dreamypatisiel.devdevdev.openai.embeddings.EmbeddingsService;
import com.dreamypatisiel.devdevdev.web.dto.SliceCustom;
import com.dreamypatisiel.devdevdev.web.dto.request.pick.ModifyPickCommentRequest;
import com.dreamypatisiel.devdevdev.web.dto.request.pick.RegisterPickRepliedCommentRequest;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentRecommendResponse;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentResponse;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentsResponse;
Expand All @@ -42,7 +41,6 @@
public class GuestPickCommentServiceV2 extends PickCommonService implements PickCommentService {

private final AnonymousMemberService anonymousMemberService;
private final PickPopularScorePolicy pickPopularScorePolicy;

private final PickVoteRepository pickVoteRepository;

Expand All @@ -54,10 +52,9 @@ public GuestPickCommentServiceV2(EmbeddingsService embeddingsService,
AnonymousMemberService anonymousMemberService,
PickPopularScorePolicy pickPopularScorePolicy,
PickVoteRepository pickVoteRepository) {
super(embeddingsService, pickBestCommentsPolicy, pickRepository, pickCommentRepository,
pickCommentRecommendRepository);
super(embeddingsService, pickBestCommentsPolicy, pickPopularScorePolicy, pickRepository,
pickCommentRepository, pickCommentRecommendRepository);
this.anonymousMemberService = anonymousMemberService;
this.pickPopularScorePolicy = pickPopularScorePolicy;
this.pickVoteRepository = pickVoteRepository;
}

Expand Down Expand Up @@ -110,11 +107,33 @@ public PickCommentResponse registerPickComment(Long pickId, PickCommentDto pickC
}

@Override
@Transactional
public PickCommentResponse registerPickRepliedComment(Long pickParentCommentId, Long pickCommentOriginParentId,
Long pickId, RegisterPickRepliedCommentRequest pickSubCommentRequest,
Long pickId, PickCommentDto pickCommentDto,
Authentication authentication) {

throw new AccessDeniedException(INVALID_ANONYMOUS_CAN_NOT_USE_THIS_FUNCTION_MESSAGE);
// 익명 회원인지 검증
AuthenticationMemberUtils.validateAnonymousMethodCall(authentication);

String contents = pickCommentDto.getContents();
String anonymousMemberId = pickCommentDto.getAnonymousMemberId();

// 익명 회원 추출
AnonymousMember anonymousMember = anonymousMemberService.findOrCreateAnonymousMember(anonymousMemberId);

// 픽픽픽 댓글 로직 수행
PickReplyContext pickReplyContext = prepareForReplyRegistration(pickParentCommentId, pickCommentOriginParentId, pickId);

PickComment findParentPickComment = pickReplyContext.parentPickComment();
PickComment findOriginParentPickComment = pickReplyContext.originParentPickComment();
Pick findPick = pickReplyContext.pick();

// 픽픽픽 서브 댓글(답글) 생성
PickComment pickRepliedComment = PickComment.createRepliedCommentByAnonymousMember(new CommentContents(contents),
findParentPickComment, findOriginParentPickComment, anonymousMember, findPick);
pickCommentRepository.save(pickRepliedComment);

return new PickCommentResponse(pickRepliedComment.getId());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ public class GuestPickService extends PickCommonService implements PickService {

public static final String INVALID_ANONYMOUS_CAN_NOT_USE_THIS_FUNCTION_MESSAGE = "비회원은 현재 해당 기능을 이용할 수 없습니다.";

private final PickPopularScorePolicy pickPopularScorePolicy;
private final PickVoteRepository pickVoteRepository;
private final TimeProvider timeProvider;
private final AnonymousMemberService anonymousMemberService;
Expand All @@ -67,9 +66,8 @@ public GuestPickService(PickRepository pickRepository, EmbeddingsService embeddi
PickPopularScorePolicy pickPopularScorePolicy,
PickVoteRepository pickVoteRepository,
TimeProvider timeProvider, AnonymousMemberService anonymousMemberService) {
super(embeddingsService, pickBestCommentsPolicy, pickRepository, pickCommentRepository,
super(embeddingsService, pickBestCommentsPolicy, pickPopularScorePolicy, pickRepository, pickCommentRepository,
pickCommentRecommendRepository);
this.pickPopularScorePolicy = pickPopularScorePolicy;
this.pickVoteRepository = pickVoteRepository;
this.anonymousMemberService = anonymousMemberService;
this.timeProvider = timeProvider;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.dreamypatisiel.devdevdev.domain.service.pick;

import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_CAN_NOT_ACTION_DELETED_PICK_COMMENT_MESSAGE;
import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_CAN_NOT_REPLY_DELETED_PICK_COMMENT_MESSAGE;
import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_NOT_APPROVAL_STATUS_PICK_COMMENT_MESSAGE;
import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_NOT_APPROVAL_STATUS_PICK_REPLY_MESSAGE;
import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_NOT_FOUND_PICK_COMMENT_MESSAGE;
import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_NOT_FOUND_PICK_MESSAGE;
import static com.dreamypatisiel.devdevdev.domain.exception.PickExceptionMessage.INVALID_NOT_FOUND_PICK_VOTE_MESSAGE;
Expand All @@ -29,7 +27,6 @@
import com.dreamypatisiel.devdevdev.openai.embeddings.EmbeddingsService;
import com.dreamypatisiel.devdevdev.web.dto.SliceCommentCustom;
import com.dreamypatisiel.devdevdev.web.dto.request.pick.ModifyPickCommentRequest;
import com.dreamypatisiel.devdevdev.web.dto.request.pick.RegisterPickRepliedCommentRequest;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentRecommendResponse;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentResponse;
import com.dreamypatisiel.devdevdev.web.dto.response.pick.PickCommentsResponse;
Expand All @@ -47,7 +44,6 @@ public class MemberPickCommentService extends PickCommonService implements PickC

private final TimeProvider timeProvider;
private final MemberProvider memberProvider;
private final PickPopularScorePolicy pickPopularScorePolicy;

private final PickRepository pickRepository;
private final PickVoteRepository pickVoteRepository;
Expand All @@ -59,11 +55,10 @@ public MemberPickCommentService(TimeProvider timeProvider, MemberProvider member
PickRepository pickRepository, PickVoteRepository pickVoteRepository,
PickCommentRepository pickCommentRepository,
PickCommentRecommendRepository pickCommentRecommendRepository) {
super(embeddingsService, pickBestCommentsPolicy, pickRepository, pickCommentRepository,
super(embeddingsService, pickBestCommentsPolicy, pickPopularScorePolicy, pickRepository, pickCommentRepository,
pickCommentRecommendRepository);
this.timeProvider = timeProvider;
this.memberProvider = memberProvider;
this.pickPopularScorePolicy = pickPopularScorePolicy;
this.pickRepository = pickRepository;
this.pickVoteRepository = pickVoteRepository;
this.pickCommentRepository = pickCommentRepository;
Expand Down Expand Up @@ -126,31 +121,20 @@ public PickCommentResponse registerPickComment(Long pickId, PickCommentDto pickC
public PickCommentResponse registerPickRepliedComment(Long pickParentCommentId,
Long pickCommentOriginParentId,
Long pickId,
RegisterPickRepliedCommentRequest pickSubCommentRequest,
PickCommentDto pickCommentDto,
Authentication authentication) {

String contents = pickSubCommentRequest.getContents();
String contents = pickCommentDto.getContents();

// 회원 조회
Member findMember = memberProvider.getMemberByAuthentication(authentication);

// 답글 대상의 픽픽픽 댓글 조회
PickComment findParentPickComment = pickCommentRepository.findWithPickByIdAndPickId(pickParentCommentId, pickId)
.orElseThrow(() -> new NotFoundException(INVALID_NOT_FOUND_PICK_COMMENT_MESSAGE));

// 픽픽픽 게시글의 승인 상태 검증
Pick findPick = findParentPickComment.getPick();
validateIsApprovalPickContentStatus(findPick, INVALID_NOT_APPROVAL_STATUS_PICK_REPLY_MESSAGE,
REGISTER);
// 댓글 총 갯수 증가 및 인기점수 반영
findPick.incrementCommentTotalCount();
findPick.changePopularScore(pickPopularScorePolicy);
// 픽픽픽 댓글 로직 수행
PickReplyContext pickReplyContext = prepareForReplyRegistration(pickParentCommentId, pickCommentOriginParentId, pickId);

// 픽픽픽 최초 댓글 검증 및 반환
PickComment findOriginParentPickComment = getAndValidateOriginParentPickComment(
pickCommentOriginParentId, findParentPickComment);
// 픽픽픽 최초 댓글의 답글 갯수 증가
findOriginParentPickComment.incrementReplyTotalCount();
PickComment findParentPickComment = pickReplyContext.parentPickComment();
PickComment findOriginParentPickComment = pickReplyContext.originParentPickComment();
Pick findPick = pickReplyContext.pick();

// 픽픽픽 서브 댓글(답글) 생성
PickComment pickRepliedComment = PickComment.createRepliedCommentByMember(new CommentContents(contents),
Expand All @@ -160,28 +144,6 @@ public PickCommentResponse registerPickRepliedComment(Long pickParentCommentId,
return new PickCommentResponse(pickRepliedComment.getId());
}

private PickComment getAndValidateOriginParentPickComment(Long pickCommentOriginParentId,
PickComment parentPickComment) {

// 픽픽픽 답글 대상의 댓글이 삭제 상태이면
validateIsDeletedPickComment(parentPickComment, INVALID_CAN_NOT_REPLY_DELETED_PICK_COMMENT_MESSAGE, REGISTER);

// 픽픽픽 답글 대상의 댓글이 최초 댓글이면
if (parentPickComment.isEqualsId(pickCommentOriginParentId)) {
return parentPickComment;
}

// 픽픽픽 답글 대상의 댓글의 메인 댓글 조회
PickComment findOriginParentPickComment = pickCommentRepository.findById(pickCommentOriginParentId)
.orElseThrow(() -> new NotFoundException(INVALID_NOT_FOUND_PICK_COMMENT_MESSAGE));

// 픽픽픽 최초 댓글이 삭제 상태이면
validateIsDeletedPickComment(findOriginParentPickComment, INVALID_CAN_NOT_REPLY_DELETED_PICK_COMMENT_MESSAGE,
REGISTER);

return findOriginParentPickComment;
}

/**
* @Note: 회원 자신이 작성한 픽픽픽 댓글/답글을 수정한다. 픽픽픽 공개 여부는 수정할 수 없다.
* @Author: 장세웅
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public class MemberPickService extends PickCommonService implements PickService
private final PickOptionRepository pickOptionRepository;
private final PickOptionImageRepository pickOptionImageRepository;
private final PickVoteRepository pickVoteRepository;
private final PickPopularScorePolicy pickPopularScorePolicy;

private final TimeProvider timeProvider;

public MemberPickService(EmbeddingsService embeddingsService, PickRepository pickRepository,
Expand All @@ -96,15 +96,14 @@ public MemberPickService(EmbeddingsService embeddingsService, PickRepository pic
PickCommentRecommendRepository pickCommentRecommendRepository,
PickPopularScorePolicy pickPopularScorePolicy,
PickBestCommentsPolicy pickBestCommentsPolicy, TimeProvider timeProvider) {
super(embeddingsService, pickBestCommentsPolicy, pickRepository, pickCommentRepository,
super(embeddingsService, pickBestCommentsPolicy, pickPopularScorePolicy, pickRepository, pickCommentRepository,
pickCommentRecommendRepository);
this.awsS3Properties = awsS3Properties;
this.awsS3Uploader = awsS3Uploader;
this.memberProvider = memberProvider;
this.pickOptionRepository = pickOptionRepository;
this.pickOptionImageRepository = pickOptionImageRepository;
this.pickVoteRepository = pickVoteRepository;
this.pickPopularScorePolicy = pickPopularScorePolicy;
this.timeProvider = timeProvider;
}

Expand All @@ -129,14 +128,12 @@ public Slice<PickMainResponse> findPicksMain(Pageable pageable, Long pickId, Pic
}

/**
* @Note: 이미지 업로드와 DB 저장을 하나의 작업(Transcation)으로 묶어서, 데이터 정합성을 유지한다.<br/> 이때 pick_option_id는 null 인 상태
* 입니다.<br/><br/>
* @Note: 이미지 업로드와 DB 저장을 하나의 작업(Transcation)으로 묶어서, 데이터 정합성을 유지한다.<br/> 이때 pick_option_id는 null 인 상태 입니다.<br/><br/>
* <p>
* 이미지 업로드 실패시 IOException이 발생할 수 있는데, 이때 catch로 처리하여 데이터 정합성 유지합니다.<br/> 즉, IOException이 발생해도 rollback하지 않는다는 의미
* 입니다. <br/><br/>
* 이미지 업로드 실패시 IOException이 발생할 수 있는데, 이때 catch로 처리하여 데이터 정합성 유지합니다.<br/> 즉, IOException이 발생해도 rollback하지 않는다는 의미 입니다.
* <br/><br/>
* <p>
* 단, Transcation이 길게 유지되면 추후 DB Connection을 오랫동안 유지하기 때문에 많은 트래픽이 발생할 때 DB Connection이 부족해지는 현상이 발생할 수
* 있습니다.<br/><br/>
* 단, Transcation이 길게 유지되면 추후 DB Connection을 오랫동안 유지하기 때문에 많은 트래픽이 발생할 때 DB Connection이 부족해지는 현상이 발생할 수 있습니다.<br/><br/>
* <p>
* (Transcation은 기본적으로 RuntimeException에 대해서만 Rollback 합니다. AmazonClient의 putObject(...)는 RuntimeException을
* 발생시킵니다.)<br/><br/>
Expand Down Expand Up @@ -282,8 +279,8 @@ public PickDetailResponse findPickDetail(Long pickId, String anonymousMemberId,
}

/**
* @Note: member 1:N pick 1:N pickOption 1:N pickVote <br/> pick 1:N pickVote N:1 member <br/> 연관관계가 다소 복잡하니, 직접
* ERD를 확인하는 것을 권장합니다. <br/> 투표 이력이 있는 경우 - 투표 이력이 없는 경우
* @Note: member 1:N pick 1:N pickOption 1:N pickVote <br/> pick 1:N pickVote N:1 member <br/> 연관관계가 다소 복잡하니, 직접 ERD를 확인하는 것을
* 권장합니다. <br/> 투표 이력이 있는 경우 - 투표 이력이 없는 경우
* @Author: ralph
* @Since: 2024.05.29
*/
Expand Down
Loading