-
Notifications
You must be signed in to change notification settings - Fork 1
[LNK-22] Leenk 생일 축하 알림 구현 #73
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
The head ref may contain hidden characters: "LNK-22-Leenk-\uC0DD\uC77C-\uCD95\uD558-\uC54C\uB9BC-\uAD6C\uD604"
Changes from 24 commits
5db50aa
980a955
c35a15e
fc961ce
18d543f
e0ffc48
91d824a
bf358e6
80612f9
35066a4
524fb34
7c558e1
3feed41
fb793ff
d582f97
90acd7a
4d79804
702e72a
1fe329a
c9520eb
536952b
a4de57c
5124e48
5fb7e38
90857c7
d2cfb5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package leets.leenk.domain.birthday.domain.service.scheduler; | ||
|
|
||
| import leets.leenk.domain.notification.application.usecase.BirthdayNotificationUsecase; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.scheduling.annotation.Scheduled; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| import java.time.LocalDate; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class BirthdayNotifyScheduler { | ||
|
|
||
| private final BirthdayNotificationUsecase birthdayNotificationUsecase; | ||
|
|
||
| @Scheduled(cron = "0 0 0 * * *") | ||
| public void sendBirthdayNotifications() { | ||
| LocalDate today = LocalDate.now(); | ||
| birthdayNotificationUsecase.announceUserBirthday(today); | ||
|
|
||
| birthdayNotificationUsecase.celebrateBirthday(today); | ||
|
|
||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package leets.leenk.domain.notification.application.mapper; | ||
|
|
||
| import leets.leenk.domain.birthday.domain.entity.BirthdayLetter; | ||
| import leets.leenk.domain.notification.domain.entity.Notification; | ||
| import leets.leenk.domain.notification.domain.entity.birthdayContent.BirthdayAnnouncementContent; | ||
| import leets.leenk.domain.notification.domain.entity.birthdayContent.BirthdayCelebrateContent; | ||
| import leets.leenk.domain.notification.domain.entity.birthdayContent.BirthdayLetterContent; | ||
| import leets.leenk.domain.notification.domain.entity.enums.NotificationType; | ||
| import leets.leenk.domain.user.domain.entity.User; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| public class BirthdayNotificationMapper { | ||
| public Notification toBirthdayAnnouncementNotification(User birthdayUser, User targetUser) { | ||
| return Notification.builder() | ||
| .userId(targetUser.getId()) | ||
| .notificationType(NotificationType.BIRTHDAY_ANNOUNCEMENT) | ||
| .content(toBirthdayAnnouncementContent(birthdayUser)) | ||
| .isRead(Boolean.FALSE) | ||
| .build(); | ||
| } | ||
|
|
||
| public Notification toBirthdayCelebrateNotification(User birthdayUser) { | ||
| return Notification.builder() | ||
| .userId(birthdayUser.getId()) | ||
| .notificationType(NotificationType.BIRTHDAY_CELEBRATE) | ||
| .content(toBirthdayCelebrateContent(birthdayUser)) | ||
| .isRead(Boolean.FALSE) | ||
| .build(); | ||
| } | ||
|
|
||
| public Notification toBirthdayLetterNotification(BirthdayLetter birthdayLetter) { | ||
| return Notification.builder() | ||
| .userId(birthdayLetter.getReceiver().getId()) | ||
| .notificationType(NotificationType.BIRTHDAY_LETTER) | ||
| .content(toBirthdayLetterContent(birthdayLetter)) | ||
| .isRead(Boolean.FALSE) | ||
| .build(); | ||
| } | ||
|
|
||
| private BirthdayAnnouncementContent toBirthdayAnnouncementContent(User birthdayUser) { | ||
| return BirthdayAnnouncementContent.builder() | ||
| .birthdayUserId(birthdayUser.getId()) | ||
| .birthdayUserName(birthdayUser.getName()) | ||
| .title(NotificationType.BIRTHDAY_ANNOUNCEMENT.getTitle()) | ||
| .body(NotificationType.BIRTHDAY_ANNOUNCEMENT.getContent()) | ||
| .build(); | ||
| } | ||
|
|
||
| private BirthdayCelebrateContent toBirthdayCelebrateContent(User birthdayUser){ | ||
| return BirthdayCelebrateContent.builder() | ||
| .birthdayUserId(birthdayUser.getId()) | ||
| .birthdayUserName(birthdayUser.getName()) | ||
| .title(NotificationType.BIRTHDAY_CELEBRATE.getTitle()) | ||
| .body(NotificationType.BIRTHDAY_CELEBRATE.getContent()) | ||
| .build(); | ||
| } | ||
|
|
||
| private BirthdayLetterContent toBirthdayLetterContent(BirthdayLetter birthdayLetter) { | ||
| return BirthdayLetterContent.builder() | ||
| .senderName(birthdayLetter.getSender().getName()) | ||
| .birthdayLetterId(birthdayLetter.getId()) | ||
| .title(NotificationType.BIRTHDAY_LETTER.getTitle()) | ||
| .body(NotificationType.BIRTHDAY_LETTER.getContent()) | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| package leets.leenk.domain.notification.application.usecase; | ||
|
|
||
| import leets.leenk.domain.birthday.domain.entity.BirthdayLetter; | ||
| import leets.leenk.domain.birthday.domain.service.BirthdayGetService; | ||
| import leets.leenk.domain.notification.application.mapper.BirthdayNotificationMapper; | ||
| import leets.leenk.domain.notification.domain.entity.Notification; | ||
| import leets.leenk.domain.notification.domain.service.NotificationSaveService; | ||
| import leets.leenk.domain.user.domain.entity.User; | ||
| import leets.leenk.domain.user.domain.entity.UserSetting; | ||
| import leets.leenk.domain.user.domain.service.user.UserGetService; | ||
| import leets.leenk.domain.user.domain.service.usersetting.UserSettingGetService; | ||
| import leets.leenk.global.sqs.application.mapper.SqsMessageEventMapper; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.context.ApplicationEventPublisher; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import java.time.LocalDate; | ||
| import java.util.List; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class BirthdayNotificationUsecase { | ||
|
|
||
| private final UserGetService userGetService; | ||
| private final UserSettingGetService userSettingGetService; | ||
| private final BirthdayGetService birthdayGetService; | ||
|
|
||
| private final BirthdayNotificationMapper birthdayNotificationMapper; | ||
| private final SqsMessageEventMapper sqsMessageEventMapper; | ||
|
|
||
| private final ApplicationEventPublisher eventPublisher; | ||
| private final NotificationSaveService notificationSaveService; | ||
|
|
||
| @Transactional | ||
| public void announceUserBirthday(LocalDate today) { | ||
| List<User> birthdayUsers = birthdayGetService.findTodayBirthdayUsers(today); | ||
| if (birthdayUsers.isEmpty()) { | ||
| return; | ||
| } | ||
|
|
||
| List<User> users = userSettingGetService.getUsersToNotifyBirthday(); | ||
|
|
||
|
|
||
| for (User receiver : users) { | ||
| for (User birthdayUser : birthdayUsers) { | ||
| if (receiver.equals(birthdayUser)) continue; | ||
|
|
||
| Notification notification = birthdayNotificationMapper | ||
| .toBirthdayAnnouncementNotification(birthdayUser, receiver); | ||
| notificationSaveService.save(notification); | ||
|
|
||
| if (receiver.getFcmToken() != null) { | ||
| eventPublisher.publishEvent( | ||
| sqsMessageEventMapper.toBirthdaySqsMessageEvent( | ||
| notification, | ||
| receiver.getFcmToken(), | ||
| birthdayUser | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| } | ||
|
|
||
| @Transactional | ||
| public void celebrateBirthday(LocalDate today){ | ||
| List<User> birthdayUsers = birthdayGetService.findTodayBirthdayUsers(today); | ||
|
|
||
| for (User birthdayUser : birthdayUsers){ | ||
| if (!isBirthdayNotificationEnabled(birthdayUser)) continue; | ||
|
|
||
| Notification notification = birthdayNotificationMapper | ||
| .toBirthdayCelebrateNotification(birthdayUser); | ||
| notificationSaveService.save(notification); | ||
|
|
||
|
|
||
| if(birthdayUser.getFcmToken() != null) { | ||
| eventPublisher.publishEvent( | ||
| sqsMessageEventMapper.toBirthdaySqsMessageEvent( | ||
| notification, | ||
| birthdayUser.getFcmToken(), | ||
| birthdayUser | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| @Transactional | ||
| public void saveBirthdayLetterNotification(BirthdayLetter birthdayLetter){ | ||
| User birthdayUser = birthdayLetter.getReceiver(); | ||
|
|
||
| if (!isBirthdayNotificationEnabled(birthdayUser)) return; | ||
|
|
||
| Notification notification = birthdayNotificationMapper.toBirthdayLetterNotification(birthdayLetter); | ||
| notificationSaveService.save(notification); | ||
|
|
||
| if(birthdayUser.getFcmToken() != null){ | ||
| eventPublisher.publishEvent( | ||
| sqsMessageEventMapper.toBirthdaySqsMessageEvent( | ||
| notification, | ||
| birthdayUser.getFcmToken(), | ||
| birthdayLetter.getSender() | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| private boolean isBirthdayNotificationEnabled(User birthdayUser) { | ||
| try { | ||
| UserSetting userSetting = userSettingGetService.findByUser(birthdayUser); | ||
| return userSetting != null && userSetting.isBirthdayNotify(); | ||
| } catch (Exception e) { | ||
| return false; | ||
| } | ||
| } | ||
|
Comment on lines
119
to
127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 너무 광범위한 예외 처리로 실제 오류가 숨겨질 수 있습니다. 현재 구현의 문제점:
다음과 같이 개선하세요: private boolean isBirthdayNotificationEnabled(User birthdayUser) {
try {
UserSetting userSetting = userSettingGetService.findByUser(birthdayUser);
return userSetting != null && userSetting.isBirthdayNotify();
- } catch (Exception e) {
+ } catch (RuntimeException e) {
+ log.error("사용자 설정 조회 실패 - userId: {}", birthdayUser.getId(), e);
return false;
}
}또는
🤖 Prompt for AI Agents |
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package leets.leenk.domain.notification.domain.entity.birthdayContent; | ||
|
|
||
| import leets.leenk.domain.notification.domain.entity.NotificationContent; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import lombok.experimental.SuperBuilder; | ||
|
|
||
| @SuperBuilder | ||
| @NoArgsConstructor | ||
| @Getter | ||
| public class BirthdayAnnouncementContent extends NotificationContent { | ||
| private Long birthdayUserId; | ||
| private String birthdayUserName; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package leets.leenk.domain.notification.domain.entity.birthdayContent; | ||
|
|
||
| import leets.leenk.domain.notification.domain.entity.NotificationContent; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import lombok.experimental.SuperBuilder; | ||
|
|
||
| @SuperBuilder | ||
| @NoArgsConstructor | ||
| @Getter | ||
| public class BirthdayCelebrateContent extends NotificationContent { | ||
| private Long birthdayUserId; | ||
| private String birthdayUserName; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package leets.leenk.domain.notification.domain.entity.birthdayContent; | ||
|
|
||
| import leets.leenk.domain.notification.domain.entity.NotificationContent; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import lombok.experimental.SuperBuilder; | ||
|
|
||
| @SuperBuilder | ||
| @NoArgsConstructor | ||
| @Getter | ||
| public class BirthdayLetterContent extends NotificationContent { | ||
| private String senderName; | ||
| private Long birthdayLetterId; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,9 @@ public record NotificationSettingUpdateRequest( | |
| Boolean newFeedNotify, | ||
|
|
||
| @Schema(description = "새로운 공감 알림 여부 수정", example = "false") | ||
| Boolean newReactionNotify | ||
| Boolean newReactionNotify, | ||
|
|
||
| @Schema(description = "생일 알림 여부 수정", example = "false") | ||
| Boolean birthdayNotify | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생일 알림 여부 별도 설정하기로 했었나요?? 왜 피그마에 화면이 없는 거 같지
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생일 알림 여부도 회의시간에 추가하기로 했었습니다!
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nabbang6 확인 부탁드려요~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 앗 확인했습니다 !! 추가해놓을게용 👍 |
||
| ) { | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
왜 삭제됏죠??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 파일은 사용하지 않는 파일이고
MediaUpdateFailedException.java에서 해당 기능을 쓰는것으로 보여서 삭제했습니다