NotificationService.java
package qwerty.chaekit.service.notification;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import qwerty.chaekit.domain.group.ReadingGroup;
import qwerty.chaekit.domain.group.activity.discussion.Discussion;
import qwerty.chaekit.domain.group.activity.discussion.comment.DiscussionComment;
import qwerty.chaekit.domain.highlight.Highlight;
import qwerty.chaekit.domain.highlight.comment.HighlightComment;
import qwerty.chaekit.domain.member.publisher.PublisherProfile;
import qwerty.chaekit.domain.member.user.UserProfile;
import qwerty.chaekit.domain.member.user.UserProfileRepository;
import qwerty.chaekit.domain.notification.entity.Notification;
import qwerty.chaekit.domain.notification.entity.NotificationType;
import qwerty.chaekit.domain.notification.repository.NotificationJpaRepository;
import qwerty.chaekit.dto.notification.NotificationResponse;
import qwerty.chaekit.dto.page.PageResponse;
import qwerty.chaekit.global.enums.ErrorCode;
import qwerty.chaekit.global.exception.ForbiddenException;
import qwerty.chaekit.global.exception.NotFoundException;
import qwerty.chaekit.global.security.resolver.UserToken;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class NotificationService {
private final NotificationJpaRepository notificationJpaRepository;
private final UserProfileRepository userProfileRepository;
private final SimpMessagingTemplate simpMessagingTemplate;
@Transactional
public void createGroupJoinRequestNotification(UserProfile receiver, UserProfile sender, ReadingGroup group) {
String message = String.format("%s님이 %s 그룹에 가입을 요청했습니다.", sender.getNickname(), group.getName());
Notification notification = new Notification(receiver, sender, null,group, null,null,null,NotificationType.GROUP_JOIN_REQUEST, message);
notificationJpaRepository.save(notification);
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
@Transactional
public void createGroupJoinApprovedNotification(UserProfile receiver, UserProfile sender, ReadingGroup group) {
String message = String.format("%s 그룹의 가입 요청이 승인되었습니다.", group.getName());
Notification notification = new Notification(receiver, sender, null,group, null,null,null,NotificationType.GROUP_JOIN_APPROVED, message);
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
@Transactional
public void createGroupJoinRejectedNotification(UserProfile receiver, UserProfile sender, ReadingGroup group) {
String message = String.format("%s 그룹의 가입 요청이 거절되었습니다.", group.getName());
Notification notification = new Notification(receiver, sender,null, group, null,null,null,NotificationType.GROUP_JOIN_REJECTED, message);
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
// @Transactional
// public void createPublisherJoinRequestNotification(UserProfile admin, PublisherProfile publisher) {
// String message = String.format("%s님이 출판사 가입을 요청했습니다.", publisher.getPublisherName());
// Notification notification = new Notification(null,admin, publisher, null, null,null,null,NotificationType.PUBLISHER_JOIN_REQUEST, message);
// notificationJpaRepository.save(notification);
// }
@Transactional
public void createPublisherApprovedNotification(PublisherProfile publisher, UserProfile admin) {
String message = "출판사 가입이 승인되었습니다.";
Notification notification = new Notification(admin,null,publisher, null,null, null,null,NotificationType.PUBLISHER_APPROVED, message);
notificationJpaRepository.save(notification);
}
// @Transactional
// public void createPublisherRejectedNotification(PublisherProfile publisher, UserProfile admin) {
// String message = "출판사 가입이 거절되었습니다.";
// Notification notification = new Notification(null, admin, publisher,null, null,null,null,NotificationType.PUBLISHER_REJECTED, message);
// notificationJpaRepository.save(notification);
// }
@Transactional
public void createDiscussionCommentNotification(UserProfile receiver, UserProfile sender, Discussion discussion) {
String message = String.format("%s님이 %s 토론에 댓글을 달았습니다.", sender.getNickname(), discussion.getTitle());
Notification notification = new Notification(receiver, sender, null, null,null,discussion ,null,NotificationType.DISCUSSION_COMMENT, message);
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
@Transactional
public void createCommentReplyNotification(UserProfile receiver, UserProfile sender, DiscussionComment comment) {
String message = String.format("%s님이 내 토론 댓글에 답글을 달았습니다.", sender.getNickname());
Notification notification = new Notification(receiver, sender, null, null,null,comment.getDiscussion(),comment,NotificationType.COMMENT_REPLY, message);
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
@Transactional
public void createHighlightCommentNotification(UserProfile receiver, UserProfile sender, Highlight highlight) {
String message = String.format("%s님이 내 하이라이트에 댓글을 달았습니다.\n하이라이트 내용: %s",
sender.getNickname(),
highlight.getMemo());
Notification notification = new Notification(receiver, sender, null, null, highlight,null, null,NotificationType.HIGHLIGHT_COMMENT, message);
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
@Transactional
public void createHighlightCommentReplyNotification(UserProfile receiver, UserProfile sender, HighlightComment comment) {
String message = String.format("%s님이 내 하이라이트 댓글에 답글을 달았습니다.\n하이라이트 내용: %s",
sender.getNickname(),
comment.getHighlight().getMemo());
Notification notification = new Notification(receiver, sender, null, null, comment.getHighlight(),null,null, NotificationType.HIGHLIGHT_COMMENT_REPLY, message);
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
@Transactional
public void createGroupBannedNotification(UserProfile receiver, ReadingGroup group) {
String message = String.format("%s에서 추방되었습니다.", group.getName());
Notification notification = Notification.builder()
.receiver(receiver)
.group(group)
.type(NotificationType.GROUP_BANNED)
.message(message)
.build();
notificationJpaRepository.save(notification);
if (receiver != null) {
NotificationResponse response = NotificationResponse.of(notification);
simpMessagingTemplate.convertAndSend("/topic/notification/" + notification.getReceiver().getId(), response);
}
}
public PageResponse<NotificationResponse> getNotifications(UserToken userToken, Pageable pageable) {
UserProfile userProfile = userProfileRepository.findById(userToken.userId())
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
Page<Notification> notifications = notificationJpaRepository.findByReceiverOrderByCreatedAtDesc(userProfile, pageable);
Page<NotificationResponse> responsePage = notifications.map(NotificationResponse::of);
return PageResponse.of(responsePage);
}
@Transactional
public void markAsRead(UserToken userToken, Long notificationId) {
UserProfile userProfile = userProfileRepository.findById(userToken.userId())
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
Notification notification = notificationJpaRepository.findById(notificationId)
.orElseThrow(() -> new NotFoundException(ErrorCode.NOTIFICATION_NOT_FOUND));
if (!notification.getReceiver().getId().equals(userProfile.getId())) {
throw new ForbiddenException(ErrorCode.NOTIFICATION_NOT_YOURS);
}
notification.markAsRead();
}
}