diff --git a/src/main/java/com/dnd/gongmuin/chat/service/ChatRoomService.java b/src/main/java/com/dnd/gongmuin/chat/service/ChatRoomService.java index 69dced06..ffe4de2b 100644 --- a/src/main/java/com/dnd/gongmuin/chat/service/ChatRoomService.java +++ b/src/main/java/com/dnd/gongmuin/chat/service/ChatRoomService.java @@ -1,11 +1,14 @@ package com.dnd.gongmuin.chat.service; +import static com.dnd.gongmuin.notification.domain.NotificationType.*; + import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; @@ -33,6 +36,7 @@ import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.member.exception.MemberErrorCode; import com.dnd.gongmuin.member.repository.MemberRepository; +import com.dnd.gongmuin.notification.dto.NotificationEvent; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.dto.response.MemberInfo; import com.dnd.gongmuin.question_post.exception.QuestionPostErrorCode; @@ -49,6 +53,7 @@ public class ChatRoomService { private final ChatRoomRepository chatRoomRepository; private final MemberRepository memberRepository; private final QuestionPostRepository questionPostRepository; + private final ApplicationEventPublisher eventPublisher; private static void validateIfAnswerer(Member member, ChatRoom chatRoom) { if (!Objects.equals(member.getId(), chatRoom.getAnswerer().getId())) { @@ -68,10 +73,17 @@ public PageResponse getChatMessages(Long chatRoomId, Pageab public ChatRoomDetailResponse createChatRoom(CreateChatRoomRequest request, Member inquirer) { QuestionPost questionPost = getQuestionPostById(request.questionPostId()); Member answerer = getMemberById(request.answererId()); + + ChatRoom chatRoom = chatRoomRepository.save( + ChatRoomMapper.toChatRoom(questionPost, inquirer, answerer) + ); + + eventPublisher.publishEvent( + new NotificationEvent(CHAT_REQUEST, chatRoom.getId(), inquirer.getId(), answerer) + ); + return ChatRoomMapper.toChatRoomDetailResponse( - chatRoomRepository.save( - ChatRoomMapper.toChatRoom(questionPost, inquirer, answerer) - ), + chatRoom, answerer ); } @@ -120,6 +132,10 @@ public AcceptChatResponse acceptChat(Long chatRoomId, Member member) { validateIfAnswerer(member, chatRoom); chatRoom.updateStatusAccepted(); + eventPublisher.publishEvent( + new NotificationEvent(CHAT_ACCEPT, chatRoom.getId(), member.getId(), chatRoom.getInquirer()) + ); + return ChatRoomMapper.toAcceptChatResponse(chatRoom); } @@ -129,6 +145,10 @@ public RejectChatResponse rejectChat(Long chatRoomId, Member member) { validateIfAnswerer(member, chatRoom); chatRoom.updateStatusRejected(); + eventPublisher.publishEvent( + new NotificationEvent(CHAT_REJECT, chatRoom.getId(), member.getId(), chatRoom.getInquirer()) + ); + return ChatRoomMapper.toRejectChatResponse(chatRoom); } diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java index 66ce4f66..09bd9ee9 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java @@ -14,7 +14,9 @@ public enum NotificationType { ANSWER("답변"), CHOSEN("채택"), - CHAT("채팅"); + CHAT_REQUEST("채팅신청"), + CHAT_REJECT("채팅거절"), + CHAT_ACCEPT("채팅수락"); private final String label; diff --git a/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java b/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java index ddf00f78..4fc567cd 100644 --- a/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java @@ -13,6 +13,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.SliceImpl; import org.springframework.test.util.ReflectionTestUtils; @@ -36,6 +37,7 @@ import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.member.exception.MemberErrorCode; import com.dnd.gongmuin.member.repository.MemberRepository; +import com.dnd.gongmuin.notification.dto.NotificationEvent; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; @@ -57,6 +59,9 @@ class ChatRoomServiceTest { @Mock private QuestionPostRepository questionPostRepository; + @Mock + private ApplicationEventPublisher eventPublisher; + @InjectMocks private ChatRoomService chatRoomService; @@ -107,6 +112,37 @@ void createChatRoom() { ); } + @DisplayName("[요청자가 채팅방을 생성 시 생성 알림이 발행된다.]") + @Test + void createChatRoomWithEventPublish() { + //given + Member inquirer = MemberFixture.member(1L); + Member answerer = MemberFixture.member(2L); + QuestionPost questionPost = QuestionPostFixture.questionPost(inquirer); + CreateChatRoomRequest request = new CreateChatRoomRequest( + questionPost.getId(), + answerer.getId() + ); + ChatRoom chatRoom = ChatRoomFixture.chatRoom(questionPost, inquirer, answerer); + + given(questionPostRepository.findById(questionPost.getId())) + .willReturn(Optional.of(questionPost)); + given(memberRepository.findById(answerer.getId())) + .willReturn(Optional.of(answerer)); + given(chatRoomRepository.save(any(ChatRoom.class))) + .willReturn(chatRoom); + + //when + ChatRoomDetailResponse response = chatRoomService.createChatRoom(request, inquirer); + + //then + assertAll( + () -> assertThat(response.questionPostId()).isEqualTo(request.questionPostId()), + () -> assertThat(response.receiverInfo().memberId()).isEqualTo(request.answererId()), + () -> verify(eventPublisher, times(1)).publishEvent(any(NotificationEvent.class)) + ); + } + @DisplayName("[요청자의 크레딧이 2000미만이면 채팅방을 생성할 수 없다.]") @Test void createChatRoom_fail() { @@ -229,6 +265,33 @@ void acceptChat() { ); } + @DisplayName("[답변자가 채팅 요청을 수락할 때 채팅 수락 알림이 발행된다.]") + @Test + void acceptChatWithEventPublish() { + //given + Long chatRoomId = 1L; + Member inquirer = MemberFixture.member(1L); + Member answerer = MemberFixture.member(2L); + int previousCredit = answerer.getCredit(); + QuestionPost questionPost = QuestionPostFixture.questionPost(inquirer); + ChatRoom chatRoom = ChatRoomFixture.chatRoom(questionPost, inquirer, answerer); + + given(chatRoomRepository.findById(chatRoomId)) + .willReturn(Optional.of(chatRoom)); + + //when + AcceptChatResponse response = chatRoomService.acceptChat(chatRoomId, answerer); + + //then + assertAll( + () -> assertThat(response.chatStatus()) + .isEqualTo(ChatStatus.ACCEPTED.getLabel()), + () -> assertThat(response.credit()) + .isEqualTo(previousCredit + CHAT_REWARD), + () -> verify(eventPublisher, times(1)).publishEvent(any(NotificationEvent.class)) + ); + } + @DisplayName("[답변자가 채팅 요청을 거절할 수 있다.]") @Test void rejectChat() { @@ -249,4 +312,27 @@ void rejectChat() { assertThat(response.chatStatus()) .isEqualTo(ChatStatus.REJECTED.getLabel()); } + + @DisplayName("[답변자가 채팅 요청을 거절할 때 채팅 거절 알림이 발행된다.]") + @Test + void rejectChatWithEventPublish() { + //given + Long chatRoomId = 1L; + Member inquirer = MemberFixture.member(1L); + Member answerer = MemberFixture.member(2L); + QuestionPost questionPost = QuestionPostFixture.questionPost(inquirer); + ChatRoom chatRoom = ChatRoomFixture.chatRoom(questionPost, inquirer, answerer); + + given(chatRoomRepository.findById(chatRoomId)) + .willReturn(Optional.of(chatRoom)); + + //when + RejectChatResponse response = chatRoomService.rejectChat(chatRoomId, answerer); + + //then + assertAll( + () -> assertThat(response.chatStatus()).isEqualTo(ChatStatus.REJECTED.getLabel()), + () -> verify(eventPublisher, times(1)).publishEvent(any(NotificationEvent.class)) + ); + } } \ No newline at end of file