diff --git a/src/main/java/com/slatto/domain/notification/controller/TodayBriefingController.java b/src/main/java/com/slatto/domain/notification/controller/TodayBriefingController.java index f3787fea..d2607013 100644 --- a/src/main/java/com/slatto/domain/notification/controller/TodayBriefingController.java +++ b/src/main/java/com/slatto/domain/notification/controller/TodayBriefingController.java @@ -22,7 +22,7 @@ public class TodayBriefingController { @Operation( summary = "오늘의 브리핑 조회", - description = "홈 화면에 표시할 오늘의 브리핑을 최대 3건까지 조회합니다. 브리핑은 일정과 최근 주요 알림 데이터를 조합해 반환합니다." + description = "홈 화면에 표시할 오늘의 브리핑을 최대 3건까지 조회합니다. 오늘 일정, 여러 날 일정의 마감 당일, 일정 시작 D-1/D-3 알림과 최근 24시간 주요 알림을 정책 우선순위 기준으로 조합해 반환합니다." ) @GetMapping("/today") public ApiResponse getTodayBriefings( diff --git a/src/main/java/com/slatto/domain/notification/enums/TodayBriefingType.java b/src/main/java/com/slatto/domain/notification/enums/TodayBriefingType.java index c5a20b42..2902a108 100644 --- a/src/main/java/com/slatto/domain/notification/enums/TodayBriefingType.java +++ b/src/main/java/com/slatto/domain/notification/enums/TodayBriefingType.java @@ -8,12 +8,13 @@ public enum TodayBriefingType { TODAY_SCHEDULE(1), - SCHEDULE_START_REMINDER(2), - RECRUITMENT_APPLIED(3), - SCHEDULE_CREATED(4), - NOTICE_CREATED(5), - FILE_UPLOADED(6), - VIDEO_FEEDBACK_COMMENTED(7); + SCHEDULE_DUE_TODAY(2), + SCHEDULE_START_REMINDER(3), + RECRUITMENT_APPLIED(4), + SCHEDULE_CREATED(5), + NOTICE_CREATED(6), + FILE_UPLOADED(7), + VIDEO_FEEDBACK_COMMENTED(8); private final int priority; } diff --git a/src/main/java/com/slatto/domain/notification/repository/NotificationRepository.java b/src/main/java/com/slatto/domain/notification/repository/NotificationRepository.java index 5bbe6304..f49b96c8 100644 --- a/src/main/java/com/slatto/domain/notification/repository/NotificationRepository.java +++ b/src/main/java/com/slatto/domain/notification/repository/NotificationRepository.java @@ -60,11 +60,11 @@ List findRecentNotificationsByCursor( and n.type in :types order by case - when n.type = :recruitmentAppliedType then 3 - when n.type = :scheduleCreatedType then 4 - when n.type = :noticeCreatedType then 5 - when n.type = :fileUploadedType then 6 - when n.type = :videoFeedbackCommentedType then 7 + when n.type = :recruitmentAppliedType then 4 + when n.type = :scheduleCreatedType then 5 + when n.type = :noticeCreatedType then 6 + when n.type = :fileUploadedType then 7 + when n.type = :videoFeedbackCommentedType then 8 else 999 end, n.updatedAt desc, diff --git a/src/main/java/com/slatto/domain/notification/service/TodayBriefingService.java b/src/main/java/com/slatto/domain/notification/service/TodayBriefingService.java index 41f04371..62602f5f 100644 --- a/src/main/java/com/slatto/domain/notification/service/TodayBriefingService.java +++ b/src/main/java/com/slatto/domain/notification/service/TodayBriefingService.java @@ -76,7 +76,7 @@ private void addTodayScheduleBriefings( schedules.forEach(schedule -> { candidates.add(BriefingCandidate.builder() - .type(TodayBriefingType.TODAY_SCHEDULE) + .type(getTodayScheduleBriefingType(schedule, today)) .content(buildTodayScheduleContent(schedule, today)) .projectId(getProjectId(schedule.getProject())) .targetType(NotificationTargetType.SCHEDULE.name()) @@ -176,7 +176,7 @@ private BriefingCandidate toNotificationCandidate(Notification notification) { private String buildTodayScheduleContent(Schedule schedule, LocalDate today) { String title = schedule.getTitle(); String projectTitle = getProjectTitle(schedule.getProject()); - String actionText = isMultiDaySchedule(schedule) && isScheduleEndDate(schedule, today) + String actionText = isScheduleDueToday(schedule, today) ? "마감이에요" : "일정이 있어요"; @@ -186,6 +186,17 @@ private String buildTodayScheduleContent(Schedule schedule, LocalDate today) { return "[" + projectTitle + "] 오늘 [" + title + "] " + actionText; } + private TodayBriefingType getTodayScheduleBriefingType(Schedule schedule, LocalDate today) { + if (isScheduleDueToday(schedule, today)) { + return TodayBriefingType.SCHEDULE_DUE_TODAY; + } + return TodayBriefingType.TODAY_SCHEDULE; + } + + private boolean isScheduleDueToday(Schedule schedule, LocalDate today) { + return isMultiDaySchedule(schedule) && isScheduleEndDate(schedule, today); + } + private String buildStartReminderContent(Schedule schedule, int dayOffset) { String title = schedule.getTitle(); String projectTitle = getProjectTitle(schedule.getProject()); @@ -198,11 +209,16 @@ private String buildStartReminderContent(Schedule schedule, int dayOffset) { } private boolean isScheduleEndDate(Schedule schedule, LocalDate date) { - return schedule.getEndAt().toLocalDate().isEqual(date); + return getInclusiveEndDate(schedule).isEqual(date); } private boolean isMultiDaySchedule(Schedule schedule) { - return !schedule.getStartAt().toLocalDate().isEqual(schedule.getEndAt().toLocalDate()); + return !schedule.getStartAt().toLocalDate().isEqual(getInclusiveEndDate(schedule)); + } + + private LocalDate getInclusiveEndDate(Schedule schedule) { + // endAt은 종료 경계값이므로 00:00 종료 일정은 전날까지 진행된 일정으로 본다. + return schedule.getEndAt().minusNanos(1).toLocalDate(); } private Long getProjectId(Project project) {