Skip to content

Commit

Permalink
Merge pull request #85 from Team-Shaka/feature/84
Browse files Browse the repository at this point in the history
✨ Feat: 알림 조회 문구의 구체화 및 읽음 처리 기능
  • Loading branch information
HyoBN authored Jul 23, 2024
2 parents 7fdfeac + 741d4fd commit 617bb61
Show file tree
Hide file tree
Showing 13 changed files with 231 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import treehouse.server.api.comment.presentation.dto.CommentRequestDTO;
import treehouse.server.api.comment.presentation.dto.CommentResponseDTO;
import treehouse.server.api.member.implementation.MemberQueryAdapter;
import treehouse.server.api.notification.business.NotificationService;
import treehouse.server.api.notification.presentation.dto.NotificationRequestDTO;
import treehouse.server.api.post.implement.PostQueryAdapter;
import treehouse.server.api.reaction.business.ReactionMapper;
import treehouse.server.api.reaction.implementation.ReactionCommandAdapter;
Expand All @@ -28,6 +30,7 @@
import treehouse.server.global.entity.comment.Comment;
import treehouse.server.global.entity.comment.CommentType;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.notification.NotificationType;
import treehouse.server.global.entity.post.Post;
import treehouse.server.global.entity.reaction.Reaction;
import treehouse.server.global.entity.report.Report;
Expand Down Expand Up @@ -63,6 +66,8 @@ public class CommentService {

private final BranchQueryAdapter branchQueryAdapter;

private final NotificationService notificationService;


public void reportComment(User user, CommentRequestDTO.reportComment request, Long treehouseId, Long postId, Long commentId){

Expand Down Expand Up @@ -161,6 +166,14 @@ public CommentResponseDTO.CommentIdResponseDto createComment(User user, Long tre

Comment comment = CommentMapper.toComment(writer, post, request.getContext(), CommentType.PARENT, -1L);
Long commentId = commentCommandAdapter.createComment(comment).getId();

//알림 생성
NotificationRequestDTO.createNotification notificationRequest = new NotificationRequestDTO.createNotification();
notificationRequest.setReceiverId(post.getWriter().getId()); // 여기서 receiver 설정 (예시)
notificationRequest.setTargetId(post.getId());
notificationRequest.setType(NotificationType.COMMENT); // 알림 타입 설정 (예시)
notificationService.createNotification(user, treehouseId, notificationRequest, null);

return CommentMapper.toIdResponseDto(commentId);
}

Expand All @@ -175,6 +188,13 @@ public CommentResponseDTO.CommentIdResponseDto createReply(User user, Long treeh

Comment comment = CommentMapper.toComment(writer, post, request.getContext(), CommentType.CHILD, parentId);
Long replyId = commentCommandAdapter.createComment(comment).getId();
//알림 생성
NotificationRequestDTO.createNotification notificationRequest = new NotificationRequestDTO.createNotification();
notificationRequest.setReceiverId(comment.getWriter().getId()); // 여기서 receiver 설정 (예시)
notificationRequest.setTargetId(comment.getId());
notificationRequest.setType(NotificationType.REPLY); // 알림 타입 설정 (예시)
notificationService.createNotification(user, treehouseId, notificationRequest, null);

return CommentMapper.toIdResponseDto(replyId);
}

Expand Down Expand Up @@ -208,6 +228,13 @@ public String reactToComment(User user, Long treehouseId, Long commentId, Commen

member.addReaction(savedReaction);

//알림 생성
NotificationRequestDTO.createNotification notificationRequest = new NotificationRequestDTO.createNotification();
notificationRequest.setReceiverId(comment.getWriter().getId()); // 여기서 receiver 설정 (예시)
notificationRequest.setTargetId(comment.getId());
notificationRequest.setType(NotificationType.COMMENT_REACTION); // 알림 타입 설정 (예시)
notificationService.createNotification(user, treehouseId, notificationRequest, savedReaction.getReactionName());

return request.getReactionName() + " is saved";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
import treehouse.server.api.invitation.presentation.dto.InvitationRequestDTO;
import treehouse.server.api.invitation.presentation.dto.InvitationResponseDTO;
import treehouse.server.api.member.implementation.MemberQueryAdapter;
import treehouse.server.api.notification.business.NotificationService;
import treehouse.server.api.notification.presentation.dto.NotificationRequestDTO;
import treehouse.server.api.treehouse.implementation.TreehouseQueryAdapter;
import treehouse.server.api.user.implement.UserQueryAdapter;
import treehouse.server.global.entity.Invitation.Invitation;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.notification.NotificationType;
import treehouse.server.global.entity.treeHouse.TreeHouse;
import treehouse.server.global.exception.GlobalErrorCode;
import treehouse.server.global.exception.ThrowClass.InvitationException;
Expand All @@ -38,6 +41,8 @@ public class InvitationService {

private final UserQueryAdapter userQueryAdapter;

private final NotificationService notificationService;

private static final Integer treeMemberRandomProfileSize = 3;


Expand Down Expand Up @@ -84,6 +89,13 @@ public InvitationResponseDTO.createInvitation createInvitation(User user, Invita

Invitation invitation = invitationCommandAdapter.saveInvitation(InvitationMapper.toInvitation(request.getPhoneNumber(), sender, receiverUser, treehouse));

//알림 생성
NotificationRequestDTO.createNotification notificationRequest = new NotificationRequestDTO.createNotification();
notificationRequest.setReceiverId(receiverUser.getId()); // 여기서 receiver 설정 (예시)
notificationRequest.setTargetId(invitation.getId());
notificationRequest.setType(NotificationType.INVITATION); // 알림 타입 설정 (예시)
notificationService.createNotification(user, invitation.getTreeHouse().getId(), notificationRequest, null);

// 리턴하기

return InvitationMapper.toCreateInvitationDTO(invitation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,41 @@

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import treehouse.server.api.notification.presentation.dto.NotificationRequestDTO;
import treehouse.server.api.notification.presentation.dto.NotificationResponseDTO;
import treehouse.server.global.common.util.TimeFormatter;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.notification.Notification;
import treehouse.server.global.entity.notification.NotificationType;

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

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NotificationMapper {

public static Notification toNotification(Member sender, Member receiver, NotificationRequestDTO.createNotification request, String reactionName) {

return Notification.builder()
.sender(sender)
.receiver(receiver)
.type(request.getType())
.targetId(request.getTargetId())
.title(NotificationUtil.getTitle(request.getType()))
.body(NotificationUtil.getBody(request.getType(), sender, request.getTargetId(), reactionName))
.receivedTime(LocalDateTime.now())
.build();
}

public static NotificationResponseDTO.getNotification toGetNotification(Notification notification, User user) {
return NotificationResponseDTO.getNotification.builder()
.type(notification.getType())
.profileImageUrl(notification.getSender().getProfileImageUrl())
.userName(notification.getSender().getName())
.receivedTime(String.valueOf(notification.getReceivedTime()))
.title(notification.getTitle())
.body(notification.getBody())
.receivedTime(TimeFormatter.format(notification.getReceivedTime()))
.treehouseId(notification.getSender().getTreeHouse().getId())
.treehouseName(notification.getSender().getTreeHouse().getName())
.isChecked(notification.isChecked())
Expand All @@ -29,4 +49,10 @@ public static NotificationResponseDTO.getNotifications toGetNotifications(List<N
.notifications(notificationDtos)
.build();
}

public static NotificationResponseDTO.readNotification toReadNotification(Notification notification) {
return NotificationResponseDTO.readNotification.builder()
.notificationId(notification.getId())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import treehouse.server.api.member.implementation.MemberQueryAdapter;
import treehouse.server.api.notification.implement.NotificationCommandAdapter;
import treehouse.server.api.notification.implement.NotificationQueryAdapter;
import treehouse.server.api.notification.presentation.dto.NotificationRequestDTO;
import treehouse.server.api.notification.presentation.dto.NotificationResponseDTO;
import treehouse.server.api.treehouse.implementation.TreehouseQueryAdapter;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.notification.Notification;
import treehouse.server.global.entity.treeHouse.TreeHouse;

import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -18,8 +23,29 @@
@Slf4j
public class NotificationService {

private final NotificationCommandAdapter notificationCommandAdapter;
private final NotificationQueryAdapter notificationQueryAdapter;

private final MemberQueryAdapter memberQueryAdapter;

private final TreehouseQueryAdapter treehouseQueryAdapter;

/**
* 알림 생성하는 로직
* @param user
* @return
*/

@Transactional
public void createNotification(User user, Long treehouseId, NotificationRequestDTO.createNotification request, String reactionName) {
TreeHouse treeHouse = treehouseQueryAdapter.getTreehouseById(treehouseId);
Member sender = memberQueryAdapter.findByUserAndTreehouse(user, treeHouse);
Member receiver = memberQueryAdapter.findById(request.getReceiverId());

Notification notification = NotificationMapper.toNotification(sender, receiver, request, reactionName);
notificationCommandAdapter.createNotification(notification);
}

/**
* 사용자의 알림을 조회하는 로직
* @param user
Expand All @@ -40,4 +66,16 @@ public NotificationResponseDTO.getNotifications getNotifications(User user){ //@
.collect(Collectors.toList());
return NotificationMapper.toGetNotifications(notificationDtos);
}

/**
* 사용자의 알림을 읽음 처리하는 로직
* @param user
* @return
*/
@Transactional
public NotificationResponseDTO.readNotification readNotification(User user, Long notificationId){
Notification notification = notificationQueryAdapter.findById(notificationId);
notificationCommandAdapter.readNotification(notification);
return NotificationMapper.toReadNotification(notification);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package treehouse.server.api.notification.business;

import org.apache.commons.lang3.function.TriFunction;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.notification.NotificationType;

import java.util.EnumMap;
import java.util.Map;

public class NotificationUtil {

private static final Map<NotificationType, String> titleMap = new EnumMap<>(NotificationType.class);
private static final Map<NotificationType, TriFunction<Member, Long, String, String>> bodyMap = new EnumMap<>(NotificationType.class);

static {
titleMap.put(NotificationType.COMMENT, "댓글 알림");
titleMap.put(NotificationType.REPLY, "대댓글 알림");
titleMap.put(NotificationType.INVITATION, "초대 알림");
titleMap.put(NotificationType.POST_REACTION, "게시글 반응 알림");
titleMap.put(NotificationType.COMMENT_REACTION, "댓글 반응 알림");

bodyMap.put(NotificationType.COMMENT, (sender, targetId, reactionName) -> sender.getName() + " 님이 댓글을 남겼습니다.");
bodyMap.put(NotificationType.REPLY, (sender, targetId, reactionName) -> sender.getName() + " 님이 답글을 남겼습니다.");
bodyMap.put(NotificationType.INVITATION, (sender, targetId, reactionName) -> sender.getName() + " 님이 트리하우스에 초대했습니다.");
bodyMap.put(NotificationType.POST_REACTION, (sender, targetId, reactionName) -> sender.getName() + " 님이 게시글에 " + reactionName + "을(를) 눌렀습니다.");
bodyMap.put(NotificationType.COMMENT_REACTION, (sender, targetId, reactionName) -> sender.getName() + " 님이 댓글에 " + reactionName + "을(를) 눌렀습니다.");
}

public static String getTitle(NotificationType type) {
return titleMap.getOrDefault(type, "Notification");
}

public static String getBody(NotificationType type, Member sender, Long targetId, String reactionName) {
return bodyMap.getOrDefault(type, (s, t, r) -> "알림이 있습니다.").apply(sender, targetId, reactionName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import treehouse.server.api.notification.persistence.NotificationRepository;
import treehouse.server.global.annotations.Adapter;
import treehouse.server.global.entity.notification.Notification;

@Adapter
@RequiredArgsConstructor
@Slf4j
public class NotificationCommandAdapter {

private final NotificationRepository notificationRepository;

public void createNotification(Notification notification){
notificationRepository.save(notification);
}

public void readNotification(Notification notification) {
notification.setChecked(true);
notificationRepository.save(notification);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package treehouse.server.api.notification.implement;

import lombok.RequiredArgsConstructor;
import treehouse.server.api.notification.persistence.NotificationRepository;
import treehouse.server.global.annotations.Adapter;
import treehouse.server.global.entity.notification.Notification;
import treehouse.server.global.exception.GlobalErrorCode;
import treehouse.server.global.exception.ThrowClass.NotificationException;

@Adapter
@RequiredArgsConstructor
public class NotificationQueryAdapter {

private final NotificationRepository notificationRepository;
public Notification findById(Long notificationId) {
return notificationRepository.findById(notificationId)
.orElseThrow(() -> new NotificationException(GlobalErrorCode.NOTIFICATION_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import treehouse.server.api.notification.business.NotificationService;
import treehouse.server.api.notification.presentation.dto.NotificationResponseDTO;
Expand All @@ -30,4 +32,13 @@ public CommonResponse<NotificationResponseDTO.getNotifications> getNotifications
){
return CommonResponse.onSuccess(notificationService.getNotifications(user));
}

@PostMapping("/users/notifications/{notificationId}")
@Operation(summary = "알림 확인 🔑 ✅", description = "사용자의 알림을 확인하여 '읽음' 상태로 변경합니다.")
public CommonResponse<NotificationResponseDTO.readNotification> readNotification(
@AuthMember @Parameter(hidden = true) User user,
@PathVariable Long notificationId
){
return CommonResponse.onSuccess(notificationService.readNotification(user, notificationId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package treehouse.server.api.notification.presentation.dto;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import treehouse.server.api.notification.business.NotificationService;
import treehouse.server.global.entity.notification.NotificationType;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NotificationRequestDTO {

@Getter
@Setter
public static class createNotification {

private String title;
private String body;
private NotificationType type;
private Long targetId;
private Long receiverId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class NotificationResponseDTO {
@AllArgsConstructor
public static class getNotification {
private NotificationType type;
private String title;
private String body;
private String profileImageUrl;
private String userName;
private String receivedTime;
Expand All @@ -30,4 +32,12 @@ public static class getNotification {
public static class getNotifications {
List<NotificationResponseDTO.getNotification> notifications;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class readNotification {
private Long notificationId;
}
}
Loading

0 comments on commit 617bb61

Please sign in to comment.