diff --git a/.github/workflows/backend-dev.yml b/.github/workflows/backend-dev.yml index 9e56c7615..4494c494f 100644 --- a/.github/workflows/backend-dev.yml +++ b/.github/workflows/backend-dev.yml @@ -8,7 +8,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: [ self-hosted, backend-dev ] defaults: run: diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml index 797f88326..7e0c561f1 100644 --- a/.github/workflows/backend-pull-request.yml +++ b/.github/workflows/backend-pull-request.yml @@ -8,7 +8,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: [ self-hosted, backend-dev ] defaults: run: diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index 9ad502606..e48a2dff2 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -10,6 +10,7 @@ import server.haengdong.application.response.ActionAppResponse; import server.haengdong.application.response.EventAppResponse; import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; import server.haengdong.domain.action.BillAction; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.action.MemberAction; @@ -88,4 +89,13 @@ private List getActionAppResponses( return actionAppResponses; } + + public MembersAppResponse findAllMembers(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + + List memberNames = memberActionRepository.findAllUniqueMemberByEvent(event); + + return new MembersAppResponse(memberNames); + } } diff --git a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java new file mode 100644 index 000000000..be8378b37 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java @@ -0,0 +1,8 @@ +package server.haengdong.application.response; + +import java.util.List; + +public record MembersAppResponse( + List memberNames +) { +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java index ebc2ffc2b..4d47bc009 100644 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java @@ -15,6 +15,13 @@ public interface MemberActionRepository extends JpaRepository findAllByEvent(@Param("event") Event event); + @Query(""" + select distinct m.memberName + from MemberAction m + where m.action.event = :event + """) + List findAllUniqueMemberByEvent(Event event); + @Modifying @Query(""" delete diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java index 816e7ed26..45f8362cd 100644 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -12,6 +12,7 @@ import server.haengdong.presentation.request.EventSaveRequest; import server.haengdong.presentation.response.EventDetailResponse; import server.haengdong.presentation.response.EventResponse; +import server.haengdong.presentation.response.MembersResponse; import server.haengdong.presentation.response.StepsResponse; @RequiredArgsConstructor @@ -40,4 +41,11 @@ public ResponseEntity findActions(@PathVariable("eventId") String return ResponseEntity.ok(stepsResponse); } + + @GetMapping("/api/events/{eventId}/members") + public ResponseEntity findAllMembers(@PathVariable("eventId") String token) { + MembersResponse response = MembersResponse.of(eventService.findAllMembers(token)); + + return ResponseEntity.ok(response); + } } diff --git a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java new file mode 100644 index 000000000..0947d9e02 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java @@ -0,0 +1,13 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MembersAppResponse; + +public record MembersResponse( + List memberNames +) { + + public static MembersResponse of(MembersAppResponse response) { + return new MembersResponse(response.memberNames()); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java index 5a3e8bce3..2affe0690 100644 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -4,6 +4,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.mockito.BDDMockito.given; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -16,13 +18,13 @@ import server.haengdong.application.response.ActionAppResponse; import server.haengdong.application.response.EventAppResponse; import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; import server.haengdong.domain.action.Action; import server.haengdong.domain.action.ActionRepository; import server.haengdong.domain.action.BillAction; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.event.EventTokenProvider; @@ -84,9 +86,9 @@ void findEventTest() { void findActionsTest() { Event event = new Event("행동대장 회식", "웨디_토큰"); Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", IN, 1L); Action action1 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "쿠키", MemberActionStatus.IN, 1L); + MemberAction memberAction1 = new MemberAction(action1, "쿠키", IN, 1L); Action action2 = new Action(event, 3L); BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); eventRepository.save(event); @@ -107,4 +109,26 @@ void findActionsTest() { tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") ); } + + @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") + @Test + void findAllMembersTest() { + String token = "웨디_토큰"; + Event event = new Event("행동대장 회식", token); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + Action action3 = new Action(event, 3L); + Action action4 = new Action(event, 4L); + BillAction billAction = new BillAction(action3, "뽕나무쟁이족발", 30000L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(action4, "쿠키", OUT, 1L); + eventRepository.save(event); + billActionRepository.save(billAction); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MembersAppResponse membersAppResponse = eventService.findAllMembers(token); + + assertThat(membersAppResponse.memberNames()).containsExactlyInAnyOrder("토다리", "쿠키"); + } } diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java index 55a48630f..4a7a50d2d 100644 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -1,6 +1,7 @@ package server.haengdong.presentation; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -9,6 +10,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,6 +22,7 @@ import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; import server.haengdong.presentation.request.EventSaveRequest; @WebMvcTest(EventController.class) @@ -63,4 +66,18 @@ void findEventTest() throws Exception { .andExpect(status().isOk()) .andExpect(jsonPath("$.eventName").value("행동대장 회식")); } + + @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") + @Test + void findAllMembersTest() throws Exception { + MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); + given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); + + mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames").isArray()) + .andExpect(jsonPath("$.memberNames[0]").value("토다리")) + .andExpect(jsonPath("$.memberNames[1]").value("쿠키")); + } }