From b2b8eabaeade4e47adf960aaf8d2fc916d4db177 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 10:47:24 +0900 Subject: [PATCH 01/47] =?UTF-8?q?[rename]=20:=20Alis=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gongmuin/member/repository/MemberCustomImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/member/repository/MemberCustomImpl.java b/src/main/java/com/dnd/gongmuin/member/repository/MemberCustomImpl.java index fd63d28..3d7d6ed 100644 --- a/src/main/java/com/dnd/gongmuin/member/repository/MemberCustomImpl.java +++ b/src/main/java/com/dnd/gongmuin/member/repository/MemberCustomImpl.java @@ -43,8 +43,8 @@ public Slice getQuestionPostsByMember(Member member, Page List content = queryFactory .select(new QQuestionPostsResponse( qp, - saved.count.coalesce(0).as("savedTotalCount"), - recommend.count.coalesce(0).as("recommendTotalCount") + saved.count.coalesce(0).as("bookmarkCount"), + recommend.count.coalesce(0).as("recommendCount") )) .from(qp) .leftJoin(saved) @@ -75,8 +75,8 @@ public Slice getAnsweredQuestionPostsByMember( queryFactory .select(new QAnsweredQuestionPostsResponse( qp, - saved.count.coalesce(0).as("savedTotalCount"), - recommend.count.coalesce(0).as("recommendTotalCount"), + saved.count.coalesce(0).as("bookmarkCount"), + recommend.count.coalesce(0).as("recommendCount"), aw1 )) .from(qp) @@ -119,8 +119,8 @@ public Slice getBookmarksByMember(Member member, Pageable pag List content = queryFactory .select(new QBookmarksResponse( qp, - saved.count.coalesce(0).as("savedTotalCount"), - recommend.count.coalesce(0).as("recommendTotalCount") + saved.count.coalesce(0).as("bookmarkCount"), + recommend.count.coalesce(0).as("recommendCount") )) .from(qp) .join(ir) From 8493febf370ff8e1c929e7f46bb0be357668e2e0 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 10:55:45 +0900 Subject: [PATCH 02/47] =?UTF-8?q?[rename]=20:=20targetUrl=20->=20targetId?= =?UTF-8?q?=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gongmuin/notification/domain/Notification.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java index c1bfb21..8501946 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java @@ -2,6 +2,7 @@ import static jakarta.persistence.ConstraintMode.*; import static jakarta.persistence.FetchType.*; +import static lombok.AccessLevel.*; import com.dnd.gongmuin.common.entity.TimeBaseEntity; import com.dnd.gongmuin.member.domain.Member; @@ -38,8 +39,8 @@ public class Notification extends TimeBaseEntity { @Column(name = "is_read", nullable = false) private Boolean isRead; - @Column(name = "target_url") - private String targetUrl; + @Column(name = "target_id") + private Long targetId; @ManyToOne(fetch = LAZY) @JoinColumn(name = "member_id", @@ -47,11 +48,11 @@ public class Notification extends TimeBaseEntity { foreignKey = @ForeignKey(NO_CONSTRAINT)) private Member member; - @Builder - public Notification(NotificationType type, Boolean isRead, String targetUrl, Member member) { + @Builder(access = PRIVATE) + private Notification(NotificationType type, Boolean isRead, Long targetId, Member member) { this.type = type; this.isRead = isRead; - this.targetUrl = targetUrl; + this.targetId = targetId; this.member = member; } } From f0f7336398d7a8da850706da962c77c6d23f16d0 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 10:58:46 +0900 Subject: [PATCH 03/47] =?UTF-8?q?[feat]=20:=20NotificationRepository=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/NotificationRepository.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java diff --git a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java new file mode 100644 index 0000000..2f7a1c7 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java @@ -0,0 +1,10 @@ +package com.dnd.gongmuin.notification.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.dnd.gongmuin.notification.domain.Notification; + +@Repository +public interface NotificationRepository extends JpaRepository { +} From ed806c84de3051a986b6b9eb8a3fc807996c1b6a Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:00:05 +0900 Subject: [PATCH 04/47] =?UTF-8?q?[feat]=20:=20NotificationService=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationService.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java new file mode 100644 index 0000000..dded0e7 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -0,0 +1,14 @@ +package com.dnd.gongmuin.notification.service; + +import org.springframework.stereotype.Service; + +import com.dnd.gongmuin.notification.repository.NotificationRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class NotificationService { + + private final NotificationRepository notificationRepository; +} From 79ad56790e856216083f09fcb51046cd021279b8 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:09:18 +0900 Subject: [PATCH 05/47] =?UTF-8?q?[feat]=20:=20Notification=20=EC=A0=95?= =?UTF-8?q?=EC=A0=81=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=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 --- .../dnd/gongmuin/notification/domain/Notification.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java index 8501946..5926784 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java @@ -55,4 +55,13 @@ private Notification(NotificationType type, Boolean isRead, Long targetId, Membe this.targetId = targetId; this.member = member; } + + public static Notification of(NotificationType type, Long targetId, Member member) { + return Notification.builder() + .type(type) + .isRead(false) + .targetId(targetId) + .member(member) + .build(); + } } From 6d189879adcdbc24736acef8703ffac4b801e202 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:09:50 +0900 Subject: [PATCH 06/47] =?UTF-8?q?[feat]=20:=20Notification=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationService.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index dded0e7..fedd0bb 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -2,6 +2,9 @@ import org.springframework.stereotype.Service; +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.domain.NotificationType; import com.dnd.gongmuin.notification.repository.NotificationRepository; import lombok.RequiredArgsConstructor; @@ -11,4 +14,15 @@ public class NotificationService { private final NotificationRepository notificationRepository; + + public void saveNotificationFromTarget(String targetType, Long targetId, Member toMember) { + NotificationType type = findTargetType(targetType); + Notification notification = Notification.of(type, targetId, toMember); + + notificationRepository.save(notification); + } + + private NotificationType findTargetType(String targetType) { + return NotificationType.of(targetType); + } } From 801e01a9b830912212309c9df4d56092d3effa06 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:15:41 +0900 Subject: [PATCH 07/47] =?UTF-8?q?[feat]=20:=20Notification=20ErrorCode=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/NotificationErrorCode.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java diff --git a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java new file mode 100644 index 0000000..ecee974 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java @@ -0,0 +1,17 @@ +package com.dnd.gongmuin.notification.exception; + +import com.dnd.gongmuin.common.exception.ErrorCode; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NotificationErrorCode implements ErrorCode { + + NOT_FOUND_NOTIFICATION_TYPE("알맞은 알림 타입을 찾을 수 없습니다.", "NOTIFICATION_001"), + SAVE_NOTIFICATION_FAILED("알림 저장을 실패했습니다.", "NOTIFICATION_002"); + + private final String message; + private final String code; +} From 6443a047cf18eef5a2b107feec5c8c47dde8be90 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:16:42 +0900 Subject: [PATCH 08/47] =?UTF-8?q?[feat]=20:=20NotificationType=20=EC=A0=95?= =?UTF-8?q?=EC=A0=81=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=82=B4=EB=B6=80=20throw=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dnd/gongmuin/notification/domain/NotificationType.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java index 63931d1..79399fa 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java @@ -2,6 +2,9 @@ import java.util.Arrays; +import com.dnd.gongmuin.common.exception.runtime.NotFoundException; +import com.dnd.gongmuin.notification.exception.NotificationErrorCode; + import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -19,7 +22,7 @@ public static NotificationType of(String input) { return Arrays.stream(values()) .filter(type -> type.isEqual(input)) .findAny() - .orElseThrow(IllegalArgumentException::new); + .orElseThrow(() -> new NotFoundException(NotificationErrorCode.NOT_FOUND_NOTIFICATION_TYPE)); } private boolean isEqual(String input) { From f13b1e17e1acb5a9c4bc38cb87fb94ed89c99bde Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:18:29 +0900 Subject: [PATCH 09/47] =?UTF-8?q?[feat]=20:=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98,=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationService.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index fedd0bb..8647bef 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -1,10 +1,13 @@ package com.dnd.gongmuin.notification.service; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.notification.domain.Notification; import com.dnd.gongmuin.notification.domain.NotificationType; +import com.dnd.gongmuin.notification.exception.NotificationErrorCode; import com.dnd.gongmuin.notification.repository.NotificationRepository; import lombok.RequiredArgsConstructor; @@ -15,11 +18,15 @@ public class NotificationService { private final NotificationRepository notificationRepository; + @Transactional public void saveNotificationFromTarget(String targetType, Long targetId, Member toMember) { NotificationType type = findTargetType(targetType); Notification notification = Notification.of(type, targetId, toMember); - - notificationRepository.save(notification); + try { + notificationRepository.save(notification); + } catch (Exception e) { + throw new ValidationException(NotificationErrorCode.SAVE_NOTIFICATION_FAILED); + } } private NotificationType findTargetType(String targetType) { From d4334041807fa19a5143a202453e237e1e7fac2e Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:22:25 +0900 Subject: [PATCH 10/47] =?UTF-8?q?[feat]=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/answer/service/AnswerService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java index f6176df..6d1bfdc 100644 --- a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java +++ b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java @@ -16,6 +16,7 @@ import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.credit_history.service.CreditHistoryService; import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.service.NotificationService; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.exception.QuestionPostErrorCode; import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; @@ -29,6 +30,7 @@ public class AnswerService { private final QuestionPostRepository questionPostRepository; private final AnswerRepository answerRepository; private final CreditHistoryService creditHistoryService; + private final NotificationService notificationService; private static void validateIfQuestioner(Member member, QuestionPost questionPost) { if (!questionPost.isQuestioner(member.getId())) { @@ -45,7 +47,10 @@ public AnswerDetailResponse registerAnswer( QuestionPost questionPost = findQuestionPostById(questionPostId); Answer answer = AnswerMapper.toAnswer(questionPostId, questionPost.isQuestioner(member.getId()), request, member); - return AnswerMapper.toAnswerDetailResponse(answerRepository.save(answer)); + Answer savedAnswer = answerRepository.save(answer); + + notificationService.saveNotificationFromTarget("답변", questionPost.getId(), questionPost.getMember()); + return AnswerMapper.toAnswerDetailResponse(savedAnswer); } @Transactional(readOnly = true) From a8aecd1c54fefdd3ee482077326be0b419b2a290 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:52:18 +0900 Subject: [PATCH 11/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20trigger?= =?UTF-8?q?=20=ED=9A=8C=EC=9B=90=20=ED=95=84=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 --- .../notification/domain/Notification.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java index 5926784..6bdef93 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java @@ -42,6 +42,9 @@ public class Notification extends TimeBaseEntity { @Column(name = "target_id") private Long targetId; + @Column(name = "trigger_member_id") + private Long triggerMemberId; + @ManyToOne(fetch = LAZY) @JoinColumn(name = "member_id", nullable = false, @@ -49,18 +52,29 @@ public class Notification extends TimeBaseEntity { private Member member; @Builder(access = PRIVATE) - private Notification(NotificationType type, Boolean isRead, Long targetId, Member member) { + private Notification( + NotificationType type, + Boolean isRead, + Long targetId, + Long triggerMemberId, + Member member) { this.type = type; this.isRead = isRead; this.targetId = targetId; + this.triggerMemberId = triggerMemberId; this.member = member; } - public static Notification of(NotificationType type, Long targetId, Member member) { + public static Notification of( + NotificationType type, + Long targetId, + Long triggerMemberId, + Member member) { return Notification.builder() .type(type) .isRead(false) .targetId(targetId) + .triggerMemberId(triggerMemberId) .member(member) .build(); } From de8f491d9bbaf36baaecfc15fa32e1b665f39673 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:52:39 +0900 Subject: [PATCH 12/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20trigger=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index 8647bef..fb14b19 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -19,9 +19,13 @@ public class NotificationService { private final NotificationRepository notificationRepository; @Transactional - public void saveNotificationFromTarget(String targetType, Long targetId, Member toMember) { + public void saveNotificationFromTarget( + String targetType, + Long targetId, + Long triggerMemberId, + Member toMember) { NotificationType type = findTargetType(targetType); - Notification notification = Notification.of(type, targetId, toMember); + Notification notification = Notification.of(type, targetId, triggerMemberId, toMember); try { notificationRepository.save(notification); } catch (Exception e) { From 301cfc6760743e8389a01c602fbb5a8d45b3193f Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 11:53:05 +0900 Subject: [PATCH 13/47] =?UTF-8?q?'[feat]=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=80=EC=9E=A5=20=EC=8B=9C=20trigger(?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=9E=91=EC=84=B1=EC=9E=90)=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dnd/gongmuin/answer/service/AnswerService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java index 6d1bfdc..519f68a 100644 --- a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java +++ b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java @@ -49,7 +49,9 @@ public AnswerDetailResponse registerAnswer( member); Answer savedAnswer = answerRepository.save(answer); - notificationService.saveNotificationFromTarget("답변", questionPost.getId(), questionPost.getMember()); + notificationService.saveNotificationFromTarget( + "답변", questionPost.getId(), member.getId(), questionPost.getMember() + ); return AnswerMapper.toAnswerDetailResponse(savedAnswer); } From 7d539324f6f887a65e172b7e54487b084e315634 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 12:04:34 +0900 Subject: [PATCH 14/47] =?UTF-8?q?[rename]=20:=20ANSWER=20label=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/notification/domain/NotificationType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java index 79399fa..a8b372d 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java @@ -12,7 +12,7 @@ @RequiredArgsConstructor public enum NotificationType { - ANSWER("댓글"), + ANSWER("답변"), CHOSEN("채택"), CHAT("채팅"); From bae47e5480bfa68f6e47d462620967a1ba750909 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 12:04:40 +0900 Subject: [PATCH 15/47] =?UTF-8?q?[feat]=20:=20=EC=B1=84=ED=83=9D=20?= =?UTF-8?q?=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EC=83=9D=EC=84=B1=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dnd/gongmuin/answer/service/AnswerService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java index 519f68a..1c9bf96 100644 --- a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java +++ b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java @@ -73,6 +73,9 @@ public AnswerDetailResponse chooseAnswer( QuestionPost questionPost = findQuestionPostById(answer.getQuestionPostId()); validateIfQuestioner(member, questionPost); chooseAnswer(questionPost, answer); + notificationService.saveNotificationFromTarget( + "채택", questionPost.getId(), member.getId(), answer.getMember() + ); return AnswerMapper.toAnswerDetailResponse(answer); } From dd8fbd52ab13b67ec0d8ed8a9bd80c2fb8d9d9fc Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 12:24:17 +0900 Subject: [PATCH 16/47] =?UTF-8?q?[test]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=8B=A8=EC=9C=84=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/NotificationServiceTest.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java diff --git a/src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java new file mode 100644 index 0000000..5d2d7cc --- /dev/null +++ b/src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java @@ -0,0 +1,56 @@ +package com.dnd.gongmuin.notification; + +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import com.dnd.gongmuin.common.fixture.MemberFixture; +import com.dnd.gongmuin.common.fixture.QuestionPostFixture; +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.domain.NotificationType; +import com.dnd.gongmuin.notification.repository.NotificationRepository; +import com.dnd.gongmuin.notification.service.NotificationService; +import com.dnd.gongmuin.question_post.domain.QuestionPost; + +@ExtendWith(MockitoExtension.class) +class NotificationServiceTest { + + @Mock + NotificationRepository notificationRepository; + + @InjectMocks + NotificationService notificationService; + + @DisplayName("타겟 타입에 맞는 알림을 만들고 저장한다.") + @Test + void saveNotificationFromTarget() { + // given + Member member1 = MemberFixture.member(); + Member member2 = MemberFixture.member2(); + ReflectionTestUtils.setField(member1, "id", 1L); + ReflectionTestUtils.setField(member2, "id", 2L); + + QuestionPost questionPost = QuestionPostFixture.questionPost(member1); + ReflectionTestUtils.setField(questionPost, "id", 1L); + + // when + notificationService.saveNotificationFromTarget("답변", questionPost.getId(), member2.getId(), member1); + + // then + verify(notificationRepository).save(any(Notification.class)); + verify(notificationRepository).save(argThat(notification -> + notification.getType().equals(NotificationType.ANSWER) && + notification.getTargetId().equals(questionPost.getId()) && + notification.getTriggerMemberId().equals(member2.getId()) && + notification.getMember().equals(member1) + )); + + } +} From d48d0f45a728b725568cee2dceb77dffd1b4b253 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:03:53 +0900 Subject: [PATCH 17/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/NotificationController.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java diff --git a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java new file mode 100644 index 0000000..47164da --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java @@ -0,0 +1,36 @@ +package com.dnd.gongmuin.notification.controller; + +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.dnd.gongmuin.common.dto.PageResponse; +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; +import com.dnd.gongmuin.notification.service.NotificationService; + +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + +@Tag(name = "알림 API", description = "알림 API") +@RestController +@RequiredArgsConstructor +public class NotificationController { + + private final NotificationService notificationService; + + @GetMapping("/api/notifications") + public ResponseEntity> getNotificationsByMember( + @RequestParam("type") String type, + @AuthenticationPrincipal Member member, + Pageable pageable) { + + PageResponse response = + notificationService.getNotificationsByMember(type, member, pageable); + + return ResponseEntity.ok(response); + } +} From 5a2bbd39c63b5e6a30fc45b28f6a3e34ac9892d0 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:04:14 +0900 Subject: [PATCH 18/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=9D=91=EB=8B=B5=20DTO=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/NotificationsResponse.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/dto/response/NotificationsResponse.java diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/response/NotificationsResponse.java b/src/main/java/com/dnd/gongmuin/notification/dto/response/NotificationsResponse.java new file mode 100644 index 0000000..05cecd5 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/dto/response/NotificationsResponse.java @@ -0,0 +1,42 @@ +package com.dnd.gongmuin.notification.dto.response; + +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.domain.Notification; +import com.querydsl.core.annotations.QueryProjection; + +public record NotificationsResponse( + + Long notificationId, + + String type, + + Boolean isRead, + + Long targetId, + + Long triggerMemberId, + + String triggerMemberNickName, + + Long targetMemberId, + + String NotificationCreatedAt +) { + + @QueryProjection + public NotificationsResponse( + Notification notification, + Member triggerMember + ) { + this( + notification.getId(), + notification.getType().getLabel(), + notification.getIsRead(), + notification.getTargetId(), + triggerMember.getId(), + triggerMember.getNickname(), + notification.getMember().getId(), + notification.getCreatedAt().toString() + ); + } +} From e225af476aa2adb905d8e02ef45b501b25ce167a Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:04:27 +0900 Subject: [PATCH 19/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=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 | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index fb14b19..be3af83 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -1,12 +1,18 @@ package com.dnd.gongmuin.notification.service; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.dnd.gongmuin.common.dto.PageMapper; +import com.dnd.gongmuin.common.dto.PageResponse; +import com.dnd.gongmuin.common.exception.runtime.NotFoundException; import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.notification.domain.Notification; import com.dnd.gongmuin.notification.domain.NotificationType; +import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; import com.dnd.gongmuin.notification.exception.NotificationErrorCode; import com.dnd.gongmuin.notification.repository.NotificationRepository; @@ -36,4 +42,19 @@ public void saveNotificationFromTarget( private NotificationType findTargetType(String targetType) { return NotificationType.of(targetType); } + + public PageResponse getNotificationsByMember( + String type, + Member member, + Pageable pageable) { + + try { + Slice responsePage = + notificationRepository.getNotificationsByMember(type, member, pageable); + + return PageMapper.toPageResponse(responsePage); + } catch (Exception e) { + throw new NotFoundException(NotificationErrorCode.NOTIFICATIONS_BY_MEMBER_FAILED); + } + } } From 5b1e37b5af8bbe02563373ae52347d2fef52acc4 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:04:45 +0900 Subject: [PATCH 20/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EA=B4=80=EB=A0=A8=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=BD=94=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 --- .../gongmuin/notification/exception/NotificationErrorCode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java index ecee974..2056110 100644 --- a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java +++ b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java @@ -10,7 +10,8 @@ public enum NotificationErrorCode implements ErrorCode { NOT_FOUND_NOTIFICATION_TYPE("알맞은 알림 타입을 찾을 수 없습니다.", "NOTIFICATION_001"), - SAVE_NOTIFICATION_FAILED("알림 저장을 실패했습니다.", "NOTIFICATION_002"); + SAVE_NOTIFICATION_FAILED("알림 저장을 실패했습니다.", "NOTIFICATION_002"), + NOTIFICATIONS_BY_MEMBER_FAILED("알림 목록을 불러오는데 실패했습니다.", "NOTIFICATION_003"); private final String message; private final String code; From a5cf36e234adafc0fe73f88ec3dfe9e970152d9e Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:05:25 +0900 Subject: [PATCH 21/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20QueryDS?= =?UTF-8?q?L=20=ED=99=98=EA=B2=BD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/repository/NotificationCustom.java | 13 +++++++++++++ .../repository/NotificationRepository.java | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustom.java diff --git a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustom.java b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustom.java new file mode 100644 index 0000000..21c1835 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustom.java @@ -0,0 +1,13 @@ +package com.dnd.gongmuin.notification.repository; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; + +public interface NotificationCustom { + + Slice getNotificationsByMember(String type, Member member, Pageable pageable); + +} diff --git a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java index 2f7a1c7..7b5b963 100644 --- a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java +++ b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationRepository.java @@ -6,5 +6,5 @@ import com.dnd.gongmuin.notification.domain.Notification; @Repository -public interface NotificationRepository extends JpaRepository { +public interface NotificationRepository extends JpaRepository, NotificationCustom { } From 1db1570361d5f0ef462bd7d00a0dbb34f24ef517 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:05:56 +0900 Subject: [PATCH 22/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20QueryDSL=20=EA=B5=AC=ED=98=84(=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/NotificationCustomImpl.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java diff --git a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java new file mode 100644 index 0000000..b6afcd0 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java @@ -0,0 +1,72 @@ +package com.dnd.gongmuin.notification.repository; + +import static com.dnd.gongmuin.notification.domain.QNotification.*; + +import java.util.List; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; + +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.domain.QMember; +import com.dnd.gongmuin.notification.domain.NotificationType; +import com.dnd.gongmuin.notification.domain.QNotification; +import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; +import com.dnd.gongmuin.notification.dto.response.QNotificationsResponse; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class NotificationCustomImpl implements NotificationCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public Slice getNotificationsByMember( + String type, + Member member, + Pageable pageable) { + QNotification nc = notification; + QMember tm = QMember.member; + + List content = queryFactory + .select(new QNotificationsResponse( + nc, + tm + )) + .from(nc) + .join(tm).on(nc.triggerMemberId.eq(tm.id)) + .where( + nc.member.eq(member), + targetTypeEq(type) + ) + .orderBy(nc.createdAt.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize() + 1L) + .fetch(); + + boolean hasNext = hasNext(pageable.getPageSize(), content); + + return new SliceImpl<>(content, pageable, hasNext); + } + + private BooleanExpression targetTypeEq(String type) { + if (type == null || type.isEmpty() || "전체".equals(type)) { + return null; + } + + return notification.type.in(NotificationType.of(type)); + } + + private boolean hasNext(int pageSize, List content) { + if (content.size() <= pageSize) { + return false; + } + content.remove(pageSize); + return true; + } +} + From a0c5371239f762cd2a17f6b2887b52436a1750cb Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:07:20 +0900 Subject: [PATCH 23/47] =?UTF-8?q?[rename]=20:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=BB=A8=EB=B2=88=EC=85=98?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD(of=20->=20from)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/notification/domain/NotificationType.java | 2 +- .../notification/repository/NotificationCustomImpl.java | 2 +- .../dnd/gongmuin/notification/service/NotificationService.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java index a8b372d..66ce4f6 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/NotificationType.java @@ -18,7 +18,7 @@ public enum NotificationType { private final String label; - public static NotificationType of(String input) { + public static NotificationType from(String input) { return Arrays.stream(values()) .filter(type -> type.isEqual(input)) .findAny() diff --git a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java index b6afcd0..9ec2229 100644 --- a/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java +++ b/src/main/java/com/dnd/gongmuin/notification/repository/NotificationCustomImpl.java @@ -58,7 +58,7 @@ private BooleanExpression targetTypeEq(String type) { return null; } - return notification.type.in(NotificationType.of(type)); + return notification.type.in(NotificationType.from(type)); } private boolean hasNext(int pageSize, List content) { diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index be3af83..931c160 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -40,7 +40,7 @@ public void saveNotificationFromTarget( } private NotificationType findTargetType(String targetType) { - return NotificationType.of(targetType); + return NotificationType.from(targetType); } public PageResponse getNotificationsByMember( From 621ebace6a07d4b0f2cc06193edea9eecbfc7c79 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 13:08:15 +0900 Subject: [PATCH 24/47] =?UTF-8?q?[style]=20:=20NotificationServiceTest=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/{ => service}/NotificationServiceTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename src/test/java/com/dnd/gongmuin/notification/{ => service}/NotificationServiceTest.java (94%) diff --git a/src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java similarity index 94% rename from src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java rename to src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java index 5d2d7cc..2ae0d12 100644 --- a/src/test/java/com/dnd/gongmuin/notification/NotificationServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java @@ -1,4 +1,4 @@ -package com.dnd.gongmuin.notification; +package com.dnd.gongmuin.notification.service; import static org.mockito.Mockito.*; @@ -16,7 +16,6 @@ import com.dnd.gongmuin.notification.domain.Notification; import com.dnd.gongmuin.notification.domain.NotificationType; import com.dnd.gongmuin.notification.repository.NotificationRepository; -import com.dnd.gongmuin.notification.service.NotificationService; import com.dnd.gongmuin.question_post.domain.QuestionPost; @ExtendWith(MockitoExtension.class) From a45a44dc23b3c1f34e7679b8dc57d8e9d79e520a Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 14:09:33 +0900 Subject: [PATCH 25/47] =?UTF-8?q?[test]=20:=20NotificationFixture=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fixture/NotificationFixture.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/java/com/dnd/gongmuin/common/fixture/NotificationFixture.java diff --git a/src/test/java/com/dnd/gongmuin/common/fixture/NotificationFixture.java b/src/test/java/com/dnd/gongmuin/common/fixture/NotificationFixture.java new file mode 100644 index 0000000..1382d5e --- /dev/null +++ b/src/test/java/com/dnd/gongmuin/common/fixture/NotificationFixture.java @@ -0,0 +1,25 @@ +package com.dnd.gongmuin.common.fixture; + +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.domain.NotificationType; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class NotificationFixture { + + public static Notification notification( + NotificationType type, + Long questionPostId, + Long triggerMemberId, + Member member) { + return Notification.of( + type, + questionPostId, + triggerMemberId, + member + ); + } +} From 4f1c2d7c4bc6edf47949f61dd8486f36de72830f Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 14:09:52 +0900 Subject: [PATCH 26/47] =?UTF-8?q?[test]=20:=20NotificationRepository=20?= =?UTF-8?q?=EB=8B=A8=EC=9C=84=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotificationRepositoryTest.java | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/test/java/com/dnd/gongmuin/notification/repository/NotificationRepositoryTest.java diff --git a/src/test/java/com/dnd/gongmuin/notification/repository/NotificationRepositoryTest.java b/src/test/java/com/dnd/gongmuin/notification/repository/NotificationRepositoryTest.java new file mode 100644 index 0000000..637ae33 --- /dev/null +++ b/src/test/java/com/dnd/gongmuin/notification/repository/NotificationRepositoryTest.java @@ -0,0 +1,148 @@ +package com.dnd.gongmuin.notification.repository; + +import static com.dnd.gongmuin.notification.domain.NotificationType.*; +import static org.assertj.core.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; + +import com.dnd.gongmuin.answer.repository.AnswerRepository; +import com.dnd.gongmuin.common.fixture.MemberFixture; +import com.dnd.gongmuin.common.fixture.NotificationFixture; +import com.dnd.gongmuin.common.fixture.QuestionPostFixture; +import com.dnd.gongmuin.common.support.DataJpaTestSupport; +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.repository.MemberRepository; +import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; +import com.dnd.gongmuin.question_post.domain.QuestionPost; +import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; + +class NotificationRepositoryTest extends DataJpaTestSupport { + + private final PageRequest pageRequest = PageRequest.of(0, 10); + + @Autowired + MemberRepository memberRepository; + + @Autowired + QuestionPostRepository questionPostRepository; + + @Autowired + AnswerRepository answerRepository; + + @Autowired + NotificationRepository notificationRepository; + + @DisplayName("회원의 알림 전체 목록을 불러온다.") + @Test + void getNotificationsByMember() { + // given + Member member1 = MemberFixture.member(); + Member member2 = MemberFixture.member2(); + Member member3 = MemberFixture.member3(); + memberRepository.saveAll(List.of(member1, member2, member3)); + + QuestionPost questionPost1 = QuestionPostFixture.questionPost(member1, "첫 번째 게시글입니다."); + questionPostRepository.save(questionPost1); + + Notification notification1 = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member2.getId(), member1 + ); + Notification notification2 = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member3.getId(), member1 + ); + Notification notification3 = NotificationFixture.notification( + CHOSEN, questionPost1.getId(), member3.getId(), member1 + ); + notificationRepository.saveAll(List.of(notification1, notification2, notification3)); + + // when + Slice notificationsByMember = notificationRepository.getNotificationsByMember("전체", + member1, pageRequest); + + // then + Assertions.assertAll( + () -> assertThat(notificationsByMember).hasSize(3), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::type) + .containsExactly( + "채택", + "답변", + "답변" + ), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::triggerMemberId) + .containsExactly( + member3.getId(), + member3.getId(), + member2.getId() + ), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::triggerMemberNickName) + .containsExactly( + member3.getNickname(), + member3.getNickname(), + member2.getNickname() + ), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::targetMemberId) + .containsExactly( + member1.getId(), + member1.getId(), + member1.getId() + ) + ); + } + + @DisplayName("회원의 알림 채택 목록을 불러온다.") + @Test + void getNotificationsByMemberWithChosen() { + // given + Member member1 = MemberFixture.member(); + Member member2 = MemberFixture.member2(); + Member member3 = MemberFixture.member3(); + memberRepository.saveAll(List.of(member1, member2, member3)); + + QuestionPost questionPost1 = QuestionPostFixture.questionPost(member1, "첫 번째 게시글입니다."); + questionPostRepository.save(questionPost1); + + Notification notification1 = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member2.getId(), member1 + ); + Notification notification2 = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member3.getId(), member1 + ); + Notification notification3 = NotificationFixture.notification( + CHOSEN, questionPost1.getId(), member3.getId(), member1 + ); + notificationRepository.saveAll(List.of(notification1, notification2, notification3)); + + // when + Slice notificationsByMember = notificationRepository.getNotificationsByMember("채택", + member1, pageRequest); + + // then + Assertions.assertAll( + () -> assertThat(notificationsByMember).hasSize(1), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::type) + .containsExactly( + "채택" + ), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::triggerMemberId) + .containsExactly( + member3.getId() + ), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::triggerMemberNickName) + .containsExactly( + member3.getNickname() + ), + () -> assertThat(notificationsByMember).extracting(NotificationsResponse::targetMemberId) + .containsExactly( + member1.getId() + ) + ); + } +} From 099741b0c8417dbd34b42a30b0a300c4f9aca5b6 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 14:18:06 +0900 Subject: [PATCH 27/47] =?UTF-8?q?[tes]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=EC=A1=B0=ED=9A=8C=20=ED=86=B5=ED=95=A9?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotificationControllerTest.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java diff --git a/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java b/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java new file mode 100644 index 0000000..bab5b1c --- /dev/null +++ b/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java @@ -0,0 +1,93 @@ +package com.dnd.gongmuin.notification.controller; + +import static com.dnd.gongmuin.notification.domain.NotificationType.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; + +import com.dnd.gongmuin.answer.repository.AnswerRepository; +import com.dnd.gongmuin.common.fixture.MemberFixture; +import com.dnd.gongmuin.common.fixture.NotificationFixture; +import com.dnd.gongmuin.common.fixture.QuestionPostFixture; +import com.dnd.gongmuin.common.support.ApiTestSupport; +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.repository.MemberRepository; +import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.repository.NotificationRepository; +import com.dnd.gongmuin.question_post.domain.QuestionPost; +import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; + +@DisplayName("[NotificationController] 통합테스트") +class NotificationControllerTest extends ApiTestSupport { + + private final PageRequest pageRequest = PageRequest.of(0, 10); + + @Autowired + MemberRepository memberRepository; + + @Autowired + QuestionPostRepository questionPostRepository; + + @Autowired + AnswerRepository answerRepository; + + @Autowired + NotificationRepository notificationRepository; + + @AfterEach + void tearDown() { + answerRepository.deleteAll(); + notificationRepository.deleteAll(); + questionPostRepository.deleteAll(); + memberRepository.deleteAll(); + } + + @DisplayName("로그인 된 회원의 알림 목록을 조회힌다.") + @Test + void test() throws Exception { + // given + Member member2 = MemberFixture.member2(); + Member member3 = MemberFixture.member3(); + memberRepository.saveAll(List.of(member2, member3)); + + QuestionPost questionPost1 = QuestionPostFixture.questionPost(loginMember, "첫 번째 게시글입니다."); + questionPostRepository.save(questionPost1); + + Notification notification1 = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member2.getId(), loginMember + ); + Notification notification2 = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member3.getId(), loginMember + ); + Notification notification3 = NotificationFixture.notification( + CHOSEN, questionPost1.getId(), member3.getId(), loginMember + ); + notificationRepository.saveAll(List.of(notification1, notification2, notification3)); + + // when // then + mockMvc.perform(get("/api/notifications") + .param("type", "전체") + .cookie(accessToken) + ) + .andExpect(status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andExpect(jsonPath("$.size").value(3)) + .andExpect(jsonPath("$.content[0].type").value(CHOSEN.getLabel())) + .andExpect(jsonPath("$.content[1].type").value(ANSWER.getLabel())) + .andExpect(jsonPath("$.content[2].type").value(ANSWER.getLabel())) + .andExpect(jsonPath("$.content[0].triggerMemberId").value(member3.getId())) + .andExpect(jsonPath("$.content[1].triggerMemberId").value(member3.getId())) + .andExpect(jsonPath("$.content[2].triggerMemberId").value(member2.getId())) + .andExpect(jsonPath("$.content[0].targetMemberId").value(loginMember.getId())) + .andExpect(jsonPath("$.content[1].targetMemberId").value(loginMember.getId())) + .andExpect(jsonPath("$.content[2].targetMemberId").value(loginMember.getId())); + } +} From 90eeb1e85f06f27f700e08554881e28e8dcddc01 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:17:27 +0900 Subject: [PATCH 28/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/NotificationController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java index 47164da..5c4d000 100644 --- a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java +++ b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java @@ -4,11 +4,15 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.dnd.gongmuin.common.dto.PageResponse; import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; +import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; import com.dnd.gongmuin.notification.service.NotificationService; @@ -33,4 +37,13 @@ public ResponseEntity> getNotificationsByMem return ResponseEntity.ok(response); } + + @PatchMapping("/api/notifications/read") + public ResponseEntity isReadNotification( + @RequestBody IsReadNotificationRequest request + ) { + IsReadNotificationResponse response = notificationService.isReadNotification(request); + + return ResponseEntity.ok(response); + } } From ec7c8d923dd10efc7a050561873ffb498f9f578a Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:17:51 +0900 Subject: [PATCH 29/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EC=9A=94=EC=B2=AD/=EC=9D=91=EB=8B=B5=20DT?= =?UTF-8?q?O=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/IsReadNotificationRequest.java | 6 ++++++ .../dto/response/IsReadNotificationResponse.java | 7 +++++++ 2 files changed, 13 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java create mode 100644 src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java b/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java new file mode 100644 index 0000000..1caf0cd --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java @@ -0,0 +1,6 @@ +package com.dnd.gongmuin.notification.dto.request; + +public record IsReadNotificationRequest( + Long notificationId +) { +} diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java b/src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java new file mode 100644 index 0000000..44a1615 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java @@ -0,0 +1,7 @@ +package com.dnd.gongmuin.notification.dto.response; + +public record IsReadNotificationResponse( + Long notificationId, + Boolean isRead +) { +} From 235779a03b0f8fb33eb800b038b8df618833f8d9 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:18:16 +0900 Subject: [PATCH 30/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20DTO=20M?= =?UTF-8?q?apper=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/dto/NotificationMapper.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java b/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java new file mode 100644 index 0000000..d6daba1 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java @@ -0,0 +1,18 @@ +package com.dnd.gongmuin.notification.dto; + +import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class NotificationMapper { + + public static IsReadNotificationResponse toIsReadNotificationResponse(Notification notification) { + return new IsReadNotificationResponse( + notification.getId(), + notification.getIsRead() + ); + } +} From 76ca070f6cf435b606a70173c82098966631d907 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:18:33 +0900 Subject: [PATCH 31/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=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 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index 931c160..9f0608b 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -12,6 +12,9 @@ import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.notification.domain.Notification; import com.dnd.gongmuin.notification.domain.NotificationType; +import com.dnd.gongmuin.notification.dto.NotificationMapper; +import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; +import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; import com.dnd.gongmuin.notification.exception.NotificationErrorCode; import com.dnd.gongmuin.notification.repository.NotificationRepository; @@ -57,4 +60,18 @@ public PageResponse getNotificationsByMember( throw new NotFoundException(NotificationErrorCode.NOTIFICATIONS_BY_MEMBER_FAILED); } } + + @Transactional + public IsReadNotificationResponse isReadNotification(IsReadNotificationRequest request) { + Notification findNotification = notificationRepository.findById(request.notificationId()) + .orElseThrow(() -> new NotFoundException(NotificationErrorCode.NOT_FOUND_NOTIFICATION)); + + if (Boolean.TRUE.equals(findNotification.getIsRead())) { + throw new ValidationException(NotificationErrorCode.NOTIFICATIONS_BY_MEMBER_FAILED); + } + + findNotification.updateIsRead(); + + return NotificationMapper.toIsReadNotificationResponse(findNotification); + } } From e7df8db2055b8b3190a92b147e30e555cb7cef1d Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:18:48 +0900 Subject: [PATCH 32/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EA=B4=80=EB=A0=A8=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=BD=94=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 --- .../notification/exception/NotificationErrorCode.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java index 2056110..d6a6a0e 100644 --- a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java +++ b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java @@ -11,7 +11,9 @@ public enum NotificationErrorCode implements ErrorCode { NOT_FOUND_NOTIFICATION_TYPE("알맞은 알림 타입을 찾을 수 없습니다.", "NOTIFICATION_001"), SAVE_NOTIFICATION_FAILED("알림 저장을 실패했습니다.", "NOTIFICATION_002"), - NOTIFICATIONS_BY_MEMBER_FAILED("알림 목록을 불러오는데 실패했습니다.", "NOTIFICATION_003"); + NOTIFICATIONS_BY_MEMBER_FAILED("알림 목록을 불러오는데 실패했습니다.", "NOTIFICATION_003"), + NOT_FOUND_NOTIFICATION("해당 알림을 찾을 수 없습니다", "NOTIFICATION_004"), + CHANGE_IS_READ_NOTIFICATION_FAILED("해당 알림의 읽음 여부 변경을 실패했습니다.", "NOTIFICATION_005"); private final String message; private final String code; From e0887ce302585f63b91bf61d708f03b919f3ee61 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:19:58 +0900 Subject: [PATCH 33/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EC=83=81=ED=83=9C=EB=B3=80=ED=99=98=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/notification/domain/Notification.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java index 6bdef93..d8be5d0 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java @@ -78,4 +78,8 @@ public static Notification of( .member(member) .build(); } + + public Boolean updateIsRead() { + return this.isRead = Boolean.TRUE; + } } From 4a8a78e9887bec5545712556a1e677ea53aedc8c Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 20:55:48 +0900 Subject: [PATCH 34/47] =?UTF-8?q?[rename]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20API=20PATH=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/controller/NotificationController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java index 5c4d000..b6f9a3b 100644 --- a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java +++ b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java @@ -38,7 +38,7 @@ public ResponseEntity> getNotificationsByMem return ResponseEntity.ok(response); } - @PatchMapping("/api/notifications/read") + @PatchMapping("/api/notification/read") public ResponseEntity isReadNotification( @RequestBody IsReadNotificationRequest request ) { From d54ab40ad8ec834b6277d7cf7c12abe69fba1e07 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 21:00:48 +0900 Subject: [PATCH 35/47] =?UTF-8?q?[fix]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=A4=91=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dnd/gongmuin/notification/service/NotificationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index 9f0608b..a98c6d1 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -67,7 +67,7 @@ public IsReadNotificationResponse isReadNotification(IsReadNotificationRequest r .orElseThrow(() -> new NotFoundException(NotificationErrorCode.NOT_FOUND_NOTIFICATION)); if (Boolean.TRUE.equals(findNotification.getIsRead())) { - throw new ValidationException(NotificationErrorCode.NOTIFICATIONS_BY_MEMBER_FAILED); + throw new ValidationException(NotificationErrorCode.CHANGE_IS_READ_NOTIFICATION_FAILED); } findNotification.updateIsRead(); From 85e0fda865f295a47b69eaeabfe94aaebca3dd0d Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 21:04:51 +0900 Subject: [PATCH 36/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EC=9A=94=EC=B2=AD=20DTO=20Validation=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/controller/NotificationController.java | 3 ++- .../notification/dto/request/IsReadNotificationRequest.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java index b6f9a3b..0852784 100644 --- a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java +++ b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java @@ -17,6 +17,7 @@ import com.dnd.gongmuin.notification.service.NotificationService; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @Tag(name = "알림 API", description = "알림 API") @@ -40,7 +41,7 @@ public ResponseEntity> getNotificationsByMem @PatchMapping("/api/notification/read") public ResponseEntity isReadNotification( - @RequestBody IsReadNotificationRequest request + @RequestBody @Valid IsReadNotificationRequest request ) { IsReadNotificationResponse response = notificationService.isReadNotification(request); diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java b/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java index 1caf0cd..62fbea6 100644 --- a/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java +++ b/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java @@ -1,6 +1,10 @@ package com.dnd.gongmuin.notification.dto.request; +import jakarta.validation.constraints.NotNull; + public record IsReadNotificationRequest( + + @NotNull(message = "알림 ID 값은 필수 값 입니다.") Long notificationId ) { } From 150316ccc441d410ec3f5ede170203ed27e1cb2f Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 21:10:07 +0900 Subject: [PATCH 37/47] =?UTF-8?q?[feat]=20:=20=ED=95=B4=EB=8B=B9=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=EC=9D=B4=20=EC=9A=94=EC=B2=AD=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=20=EC=95=8C=EB=A6=BC=EC=9D=B8=EC=A7=80=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/NotificationController.java | 5 +++-- .../notification/service/NotificationService.java | 12 +++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java index 0852784..e991806 100644 --- a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java +++ b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java @@ -41,9 +41,10 @@ public ResponseEntity> getNotificationsByMem @PatchMapping("/api/notification/read") public ResponseEntity isReadNotification( - @RequestBody @Valid IsReadNotificationRequest request + @RequestBody @Valid IsReadNotificationRequest request, + @AuthenticationPrincipal Member member ) { - IsReadNotificationResponse response = notificationService.isReadNotification(request); + IsReadNotificationResponse response = notificationService.isReadNotification(request, member); return ResponseEntity.ok(response); } diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index a98c6d1..ed508ef 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -1,5 +1,7 @@ package com.dnd.gongmuin.notification.service; +import java.util.Objects; + import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; @@ -62,10 +64,14 @@ public PageResponse getNotificationsByMember( } @Transactional - public IsReadNotificationResponse isReadNotification(IsReadNotificationRequest request) { + public IsReadNotificationResponse isReadNotification(IsReadNotificationRequest request, Member member) { Notification findNotification = notificationRepository.findById(request.notificationId()) .orElseThrow(() -> new NotFoundException(NotificationErrorCode.NOT_FOUND_NOTIFICATION)); + if (!isNotificationOwnedByMember(findNotification, member)) { + throw new ValidationException(NotificationErrorCode.INVALID_NOTIFICATION_OWNER); + } + if (Boolean.TRUE.equals(findNotification.getIsRead())) { throw new ValidationException(NotificationErrorCode.CHANGE_IS_READ_NOTIFICATION_FAILED); } @@ -74,4 +80,8 @@ public IsReadNotificationResponse isReadNotification(IsReadNotificationRequest r return NotificationMapper.toIsReadNotificationResponse(findNotification); } + + private boolean isNotificationOwnedByMember(Notification notification, Member member) { + return Objects.equals(notification.getMember().getId(), member.getId()); + } } From 738d5808be758c3573e8a4d87853f7eaa15611de Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 21:15:40 +0900 Subject: [PATCH 38/47] =?UTF-8?q?[test]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=8B=A8=EC=9C=84=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationServiceTest.java | 87 ++++++++++++++++++- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java index 2ae0d12..1cacc1d 100644 --- a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java @@ -1,6 +1,11 @@ package com.dnd.gongmuin.notification.service; -import static org.mockito.Mockito.*; +import static com.dnd.gongmuin.notification.domain.NotificationType.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,11 +15,14 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; +import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.common.fixture.MemberFixture; +import com.dnd.gongmuin.common.fixture.NotificationFixture; import com.dnd.gongmuin.common.fixture.QuestionPostFixture; import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.notification.domain.Notification; -import com.dnd.gongmuin.notification.domain.NotificationType; +import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; +import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; import com.dnd.gongmuin.notification.repository.NotificationRepository; import com.dnd.gongmuin.question_post.domain.QuestionPost; @@ -45,11 +53,84 @@ void saveNotificationFromTarget() { // then verify(notificationRepository).save(any(Notification.class)); verify(notificationRepository).save(argThat(notification -> - notification.getType().equals(NotificationType.ANSWER) && + notification.getType().equals(ANSWER) && notification.getTargetId().equals(questionPost.getId()) && notification.getTriggerMemberId().equals(member2.getId()) && notification.getMember().equals(member1) )); + } + + @DisplayName("알림의 안읽음 상태를 읽음 상태로 변경한다.") + @Test + void isReadNotification() { + // given + Member member1 = MemberFixture.member(); + Member member2 = MemberFixture.member2(); + + QuestionPost questionPost = QuestionPostFixture.questionPost(member1); + Notification notification = NotificationFixture.notification( + ANSWER, + questionPost.getId(), + member2.getId(), + member1 + ); + IsReadNotificationRequest request = new IsReadNotificationRequest(1L); + + given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); + + // when + IsReadNotificationResponse response = notificationService.isReadNotification(request, member1); + + // then + assertAll( + () -> assertThat(response.notificationId()).isEqualTo(notification.getId()), + () -> assertThat(response.isRead()).isTrue() + ); + } + + @DisplayName("요청 회원이 특정 알림의 소유주가 아니라면 예외가 발생한다.") + @Test + void isReadNotificationThrowsExceptionWhenMemberIsNotOwner() { + // given + Member member1 = MemberFixture.member(); + Member member2 = MemberFixture.member2(); + + QuestionPost questionPost = QuestionPostFixture.questionPost(member1); + Notification notification = NotificationFixture.notification( + ANSWER, + questionPost.getId(), + member2.getId(), + member1 + ); + notification.updateIsRead(); + IsReadNotificationRequest request = new IsReadNotificationRequest(1L); + + given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); + + // when // then + assertThrows(ValidationException.class, () -> notificationService.isReadNotification(request, member2)); + } + + @DisplayName("읽었던 알림의 읽음 상태 변화를 하면 예외가 발생한다.") + @Test + void isReadNotificationThrowsExceptionWhenAlreadyRead() { + // given + Member member1 = MemberFixture.member(); + Member member2 = MemberFixture.member2(); + + QuestionPost questionPost = QuestionPostFixture.questionPost(member1); + Notification notification = NotificationFixture.notification( + ANSWER, + questionPost.getId(), + member2.getId(), + member1 + ); + notification.updateIsRead(); + IsReadNotificationRequest request = new IsReadNotificationRequest(1L); + + given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); + // when // then + assertThrows(ValidationException.class, () -> notificationService.isReadNotification(request, member1)); } } From a27a2854327545abe9ba3af61e4720eb53b21dbc Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 21:16:00 +0900 Subject: [PATCH 39/47] =?UTF-8?q?[test]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EA=B8=B0=20API=20=ED=86=B5=ED=95=A9=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotificationControllerTest.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java b/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java index bab5b1c..48a2cfc 100644 --- a/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java @@ -1,6 +1,7 @@ package com.dnd.gongmuin.notification.controller; import static com.dnd.gongmuin.notification.domain.NotificationType.*; +import static org.springframework.http.MediaType.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -21,6 +22,7 @@ import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.member.repository.MemberRepository; import com.dnd.gongmuin.notification.domain.Notification; +import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; import com.dnd.gongmuin.notification.repository.NotificationRepository; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; @@ -52,7 +54,7 @@ void tearDown() { @DisplayName("로그인 된 회원의 알림 목록을 조회힌다.") @Test - void test() throws Exception { + void getNotificationsByMember() throws Exception { // given Member member2 = MemberFixture.member2(); Member member3 = MemberFixture.member3(); @@ -90,4 +92,32 @@ void test() throws Exception { .andExpect(jsonPath("$.content[1].targetMemberId").value(loginMember.getId())) .andExpect(jsonPath("$.content[2].targetMemberId").value(loginMember.getId())); } + + @DisplayName("회원의 특정 알림을 읽음 여부로 변경한다.") + @Test + void isReadNotification() throws Exception { + // given + Member member2 = MemberFixture.member2(); + memberRepository.save(member2); + + QuestionPost questionPost1 = QuestionPostFixture.questionPost(loginMember, "첫 번째 게시글입니다."); + questionPostRepository.save(questionPost1); + + Notification notification = NotificationFixture.notification( + ANSWER, questionPost1.getId(), member2.getId(), loginMember + ); + notificationRepository.save(notification); + + IsReadNotificationRequest request = new IsReadNotificationRequest(notification.getId()); + + // when // then + mockMvc.perform(patch("/api/notification/read") + .content(toJson(request)) + .contentType(APPLICATION_JSON) + .cookie(accessToken) + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("notificationId").value(notification.getId())) + .andExpect(jsonPath("isRead").value(Boolean.TRUE)); + } } From a9e2a8e3d54fa8d5ea0dd12bc676a9d1aa4e0bd8 Mon Sep 17 00:00:00 2001 From: dudxo Date: Sun, 1 Sep 2024 21:16:37 +0900 Subject: [PATCH 40/47] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=86=8C=EC=9C=A0=EC=A3=BC=20=EA=B4=80=EB=A0=A8=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=BD=94=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 --- .../gongmuin/notification/exception/NotificationErrorCode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java index d6a6a0e..0d67bb8 100644 --- a/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java +++ b/src/main/java/com/dnd/gongmuin/notification/exception/NotificationErrorCode.java @@ -13,7 +13,8 @@ public enum NotificationErrorCode implements ErrorCode { SAVE_NOTIFICATION_FAILED("알림 저장을 실패했습니다.", "NOTIFICATION_002"), NOTIFICATIONS_BY_MEMBER_FAILED("알림 목록을 불러오는데 실패했습니다.", "NOTIFICATION_003"), NOT_FOUND_NOTIFICATION("해당 알림을 찾을 수 없습니다", "NOTIFICATION_004"), - CHANGE_IS_READ_NOTIFICATION_FAILED("해당 알림의 읽음 여부 변경을 실패했습니다.", "NOTIFICATION_005"); + CHANGE_IS_READ_NOTIFICATION_FAILED("해당 알림의 읽음 여부 변경을 실패했습니다.", "NOTIFICATION_005"), + INVALID_NOTIFICATION_OWNER("해당 알림의 주인이 아닙니다.", "NOTIFICATION_006"); private final String message; private final String code; From e73f1af38252c26cee0899ca4466cd5353ad6482 Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 17:34:55 +0900 Subject: [PATCH 41/47] =?UTF-8?q?[test]=20:=20=EB=8B=A8=EC=9C=84=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9A=A9=20Fixture=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationServiceTest.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java index 1cacc1d..ec36cc4 100644 --- a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java @@ -13,7 +13,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.common.fixture.MemberFixture; @@ -39,13 +38,10 @@ class NotificationServiceTest { @Test void saveNotificationFromTarget() { // given - Member member1 = MemberFixture.member(); - Member member2 = MemberFixture.member2(); - ReflectionTestUtils.setField(member1, "id", 1L); - ReflectionTestUtils.setField(member2, "id", 2L); + Member member1 = MemberFixture.member(1L); + Member member2 = MemberFixture.member(2L); - QuestionPost questionPost = QuestionPostFixture.questionPost(member1); - ReflectionTestUtils.setField(questionPost, "id", 1L); + QuestionPost questionPost = QuestionPostFixture.questionPost(1L); // when notificationService.saveNotificationFromTarget("답변", questionPost.getId(), member2.getId(), member1); From b9e4a4c73c82c6666d9c0e812935abd954ba3f14 Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 17:39:10 +0900 Subject: [PATCH 42/47] =?UTF-8?q?[refactor]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20String=EC=9D=B4=20=EC=95=84=EB=8B=8C=20Enu?= =?UTF-8?q?m=EC=9C=BC=EB=A1=9C=20=EB=B0=94=EB=A1=9C=20=EB=B0=9B=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/answer/service/AnswerService.java | 6 ++++-- .../gongmuin/notification/service/NotificationService.java | 7 +------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java index 1c9bf96..2ee605e 100644 --- a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java +++ b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java @@ -1,5 +1,7 @@ package com.dnd.gongmuin.answer.service; +import static com.dnd.gongmuin.notification.domain.NotificationType.*; + import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,7 +52,7 @@ public AnswerDetailResponse registerAnswer( Answer savedAnswer = answerRepository.save(answer); notificationService.saveNotificationFromTarget( - "답변", questionPost.getId(), member.getId(), questionPost.getMember() + ANSWER, questionPost.getId(), member.getId(), questionPost.getMember() ); return AnswerMapper.toAnswerDetailResponse(savedAnswer); } @@ -74,7 +76,7 @@ public AnswerDetailResponse chooseAnswer( validateIfQuestioner(member, questionPost); chooseAnswer(questionPost, answer); notificationService.saveNotificationFromTarget( - "채택", questionPost.getId(), member.getId(), answer.getMember() + CHOSEN, questionPost.getId(), member.getId(), answer.getMember() ); return AnswerMapper.toAnswerDetailResponse(answer); diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index ed508ef..a1daf2b 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -31,11 +31,10 @@ public class NotificationService { @Transactional public void saveNotificationFromTarget( - String targetType, + NotificationType type, Long targetId, Long triggerMemberId, Member toMember) { - NotificationType type = findTargetType(targetType); Notification notification = Notification.of(type, targetId, triggerMemberId, toMember); try { notificationRepository.save(notification); @@ -44,10 +43,6 @@ public void saveNotificationFromTarget( } } - private NotificationType findTargetType(String targetType) { - return NotificationType.from(targetType); - } - public PageResponse getNotificationsByMember( String type, Member member, From 2d760b5bff968e373fce50085c519fcd418e0fae Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 17:39:30 +0900 Subject: [PATCH 43/47] =?UTF-8?q?[test]=20:=20=EB=B3=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gongmuin/notification/service/NotificationServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java index ec36cc4..dc539d3 100644 --- a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java @@ -44,7 +44,7 @@ void saveNotificationFromTarget() { QuestionPost questionPost = QuestionPostFixture.questionPost(1L); // when - notificationService.saveNotificationFromTarget("답변", questionPost.getId(), member2.getId(), member1); + notificationService.saveNotificationFromTarget(ANSWER, questionPost.getId(), member2.getId(), member1); // then verify(notificationRepository).save(any(Notification.class)); From dfdfccf0db2e41a23a2ff9a9755cb7fb35ff6256 Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 17:42:13 +0900 Subject: [PATCH 44/47] =?UTF-8?q?[rename]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9D=BD=EC=9D=8C=20=EC=97=AC=EB=B6=80=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?DTO,=20Method=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/NotificationController.java | 10 +++++----- .../notification/dto/NotificationMapper.java | 6 +++--- ...Request.java => readNotificationRequest.java} | 2 +- ...sponse.java => readNotificationResponse.java} | 2 +- .../service/NotificationService.java | 6 +++--- .../controller/NotificationControllerTest.java | 4 ++-- .../service/NotificationServiceTest.java | 16 ++++++++-------- 7 files changed, 23 insertions(+), 23 deletions(-) rename src/main/java/com/dnd/gongmuin/notification/dto/request/{IsReadNotificationRequest.java => readNotificationRequest.java} (82%) rename src/main/java/com/dnd/gongmuin/notification/dto/response/{IsReadNotificationResponse.java => readNotificationResponse.java} (69%) diff --git a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java index e991806..24ed7bf 100644 --- a/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java +++ b/src/main/java/com/dnd/gongmuin/notification/controller/NotificationController.java @@ -11,9 +11,9 @@ import com.dnd.gongmuin.common.dto.PageResponse; import com.dnd.gongmuin.member.domain.Member; -import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; -import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; +import com.dnd.gongmuin.notification.dto.request.readNotificationRequest; import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; +import com.dnd.gongmuin.notification.dto.response.readNotificationResponse; import com.dnd.gongmuin.notification.service.NotificationService; import io.swagger.v3.oas.annotations.tags.Tag; @@ -40,11 +40,11 @@ public ResponseEntity> getNotificationsByMem } @PatchMapping("/api/notification/read") - public ResponseEntity isReadNotification( - @RequestBody @Valid IsReadNotificationRequest request, + public ResponseEntity readNotification( + @RequestBody @Valid readNotificationRequest request, @AuthenticationPrincipal Member member ) { - IsReadNotificationResponse response = notificationService.isReadNotification(request, member); + readNotificationResponse response = notificationService.readNotification(request, member); return ResponseEntity.ok(response); } diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java b/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java index d6daba1..ca73e37 100644 --- a/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java +++ b/src/main/java/com/dnd/gongmuin/notification/dto/NotificationMapper.java @@ -1,7 +1,7 @@ package com.dnd.gongmuin.notification.dto; import com.dnd.gongmuin.notification.domain.Notification; -import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; +import com.dnd.gongmuin.notification.dto.response.readNotificationResponse; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -9,8 +9,8 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class NotificationMapper { - public static IsReadNotificationResponse toIsReadNotificationResponse(Notification notification) { - return new IsReadNotificationResponse( + public static readNotificationResponse toIsReadNotificationResponse(Notification notification) { + return new readNotificationResponse( notification.getId(), notification.getIsRead() ); diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java b/src/main/java/com/dnd/gongmuin/notification/dto/request/readNotificationRequest.java similarity index 82% rename from src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java rename to src/main/java/com/dnd/gongmuin/notification/dto/request/readNotificationRequest.java index 62fbea6..08e970c 100644 --- a/src/main/java/com/dnd/gongmuin/notification/dto/request/IsReadNotificationRequest.java +++ b/src/main/java/com/dnd/gongmuin/notification/dto/request/readNotificationRequest.java @@ -2,7 +2,7 @@ import jakarta.validation.constraints.NotNull; -public record IsReadNotificationRequest( +public record readNotificationRequest( @NotNull(message = "알림 ID 값은 필수 값 입니다.") Long notificationId diff --git a/src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java b/src/main/java/com/dnd/gongmuin/notification/dto/response/readNotificationResponse.java similarity index 69% rename from src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java rename to src/main/java/com/dnd/gongmuin/notification/dto/response/readNotificationResponse.java index 44a1615..599f9af 100644 --- a/src/main/java/com/dnd/gongmuin/notification/dto/response/IsReadNotificationResponse.java +++ b/src/main/java/com/dnd/gongmuin/notification/dto/response/readNotificationResponse.java @@ -1,6 +1,6 @@ package com.dnd.gongmuin.notification.dto.response; -public record IsReadNotificationResponse( +public record readNotificationResponse( Long notificationId, Boolean isRead ) { diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index a1daf2b..b6b1fff 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -15,9 +15,9 @@ import com.dnd.gongmuin.notification.domain.Notification; import com.dnd.gongmuin.notification.domain.NotificationType; import com.dnd.gongmuin.notification.dto.NotificationMapper; -import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; -import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; +import com.dnd.gongmuin.notification.dto.request.readNotificationRequest; import com.dnd.gongmuin.notification.dto.response.NotificationsResponse; +import com.dnd.gongmuin.notification.dto.response.readNotificationResponse; import com.dnd.gongmuin.notification.exception.NotificationErrorCode; import com.dnd.gongmuin.notification.repository.NotificationRepository; @@ -59,7 +59,7 @@ public PageResponse getNotificationsByMember( } @Transactional - public IsReadNotificationResponse isReadNotification(IsReadNotificationRequest request, Member member) { + public readNotificationResponse readNotification(readNotificationRequest request, Member member) { Notification findNotification = notificationRepository.findById(request.notificationId()) .orElseThrow(() -> new NotFoundException(NotificationErrorCode.NOT_FOUND_NOTIFICATION)); diff --git a/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java b/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java index 48a2cfc..37d738e 100644 --- a/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/controller/NotificationControllerTest.java @@ -22,7 +22,7 @@ import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.member.repository.MemberRepository; import com.dnd.gongmuin.notification.domain.Notification; -import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; +import com.dnd.gongmuin.notification.dto.request.readNotificationRequest; import com.dnd.gongmuin.notification.repository.NotificationRepository; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; @@ -108,7 +108,7 @@ void isReadNotification() throws Exception { ); notificationRepository.save(notification); - IsReadNotificationRequest request = new IsReadNotificationRequest(notification.getId()); + readNotificationRequest request = new readNotificationRequest(notification.getId()); // when // then mockMvc.perform(patch("/api/notification/read") diff --git a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java index dc539d3..e938770 100644 --- a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java @@ -20,8 +20,8 @@ import com.dnd.gongmuin.common.fixture.QuestionPostFixture; import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.notification.domain.Notification; -import com.dnd.gongmuin.notification.dto.request.IsReadNotificationRequest; -import com.dnd.gongmuin.notification.dto.response.IsReadNotificationResponse; +import com.dnd.gongmuin.notification.dto.request.readNotificationRequest; +import com.dnd.gongmuin.notification.dto.response.readNotificationResponse; import com.dnd.gongmuin.notification.repository.NotificationRepository; import com.dnd.gongmuin.question_post.domain.QuestionPost; @@ -70,12 +70,12 @@ void isReadNotification() { member2.getId(), member1 ); - IsReadNotificationRequest request = new IsReadNotificationRequest(1L); + readNotificationRequest request = new readNotificationRequest(1L); given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); // when - IsReadNotificationResponse response = notificationService.isReadNotification(request, member1); + readNotificationResponse response = notificationService.readNotification(request, member1); // then assertAll( @@ -99,12 +99,12 @@ void isReadNotificationThrowsExceptionWhenMemberIsNotOwner() { member1 ); notification.updateIsRead(); - IsReadNotificationRequest request = new IsReadNotificationRequest(1L); + readNotificationRequest request = new readNotificationRequest(1L); given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); // when // then - assertThrows(ValidationException.class, () -> notificationService.isReadNotification(request, member2)); + assertThrows(ValidationException.class, () -> notificationService.readNotification(request, member2)); } @DisplayName("읽었던 알림의 읽음 상태 변화를 하면 예외가 발생한다.") @@ -122,11 +122,11 @@ void isReadNotificationThrowsExceptionWhenAlreadyRead() { member1 ); notification.updateIsRead(); - IsReadNotificationRequest request = new IsReadNotificationRequest(1L); + readNotificationRequest request = new readNotificationRequest(1L); given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); // when // then - assertThrows(ValidationException.class, () -> notificationService.isReadNotification(request, member1)); + assertThrows(ValidationException.class, () -> notificationService.readNotification(request, member1)); } } From b7b28ee024875350d8ccc000851204bab6f8b2c3 Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 17:44:47 +0900 Subject: [PATCH 45/47] =?UTF-8?q?[rename]=20:=20Method=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/notification/domain/Notification.java | 4 ++-- .../gongmuin/notification/service/NotificationService.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java index d8be5d0..216e227 100644 --- a/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java +++ b/src/main/java/com/dnd/gongmuin/notification/domain/Notification.java @@ -79,7 +79,7 @@ public static Notification of( .build(); } - public Boolean updateIsRead() { - return this.isRead = Boolean.TRUE; + public void updateIsReadTrue() { + this.isRead = Boolean.TRUE; } } diff --git a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java index b6b1fff..b79aedd 100644 --- a/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java +++ b/src/main/java/com/dnd/gongmuin/notification/service/NotificationService.java @@ -71,7 +71,7 @@ public readNotificationResponse readNotification(readNotificationRequest request throw new ValidationException(NotificationErrorCode.CHANGE_IS_READ_NOTIFICATION_FAILED); } - findNotification.updateIsRead(); + findNotification.updateIsReadTrue(); return NotificationMapper.toIsReadNotificationResponse(findNotification); } From 5f39f54cda641f2191659b69797ef1052620e389 Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 18:00:12 +0900 Subject: [PATCH 46/47] =?UTF-8?q?[test]=20:=20=EB=B3=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20method=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/service/NotificationServiceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java index e938770..353aaf4 100644 --- a/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/notification/service/NotificationServiceTest.java @@ -98,7 +98,7 @@ void isReadNotificationThrowsExceptionWhenMemberIsNotOwner() { member2.getId(), member1 ); - notification.updateIsRead(); + notification.updateIsReadTrue(); readNotificationRequest request = new readNotificationRequest(1L); given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); @@ -121,7 +121,7 @@ void isReadNotificationThrowsExceptionWhenAlreadyRead() { member2.getId(), member1 ); - notification.updateIsRead(); + notification.updateIsReadTrue(); readNotificationRequest request = new readNotificationRequest(1L); given(notificationRepository.findById(anyLong())).willReturn(Optional.ofNullable(notification)); From d3f666b8882291dcea4a27e89f854db28746bd85 Mon Sep 17 00:00:00 2001 From: dudxo Date: Mon, 2 Sep 2024 18:00:35 +0900 Subject: [PATCH 47/47] =?UTF-8?q?[test]=20:=20NotificationService=20mock?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dnd/gongmuin/answer/service/AnswerServiceTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java b/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java index 17a8022..520aab5 100644 --- a/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java @@ -31,6 +31,7 @@ import com.dnd.gongmuin.credit_history.service.CreditHistoryService; import com.dnd.gongmuin.member.domain.Member; import com.dnd.gongmuin.member.exception.MemberErrorCode; +import com.dnd.gongmuin.notification.service.NotificationService; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.exception.QuestionPostErrorCode; import com.dnd.gongmuin.question_post.repository.QuestionPostRepository; @@ -50,6 +51,9 @@ class AnswerServiceTest { @Mock private CreditHistoryService creditHistoryService; + @Mock + private NotificationService notificationService; + @InjectMocks private AnswerService answerService;