-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
알림 기능 구현 (이벤트 발행 및 구독, 알림 조회, 알림 삭제, 알림 업데이트) #625
Merged
Merged
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
6adff16
feat: 알람 내 값객체 구현 (제목, 내용, 연관 식별자값, 읽기 여부, 알람 타입, 알람 메시지 모음)
hyena0608 dbdaac8
feat: 알람 엔티티 구현
hyena0608 6008273
feat: 알람 예외 클래스 구현
hyena0608 e86b31d
feat: 알람 목록 조회 레포지터리 기능 구현
hyena0608 8387f3c
feat: 알람 소프트 딜리트, 읽기 여부 true 업데이트 레포지터리 기능 구현
hyena0608 9b273e1
feat: 알람 소프트 딜리트, 읽기 여부 true 업데이트 서비스 기능 구현
hyena0608 a4e5fcb
feat: 알람 목록 조회 서비스 기능 구현
hyena0608 c3c91e3
feat: 알람 읽음 여부 기록 및 삭제 API 구현
hyena0608 9dbf347
feat: 사용자 알람 목록 조회 API 구현
hyena0608 594d028
feat: 러너 게시글 식별자값으로 러너 게시글과 서포터, 사용자 조회 레포지터리 기능 구현
hyena0608 613ded3
feat: 알람 이벤트 (러너 게시글 리뷰 완료, 러너 게시글 서포터 할당, 러너 게시글 서포터 지원) 리스너 구현
hyena0608 7cd4773
feat: 이벤트 (러너 게시글 리뷰 완료, 러너 게시글 서포터 할당, 러너 게시글 서포터 지원) 발행 구현
hyena0608 395ec4b
Merge remote-tracking branch 'origin/dev/BE' into dev/BE
hyena0608 f70698e
Merge remote-tracking branch 'origin/dev/BE' into dev/BE
hyena0608 cf176df
feat: 알람 생성 시간 초단위 삭제를 위한 BaseEntity 상속 클래스 구현
hyena0608 99c1e62
refactor: 알람 이벤트 리스너 내부 메서드 리팩터링
hyena0608 3e12959
test: 로그인된 사용자 알람 목록 조회에서 알람 생성시간 테스트 수정
hyena0608 15db043
test: 테스트용 알람 조회 레포지터리 구현 및 테스트용 회원 조회 레포지터리 수정
hyena0608 7c648b6
test: 알람 읽음 여부 기록 업데이트 인수 테스트
hyena0608 af44d16
test: 러너 게시글 지원자 생성 인수 서포트 내부 사용하지 않는 검증문 삭제
hyena0608 b9a839e
test: 알람 삭제 인수 테스트
hyena0608 bce0fbe
test: 로그인된 사용자 알람 목록 조회 인수 테스트
hyena0608 d88f40b
chore: flyway 알람 테이블 생성, 알람 사용자(member) 외래키 제약조건 추가
hyena0608 e1edbe2
test: 알람 삭제, 업데이트 restdocs pathVariable 추가
hyena0608 ffbe8ad
docs: 로그인된 사용자 알람 목록 조회, 알람 삭제, 알람 읽음 여부 업데이트 api 문서 추가
hyena0608 844582a
style: 사용하지 않는 메서드 삭제 및 정렬
hyena0608 48d2bc2
test: 테스트 로그 삭제
hyena0608 444613a
style: 사용하지 않는 메서드 삭제
hyena0608 3964795
test: 실험용 테스트 코드 삭제
hyena0608 ce69d94
docs: API 문서 Index 추가
hyena0608 9e8fdd4
style: 알람(Alarm)을 알림(Notification)으로 수정
hyena0608 43c8b49
test: willDoNothing()을 doNothing()으로 수정
hyena0608 2c5d1d9
test: 이벤트 발행 카운트 테스트 수정
hyena0608 325636b
refactor: IsRead 를 정적 팩터리 메서드를 이용해서 생성하도록 리팩터링
hyena0608 a9f2a15
feat: 알림 읽음 여부 수정 기능 구현
hyena0608 02d962c
feat: 알림 읽음 여부 수정 서비스 리팩터링
hyena0608 7befc7a
refactor: 알림 이벤트 리스너 내부 NotificationText 를 문자열로 리팩터링
hyena0608 3dc95e4
feat: 알림 목록 조회 querydsl 기능 구현
hyena0608 771524d
refactor: JpaRepository 조회 레포지터리를 Querydsl 레포지터리로 리팩터링
hyena0608 00731b6
Merge remote-tracking branch 'origin/dev/BE' into feat/624
hyena0608 ad5418c
test: 알림 Restdocs 테스트 수정
hyena0608 539b493
test: 러너 게시글에 서포터 조인 조회 기능 테스트 수정
hyena0608 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
backend/baton/src/docs/asciidoc/NotificationDeleteApi.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
ifndef::snippets[] | ||
:snippets: ../../../build/generated-snippets | ||
endif::[] | ||
:doctype: book | ||
:icons: font | ||
:source-highlighter: highlight.js | ||
:toc: left | ||
:toclevels: 3 | ||
:sectlinks: | ||
:operation-http-request-title: Example Request | ||
:operation-http-response-title: Example Response | ||
|
||
==== *알림 삭제 API* | ||
|
||
===== *Http Request* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-delete-api-test/delete-notification-by-notification-id/http-request.adoc[] | ||
|
||
===== *Http Request Headers* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-delete-api-test/delete-notification-by-notification-id/request-headers.adoc[] | ||
|
||
===== *Http Request Path Parameters* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-delete-api-test/delete-notification-by-notification-id/path-parameters.adoc[] | ||
|
||
===== *Http Response* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-delete-api-test/delete-notification-by-notification-id/http-response.adoc[] |
29 changes: 29 additions & 0 deletions
29
backend/baton/src/docs/asciidoc/NotificationLoginReadApi.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
ifndef::snippets[] | ||
:snippets: ../../../build/generated-snippets | ||
endif::[] | ||
:doctype: book | ||
:icons: font | ||
:source-highlighter: highlight.js | ||
:toc: left | ||
:toclevels: 3 | ||
:sectlinks: | ||
:operation-http-request-title: Example Request | ||
:operation-http-response-title: Example Response | ||
|
||
==== *로그인된 사용자 알림 목록 조회 API* | ||
|
||
===== *Http Request* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-read-with-logined-member-api-test/read-notifications-by-member-id/http-request.adoc[] | ||
|
||
===== *Http Request Headers* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-read-with-logined-member-api-test/read-notifications-by-member-id/request-headers.adoc[] | ||
|
||
===== *Http Response* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-read-with-logined-member-api-test/read-notifications-by-member-id/http-response.adoc[] | ||
|
||
===== *Http Response Fields* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-read-with-logined-member-api-test/read-notifications-by-member-id/response-fields.adoc[] |
29 changes: 29 additions & 0 deletions
29
backend/baton/src/docs/asciidoc/NotificationUpdateApi.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
ifndef::snippets[] | ||
:snippets: ../../../build/generated-snippets | ||
endif::[] | ||
:doctype: book | ||
:icons: font | ||
:source-highlighter: highlight.js | ||
:toc: left | ||
:toclevels: 3 | ||
:sectlinks: | ||
:operation-http-request-title: Example Request | ||
:operation-http-response-title: Example Response | ||
|
||
==== *알림 읽음 여부 업데이트 API* | ||
|
||
===== *Http Request* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-update-api-test/update-notification-is-read-true-by-member/http-request.adoc[] | ||
|
||
===== *Http Request Headers* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-update-api-test/update-notification-is-read-true-by-member/request-headers.adoc[] | ||
|
||
===== *Http Request Path Parameters* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-update-api-test/update-notification-is-read-true-by-member/path-parameters.adoc[] | ||
|
||
===== *Http Response* | ||
|
||
include::{snippets}/../../build/generated-snippets/notification-update-api-test/update-notification-is-read-true-by-member/http-response.adoc[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
backend/baton/src/main/java/touch/baton/domain/common/TruncatedBaseEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package touch.baton.domain.common; | ||
|
||
import java.time.LocalDateTime; | ||
import java.time.temporal.ChronoUnit; | ||
|
||
public abstract class TruncatedBaseEntity extends BaseEntity { | ||
|
||
@Override | ||
public LocalDateTime getCreatedAt() { | ||
return super.getCreatedAt().truncatedTo(ChronoUnit.MINUTES); | ||
} | ||
|
||
@Override | ||
public LocalDateTime getDeletedAt() { | ||
return super.getDeletedAt().truncatedTo(ChronoUnit.MINUTES); | ||
} | ||
|
||
@Override | ||
public LocalDateTime getUpdatedAt() { | ||
return super.getUpdatedAt().truncatedTo(ChronoUnit.MINUTES); | ||
} | ||
} |
146 changes: 146 additions & 0 deletions
146
backend/baton/src/main/java/touch/baton/domain/notification/command/Notification.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package touch.baton.domain.notification.command; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Embedded; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.Enumerated; | ||
import jakarta.persistence.ForeignKey; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.JoinColumn; | ||
import jakarta.persistence.ManyToOne; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import org.hibernate.annotations.SQLDelete; | ||
import org.hibernate.annotations.Where; | ||
import touch.baton.domain.common.TruncatedBaseEntity; | ||
import touch.baton.domain.member.command.Member; | ||
import touch.baton.domain.notification.command.vo.IsRead; | ||
import touch.baton.domain.notification.command.vo.NotificationMessage; | ||
import touch.baton.domain.notification.command.vo.NotificationReferencedId; | ||
import touch.baton.domain.notification.command.vo.NotificationTitle; | ||
import touch.baton.domain.notification.command.vo.NotificationType; | ||
import touch.baton.domain.notification.exception.NotificationDomainException; | ||
|
||
import java.util.Objects; | ||
|
||
import static jakarta.persistence.EnumType.STRING; | ||
import static jakarta.persistence.FetchType.LAZY; | ||
import static jakarta.persistence.GenerationType.IDENTITY; | ||
import static lombok.AccessLevel.PROTECTED; | ||
|
||
@Getter | ||
@NoArgsConstructor(access = PROTECTED) | ||
@Where(clause = "deleted_at IS NULL") | ||
@SQLDelete(sql = "UPDATE notification SET deleted_at = now() WHERE id = ?") | ||
@Entity | ||
public class Notification extends TruncatedBaseEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = IDENTITY) | ||
private Long id; | ||
|
||
@Embedded | ||
private NotificationTitle notificationTitle; | ||
|
||
@Embedded | ||
private NotificationMessage notificationMessage; | ||
|
||
@Enumerated(STRING) | ||
@Column(nullable = false) | ||
private NotificationType notificationType; | ||
|
||
@Embedded | ||
private NotificationReferencedId notificationReferencedId; | ||
|
||
@Embedded | ||
private IsRead isRead; | ||
|
||
@ManyToOne(fetch = LAZY) | ||
@JoinColumn(name = "member_id", | ||
nullable = false, | ||
foreignKey = @ForeignKey(name = "fk_notification_to_member")) | ||
private Member member; | ||
|
||
@Builder | ||
private Notification(final NotificationTitle notificationTitle, | ||
final NotificationMessage notificationMessage, | ||
final NotificationType notificationType, | ||
final NotificationReferencedId notificationReferencedId, | ||
final IsRead isRead, | ||
final Member member | ||
) { | ||
this(null, notificationTitle, notificationMessage, notificationType, notificationReferencedId, isRead, member); | ||
} | ||
|
||
private Notification(final Long id, | ||
final NotificationTitle notificationTitle, | ||
final NotificationMessage notificationMessage, | ||
final NotificationType notificationType, | ||
final NotificationReferencedId notificationReferencedId, | ||
final IsRead isRead, | ||
final Member member | ||
) { | ||
validateNotNull(notificationTitle, notificationMessage, notificationType, notificationReferencedId, isRead, member); | ||
this.id = id; | ||
this.notificationTitle = notificationTitle; | ||
this.notificationMessage = notificationMessage; | ||
this.notificationType = notificationType; | ||
this.notificationReferencedId = notificationReferencedId; | ||
this.isRead = isRead; | ||
this.member = member; | ||
} | ||
|
||
private void validateNotNull(final NotificationTitle notificationTitle, | ||
final NotificationMessage notificationMessage, | ||
final NotificationType notificationType, | ||
final NotificationReferencedId notificationReferencedId, | ||
final IsRead isRead, | ||
final Member member | ||
) { | ||
if (notificationTitle == null) { | ||
throw new NotificationDomainException("NotificationTitle 의 notificationTitle 은 null 일 수 없습니다."); | ||
} | ||
if (notificationMessage == null) { | ||
throw new NotificationDomainException("NotificationMessage 의 notificationMessage 는 null 일 수 없습니다."); | ||
} | ||
if (notificationType == null) { | ||
throw new NotificationDomainException("NotificationType 의 notificationType 는 null 일 수 없습니다."); | ||
} | ||
if (notificationReferencedId == null) { | ||
throw new NotificationDomainException("NotificationReferencedId 의 notificationReferencedId 은 null 일 수 없습니다."); | ||
} | ||
if (isRead == null) { | ||
throw new NotificationDomainException("IsRead 의 isRead 는 null 일 수 없습니다."); | ||
} | ||
if (member == null) { | ||
throw new NotificationDomainException("Member 의 member 는 null 일 수 없습니다."); | ||
} | ||
} | ||
|
||
public void markAsRead(final Member currentMember) { | ||
if (!this.member.equals(currentMember)) { | ||
throw new NotificationDomainException("Notification 의 주인(사용자)가 아니므로 알림의 읽은 여부를 수정할 수 없습니다."); | ||
} | ||
|
||
this.isRead = IsRead.asRead(); | ||
} | ||
|
||
public boolean isNotOwner(final Member currentMember) { | ||
return !this.member.equals(currentMember); | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
final Notification notification = (Notification) o; | ||
return Objects.equals(id, notification.id); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(id); | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
...ava/touch/baton/domain/notification/command/controller/NotificationCommandController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package touch.baton.domain.notification.command.controller; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.PatchMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import touch.baton.domain.notification.command.service.NotificationCommandService; | ||
import touch.baton.domain.member.command.Member; | ||
import touch.baton.domain.oauth.query.controller.resolver.AuthMemberPrincipal; | ||
|
||
@RequiredArgsConstructor | ||
@RequestMapping("/api/v1/notifications") | ||
@RestController | ||
public class NotificationCommandController { | ||
|
||
private final NotificationCommandService notificationCommandService; | ||
|
||
@PatchMapping("/{notificationId}") | ||
public ResponseEntity<Void> updateNotificationIsReadTrueByNotificationId(@AuthMemberPrincipal final Member member, | ||
@PathVariable final Long notificationId | ||
) { | ||
notificationCommandService.updateNotificationIsReadTrueByMember(member, notificationId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@DeleteMapping("/{notificationId}") | ||
public ResponseEntity<Void> deleteNotificationByNotificationId(@AuthMemberPrincipal final Member member, | ||
@PathVariable final Long notificationId | ||
) { | ||
notificationCommandService.deleteNotificationByMember(member, notificationId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
...rc/main/java/touch/baton/domain/notification/command/event/NotificationEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package touch.baton.domain.notification.command.event; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.transaction.event.TransactionalEventListener; | ||
import touch.baton.domain.member.command.Member; | ||
import touch.baton.domain.notification.command.Notification; | ||
import touch.baton.domain.notification.command.repository.NotificationCommandRepository; | ||
import touch.baton.domain.notification.command.vo.IsRead; | ||
import touch.baton.domain.notification.command.vo.NotificationMessage; | ||
import touch.baton.domain.notification.command.vo.NotificationReferencedId; | ||
import touch.baton.domain.notification.command.vo.NotificationTitle; | ||
import touch.baton.domain.notification.command.vo.NotificationType; | ||
import touch.baton.domain.notification.exception.NotificationBusinessException; | ||
import touch.baton.domain.runnerpost.command.RunnerPost; | ||
import touch.baton.domain.runnerpost.command.event.RunnerPostApplySupporterEvent; | ||
import touch.baton.domain.runnerpost.command.event.RunnerPostAssignSupporterEvent; | ||
import touch.baton.domain.runnerpost.command.event.RunnerPostReviewStatusDoneEvent; | ||
import touch.baton.domain.runnerpost.query.repository.RunnerPostQueryRepository; | ||
|
||
import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW; | ||
import static org.springframework.transaction.event.TransactionPhase.AFTER_COMMIT; | ||
|
||
@RequiredArgsConstructor | ||
@Component | ||
public class NotificationEventListener { | ||
|
||
private final NotificationCommandRepository notificationCommandRepository; | ||
private final RunnerPostQueryRepository runnerPostQueryRepository; | ||
|
||
@TransactionalEventListener(phase = AFTER_COMMIT) | ||
@Transactional(propagation = REQUIRES_NEW) | ||
public void subscribeRunnerPostApplySupporterEvent(final RunnerPostApplySupporterEvent event) { | ||
final RunnerPost foundRunnerPost = getRunnerPostWithRunnerOrThrowException(event.runnerPostId()); | ||
|
||
notificationCommandRepository.save( | ||
createNotification("서포터의 제안이 왔습니다.", foundRunnerPost, foundRunnerPost.getRunner().getMember()) | ||
); | ||
} | ||
|
||
private RunnerPost getRunnerPostWithRunnerOrThrowException(final Long runnerPostId) { | ||
return runnerPostQueryRepository.joinMemberByRunnerPostId(runnerPostId) | ||
.orElseThrow(() -> new NotificationBusinessException("러너 게시글 식별자값으로 러너 게시글과 러너(작성자)를 조회하던 도중에 오류가 발생하였습니다.")); | ||
} | ||
|
||
private Notification createNotification(final String notificationTitle, final RunnerPost runnerPost, final Member targetMember) { | ||
return Notification.builder() | ||
.notificationTitle(new NotificationTitle(notificationTitle)) | ||
.notificationMessage(new NotificationMessage(String.format("관련 게시글 - %s", runnerPost.getTitle().getValue()))) | ||
.notificationType(NotificationType.RUNNER_POST) | ||
.notificationReferencedId(new NotificationReferencedId(runnerPost.getId())) | ||
.isRead(IsRead.asUnRead()) | ||
.member(targetMember) | ||
.build(); | ||
} | ||
|
||
@TransactionalEventListener(phase = AFTER_COMMIT) | ||
@Transactional(propagation = REQUIRES_NEW) | ||
public void subscribeRunnerPostReviewStatusDoneEvent(final RunnerPostReviewStatusDoneEvent event) { | ||
final RunnerPost foundRunnerPost = getRunnerPostWithRunnerOrThrowException(event.runnerPostId()); | ||
|
||
notificationCommandRepository.save( | ||
createNotification("코드 리뷰 상태가 완료로 변경되었습니다.", foundRunnerPost, foundRunnerPost.getRunner().getMember()) | ||
); | ||
} | ||
|
||
@TransactionalEventListener(phase = AFTER_COMMIT) | ||
@Transactional(propagation = REQUIRES_NEW) | ||
public void subscribeRunnerPostAssignSupporterEvent(final RunnerPostAssignSupporterEvent event) { | ||
final RunnerPost foundRunnerPost = getRunnerPostWithSupporterOrThrowException(event.runnerPostId()); | ||
|
||
notificationCommandRepository.save( | ||
createNotification("코드 리뷰 매칭이 완료되었습니다.", foundRunnerPost, foundRunnerPost.getSupporter().getMember()) | ||
); | ||
} | ||
|
||
private RunnerPost getRunnerPostWithSupporterOrThrowException(final Long runnerPostId) { | ||
return runnerPostQueryRepository.joinSupporterByRunnerPostId(runnerPostId) | ||
.orElseThrow(() -> new NotificationBusinessException("러너 게시글 식별자값으로 러너 게시글과 서포터(지원자)를 조회하던 도중에 오류가 발생하였습니다.")); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굿굿