From cca00e301535994f6ec05b0d835180b89291da0f Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 17:13:09 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=EA=B0=9C=EC=9D=B8=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=ED=83=80=EC=9E=85=20=ED=99=95=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/enums/NotificationTargetType.java | 4 +++- .../slatto/domain/notification/enums/NotificationType.java | 1 + .../domain/notification/service/NotificationService.java | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/slatto/domain/notification/enums/NotificationTargetType.java b/src/main/java/com/slatto/domain/notification/enums/NotificationTargetType.java index 4237234f..6db65231 100644 --- a/src/main/java/com/slatto/domain/notification/enums/NotificationTargetType.java +++ b/src/main/java/com/slatto/domain/notification/enums/NotificationTargetType.java @@ -8,5 +8,7 @@ public enum NotificationTargetType { SCHEDULE, PROJECT, VIDEO, - RECRUITMENT + RECRUITMENT, + NOTICE, + PROJECT_FILE } diff --git a/src/main/java/com/slatto/domain/notification/enums/NotificationType.java b/src/main/java/com/slatto/domain/notification/enums/NotificationType.java index 04c4a3d4..fda81afc 100644 --- a/src/main/java/com/slatto/domain/notification/enums/NotificationType.java +++ b/src/main/java/com/slatto/domain/notification/enums/NotificationType.java @@ -3,6 +3,7 @@ public enum NotificationType { SCHEDULE_ASSIGNED, PROJECT_INVITED, + PROJECT_JOINED, VIDEO_FEEDBACK_COMMENTED, RECRUITMENT_APPLIED, SCHEDULE_CREATED, diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index b1e75a93..55d6c408 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -607,6 +607,7 @@ private String createFallbackTitle(NotificationType type) { return switch (type) { case SCHEDULE_ASSIGNED -> "일정 담당자 지정"; case PROJECT_INVITED -> "프로젝트 초대"; + case PROJECT_JOINED -> "합류"; case VIDEO_FEEDBACK_COMMENTED -> "새로운 피드백"; case RECRUITMENT_APPLIED -> "새로운 지원자"; case SCHEDULE_CREATED -> "새 일정"; From f6e4d084bfa3e8c6d58d500931072a53d1fb3d35 Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 17:17:09 +0900 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=ED=95=A9=EB=A5=98=20=EC=9D=BC=EC=A0=95=20=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=20=ED=8C=8C=EC=9D=BC=20=EC=95=8C=EB=A6=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationService.java | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 55d6c408..4583ae2f 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -251,6 +251,63 @@ public void createProjectInvitationNotification( .build()); } + /** + * 프로젝트 합류 알림을 프로젝트 참여자에게 생성한다. + * 합류자 본인도 수신 대상에 포함할 수 있다. + */ + @Transactional + public void createProjectJoinedNotifications( + Long projectId, + String projectTitle, + String joinerName, + List recipientIds + ) { + validateRequiredId(projectId); + validateRequiredText(projectTitle); + validateRequiredText(joinerName); + + createNotifications(NotificationCreateCommand.builder() + .recipientIds(recipientIds) + .projectId(projectId) + .type(NotificationType.PROJECT_JOINED) + .title(createProjectJoinedTitle(projectTitle)) + .content(createProjectJoinedContent(joinerName)) + .targetType(NotificationTargetType.PROJECT) + .targetId(projectId) + .build()); + } + + /** + * 프로젝트에 새 일정이 등록되었을 때 프로젝트 참여자에게 알림을 생성한다. + */ + @Transactional + public void createScheduleCreatedNotifications( + Long projectId, + Long scheduleId, + String projectTitle, + String scheduleTitle, + String creatorName, + List recipientIds, + Long actorUserId + ) { + validateRequiredId(projectId); + validateRequiredId(scheduleId); + validateRequiredText(projectTitle); + validateRequiredText(scheduleTitle); + validateRequiredText(creatorName); + + createNotifications(NotificationCreateCommand.builder() + .recipientIds(recipientIds) + .projectId(projectId) + .type(NotificationType.SCHEDULE_CREATED) + .title(createScheduleCreatedTitle(projectTitle)) + .content(createScheduleCreatedContent(scheduleTitle, creatorName)) + .targetType(NotificationTargetType.SCHEDULE) + .targetId(scheduleId) + .excludeUserId(actorUserId) + .build()); + } + /** * 영상 피드백 댓글 알림을 생성하거나 기존 미읽음 알림을 갱신한다. * 동일 영상 기준으로 그룹핑하므로 targetId는 feedbackId가 아니라 videoId를 사용한다. @@ -372,6 +429,71 @@ public void createRecruitmentAppliedNotification( ); } + /** + * 프로젝트 공지가 등록되었을 때 프로젝트 참여자에게 알림을 생성한다. + */ + @Transactional + public void createNoticeCreatedNotifications( + Long projectId, + Long noticeId, + String projectTitle, + String noticeTitle, + String creatorName, + List recipientIds, + Long actorUserId + ) { + validateRequiredId(projectId); + validateRequiredId(noticeId); + validateRequiredText(projectTitle); + validateRequiredText(noticeTitle); + validateRequiredText(creatorName); + + createNotifications(NotificationCreateCommand.builder() + .recipientIds(recipientIds) + .projectId(projectId) + .type(NotificationType.NOTICE_CREATED) + .title(createNoticeCreatedTitle(projectTitle)) + .content(createNoticeCreatedContent(noticeTitle, creatorName)) + .targetType(NotificationTargetType.NOTICE) + .targetId(noticeId) + .excludeUserId(actorUserId) + .build()); + } + + /** + * 프로젝트 파일 등록 알림을 생성한다. + * 여러 파일을 한 번에 업로드한 경우 fileCount 기준으로 문구를 만든다. + */ + @Transactional + public void createFileUploadedNotifications( + Long projectId, + String projectTitle, + String fileName, + int fileCount, + String uploaderName, + List recipientIds, + Long actorUserId + ) { + validateRequiredId(projectId); + validateRequiredText(projectTitle); + validateRequiredText(uploaderName); + validatePositiveCount(fileCount); + if (fileCount == 1) { + validateRequiredText(fileName); + } + + createNotifications(NotificationCreateCommand.builder() + .recipientIds(recipientIds) + .projectId(projectId) + .type(NotificationType.FILE_UPLOADED) + .title(createFileUploadedTitle(projectTitle)) + .content(createFileUploadedContent(fileName, fileCount, uploaderName)) + .targetType(NotificationTargetType.PROJECT_FILE) + .targetId(projectId) + .excludeUserId(actorUserId) + .build()); + } + private void validateActiveUser(Long currentUserId) { if (!userRepository.existsByIdAndDeletedAtIsNull(currentUserId)) { throw new BaseException(CommonErrorCode.NOT_FOUND); @@ -437,6 +559,12 @@ private void validateRequiredText(String text) { } } + private void validatePositiveCount(int count) { + if (count <= 0) { + throw new BaseException(CommonErrorCode.BAD_REQUEST); + } + } + private void createOrUpdateGroupedNotification( Users recipient, Project project, @@ -571,6 +699,22 @@ private String createProjectInvitationContent(String projectTitle, String invite return inviterName + "님이 [" + projectTitle + "] 프로젝트에 초대했어요"; } + private String createProjectJoinedTitle(String projectTitle) { + return joinTitle(projectTitle, "합류"); + } + + private String createProjectJoinedContent(String joinerName) { + return joinerName + "님이 프로젝트에 합류했어요"; + } + + private String createScheduleCreatedTitle(String projectTitle) { + return joinTitle(projectTitle, "새 일정"); + } + + private String createScheduleCreatedContent(String scheduleTitle, String creatorName) { + return creatorName + "님이 [" + scheduleTitle + "] 일정을 등록했어요"; + } + private String createVideoFeedbackCommentedTitle(String projectTitle) { return joinTitle(projectTitle, "새로운 피드백"); } @@ -603,6 +747,26 @@ private String createRecruitmentAppliedContent( return "[" + recruitmentTitle + "]에 새로운 지원자 " + groupCount + "명이 지원했어요"; } + private String createNoticeCreatedTitle(String projectTitle) { + return joinTitle(projectTitle, "새 공지"); + } + + private String createNoticeCreatedContent(String noticeTitle, String creatorName) { + return creatorName + "님이 새 공지를 등록했어요: " + noticeTitle; + } + + private String createFileUploadedTitle(String projectTitle) { + return joinTitle(projectTitle, "새 파일"); + } + + private String createFileUploadedContent(String fileName, int fileCount, String uploaderName) { + if (fileCount == 1) { + return uploaderName + "님이 [" + fileName + "] 파일을 등록했어요"; + } + + return uploaderName + "님이 파일 " + fileCount + "개를 등록했어요"; + } + private String createFallbackTitle(NotificationType type) { return switch (type) { case SCHEDULE_ASSIGNED -> "일정 담당자 지정"; From 1ca9bbfec4d49e05d2fc2719d11e6b5da7910d0e Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 17:53:29 +0900 Subject: [PATCH 03/10] =?UTF-8?q?fix:=20=EC=9D=BC=EC=A0=95=20=EB=8B=B4?= =?UTF-8?q?=EB=8B=B9=EC=9E=90=20=EC=A7=80=EC=A0=95=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AC=B8=EA=B5=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationService.java | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 4583ae2f..499382ea 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -184,18 +184,31 @@ public void createScheduleAssignedNotifications( List recipients, Long writerId ) { - createNotifications(NotificationCreateCommand.builder() - .recipientIds(recipients.stream() - .map(Users::getId) - .toList()) - .projectId(project != null ? project.getId() : null) - .type(NotificationType.SCHEDULE_ASSIGNED) - .title(createScheduleAssignedTitle(project != null ? project.getTitle() : null)) - .content(createScheduleAssignedContent(scheduleTitle)) - .targetType(NotificationTargetType.SCHEDULE) - .targetId(scheduleId) - .excludeUserId(writerId) - .build()); + validateRequiredId(scheduleId); + validateRequiredText(scheduleTitle); + if (recipients == null) { + throw new BaseException(CommonErrorCode.BAD_REQUEST); + } + + Project notificationProject = getProjectOrNull(project != null ? project.getId() : null); + String title = createScheduleAssignedTitle(project != null ? project.getTitle() : null); + String targetType = getTargetTypeName(NotificationTargetType.SCHEDULE); + + List notifications = recipients.stream() + .filter(Objects::nonNull) + .filter(recipient -> !Objects.equals(recipient.getId(), writerId)) + .map(recipient -> Notification.create( + recipient, + notificationProject, + NotificationType.SCHEDULE_ASSIGNED, + title, + createScheduleAssignedContent(scheduleTitle, recipient.getNickname()), + targetType, + scheduleId + )) + .toList(); + + notificationRepository.saveAll(notifications); } /** @@ -683,8 +696,8 @@ private NotificationListResponse.NotificationSummary toSummary(Notification noti .build(); } - private String createScheduleAssignedContent(String scheduleTitle) { - return "'" + scheduleTitle + "' 일정 담당자로 지정되었습니다."; + private String createScheduleAssignedContent(String scheduleTitle, String assigneeName) { + return assigneeName + "님이 [" + scheduleTitle + "] 담당자로 지정했어요"; } private String createScheduleAssignedTitle(String projectTitle) { From 54e995688a3e64744628c2ea5a5146aa3eaf7bee Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 18:02:13 +0900 Subject: [PATCH 04/10] =?UTF-8?q?fix:=20=EC=A7=80=EC=9B=90=EC=9E=90=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=9C=EB=AA=A9=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationService.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 499382ea..1ac077c8 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -390,7 +390,7 @@ public void createVideoFeedbackCommentedNotifications( * 새로운 지원자 발생 알림을 생성하거나 기존 미읽음 알림을 갱신한다. * 동일 공고 기준으로 그룹핑하므로 targetId는 recruitmentId를 사용한다. * - * @deprecated 알림 문구는 알림 도메인에서 관리하므로 recruitmentTitle과 applicantName을 받는 메서드를 사용한다. + * @deprecated 알림 문구는 알림 도메인에서 관리하므로 projectTitle, recruitmentTitle, applicantName을 받는 메서드를 사용한다. */ @Deprecated @Transactional @@ -419,18 +419,20 @@ public void createRecruitmentAppliedNotification( public void createRecruitmentAppliedNotification( Long recipientId, Long recruitmentId, + String projectTitle, String recruitmentTitle, String applicantName ) { validateRequiredId(recipientId); validateRequiredId(recruitmentId); + validateRequiredText(projectTitle); validateRequiredText(recruitmentTitle); validateRequiredText(applicantName); NotificationCreateCommand command = NotificationCreateCommand.builder() .recipientIds(List.of(recipientId)) .type(NotificationType.RECRUITMENT_APPLIED) - .title(createRecruitmentAppliedTitle(recruitmentTitle)) + .title(createRecruitmentAppliedTitle(projectTitle)) .content(createRecruitmentAppliedContent(recruitmentTitle, applicantName, 1)) .targetType(NotificationTargetType.RECRUITMENT) .targetId(recruitmentId) @@ -744,8 +746,8 @@ private String createVideoFeedbackCommentedContent( return "[" + videoTitle + "]에 새로운 피드백 " + groupCount + "건이 등록되었어요"; } - private String createRecruitmentAppliedTitle(String recruitmentTitle) { - return joinTitle(recruitmentTitle, "새로운 지원자"); + private String createRecruitmentAppliedTitle(String projectTitle) { + return joinTitle(projectTitle, "새로운 지원자"); } private String createRecruitmentAppliedContent( From ffa532eab84182eb1e4de6638852441337ba8574 Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 19:07:17 +0900 Subject: [PATCH 05/10] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=95=8C=EB=A6=BC=20=EA=B7=B8=EB=A3=B9=ED=95=91=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationService.java | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 1ac077c8..f0e1b69e 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -477,32 +477,27 @@ public void createNoticeCreatedNotifications( /** * 프로젝트 파일 등록 알림을 생성한다. - * 여러 파일을 한 번에 업로드한 경우 fileCount 기준으로 문구를 만든다. */ @Transactional public void createFileUploadedNotifications( Long projectId, String projectTitle, String fileName, - int fileCount, String uploaderName, List recipientIds, Long actorUserId ) { validateRequiredId(projectId); validateRequiredText(projectTitle); + validateRequiredText(fileName); validateRequiredText(uploaderName); - validatePositiveCount(fileCount); - if (fileCount == 1) { - validateRequiredText(fileName); - } createNotifications(NotificationCreateCommand.builder() .recipientIds(recipientIds) .projectId(projectId) .type(NotificationType.FILE_UPLOADED) .title(createFileUploadedTitle(projectTitle)) - .content(createFileUploadedContent(fileName, fileCount, uploaderName)) + .content(createFileUploadedContent(fileName, uploaderName)) .targetType(NotificationTargetType.PROJECT_FILE) .targetId(projectId) .excludeUserId(actorUserId) @@ -574,12 +569,6 @@ private void validateRequiredText(String text) { } } - private void validatePositiveCount(int count) { - if (count <= 0) { - throw new BaseException(CommonErrorCode.BAD_REQUEST); - } - } - private void createOrUpdateGroupedNotification( Users recipient, Project project, @@ -774,12 +763,8 @@ private String createFileUploadedTitle(String projectTitle) { return joinTitle(projectTitle, "새 파일"); } - private String createFileUploadedContent(String fileName, int fileCount, String uploaderName) { - if (fileCount == 1) { - return uploaderName + "님이 [" + fileName + "] 파일을 등록했어요"; - } - - return uploaderName + "님이 파일 " + fileCount + "개를 등록했어요"; + private String createFileUploadedContent(String fileName, String uploaderName) { + return uploaderName + "님이 [" + fileName + "] 파일을 등록했어요"; } private String createFallbackTitle(NotificationType type) { From 8928c042b37071d54aaa4749a32644d07fa03017 Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 19:19:44 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=B4=88=EB=8C=80=20=EC=95=8C=EB=A6=BC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/enums/NotificationType.java | 1 - .../service/NotificationService.java | 62 ------------------- 2 files changed, 63 deletions(-) diff --git a/src/main/java/com/slatto/domain/notification/enums/NotificationType.java b/src/main/java/com/slatto/domain/notification/enums/NotificationType.java index fda81afc..c5fa5d99 100644 --- a/src/main/java/com/slatto/domain/notification/enums/NotificationType.java +++ b/src/main/java/com/slatto/domain/notification/enums/NotificationType.java @@ -2,7 +2,6 @@ public enum NotificationType { SCHEDULE_ASSIGNED, - PROJECT_INVITED, PROJECT_JOINED, VIDEO_FEEDBACK_COMMENTED, RECRUITMENT_APPLIED, diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index f0e1b69e..b2285fe7 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -211,59 +211,6 @@ public void createScheduleAssignedNotifications( notificationRepository.saveAll(notifications); } - /** - * 프로젝트 초대 알림을 생성한다. - * 클릭 대상은 프로젝트 상세 화면이다. - * - * @deprecated 알림 문구는 알림 도메인에서 관리하므로 projectTitle을 받는 메서드를 사용한다. - */ - @Deprecated - @Transactional - public void createProjectInvitationNotification( - Long recipientId, - Long projectId, - String content - ) { - validateRequiredId(recipientId); - validateRequiredId(projectId); - - createNotification(NotificationCreateCommand.builder() - .recipientIds(List.of(recipientId)) - .projectId(projectId) - .type(NotificationType.PROJECT_INVITED) - .title(createFallbackTitle(NotificationType.PROJECT_INVITED)) - .content(content) - .targetType(NotificationTargetType.PROJECT) - .targetId(projectId) - .build()); - } - - /** - * 프로젝트 초대 알림 문구를 정책에 맞춰 생성한다. - */ - @Transactional - public void createProjectInvitationNotification( - Long recipientId, - Long projectId, - String projectTitle, - String inviterName - ) { - validateRequiredId(projectId); - validateRequiredId(recipientId); - validateRequiredText(projectTitle); - validateRequiredText(inviterName); - - createNotification(NotificationCreateCommand.builder() - .recipientIds(List.of(recipientId)) - .projectId(projectId) - .type(NotificationType.PROJECT_INVITED) - .title(createProjectInvitationTitle(projectTitle)) - .content(createProjectInvitationContent(projectTitle, inviterName)) - .targetType(NotificationTargetType.PROJECT) - .targetId(projectId) - .build()); - } - /** * 프로젝트 합류 알림을 프로젝트 참여자에게 생성한다. * 합류자 본인도 수신 대상에 포함할 수 있다. @@ -695,14 +642,6 @@ private String createScheduleAssignedTitle(String projectTitle) { return joinTitle(projectTitle, "일정 담당자 지정"); } - private String createProjectInvitationTitle(String projectTitle) { - return joinTitle(projectTitle, "프로젝트 초대"); - } - - private String createProjectInvitationContent(String projectTitle, String inviterName) { - return inviterName + "님이 [" + projectTitle + "] 프로젝트에 초대했어요"; - } - private String createProjectJoinedTitle(String projectTitle) { return joinTitle(projectTitle, "합류"); } @@ -770,7 +709,6 @@ private String createFileUploadedContent(String fileName, String uploaderName) { private String createFallbackTitle(NotificationType type) { return switch (type) { case SCHEDULE_ASSIGNED -> "일정 담당자 지정"; - case PROJECT_INVITED -> "프로젝트 초대"; case PROJECT_JOINED -> "합류"; case VIDEO_FEEDBACK_COMMENTED -> "새로운 피드백"; case RECRUITMENT_APPLIED -> "새로운 지원자"; From 7127b2d5869b244738c0228758a2573588546f31 Mon Sep 17 00:00:00 2001 From: guingguing Date: Wed, 5 Aug 2026 20:32:16 +0900 Subject: [PATCH 07/10] =?UTF-8?q?fix:=20=EC=A7=80=EC=9B=90=EC=9E=90=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=83=9D=EC=84=B1=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=98=B8=ED=99=98=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationService.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index b2285fe7..0ffd41b1 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -391,6 +391,26 @@ public void createRecruitmentAppliedNotification( ); } + /** + * 공고 프로젝트명을 알 수 없는 기존 호출부에서 사용하는 지원자 알림 생성 메서드다. + * 프로젝트명을 전달할 수 있는 경우에는 5개 인자 메서드를 사용한다. + */ + @Transactional + public void createRecruitmentAppliedNotification( + Long recipientId, + Long recruitmentId, + String recruitmentTitle, + String applicantName + ) { + createRecruitmentAppliedNotification( + recipientId, + recruitmentId, + recruitmentTitle, + recruitmentTitle, + applicantName + ); + } + /** * 프로젝트 공지가 등록되었을 때 프로젝트 참여자에게 알림을 생성한다. */ From 242c2556095ffa1e6f5b2afa7b8ca653cd17c197 Mon Sep 17 00:00:00 2001 From: guingguing Date: Thu, 6 Aug 2026 00:42:47 +0900 Subject: [PATCH 08/10] =?UTF-8?q?fix:=20=EC=9D=BC=EC=A0=95=20=EB=8B=B4?= =?UTF-8?q?=EB=8B=B9=EC=9E=90=20=EC=95=8C=EB=A6=BC=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=88=98=EC=8B=A0=EC=9E=90=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/service/NotificationService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 0ffd41b1..7e9e2a8e 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -185,6 +185,7 @@ public void createScheduleAssignedNotifications( Long writerId ) { validateRequiredId(scheduleId); + validateRequiredId(writerId); validateRequiredText(scheduleTitle); if (recipients == null) { throw new BaseException(CommonErrorCode.BAD_REQUEST); @@ -193,9 +194,11 @@ public void createScheduleAssignedNotifications( Project notificationProject = getProjectOrNull(project != null ? project.getId() : null); String title = createScheduleAssignedTitle(project != null ? project.getTitle() : null); String targetType = getTargetTypeName(NotificationTargetType.SCHEDULE); + Set recipientIds = new HashSet<>(); List notifications = recipients.stream() .filter(Objects::nonNull) + .filter(recipient -> recipientIds.add(recipient.getId())) .filter(recipient -> !Objects.equals(recipient.getId(), writerId)) .map(recipient -> Notification.create( recipient, @@ -252,6 +255,7 @@ public void createScheduleCreatedNotifications( ) { validateRequiredId(projectId); validateRequiredId(scheduleId); + validateRequiredId(actorUserId); validateRequiredText(projectTitle); validateRequiredText(scheduleTitle); validateRequiredText(creatorName); @@ -285,6 +289,7 @@ public void createVideoFeedbackCommentedNotifications( ) { validateRequiredId(projectId); validateRequiredId(videoId); + validateRequiredId(actorUserId); createOrUpdateGroupedNotifications(NotificationCreateCommand.builder() .recipientIds(recipientIds) @@ -312,6 +317,7 @@ public void createVideoFeedbackCommentedNotifications( ) { validateRequiredId(projectId); validateRequiredId(videoId); + validateRequiredId(actorUserId); validateRequiredText(videoTitle); validateRequiredText(commenterName); Project project = getProjectOrNull(projectId); @@ -426,6 +432,7 @@ public void createNoticeCreatedNotifications( ) { validateRequiredId(projectId); validateRequiredId(noticeId); + validateRequiredId(actorUserId); validateRequiredText(projectTitle); validateRequiredText(noticeTitle); validateRequiredText(creatorName); @@ -455,6 +462,7 @@ public void createFileUploadedNotifications( Long actorUserId ) { validateRequiredId(projectId); + validateRequiredId(actorUserId); validateRequiredText(projectTitle); validateRequiredText(fileName); validateRequiredText(uploaderName); From 999b6fdc839cb77d6f239d4fcd69dbd43017de65 Mon Sep 17 00:00:00 2001 From: guingguing Date: Thu, 6 Aug 2026 00:52:42 +0900 Subject: [PATCH 09/10] =?UTF-8?q?fix:=20=EC=9D=BC=EC=A0=95=20=EB=8B=B4?= =?UTF-8?q?=EB=8B=B9=EC=9E=90=20=EC=95=8C=EB=A6=BC=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=AC=B8=EA=B5=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../slatto/domain/notification/service/NotificationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 7e9e2a8e..6fe37d41 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -663,7 +663,7 @@ private NotificationListResponse.NotificationSummary toSummary(Notification noti } private String createScheduleAssignedContent(String scheduleTitle, String assigneeName) { - return assigneeName + "님이 [" + scheduleTitle + "] 담당자로 지정했어요"; + return assigneeName + "님이 [" + scheduleTitle + "] 담당자로 지정되었어요"; } private String createScheduleAssignedTitle(String projectTitle) { From e377f8993ea25a028c15a19e267c46b17f62ddd0 Mon Sep 17 00:00:00 2001 From: guingguing Date: Thu, 6 Aug 2026 01:24:11 +0900 Subject: [PATCH 10/10] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=94=BC=EB=93=9C=EB=B0=B1=20=EC=95=8C=EB=A6=BC=20=ED=96=89?= =?UTF-8?q?=EC=9C=84=EC=9E=90=20ID=20null=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../slatto/domain/notification/service/NotificationService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/slatto/domain/notification/service/NotificationService.java b/src/main/java/com/slatto/domain/notification/service/NotificationService.java index 6fe37d41..92abbe22 100644 --- a/src/main/java/com/slatto/domain/notification/service/NotificationService.java +++ b/src/main/java/com/slatto/domain/notification/service/NotificationService.java @@ -289,7 +289,6 @@ public void createVideoFeedbackCommentedNotifications( ) { validateRequiredId(projectId); validateRequiredId(videoId); - validateRequiredId(actorUserId); createOrUpdateGroupedNotifications(NotificationCreateCommand.builder() .recipientIds(recipientIds) @@ -317,7 +316,6 @@ public void createVideoFeedbackCommentedNotifications( ) { validateRequiredId(projectId); validateRequiredId(videoId); - validateRequiredId(actorUserId); validateRequiredText(videoTitle); validateRequiredText(commenterName); Project project = getProjectOrNull(projectId);