Skip to content

Commit

Permalink
fix : 알림 같이 가기 요청이 이미 존재한 경우 다시 알림을 보낼 수 없도록 validation 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
java-saeng committed Aug 8, 2023
1 parent 1394ea1 commit 2e06fc9
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.emmsale.notification.application;

import static com.emmsale.member.exception.MemberExceptionType.NOT_FOUND_MEMBER;
import static com.emmsale.notification.exception.NotificationExceptionType.ALREADY_EXIST_NOTIFICATION;
import static com.emmsale.notification.exception.NotificationExceptionType.BAD_REQUEST_MEMBER_ID;
import static com.emmsale.notification.exception.NotificationExceptionType.NOT_FOUND_NOTIFICATION;

Expand Down Expand Up @@ -35,16 +36,16 @@ public class NotificationCommandService {
public NotificationResponse create(final NotificationRequest notificationRequest) {
final Long senderId = notificationRequest.getSenderId();
final Long receiverId = notificationRequest.getReceiverId();
final Long eventId = notificationRequest.getEventId();

final List<Long> memberIds = List.of(senderId, receiverId);

validateExistedSenderOrReceiver(memberIds);
validateAlreadyExistedNotification(senderId, receiverId, eventId);
validateExistedSenderOrReceiver(List.of(senderId, receiverId));

final Notification savedNotification = notificationRepository.save(
new Notification(
senderId,
receiverId,
notificationRequest.getEventId(),
eventId,
notificationRequest.getMessage()
));

Expand All @@ -53,6 +54,18 @@ public NotificationResponse create(final NotificationRequest notificationRequest
return NotificationResponse.from(savedNotification);
}

private void validateAlreadyExistedNotification(
final Long senderId,
final Long receiverId,
final Long eventId
) {
if (notificationRepository.existsBySenderIdAndReceiverIdAndEventId(
senderId, receiverId, eventId
)) {
throw new NotificationException(ALREADY_EXIST_NOTIFICATION);
}
}

private void validateExistedSenderOrReceiver(final List<Long> memberIds) {
if (isNotExistedSenderOrReceiver(memberIds)) {
throw new NotificationException(BAD_REQUEST_MEMBER_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@
public interface NotificationRepository extends JpaRepository<Notification, Long> {

List<Notification> findAllByReceiverId(Long memberId);

boolean existsBySenderIdAndReceiverIdAndEventId(
final Long senderId, final Long receiverId, final Long eventId
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ public enum NotificationExceptionType implements BaseExceptionType {
FIREBASE_CONNECT_ERROR(
HttpStatus.INTERNAL_SERVER_ERROR,
"파이어베이스 접속 시 발생한 에러"
);
),

ALREADY_EXIST_NOTIFICATION(
HttpStatus.BAD_REQUEST,
"이미 요청된 알림입니다."
)

;

private final HttpStatus httpStatus;
private final String errorMessage;
Expand Down
62 changes: 31 additions & 31 deletions backend/emm-sale/src/main/resources/static/docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -466,14 +466,14 @@ <h1>Kerdy API Docs</h1>
<li><a href="#_event">Event</a>
<ul class="sectlevel2">
<li><a href="#_get_행사_상세정보_조회"><code>GET</code> : 행사 상세정보 조회</a></li>
<li><a href="#_post_컨퍼런스에_함께가기_요청컨퍼런스에_함께_가는_멤버에_등록"><code>POST</code> : 컨퍼런스에 함께가기 요청(컨퍼런스에 함께 가는 멤버에 등록)</a></li>
<li><a href="#_delete_컨퍼런스에_함께가기_요청_취소컨퍼런스에_함께_가는_멤버에서_삭제"><code>DELETE</code> : 컨퍼런스에 함께가기 요청 취소(컨퍼런스에 함께 가는 멤버에서 삭제)</a></li>
<li><a href="#_get_event에_이미_참여한_멤버인지_확인"><code>GET</code>: Event에 이미 참여한 멤버인지 확인</a></li>
<li><a href="#_post_행사에_함께가기_요청행사에_함께_가는_멤버에_등록"><code>POST</code> : 행사에 함께가기 요청(행사에 함께 가는 멤버에 등록)</a></li>
<li><a href="#_delete_행사에_함께가기_요청_취소행사에_함께_가는_멤버에서_삭제"><code>DELETE</code> : 행사에 함께가기 요청 취소(행사에 함께 가는 멤버에서 삭제)</a></li>
<li><a href="#_get_행사사에_이미_참여한_멤버인지_확인"><code>GET</code>: 행사사에 이미 참여한 멤버인지 확인</a></li>
<li><a href="#_get_행사_목록_조회"><code>GET</code>: 행사 목록 조회</a></li>
<li><a href="#_get_행사_참여자_목록_조회"><code>GET</code> : 행사 참여자 목록 조회</a></li>
<li><a href="#_post_이벤트_생성"><code>POST</code> : 이벤트 생성</a></li>
<li><a href="#_put_이벤트_업데이트"><code>PUT</code> : 이벤트 업데이트</a></li>
<li><a href="#_put_이벤트_삭제"><code>PUT</code> : 이벤트 삭제</a></li>
<li><a href="#_post_행사_생성"><code>POST</code> : 행사 생성</a></li>
<li><a href="#_put_행사_업데이트"><code>PUT</code> : 행사 업데이트</a></li>
<li><a href="#_put_행사_삭제"><code>PUT</code> : 행사 삭제</a></li>
</ul>
</li>
<li><a href="#_comment">Comment</a>
Expand Down Expand Up @@ -1200,7 +1200,7 @@ <h3 id="_get_행사_상세정보_조회"><a class="link" href="#_get_행사_상
</table>
</div>
<div class="sect2">
<h3 id="_post_컨퍼런스에_함께가기_요청컨퍼런스에_함께_가는_멤버에_등록"><a class="link" href="#_post_컨퍼런스에_함께가기_요청컨퍼런스에_함께_가는_멤버에_등록"><code>POST</code> : 컨퍼런스에 함께가기 요청(컨퍼런스에 함께 가는 멤버에 등록)</a></h3>
<h3 id="_post_행사에_함께가기_요청행사에_함께_가는_멤버에_등록"><a class="link" href="#_post_행사에_함께가기_요청행사에_함께_가는_멤버에_등록"><code>POST</code> : 행사에 함께가기 요청(행사에 함께 가는 멤버에 등록)</a></h3>
<div class="listingblock">
<div class="title">HTTP request</div>
<div class="content">
Expand All @@ -1224,7 +1224,7 @@ <h3 id="_post_컨퍼런스에_함께가기_요청컨퍼런스에_함께_가는_
</div>
</div>
<div class="sect2">
<h3 id="_delete_컨퍼런스에_함께가기_요청_취소컨퍼런스에_함께_가는_멤버에서_삭제"><a class="link" href="#_delete_컨퍼런스에_함께가기_요청_취소컨퍼런스에_함께_가는_멤버에서_삭제"><code>DELETE</code> : 컨퍼런스에 함께가기 요청 취소(컨퍼런스에 함께 가는 멤버에서 삭제)</a></h3>
<h3 id="_delete_행사에_함께가기_요청_취소행사에_함께_가는_멤버에서_삭제"><a class="link" href="#_delete_행사에_함께가기_요청_취소행사에_함께_가는_멤버에서_삭제"><code>DELETE</code> : 행사에 함께가기 요청 취소(행사에 함께 가는 멤버에서 삭제)</a></h3>
<div class="listingblock">
<div class="title">HTTP request</div>
<div class="content">
Expand Down Expand Up @@ -1266,7 +1266,7 @@ <h3 id="_delete_컨퍼런스에_함께가기_요청_취소컨퍼런스에_함께
</div>
</div>
<div class="sect2">
<h3 id="_get_event에_이미_참여한_멤버인지_확인"><a class="link" href="#_get_event에_이미_참여한_멤버인지_확인"><code>GET</code>: Event에 이미 참여한 멤버인지 확인</a></h3>
<h3 id="_get_행사사에_이미_참여한_멤버인지_확인"><a class="link" href="#_get_행사사에_이미_참여한_멤버인지_확인"><code>GET</code>: 행사사에 이미 참여한 멤버인지 확인</a></h3>
<div class="listingblock">
<div class="title">HTTP request</div>
<div class="content">
Expand Down Expand Up @@ -1508,7 +1508,7 @@ <h3 id="_get_행사_참여자_목록_조회"><a class="link" href="#_get_행사_
</table>
</div>
<div class="sect2">
<h3 id="_post_이벤트_생성"><a class="link" href="#_post_이벤트_생성"><code>POST</code> : 이벤트 생성</a></h3>
<h3 id="_post_행사_생성"><a class="link" href="#_post_행사_생성"><code>POST</code> : 행사 생성</a></h3>
<div class="listingblock">
<div class="title">HTTP request</div>
<div class="content">
Expand Down Expand Up @@ -1686,7 +1686,7 @@ <h3 id="_post_이벤트_생성"><a class="link" href="#_post_이벤트_생성"><
</table>
</div>
<div class="sect2">
<h3 id="_put_이벤트_업데이트"><a class="link" href="#_put_이벤트_업데이트"><code>PUT</code> : 이벤트 업데이트</a></h3>
<h3 id="_put_행사_업데이트"><a class="link" href="#_put_행사_업데이트"><code>PUT</code> : 행사 업데이트</a></h3>
<div class="listingblock">
<div class="title">HTTP request</div>
<div class="content">
Expand Down Expand Up @@ -1864,7 +1864,7 @@ <h3 id="_put_이벤트_업데이트"><a class="link" href="#_put_이벤트_업
</table>
</div>
<div class="sect2">
<h3 id="_put_이벤트_삭제"><a class="link" href="#_put_이벤트_삭제"><code>PUT</code> : 이벤트 삭제</a></h3>
<h3 id="_put_행사_삭제"><a class="link" href="#_put_행사_삭제"><code>PUT</code> : 행사 삭제</a></h3>
<div class="listingblock">
<div class="title">HTTP request</div>
<div class="content">
Expand Down Expand Up @@ -1925,8 +1925,8 @@ <h3 id="_get_댓글_모두_조회"><a class="link" href="#_get_댓글_모두_조
"commentId" : 4,
"parentId" : null,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:10",
"updatedAt" : "2023:08:03:12:52:10",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand All @@ -1939,8 +1939,8 @@ <h3 id="_get_댓글_모두_조회"><a class="link" href="#_get_댓글_모두_조
"commentId" : 5,
"parentId" : null,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:10",
"updatedAt" : "2023:08:03:12:52:10",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand All @@ -1951,8 +1951,8 @@ <h3 id="_get_댓글_모두_조회"><a class="link" href="#_get_댓글_모두_조
"commentId" : 2,
"parentId" : 1,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:10",
"updatedAt" : "2023:08:03:12:52:10",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand All @@ -1962,8 +1962,8 @@ <h3 id="_get_댓글_모두_조회"><a class="link" href="#_get_댓글_모두_조
"commentId" : 3,
"parentId" : 1,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:10",
"updatedAt" : "2023:08:03:12:52:10",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand Down Expand Up @@ -2136,8 +2136,8 @@ <h3 id="_get_특정_댓글_조회대댓글_있을_경우_같이_조회"><a class
"commentId" : 5,
"parentId" : null,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:11",
"updatedAt" : "2023:08:03:12:52:11",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand All @@ -2148,8 +2148,8 @@ <h3 id="_get_특정_댓글_조회대댓글_있을_경우_같이_조회"><a class
"commentId" : 2,
"parentId" : 1,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:11",
"updatedAt" : "2023:08:03:12:52:11",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand All @@ -2159,8 +2159,8 @@ <h3 id="_get_특정_댓글_조회대댓글_있을_경우_같이_조회"><a class
"commentId" : 3,
"parentId" : 1,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:11",
"updatedAt" : "2023:08:03:12:52:11",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand Down Expand Up @@ -2321,8 +2321,8 @@ <h3 id="_post_댓글_및_대댓글_생성"><a class="link" href="#_post_댓글_
"commentId" : 2,
"parentId" : 1,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:11",
"updatedAt" : "2023:08:03:12:52:11",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand Down Expand Up @@ -2501,8 +2501,8 @@ <h3 id="_patch_댓글_수정"><a class="link" href="#_patch_댓글_수정"><code
"commentId" : 5,
"parentId" : null,
"eventId" : 1,
"createdAt" : "2023:08:03:12:52:11",
"updatedAt" : "2023:08:03:12:52:11",
"createdAt" : "2023:08:08:14:54:06",
"updatedAt" : "2023:08:08:14:54:06",
"memberId" : 1,
"memberImageUrl" : "이미지",
"memberName" : "이름1",
Expand Down Expand Up @@ -3030,7 +3030,7 @@ <h3 id="_get_사용자가_받은_모든_알림_목록_조회"><a class="link" hr
<div id="footer">
<div id="footer-text">
Version 0.0.1-SNAPSHOT<br>
Last updated 2023-08-03 12:34:57 +0900
Last updated 2023-08-03 15:52:08 +0900
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/github.min.css">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.emmsale.notification.domain;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.jdbc.Sql;

@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Sql("/data-test.sql")
class NotificationRepositoryTest {

@Autowired
private NotificationRepository notificationRepository;

private Notification 알림1;

@BeforeEach
void init() {
알림1 = new Notification(1L, 2L, 1L, "알림1");
notificationRepository.save(알림1);
}

@ParameterizedTest
@CsvSource({
"1,2,1,true",
"1,2,2,false"
})
@DisplayName("existsBySenderIdAndReceiverIdAndEventId() : receiverId, senderId, EventId를 통해서 알림이 존재하는지 확인할 수 있다.")
void test_existsBySenderIdAndReceiverIdAndEventId(
final Long senderId, final Long receiverId, final Long eventId, final boolean result
) throws Exception {
//when & then
assertEquals(notificationRepository.existsBySenderIdAndReceiverIdAndEventId(
senderId, receiverId, eventId), result);
}
}

0 comments on commit 2e06fc9

Please sign in to comment.