Skip to content

Commit

Permalink
[FEAT] 채팅방 들어왔을 때 해당 채팅방 알림 모두 읽기 (#164)
Browse files Browse the repository at this point in the history
* style: 코드 포맷팅

* feat: 특정 채팅방에 대한 알림을 모두 읽는 서비스 메서드 구현

* feat: 회원과 url에 해당하는 알림을 모두 읽는 벌크 쿼리 구현

* refactor: 다른 서비스들처럼 findByIdOrThrow 메서드 분리

* feat: 리터럴 상수를 관리하는 BuddyBridgeStatic 클래스 구현

- 채팅방, 게시글 URL 접두사 상수 정의
- 알림 메시지 포맷 상수 정의
- 알림 URL 생성을 위한 유틸리티 메서드 추가

* style: 불필요한 공백 제거
  • Loading branch information
Profile-exe authored Sep 27, 2024
1 parent 5a676de commit 6987c52
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package econo.buddybridge.chat.chatmessage.service;

import static econo.buddybridge.common.consts.BuddyBridgeStatic.CHAT_NOTIFICATION_MESSAGE;
import static econo.buddybridge.common.consts.BuddyBridgeStatic.CHAT_NOTIFICATION_URL;

import econo.buddybridge.chat.chatmessage.dto.ChatMessageReqDto;
import econo.buddybridge.chat.chatmessage.dto.ChatMessageResDto;
import econo.buddybridge.chat.chatmessage.entity.ChatMessage;
Expand All @@ -12,13 +15,12 @@
import econo.buddybridge.member.service.MemberService;
import econo.buddybridge.notification.entity.NotificationType;
import econo.buddybridge.notification.service.EmitterService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class ChatMessageService {
Expand Down Expand Up @@ -46,8 +48,8 @@ public ChatMessageResDto save(Long senderId, ChatMessageReqDto chatMessageReqDto

emitterService.send( // 채팅을 받는 사용자에게 알림 전송
receiver,
sender.getName() + "님이 메시지를 보냈습니다. - " + chatMessage.getContent(),
"/chat/" + matching.getId(),
String.format(CHAT_NOTIFICATION_MESSAGE, sender.getName(), chatMessage.getContent()),
String.format(CHAT_NOTIFICATION_URL, matching.getId()),
NotificationType.CHAT
);

Expand Down Expand Up @@ -91,5 +93,4 @@ public ChatMessageResDto getLastChatMessage(Long matchingId) {
.createdAt(chatMessage.getCreatedAt())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package econo.buddybridge.comment.service;

import static econo.buddybridge.common.consts.BuddyBridgeStatic.COMMENT_NOTIFICATION_MESSAGE;
import static econo.buddybridge.common.consts.BuddyBridgeStatic.getCommentNotificationUrl;

import econo.buddybridge.comment.dto.CommentCustomPage;
import econo.buddybridge.comment.dto.CommentReqDto;
import econo.buddybridge.comment.dto.MyPageCommentCustomPage;
Expand Down Expand Up @@ -70,25 +73,13 @@ public Long createComment(CommentReqDto commentReqDto, Long postId, Long memberI

private void sendNotificationToPostAuthor(Member member, Comment comment, Post post) {
// 알림 내용은 댓글 작성자 이름과 댓글 내용
String notificationContent = member.getName() + "님이 댓글을 남겼습니다. - " + comment.getContent();
String notificationContent = String.format(COMMENT_NOTIFICATION_MESSAGE, member.getName(), comment.getContent());
String notificationUrl = getCommentNotificationUrl(post.getPostType(), post.getId());

// 댓글 알림은 게시글 작성자에게 전송
emitterService.send(post.getAuthor(), notificationContent, notificationUrl, NotificationType.COMMENT);
}

private String getCommentNotificationUrl(PostType postType, Long postId) {
switch (postType) {
case TAKER -> { // 도와줄래요? 게시글
return "/help-me/" + postId;
}
case GIVER -> { // 도와줄게요! 게시글
return "/help-you/" + postId;
}
}
return "";
}

@Transactional // 댓글 수정
public Long updateComment(Long commentId, CommentReqDto commentReqDto, Long memberId) {
Comment comment = findCommentByIdOrThrow(commentId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package econo.buddybridge.common.consts;

import econo.buddybridge.post.entity.PostType;

public class BuddyBridgeStatic {

public static final String CHAT_ROOM_PREFIX = "/chat/";
public static final String POST_TAKER_PREFIX = "/help-me/";
public static final String POST_GIVER_PREFIX = "/help-you/";

public static final String CHAT_NOTIFICATION_MESSAGE = "%s님이 메시지를 보냈습니다. - %s";
public static final String COMMENT_NOTIFICATION_MESSAGE = "%s님이 댓글을 남겼습니다. - %s";

public static final String CHAT_NOTIFICATION_URL = CHAT_ROOM_PREFIX + "%d";
public static final String COMMENT_NOTIFICATION_URL_TAKER = POST_TAKER_PREFIX + "%d";
public static final String COMMENT_NOTIFICATION_URL_GIVER = POST_GIVER_PREFIX + "%d";

public static String getCommentNotificationUrl(PostType postType, Long postId) {
return PostType.TAKER.equals(postType)
? String.format(COMMENT_NOTIFICATION_URL_TAKER, postId)
: String.format(COMMENT_NOTIFICATION_URL_GIVER, postId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class MatchingRoomController {

// 채팅방 목록 조회
@Operation(summary = "채팅방 목록 조회", description = "채팅방 목록을 조회합니다.")
@GetMapping("")
@GetMapping
public ApiResponse<ApiResponse.CustomBody<MatchingCustomPage>> getAllMatchingRooms(
@RequestParam("limit") Integer size,
@RequestParam(value = "cursor", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime cursor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,44 @@
import econo.buddybridge.matching.repository.MatchingRepositoryCustom;
import econo.buddybridge.member.entity.Member;
import econo.buddybridge.member.service.MemberService;
import econo.buddybridge.notification.service.NotificationService;
import econo.buddybridge.post.entity.Post;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@RequiredArgsConstructor
public class MatchingRoomService {

private final MemberService memberService;
private final ChatMessageRepository chatMessageRepository;
private final MatchingRepositoryCustom matchingRepositoryCustom;
private final MatchingService matchingService;
private final NotificationService notificationService;

@Transactional
public MatchingCustomPage getMatchings(Long memberId, Integer size, LocalDateTime cursor, MatchingStatus matchingStatus){
PageRequest page = PageRequest.of(0,size);
public MatchingCustomPage getMatchings(Long memberId, Integer size, LocalDateTime cursor, MatchingStatus matchingStatus) {
PageRequest page = PageRequest.of(0, size);
return matchingRepositoryCustom.findMatchings(memberId, size, cursor, matchingStatus, page);
}

@Transactional // 메시지 조회
public ChatMessageCustomPage getMatchingRoomMessages(Long memberId, Long matchingId, Integer size, Long cursor){
public ChatMessageCustomPage getMatchingRoomMessages(Long memberId, Long matchingId, Integer size, Long cursor) {

// 사용자 확인 // TODO: 예외처리 필요, 사용자가 매칭방에 속해있지 않을 경우 500 발생
Matching matching = matchingService.findMatchingByIdOrThrow(matchingId);

if (!matching.getGiver().getId().equals(memberId) && !matching.getTaker().getId().equals(memberId)){
if (!matching.getGiver().getId().equals(memberId) && !matching.getTaker().getId().equals(memberId)) {
throw MatchingUnauthorizedAccessException.EXCEPTION;
}

Pageable pageable = PageRequest.of(0, size+1);
Pageable pageable = PageRequest.of(0, size + 1);
Slice<ChatMessage> chatMessagesSlice;

if (cursor == null) {
Expand All @@ -57,6 +58,8 @@ public ChatMessageCustomPage getMatchingRoomMessages(Long memberId, Long matchin
chatMessagesSlice = chatMessageRepository.findByMatchingIdAndIdGreaterThan(matchingId, cursor, pageable);
}

notificationService.markAsReadByMatchingRoom(memberId, matchingId); // 해당 매칭방의 알림을 읽음 처리

Post post = matching.getPost();

Member receiver = getReceiver(matching, memberId);
Expand Down Expand Up @@ -86,12 +89,12 @@ public ChatMessageCustomPage getMatchingRoomMessages(Long memberId, Long matchin

private Member getReceiver(Matching matching, Long memberId) {
Long receiverId;
if (matching.getGiver().getId().equals(memberId)){
if (matching.getGiver().getId().equals(memberId)) {
receiverId = matching.getTaker().getId();
} else {
receiverId = matching.getGiver().getId();
}

return memberService.findMemberByIdOrThrow(receiverId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
public interface NotificationRepository extends JpaRepository<Notification, Long>, NotificationRepositoryCustom {

@Modifying(flushAutomatically = true, clearAutomatically = true)
@Query("update Notification n set n.isRead = true where n.receiver.id = :memberId")
@Query("update Notification n set n.isRead = true where n.receiver.id = :memberId")
void markAllAsRead(@Param("memberId") Long memberId);

@Modifying(flushAutomatically = true, clearAutomatically = true)
@Query("update Notification n set n.isRead = true where n.receiver.id = :memberId and n.url = :url")
void markAsReadByMemberIdAndUrl(@Param("memberId") Long memberId, @Param("url") String url);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package econo.buddybridge.notification.service;

import static econo.buddybridge.common.consts.BuddyBridgeStatic.CHAT_NOTIFICATION_URL;

import econo.buddybridge.member.entity.Member;
import econo.buddybridge.member.service.MemberService;
import econo.buddybridge.notification.dto.NotificationCustomPage;
Expand Down Expand Up @@ -33,8 +35,7 @@ public NotificationCustomPage getNotifications(Long memberId, Integer size, Long
public void markAsRead(Long notificationId, Long memberId) {
Member member = memberService.findMemberByIdOrThrow(memberId);

Notification notification = notificationRepository.findById(notificationId)
.orElseThrow(() -> NotificationNotFoundException.EXCEPTION);
Notification notification = findNotificationByIdOrThrow(notificationId);

if (!notification.getReceiver().getId().equals(member.getId())) {
throw NotificationAccessDeniedException.EXCEPTION;
Expand All @@ -43,9 +44,21 @@ public void markAsRead(Long notificationId, Long memberId) {
notification.markAsRead();
}

private Notification findNotificationByIdOrThrow(Long notificationId) {
return notificationRepository.findById(notificationId)
.orElseThrow(() -> NotificationNotFoundException.EXCEPTION);
}

@Transactional
public void markAllAsRead(Long memberId) {
Member member = memberService.findMemberByIdOrThrow(memberId);
notificationRepository.markAllAsRead(member.getId());
}

@Transactional
public void markAsReadByMatchingRoom(Long memberId, Long matchingId) {
Member member = memberService.findMemberByIdOrThrow(memberId);
String chatRoomUrl = String.format(CHAT_NOTIFICATION_URL, matchingId);
notificationRepository.markAsReadByMemberIdAndUrl(member.getId(), chatRoomUrl);
}
}

0 comments on commit 6987c52

Please sign in to comment.