From b820ae3052c9b5d6c77aa917683fe11d7cb47330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=95=84?= <143075401+alsdddk@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:15:08 +0900 Subject: [PATCH 1/5] =?UTF-8?q?chore:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20enum=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/whatta/Whatta/event/service/EventService.java | 3 +++ .../Whatta/notification/entity/ScheduledNotification.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java b/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java index cabdfe50..e6268e40 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java +++ b/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java @@ -2,6 +2,7 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import whatta.Whatta.event.entity.Event; import whatta.Whatta.event.mapper.EventMapper; import whatta.Whatta.event.payload.request.EventCreateRequest; @@ -160,10 +161,12 @@ public EventDetailsResponse updateEvent(String userId, String eventId, EventUpda return eventMapper.toEventDetailsResponse(updatedEvent); } + @Transactional public void deleteEvent(String userId, String eventId) { Event event = eventRepository.findEventByIdAndUserId(eventId, userId) .orElseThrow(() -> new RestApiException(ErrorCode.EVENT_NOT_FOUND)); + scheduledNotiService.cancelReminder(eventId); eventRepository.delete(event); } } diff --git a/server/Whatta/src/main/java/whatta/Whatta/notification/entity/ScheduledNotification.java b/server/Whatta/src/main/java/whatta/Whatta/notification/entity/ScheduledNotification.java index 6e7fd1e2..c15f0c3a 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/notification/entity/ScheduledNotification.java +++ b/server/Whatta/src/main/java/whatta/Whatta/notification/entity/ScheduledNotification.java @@ -24,7 +24,7 @@ public class ScheduledNotification { @Builder.Default private NotiStatus status = NotiStatus.ACTIVE; - private NotificationTargetType targetType; // EVENT, TASK, SUMMARY + private NotificationTargetType targetType; // EVENT, TASK private String targetId; private LocalDateTime triggerAt; From ee7f57b73905312a5b16b9f21e7917a59abcf7ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=95=84?= <143075401+alsdddk@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:19:26 +0900 Subject: [PATCH 2/5] =?UTF-8?q?chore:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20enum=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Whatta/notification/enums/NotificationTargetType.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/Whatta/src/main/java/whatta/Whatta/notification/enums/NotificationTargetType.java b/server/Whatta/src/main/java/whatta/Whatta/notification/enums/NotificationTargetType.java index 66ba8781..1e0abe87 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/notification/enums/NotificationTargetType.java +++ b/server/Whatta/src/main/java/whatta/Whatta/notification/enums/NotificationTargetType.java @@ -2,6 +2,5 @@ public enum NotificationTargetType { EVENT, - TASK, - SUMMARY + TASK } From 417a6832c198f7d20ceb7d8e0399f282ac8316b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=95=84?= <143075401+alsdddk@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:23:02 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feature:=20event/task=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=EC=8B=9C=20=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20cancel=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Whatta/event/service/EventService.java | 2 +- .../ScheduledNotificationRepository.java | 2 +- .../service/ScheduledNotificationService.java | 34 ++++++++----------- .../Whatta/task/service/TaskService.java | 1 + 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java b/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java index e6268e40..d5a8203e 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java +++ b/server/Whatta/src/main/java/whatta/Whatta/event/service/EventService.java @@ -166,7 +166,7 @@ public void deleteEvent(String userId, String eventId) { Event event = eventRepository.findEventByIdAndUserId(eventId, userId) .orElseThrow(() -> new RestApiException(ErrorCode.EVENT_NOT_FOUND)); - scheduledNotiService.cancelReminder(eventId); + scheduledNotiService.cancelScheduledNotification(eventId); eventRepository.delete(event); } } diff --git a/server/Whatta/src/main/java/whatta/Whatta/notification/repository/ScheduledNotificationRepository.java b/server/Whatta/src/main/java/whatta/Whatta/notification/repository/ScheduledNotificationRepository.java index e63a731a..398b6188 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/notification/repository/ScheduledNotificationRepository.java +++ b/server/Whatta/src/main/java/whatta/Whatta/notification/repository/ScheduledNotificationRepository.java @@ -13,7 +13,7 @@ @Repository public interface ScheduledNotificationRepository extends MongoRepository { - Optional findByTargetTypeAndTargetIdAndStatus(NotificationTargetType targetType, String targetId, NotiStatus status); + Optional findByTargetIdAndStatus(String targetId, NotiStatus status); Optional findByTargetTypeAndTargetIdAndStatusAndTriggerAtAfter(NotificationTargetType targetType, String targetId, NotiStatus status, LocalDateTime now); diff --git a/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java b/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java index 1a9652ef..200f5e47 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java +++ b/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java @@ -4,9 +4,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import whatta.Whatta.event.entity.Event; +import whatta.Whatta.event.repository.EventRepository; import whatta.Whatta.global.repeat.Repeat; -import whatta.Whatta.global.repeat.RepeatUnit; -import whatta.Whatta.global.util.RepeatUtil; import whatta.Whatta.notification.entity.ScheduledNotification; import whatta.Whatta.notification.enums.NotiStatus; import whatta.Whatta.notification.enums.NotificationTargetType; @@ -14,9 +13,7 @@ import whatta.Whatta.task.entity.Task; import whatta.Whatta.user.payload.dto.ReminderNoti; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.List; import static whatta.Whatta.global.util.RepeatUtil.findNextOccurrenceStartAfter; @@ -26,18 +23,13 @@ public class ScheduledNotificationService { private final ScheduledNotificationRepository scheduledNotiRepository; + private final EventRepository eventRepository; //-------------reminder--------------- //1. event 생성/수정 시 public void createScheduledNotification(Event event) { if(event.getReminderNotiAt() == null) { //알림 off: 기존 스케줄 있으면 취소 - scheduledNotiRepository.findByTargetTypeAndTargetIdAndStatus(NotificationTargetType.EVENT, event.getId(), NotiStatus.ACTIVE) - .ifPresent(schedule -> { - ScheduledNotification canceled = schedule.toBuilder() - .status(NotiStatus.CANCELED) - .build(); - scheduledNotiRepository.save(canceled); - }); + cancelScheduledNotification(event.getId()); return; } @@ -59,16 +51,10 @@ public void createScheduledNotification(Event event) { scheduledNotiRepository.save(base); } - //2. task 생성 수정 시 + //2. task 생성/수정 시 public void createScheduledNotification(Task task) { if(task.getReminderNotiAt() == null) { //알림 off: 기존 스케줄 있으면 취소 - scheduledNotiRepository.findByTargetTypeAndTargetIdAndStatus(NotificationTargetType.TASK, task.getId(), NotiStatus.ACTIVE) - .ifPresent(schedule -> { - ScheduledNotification canceled = schedule.toBuilder() - .status(NotiStatus.CANCELED) - .build(); - scheduledNotiRepository.save(canceled); - }); + cancelScheduledNotification(task.getId()); return; } @@ -90,6 +76,16 @@ public void createScheduledNotification(Task task) { scheduledNotiRepository.save(base); } + public void cancelScheduledNotification(String targetId) { + scheduledNotiRepository.findByTargetIdAndStatus(targetId, NotiStatus.ACTIVE) + .ifPresent(schedule -> { + ScheduledNotification canceled = schedule.toBuilder() + .status(NotiStatus.CANCELED) + .build(); + scheduledNotiRepository.save(canceled); + }); + } + private LocalDateTime calculateTriggerAt(LocalDateTime startAt, Repeat repeat, ReminderNoti offset) { LocalDateTime now = LocalDateTime.now(); diff --git a/server/Whatta/src/main/java/whatta/Whatta/task/service/TaskService.java b/server/Whatta/src/main/java/whatta/Whatta/task/service/TaskService.java index a9595478..89cfb7c3 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/task/service/TaskService.java +++ b/server/Whatta/src/main/java/whatta/Whatta/task/service/TaskService.java @@ -183,6 +183,7 @@ public void deleteTask(String userId, String taskId) { throw new RestApiException(ErrorCode.TASK_NOT_FOUND); } + scheduledNotiService.cancelScheduledNotification(taskId); taskRepository.deleteById(taskId); } From 431f36088dd9f3ba194f3928f5c76c1838430494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=95=84?= <143075401+alsdddk@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:05:48 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feature:=20nextTriggerAt=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ScheduledNotificationService.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java b/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java index 200f5e47..7daade23 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java +++ b/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java @@ -5,6 +5,8 @@ import org.springframework.transaction.annotation.Transactional; import whatta.Whatta.event.entity.Event; import whatta.Whatta.event.repository.EventRepository; +import whatta.Whatta.global.exception.ErrorCode; +import whatta.Whatta.global.exception.RestApiException; import whatta.Whatta.global.repeat.Repeat; import whatta.Whatta.notification.entity.ScheduledNotification; import whatta.Whatta.notification.enums.NotiStatus; @@ -132,5 +134,25 @@ public void afterReminderSent(ScheduledNotification noti) { scheduledNotiRepository.save(updated); //반복일정의 경우 다음 알림에 저장 + Event target = eventRepository.findById(noti.getTargetId()) + .orElseThrow(() -> new RestApiException(ErrorCode.EVENT_NOT_FOUND)); + + LocalDateTime nextTriggerAt = calculateTriggerAt(LocalDateTime.of(target.getStartDate(), target.getStartTime()), target.getRepeat(), target.getReminderNotiAt()); + + if (nextTriggerAt == null) { + return; + } + //해당 이벤트의 아직 안보낸 ACTIVE 알림이 있으면 update, 없으면 새로 생성 + ScheduledNotification base = scheduledNotiRepository.findByTargetTypeAndTargetIdAndStatusAndTriggerAtAfter( + NotificationTargetType.EVENT, target.getId(), NotiStatus.ACTIVE, LocalDateTime.now()) + .orElseGet(() -> ScheduledNotification.builder() + .userId(target.getUserId()) + .status(NotiStatus.ACTIVE) + .targetType(NotificationTargetType.EVENT) + .targetId(target.getId()) + .triggerAt(nextTriggerAt) + .build()); + + scheduledNotiRepository.save(base); } } From ce099e1d319f93eec966d7031742af9f72d63720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=95=84?= <143075401+alsdddk@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:35:11 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20event/task=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EC=8B=9C,=20=EC=88=98=EC=A0=95=EB=90=9C=20triggerAt=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ScheduledNotificationService.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java b/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java index 7daade23..3a098368 100644 --- a/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java +++ b/server/Whatta/src/main/java/whatta/Whatta/notification/service/ScheduledNotificationService.java @@ -38,7 +38,7 @@ public void createScheduledNotification(Event event) { //알림 시각 계산 LocalDateTime triggerAt = calculateTriggerAt(LocalDateTime.of(event.getStartDate(), event.getStartTime()), event.getRepeat(), event.getReminderNotiAt()); - if(triggerAt == null) { return;} + if(triggerAt == null) { return; } //해당 이벤트의 아직 안보낸 ACTIVE 알림이 있으면 update, 없으면 새로 생성 ScheduledNotification base = scheduledNotiRepository.findByTargetTypeAndTargetIdAndStatusAndTriggerAtAfter( NotificationTargetType.EVENT, event.getId(), NotiStatus.ACTIVE, LocalDateTime.now()) @@ -47,10 +47,12 @@ public void createScheduledNotification(Event event) { .status(NotiStatus.ACTIVE) .targetType(NotificationTargetType.EVENT) .targetId(event.getId()) - .triggerAt(triggerAt) .build()); - scheduledNotiRepository.save(base); + scheduledNotiRepository.save(base.toBuilder() + .triggerAt(triggerAt) + .updatedAt(LocalDateTime.now()) + .build()); } //2. task 생성/수정 시 @@ -60,10 +62,10 @@ public void createScheduledNotification(Task task) { return; } - //알림 시각 계산 ** 임시로 task 반복 x ** + //알림 시각 계산 LocalDateTime triggerAt = calculateTriggerAt(LocalDateTime.of(task.getPlacementDate(), task.getPlacementTime()), null, task.getReminderNotiAt()); - if(triggerAt == null) { return;} + if(triggerAt == null) { return; } //해당 이벤트의 아직 안보낸 ACTIVE 알림이 있으면 update, 없으면 새로 생성 ScheduledNotification base = scheduledNotiRepository.findByTargetTypeAndTargetIdAndStatusAndTriggerAtAfter( NotificationTargetType.TASK, task.getId(), NotiStatus.ACTIVE, LocalDateTime.now()) @@ -72,10 +74,12 @@ public void createScheduledNotification(Task task) { .status(NotiStatus.ACTIVE) .targetType(NotificationTargetType.TASK) .targetId(task.getId()) - .triggerAt(triggerAt) .build()); - scheduledNotiRepository.save(base); + scheduledNotiRepository.save(base.toBuilder() + .triggerAt(triggerAt) + .updatedAt(LocalDateTime.now()) + .build()); } public void cancelScheduledNotification(String targetId) {