diff --git a/src/main/java/com/dnd/gongmuin/post_interaction/domain/InteractionCount.java b/src/main/java/com/dnd/gongmuin/post_interaction/domain/InteractionCount.java index 721ad863..3cc70f35 100644 --- a/src/main/java/com/dnd/gongmuin/post_interaction/domain/InteractionCount.java +++ b/src/main/java/com/dnd/gongmuin/post_interaction/domain/InteractionCount.java @@ -51,7 +51,7 @@ public int increaseCount() { public int decreaseCount() { if (count == 0) { - throw new ValidationException(InteractionErrorCode.UNINTERACTION_NOT_ALLOWED); + throw new ValidationException(InteractionErrorCode.INTERACTION_UNDO_NOT_ALLOWED); } return --count; } diff --git a/src/main/java/com/dnd/gongmuin/post_interaction/dto/InteractionMapper.java b/src/main/java/com/dnd/gongmuin/post_interaction/dto/InteractionMapper.java index c38f2e30..2941de57 100644 --- a/src/main/java/com/dnd/gongmuin/post_interaction/dto/InteractionMapper.java +++ b/src/main/java/com/dnd/gongmuin/post_interaction/dto/InteractionMapper.java @@ -10,7 +10,7 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class InteractionMapper { - public static Interaction toPostInteraction(Long questionPostId, Long memberId, InteractionType type) { + public static Interaction toInteraction(Long questionPostId, Long memberId, InteractionType type) { return Interaction.of( type, memberId, @@ -18,14 +18,14 @@ public static Interaction toPostInteraction(Long questionPostId, Long memberId, ); } - public static InteractionCount toPostInteractionCount(Long questionPostId, InteractionType type) { + public static InteractionCount toInteractionCount(Long questionPostId, InteractionType type) { return InteractionCount.of( type, questionPostId ); } - public static InteractionResponse toPostInteractionResponse(int count, InteractionType type) { + public static InteractionResponse toInteractionResponse(int count, InteractionType type) { return new InteractionResponse( count, type.getLabel() ); diff --git a/src/main/java/com/dnd/gongmuin/post_interaction/exception/InteractionErrorCode.java b/src/main/java/com/dnd/gongmuin/post_interaction/exception/InteractionErrorCode.java index 2c37d569..a891382d 100644 --- a/src/main/java/com/dnd/gongmuin/post_interaction/exception/InteractionErrorCode.java +++ b/src/main/java/com/dnd/gongmuin/post_interaction/exception/InteractionErrorCode.java @@ -9,11 +9,13 @@ @RequiredArgsConstructor public enum InteractionErrorCode implements ErrorCode { - NOT_FOUND_POST_INTERACTION("상호작용 이력이 존재하지 않습니다.", "PI_001"), - ALREADY_INTERACTED("이미 해당 작업을 수행했습니다.", "PI_002"), - UNINTERACTION_NOT_ALLOWED("상호작용 수가 0이하가 될 수 없습니다.", "PI_003"), - INTERACTION_NOT_ALLOWED("본인 게시물은 상호작용할 수 없습니다", "PI_004"), - NOT_FOUND_TYPE("북마크와 추천 중 하나를 입력해주세요", "PI_005"); + NOT_FOUND_INTERACTION("상호작용 이력이 존재하지 않습니다.", "PI_001"), + NOT_FOUND_INTERACTION_COUNT("상호작용 수 이력이 존재하지 않습니다.", "PI_002"), + + ALREADY_INTERACTED("이미 해당 작업을 수행했습니다.", "PI_003"), + INTERACTION_UNDO_NOT_ALLOWED("상호작용 수가 0이하가 될 수 없습니다.", "PI_004"), + INTERACTION_NOT_ALLOWED("본인 게시물은 상호작용할 수 없습니다", "PI_005"), + NOT_FOUND_TYPE("북마크와 추천 중 하나를 입력해주세요", "PI_006"); private final String message; private final String code; diff --git a/src/main/java/com/dnd/gongmuin/post_interaction/service/InteractionService.java b/src/main/java/com/dnd/gongmuin/post_interaction/service/InteractionService.java index 6b874e2a..127f4ca8 100644 --- a/src/main/java/com/dnd/gongmuin/post_interaction/service/InteractionService.java +++ b/src/main/java/com/dnd/gongmuin/post_interaction/service/InteractionService.java @@ -33,47 +33,37 @@ public InteractionResponse activateInteraction( Long memberId, InteractionType type // 북마크, 추천 ) { - int count; - if (!interactionRepository.existsByQuestionPostIdAndMemberIdAndType // 상호 작용 존재x -> 저장 - (questionPostId, memberId, type) - ) { - count = createInteraction(questionPostId, memberId, type); - } else { // 존재 -> 값 업데이트 - count = updateInteractionAndCount(questionPostId, memberId, type, true); - } - return InteractionMapper.toPostInteractionResponse( - count, type - ); + validateIfPostExistsAndNotQuestioner(questionPostId, memberId); + + interactionRepository + .findByQuestionPostIdAndMemberIdAndType(questionPostId, memberId, type) + .ifPresentOrElse( + interaction -> interaction.updateIsInteracted(true), + () -> interactionRepository.save( + InteractionMapper.toInteraction(questionPostId, memberId, type) + ) + ); + + int count = interactionCountRepository + .findByQuestionPostIdAndType(questionPostId, type) + .map(InteractionCount::increaseCount) + .orElseGet(() -> interactionCountRepository.save( + InteractionMapper.toInteractionCount(questionPostId, type) + ).getCount()); + return InteractionMapper.toInteractionResponse(count, type); } @Transactional public InteractionResponse inactivateInteraction( Long questionPostId, Long memberId, - InteractionType type - ) { - int count = updateInteractionAndCount(questionPostId, memberId, type, false); - return InteractionMapper.toPostInteractionResponse( - count, type - ); - } - - private int createInteraction( - Long questionPostId, - Long memberId, - InteractionType type + InteractionType type // 북마크, 추천 ) { - validateIfPostExistsAndNotQuestioner(questionPostId, memberId); - interactionRepository.save( - InteractionMapper.toPostInteraction(questionPostId, memberId, type) - ); - return interactionCountRepository // 게시글 상호작용이 없어도 타 회원에 인해 게시글 상호작용 수가 있을 수 있음 - .findByQuestionPostIdAndType(questionPostId, type) - .orElseGet( - () -> interactionCountRepository - .save(InteractionMapper.toPostInteractionCount(questionPostId, type)) // 생성 시 count 1로 초기화 - ) - .getCount(); + getPostInteraction(questionPostId, memberId, type) + .updateIsInteracted(false); + int count = getPostInteractionCount(questionPostId, type) + .decreaseCount(); + return InteractionMapper.toInteractionResponse(count, type); } private void validateIfPostExistsAndNotQuestioner( @@ -87,35 +77,15 @@ private void validateIfPostExistsAndNotQuestioner( } } - private int updateInteractionAndCount( - Long questionPostId, - Long memberId, - InteractionType type, - boolean isActivate - ) { - int count; - Interaction interaction = getPostInteraction(questionPostId, memberId, type); - InteractionCount interactionCount = getPostInteractionCount(questionPostId, type); - - if (isActivate) { //활성화 - interaction.updateIsInteracted(true); - count = interactionCount.increaseCount(); - } else { // 비활성화 - interaction.updateIsInteracted(false); - count = interactionCount.decreaseCount(); - } - return count; - } - private Interaction getPostInteraction(Long questionPostId, Long memberId, InteractionType type) { return interactionRepository.findByQuestionPostIdAndMemberIdAndType( questionPostId, memberId, type - ).orElseThrow(() -> new NotFoundException(InteractionErrorCode.NOT_FOUND_POST_INTERACTION)); + ).orElseThrow(() -> new NotFoundException(InteractionErrorCode.NOT_FOUND_INTERACTION)); } private InteractionCount getPostInteractionCount(Long questionPostId, InteractionType type) { return interactionCountRepository .findByQuestionPostIdAndType(questionPostId, type) - .orElseThrow(); + .orElseThrow(() -> new NotFoundException(InteractionErrorCode.NOT_FOUND_INTERACTION_COUNT)); } } diff --git a/src/test/java/com/dnd/gongmuin/post_interaction/service/InteractionServiceTest.java b/src/test/java/com/dnd/gongmuin/post_interaction/service/InteractionServiceTest.java index 8da123e2..ae24b8ee 100644 --- a/src/test/java/com/dnd/gongmuin/post_interaction/service/InteractionServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/post_interaction/service/InteractionServiceTest.java @@ -33,6 +33,7 @@ class InteractionServiceTest { private final Member questioner = MemberFixture.member(1L); private final Member interactor = MemberFixture.member(2L); + private final InteractionType type = InteractionType.RECOMMEND; @Mock private InteractionRepository interactionRepository; @@ -46,28 +47,27 @@ class InteractionServiceTest { @InjectMocks private InteractionService interactionService; - @DisplayName("[상호작용을 새로 활성화한다. 기존에 게시글 상호작용 수가 저장되어 있다.]") + @DisplayName("[게시글에 최초로 추천을 한다.]") @Test void activateInteraction_create1() { //given - InteractionType type = InteractionType.RECOMMEND; QuestionPost questionPost = QuestionPostFixture.questionPost(1L, questioner); Interaction interaction = Interaction.of(type, interactor.getId(), questionPost.getId()); InteractionCount interactionCount = InteractionCount.of(type, interactor.getId()); - given(interactionRepository.existsByQuestionPostIdAndMemberIdAndType( - questionPost.getId(), interactor.getId(), type - )).willReturn(false); // 생성 given(questionPostRepository.findById(questionPost.getId())) .willReturn(Optional.of(questionPost)); given(interactionRepository.save(any(Interaction.class))) .willReturn(interaction); given(interactionCountRepository.findByQuestionPostIdAndType( - questionPost.getId(), type)).willReturn(Optional.of(interactionCount)); + questionPost.getId(), type) + ).willReturn(Optional.empty()); + given(interactionCountRepository.save(any(InteractionCount.class))) + .willReturn(interactionCount); //when - InteractionResponse response = interactionService.activateInteraction(1L, 2L, - type); + InteractionResponse response + = interactionService.activateInteraction(1L, interactor.getId(), type); //then assertAll( @@ -76,43 +76,37 @@ void activateInteraction_create1() { ); } - @DisplayName("[상호작용을 새로 활성화한다. 기존에 게시글 상호작용 수가 저장되어있지 않다.]") + @DisplayName("[다른 사람이 추천했던 게시글에 대해 추천한다.]") @Test void activateInteraction_create2() { //given - InteractionType type = InteractionType.RECOMMEND; QuestionPost questionPost = QuestionPostFixture.questionPost(1L, questioner); Interaction interaction = Interaction.of(type, interactor.getId(), questionPost.getId()); InteractionCount interactionCount = InteractionCount.of(type, interactor.getId()); - given(interactionRepository.existsByQuestionPostIdAndMemberIdAndType( - questionPost.getId(), interactor.getId(), type - )).willReturn(false); // 생성 given(questionPostRepository.findById(questionPost.getId())) .willReturn(Optional.of(questionPost)); given(interactionRepository.save(any(Interaction.class))) .willReturn(interaction); given(interactionCountRepository.findByQuestionPostIdAndType( - questionPost.getId(), type)).willReturn(Optional.empty()); - given(interactionCountRepository.save(any(InteractionCount.class))) - .willReturn(interactionCount); + questionPost.getId(), type) + ).willReturn(Optional.of(interactionCount)); //when - InteractionResponse response - = interactionService.activateInteraction(1L, 2L, type); + InteractionResponse response = interactionService + .activateInteraction(1L, interactor.getId(), type); //then assertAll( - () -> assertThat(response.count()).isEqualTo(1), + () -> assertThat(response.count()).isEqualTo(2), () -> assertThat(response.interactionType()).isEqualTo(type.getLabel()) ); } - @DisplayName("[비활성화된 상호작용을 재활성화한다.]") + @DisplayName("[기존에 추천 취소했던 게시글을 재추천한다.]") @Test void activateInteraction_update() { //given - InteractionType type = InteractionType.RECOMMEND; QuestionPost questionPost = QuestionPostFixture.questionPost(1L, questioner); Interaction interaction = InteractionFixture.interaction(1L, type, interactor.getId(), questionPost.getId()); @@ -121,21 +115,22 @@ void activateInteraction_update() { interaction.updateIsInteracted(false); interactionCount.decreaseCount(); - given(interactionRepository.existsByQuestionPostIdAndMemberIdAndType( - questionPost.getId(), interactor.getId(), type - )).willReturn(true); // 업데이트 + given(questionPostRepository.findById(questionPost.getId())) + .willReturn(Optional.of(questionPost)); + given(interactionRepository.findByQuestionPostIdAndMemberIdAndType( questionPost.getId(), interactor.getId(), type )).willReturn(Optional.of(interaction)); + given(interactionCountRepository.findByQuestionPostIdAndType( interactionCount.getId(), type)) .willReturn(Optional.of(interactionCount)); //when - InteractionResponse response = interactionService.activateInteraction(1L, 2L, - type); + InteractionResponse response = + interactionService.activateInteraction(1L, interactor.getId(), type); //then assertAll( @@ -144,29 +139,30 @@ void activateInteraction_update() { ); } - @DisplayName("[활성화된 상호작용을 비활성화한다.]") + @DisplayName("[게시글 추천을 취소한다.]") @Test void inactivateInteraction() { //given - InteractionType type = InteractionType.RECOMMEND; QuestionPost questionPost = QuestionPostFixture.questionPost(1L, questioner); - Interaction interaction = InteractionFixture.interaction(1L, type, interactor.getId(), - questionPost.getId()); - InteractionCount interactionCount = InteractionCountFixture.interactionCount(1L, type, - interactor.getId()); + Interaction interaction = InteractionFixture.interaction( + 1L, type, interactor.getId(), questionPost.getId() + ); + InteractionCount interactionCount = + InteractionCountFixture.interactionCount(1L, type, interactor.getId()); given(interactionRepository.findByQuestionPostIdAndMemberIdAndType( questionPost.getId(), interactor.getId(), type )).willReturn(Optional.of(interaction)); + given(interactionCountRepository.findByQuestionPostIdAndType( - interactionCount.getId(), type)) - .willReturn(Optional.of(interactionCount)); + interactionCount.getId(), type) + ).willReturn(Optional.of(interactionCount)); //when - InteractionResponse response = interactionService.inactivateInteraction(1L, 2L, - type); + InteractionResponse response = interactionService + .inactivateInteraction(1L, interactor.getId(), type); //then assertAll(