diff --git a/backend/emm-sale/src/docs/asciidoc/index.adoc b/backend/emm-sale/src/docs/asciidoc/index.adoc index 981e35806..d6d7cf96f 100644 --- a/backend/emm-sale/src/docs/asciidoc/index.adoc +++ b/backend/emm-sale/src/docs/asciidoc/index.adoc @@ -141,6 +141,14 @@ include::{snippets}/participate-event-cancel/http-request.adoc[] .HTTP response include::{snippets}/participate-event-cancel/http-response.adoc[] +=== `GET`: Event에 이미 참여한 멤버인지 확인 + +.HTTP request +include::{snippets}/check-already-participate/http-request.adoc[] + +.HTTP response +include::{snippets}/check-already-participate/http-response.adoc[] + === `GET`: 행사 목록 조회 .HTTP request diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java b/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java index 3398a4663..f345bb04a 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java @@ -41,7 +41,7 @@ public ResponseEntity findEventById(@PathVariable final Lon } @PostMapping("/{eventId}/participants") - public ResponseEntity participateEvent( + public ResponseEntity participateEvent( @PathVariable final Long eventId, @RequestBody final EventParticipateRequest request, final Member member @@ -88,16 +88,24 @@ public EventDetailResponse addEvent( return eventService.addEvent(request, LocalDate.now()); } - @PutMapping("/{event-id}") + @PutMapping("/{eventId}") @ResponseStatus(HttpStatus.OK) - public EventDetailResponse updateEvent(@PathVariable(name = "event-id") final Long eventId, + public EventDetailResponse updateEvent(@PathVariable final Long eventId, @RequestBody @Valid final EventDetailRequest request) { return eventService.updateEvent(eventId, request, LocalDate.now()); } - @DeleteMapping("/{event-id}") + @DeleteMapping("/{eventId}") @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteEvent(@PathVariable(name = "event-id") final Long eventId) { + public void deleteEvent(@PathVariable final Long eventId) { eventService.deleteEvent(eventId); } + + @GetMapping("/{eventId}/participants/already-participate") + public ResponseEntity isAlreadyParticipate( + @PathVariable final Long eventId, + @RequestParam(name = "member-id") final Long memberId + ) { + return ResponseEntity.ok(eventService.isAlreadyParticipate(eventId, memberId)); + } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/application/EventService.java b/backend/emm-sale/src/main/java/com/emmsale/event/application/EventService.java index f8d9da25e..cd5ac9e54 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/application/EventService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/application/EventService.java @@ -249,4 +249,8 @@ private List findAllPersistTagsOrElseThrow(final List tags) { .orElseThrow(() -> new EventException(EventExceptionType.NOT_FOUND_TAG))) .collect(toList()); } + + public Boolean isAlreadyParticipate(final Long eventId, final Long memberId) { + return participantRepository.existsByEventIdAndMemberId(eventId, memberId); + } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/ParticipantRepository.java b/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/ParticipantRepository.java index d0cf2b299..df0c7a6ff 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/ParticipantRepository.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/ParticipantRepository.java @@ -9,4 +9,6 @@ public interface ParticipantRepository extends JpaRepository { Optional findByMemberIdAndEventId(final Long memberId, final Long eventId); + + Boolean existsByEventIdAndMemberId(final Long eventId, final Long memberId); } diff --git a/backend/emm-sale/src/main/resources/http/event.http b/backend/emm-sale/src/main/resources/http/event.http index c055e3041..25509f4b6 100644 --- a/backend/emm-sale/src/main/resources/http/event.http +++ b/backend/emm-sale/src/main/resources/http/event.http @@ -46,3 +46,6 @@ Authorization: bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNjkwMTk2OTY5L ### 행사 참여자 목록 조회 GET http://localhost:8080/events/1/participants + +### 멤버가 행사에 참여했는지 확인 +GET http://localhost:8080/events/1/participants/already-participate?member-id=1 diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/api/EventApiTest.java b/backend/emm-sale/src/test/java/com/emmsale/event/api/EventApiTest.java index 85e0aef82..0f580c32d 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/event/api/EventApiTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/event/api/EventApiTest.java @@ -4,6 +4,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; @@ -448,4 +449,20 @@ void addEventWithUnformattedEndDateTimeTest(final String endDateTime) throws Exc result.andExpect(status().isBadRequest()); } } + + @Test + @DisplayName("이미 Event에 멤버가 참여헀는지 확인할 수 있다.") + void isAlreadyParticipate() throws Exception { + //given + final Long memberId = 2L; + final Long eventId = 3L; + given(eventService.isAlreadyParticipate(eventId, memberId)).willReturn(true); + + //when && then + mockMvc.perform( + get("/events/{eventId}/participants/already-participate?member-id={memberId}" + , eventId, memberId) + ) + .andDo(document("check-already-participate")); + } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceTest.java index d7be4eadc..0be317e74 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceTest.java @@ -19,6 +19,7 @@ import static com.emmsale.event.exception.EventExceptionType.NOT_FOUND_PARTICIPANT; import static com.emmsale.event.exception.EventExceptionType.NOT_FOUND_TAG; import static com.emmsale.event.exception.EventExceptionType.START_DATE_TIME_AFTER_END_DATE_TIME; +import static com.emmsale.member.MemberFixture.memberFixture; import static com.emmsale.tag.TagFixture.AI; import static com.emmsale.tag.TagFixture.IOS; import static com.emmsale.tag.TagFixture.백엔드; @@ -804,5 +805,38 @@ void deleteEventWithNotExistsEventTest() { } } + @Nested + @DisplayName("이벤트에 이미 참가한 멤버인지 확인할 수 있다.") + class isAlreadyParticipate { + + @Test + @DisplayName("이벤트에 이미 참가한 경우 true를 반환한다.") + void alreadyParticipateThenTrue() { + //given + final Event 인프콘 = eventRepository.save(인프콘_2023()); + final Member 멤버 = memberRepository.save(memberFixture()); + eventService.participate(인프콘.getId(), 멤버.getId(), 멤버); + + //when + final Boolean actual = eventService.isAlreadyParticipate(인프콘.getId(), 멤버.getId()); + + //then + assertThat(actual).isTrue(); + } + + @Test + @DisplayName("이벤트에 참가히자 않은 경우 false를 반환한다.") + void isNotAlreadyParticipateThenFalse() { + //given + final Event 인프콘 = eventRepository.save(인프콘_2023()); + final Member 멤버 = memberRepository.save(memberFixture()); + + //when + final Boolean actual = eventService.isAlreadyParticipate(인프콘.getId(), 멤버.getId()); + + //then + assertThat(actual).isFalse(); + } + } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/domain/repository/ParticipantRepositoryTest.java b/backend/emm-sale/src/test/java/com/emmsale/event/domain/repository/ParticipantRepositoryTest.java new file mode 100644 index 000000000..37604cfca --- /dev/null +++ b/backend/emm-sale/src/test/java/com/emmsale/event/domain/repository/ParticipantRepositoryTest.java @@ -0,0 +1,67 @@ +package com.emmsale.event.domain.repository; + +import static com.emmsale.event.EventFixture.인프콘_2023; +import static com.emmsale.member.MemberFixture.memberFixture; +import static org.assertj.core.api.Assertions.assertThat; + +import com.emmsale.event.domain.Event; +import com.emmsale.event.domain.Participant; +import com.emmsale.member.domain.Member; +import com.emmsale.member.domain.MemberRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +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; + +@Sql("/data-test.sql") +@AutoConfigureTestDatabase(replace = Replace.NONE) +@DataJpaTest +class ParticipantRepositoryTest { + + @Autowired + private ParticipantRepository participantRepository; + @Autowired + private MemberRepository memberRepository; + @Autowired + private EventRepository eventRepository; + + @Nested + @DisplayName("eventId와 memberId로 Participant가 존재하는 지 확인할 수 있다.") + class ExistsByEventIdAndMemberId { + + @Test + @DisplayName("Participant가 존재하는 경우 true를 반환한다.") + void alreadyParticipateThenTrue() { + //given + final Event 인프콘 = eventRepository.save(인프콘_2023()); + final Member 멤버 = memberRepository.save(memberFixture()); + participantRepository.save(new Participant(멤버, 인프콘)); + + //when + final Boolean actual = participantRepository.existsByEventIdAndMemberId(인프콘.getId(), + 멤버.getId()); + + //then + assertThat(actual).isTrue(); + } + + @Test + @DisplayName("Particpant가 존재하지 않는 false를 반환한다.") + void isNotAlreadyParticipateThenFalse() { + //given + final Event 인프콘 = eventRepository.save(인프콘_2023()); + final Member 멤버 = memberRepository.save(memberFixture()); + + //when + final Boolean actual = participantRepository.existsByEventIdAndMemberId(인프콘.getId(), + 멤버.getId()); + + //then + assertThat(actual).isFalse(); + } + } +}