Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OING-379] feat: 알림 목록 조회 기능 추가 #280

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
2 changes: 2 additions & 0 deletions common/src/main/java/com/oing/domain/BaseEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

Expand All @@ -18,6 +19,7 @@
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
@Setter
public class BaseEntity {
@CreatedDate
@Column(name = "created_at", updatable = false, nullable = false)
Expand Down
4 changes: 4 additions & 0 deletions common/src/main/java/com/oing/service/MemberBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public interface MemberBridge {
*/
boolean isDeletedMember(String memberId);

boolean isBirthDayMember(String memberId);

List<String> getFamilyMembersIdsByFamilyId(String familyId);

String getMemberNameByMemberId(String memberId);
Expand All @@ -42,5 +44,7 @@ public interface MemberBridge {

List<String> getFamilyMemberProfileImgUrlsByFamilyId(String familyId);

String getMemberProfileImgUrlByMemberId(String memberId);

int getFamilyMemberCountByFamilyId(String familyId);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.oing.controller;

import com.oing.domain.ProfileStyle;
import com.oing.dto.response.NotificationResponse;
import com.oing.restapi.UserNotificationHistoryApi;
import com.oing.service.UserNotificationHistoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;

import java.time.ZonedDateTime;
import java.util.List;

@RequiredArgsConstructor
@Controller
public class UserNotificationHistoryController implements UserNotificationHistoryApi {

private final UserNotificationHistoryService userNotificationHistoryService;

@Override
public List<NotificationResponse> getMyRecentNotifications(String loginMemberId) {
return userNotificationHistoryService.getRecentUserNotifications(loginMemberId);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.oing.domain;

public enum NotificationStyle {
public enum ProfileStyle {
BIRTHDAY, NONE;
}
40 changes: 40 additions & 0 deletions gateway/src/main/java/com/oing/domain/UserNotificationHistory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.oing.domain;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity(name = "user_notification_history")
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
@AllArgsConstructor
@Getter
@Builder
@Table(indexes = {
@Index(name = "user_notification_history_idx1", columnList = "sender_member_id"),
@Index(name = "user_notification_history_idx2", columnList = "receiver_member_id")
})
public class UserNotificationHistory extends BaseEntity {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저희 플젝에서 회원은 Member로 나타내고 있어서 통일성을 위해 User 대신 MemberNotificationHistory로 바꾸는 건 어떠신가요??

@Id
@Column(name = "user_notification_history_id", columnDefinition = "CHAR(26)", nullable = false)
private String id;

@Column(name = "title", nullable = false)
private String title;

@Column(name = "content", nullable = false)
private String content;

@Column(name = "aos_deep_link")
private String aosDeepLink;

@Column(name = "ios_deep_link")
private String iosDeepLink;

@Column(name = "sender_member_id", columnDefinition = "CHAR(26)", nullable = false)
private String senderMemberId;

@Column(name = "receiver_member_id", columnDefinition = "CHAR(26)", nullable = false)
private String receiverMemberId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.oing.dto.request;

import com.oing.domain.UserNotificationHistory;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

@Schema(description = "유저 알림 이력 생성 요청")
public record CreateUserNotificationHistoryDTO(
@NotBlank
@Schema(description = "알림 제목", example = "엄마님이 내 생존신고에 댓글을 달았어요")
String title,

@NotBlank
@Schema(description = "알림 내용", example = "우와~ 맛있겠다!!")
String content,

@Schema(description = "AOS 딥링크", example = "post/view/123?openComment=true")
String aosDeepLink,

@Schema(description = "iOS 딥링크", example = "post/view/123?openComment=true&dateOfPost=2024-12-24")
String iosDeepLink,

@Size(min = 26, max = 26)
@Schema(description = "알림 전송자 유저 ID", example = "01HGW2N7EHJVJ4CJ999RRS2E97")
String senderMemberId,

@Size(min = 26, max = 26)
@Schema(description = "알림 수신자 유저 ID", example = "01HGW2N7EHJVJ4CJ999RRS2E97")
String receiverMemberId
) {
public UserNotificationHistory toEntity(String id) {
return UserNotificationHistory.builder()
.id(id)
.title(title)
.content(content)
.aosDeepLink(aosDeepLink)
.iosDeepLink(iosDeepLink)
.senderMemberId(senderMemberId)
.receiverMemberId(receiverMemberId)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package com.oing.dto.response;

import com.oing.domain.NotificationStyle;
import com.oing.domain.ProfileStyle;
import com.oing.domain.UserNotificationHistory;
import io.swagger.v3.oas.annotations.media.Schema;

import java.time.ZoneId;
import java.time.ZonedDateTime;

@Schema(description = "알림 응답")
public record NotificationResponse(
@Schema(description = "노티 ID", example = "01HGW2N7EHJVJ4CJ999RRS2E97")
String notificationId,

@Schema(description = "발송자 이미지 url", example = "https://..")
String senderImageUrl,
@Schema(description = "발송자 프로필 이미지 url", example = "https://..")
String senderProfileImageUrl,

@Schema(description = "알림 스타일", example = "BIRTHDAY")
NotificationStyle style,
@Schema(description = "발송자 프로필 스타일", example = "BIRTHDAY")
ProfileStyle sencerProfileStyle,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타가 있어요! senderProfileStyle로 바꿔주세요~


@Schema(description = "알림 제목", example = "우리 가족 모두가 생존신고를 완료했어요")
String title,
Expand All @@ -31,4 +33,16 @@ public record NotificationResponse(
@Schema(description = "알림 생성 시간", example = "2023-12-23T01:53:21.577347+09:00")
ZonedDateTime createdAt
) {
public static NotificationResponse of(UserNotificationHistory userNotificationHistory, String senderProfileImageUrl, ProfileStyle profileStyle) {
return new NotificationResponse(
userNotificationHistory.getId(),
senderProfileImageUrl,
profileStyle,
userNotificationHistory.getTitle(),
userNotificationHistory.getContent(),
userNotificationHistory.getIosDeepLink(),
userNotificationHistory.getAosDeepLink(),
userNotificationHistory.getCreatedAt().atZone(ZoneId.systemDefault())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import com.oing.domain.Member;
import com.oing.domain.Post;
import com.oing.domain.PostType;
import com.oing.service.FCMNotificationService;
import com.oing.service.MemberDeviceService;
import com.oing.service.MemberService;
import com.oing.service.PostService;
import com.oing.service.*;
import com.oing.util.FCMNotificationUtil;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
Expand All @@ -24,10 +21,12 @@
@Component
@RequiredArgsConstructor
public class FamilyNotificationEventListener {

public final MemberService memberService;
private final MemberDeviceService memberDeviceService;
private final FCMNotificationService fcmNotificationService;
private final PostService memberPostService;
private final UserNotificationHistoryService userNotificationHistoryService;

@Transactional(Transactional.TxType.REQUIRES_NEW)
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
Expand Down Expand Up @@ -59,12 +58,17 @@ public void onPostCreatedEvent(PostCreatedEvent postCreatedEvent) {
fcmNotificationService.sendMulticastMessage(multicastMessage);

if(memberPostService.isNewPostMadeMissionUnlocked(familyId)) {
sendMissionUnlockedMessages(familyMemberIds);
onMissionUnlockedEvent(familyMemberIds);
}
}
}
}

private void onMissionUnlockedEvent(List<String> familyMemberIds) {
userNotificationHistoryService.appendMissionUnlockedNotiHistory(familyMemberIds);
sendMissionUnlockedMessages(familyMemberIds);
}

private void sendMissionUnlockedMessages(List<String> familyMemberIds) {
// 방금 막 미션이 언락 되었다면..
HashSet<String> missionTargetFcmTokens = new HashSet<>();
Expand All @@ -91,8 +95,18 @@ public void onPostCommentCreatedEvent(CommentCreatedEvent commentCreatedEvent) {
Post sourcePost = comment.getPost();
String postAuthorId = sourcePost.getMemberId(); //게시물 작성자 ID
Member author = memberService.getMemberByMemberId(comment.getMemberId()); //댓글 작성자
String aosDeepLink = "post/view/" + sourcePost.getId() + "?openComment=true"; //트리거된 게시글의 댓글창 딥링크
String iosDeepLink = "post/view/" + sourcePost.getId() + "?openComment=true&dateOfPost=" + sourcePost.getCreatedAt().toLocalDate().toString();

// 댓글이 달린 게시물 작성자 알림
if (!postAuthorId.equals(comment.getMemberId())) { //내가 내 게시물에 단 댓글이 아니라면

// 알림 이력 적재
userNotificationHistoryService.appendCommentNotiHistory(
author.getName(), comment.getContent(), comment.getMemberId(), postAuthorId, aosDeepLink, iosDeepLink
);

// FCM 알림 발송
List<String> targetFcmTokens = memberDeviceService.getFcmTokensByMemberId(postAuthorId);
if(!targetFcmTokens.isEmpty()) {
MulticastMessage multicastMessage = MulticastMessage.builder()
Expand All @@ -101,17 +115,18 @@ public void onPostCommentCreatedEvent(CommentCreatedEvent commentCreatedEvent) {
String.format("%s님이 내 피드에 남긴 댓글", author.getName()),
String.format("\"%s\"", comment.getContent()))
)
.putData("aosDeepLink", "post/view/" + sourcePost.getId() + "?openComment=true")
.putData("iosDeepLink", "post/view/" + sourcePost.getId() + "?openComment=true&dateOfPost="
+ sourcePost.getCreatedAt().toLocalDate().toString())
.putData("aosDeepLink", aosDeepLink)
.putData("iosDeepLink", iosDeepLink)
.addAllTokens(targetFcmTokens)
.setApnsConfig(FCMNotificationUtil.buildApnsConfig())
.setAndroidConfig(FCMNotificationUtil.buildAndroidConfig())
.build();
fcmNotificationService.sendMulticastMessage(multicastMessage);
}

}

// 게시물 댓글 연관자들 알림
Set<String> relatedMemberIds =
sourcePost.getComments().stream().map(Comment::getMemberId).collect(Collectors.toSet());
relatedMemberIds.remove(comment.getMemberId()); // 댓글 단 사람은 제외
Expand All @@ -123,15 +138,15 @@ public void onPostCommentCreatedEvent(CommentCreatedEvent commentCreatedEvent) {
}

if (targetFcmTokens.isEmpty()) return;
// FCM 알림 발송
MulticastMessage multicastMessage = MulticastMessage.builder()
.setNotification(
FCMNotificationUtil.buildNotification(
String.format("%s님의 댓글", author.getName()),
String.format("\"%s\"", comment.getContent()))
)
.putData("aosDeepLink", "post/view/" + sourcePost.getId() + "?openComment=true")
.putData("iosDeepLink", "post/view/" + sourcePost.getId() + "?openComment=true&dateOfPost="
+ sourcePost.getCreatedAt().toLocalDate().toString())
.putData("aosDeepLink", aosDeepLink)
.putData("iosDeepLink", iosDeepLink)
.addAllTokens(targetFcmTokens)
.setApnsConfig(FCMNotificationUtil.buildApnsConfig())
.setAndroidConfig(FCMNotificationUtil.buildAndroidConfig())
Expand Down
Loading
Loading