diff --git a/backend/src/main/java/com/happy/friendogly/playground/controller/PlaygroundController.java b/backend/src/main/java/com/happy/friendogly/playground/controller/PlaygroundController.java index 80ad5cb4a..def537584 100644 --- a/backend/src/main/java/com/happy/friendogly/playground/controller/PlaygroundController.java +++ b/backend/src/main/java/com/happy/friendogly/playground/controller/PlaygroundController.java @@ -5,6 +5,7 @@ import com.happy.friendogly.playground.dto.request.SavePlaygroundRequest; import com.happy.friendogly.playground.dto.request.UpdatePlaygroundArrivalRequest; import com.happy.friendogly.playground.dto.request.UpdatePlaygroundMemberMessageRequest; +import com.happy.friendogly.playground.dto.response.FindMyPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundDetailResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundSummaryResponse; @@ -25,12 +26,18 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/playgrounds") public class PlaygroundController { + private static final String MIN_KOREA_LATITUDE = "33.0637"; + private static final String MAX_KOREA_LATITUDE = "43.0042"; + private static final String MIN_KOREA_LONGITUDE = "124.1104"; + private static final String MAX_KOREA_LONGITUDE = "131.4220"; + private final PlaygroundCommandService playgroundCommandService; private final PlaygroundQueryService playgroundQueryService; @@ -64,8 +71,26 @@ public ApiResponse findSummaryById(@PathVariable } @GetMapping("/locations") - public ApiResponse> findAllLocation(@Auth Long memberId) { - return ApiResponse.ofSuccess(playgroundQueryService.findLocations(memberId)); + public ApiResponse> findAllLocations( + @Auth Long memberId, + @RequestParam(defaultValue = MIN_KOREA_LATITUDE) double startLatitude, + @RequestParam(defaultValue = MAX_KOREA_LATITUDE) double endLatitude, + @RequestParam(defaultValue = MIN_KOREA_LONGITUDE) double startLongitude, + @RequestParam(defaultValue = MAX_KOREA_LONGITUDE) double endLongitude + ) { + List findPlaygroundLocationResponses = playgroundQueryService.findLocations( + memberId, + startLatitude, + endLatitude, + startLongitude, + endLongitude + ); + return ApiResponse.ofSuccess(findPlaygroundLocationResponses); + } + + @GetMapping("/locations/mine") + public ApiResponse findMyLocation(@Auth Long memberId) { + return ApiResponse.ofSuccess(playgroundQueryService.findMyPlaygroundLocation(memberId)); } @PatchMapping("/arrival") diff --git a/backend/src/main/java/com/happy/friendogly/playground/dto/response/FindMyPlaygroundLocationResponse.java b/backend/src/main/java/com/happy/friendogly/playground/dto/response/FindMyPlaygroundLocationResponse.java new file mode 100644 index 000000000..f003be932 --- /dev/null +++ b/backend/src/main/java/com/happy/friendogly/playground/dto/response/FindMyPlaygroundLocationResponse.java @@ -0,0 +1,9 @@ +package com.happy.friendogly.playground.dto.response; + +public record FindMyPlaygroundLocationResponse( + Long id, + double latitude, + double longitude +) { + +} diff --git a/backend/src/main/java/com/happy/friendogly/playground/service/PlaygroundQueryService.java b/backend/src/main/java/com/happy/friendogly/playground/service/PlaygroundQueryService.java index 0cc18267f..5c1edbac6 100644 --- a/backend/src/main/java/com/happy/friendogly/playground/service/PlaygroundQueryService.java +++ b/backend/src/main/java/com/happy/friendogly/playground/service/PlaygroundQueryService.java @@ -5,6 +5,7 @@ import com.happy.friendogly.pet.repository.PetRepository; import com.happy.friendogly.playground.domain.Playground; import com.happy.friendogly.playground.domain.PlaygroundMember; +import com.happy.friendogly.playground.dto.response.FindMyPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundDetailResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundSummaryResponse; @@ -84,8 +85,19 @@ private int getArrivedPetCount(PlaygroundMember playgroundMember, List pets return 0; } - public List findLocations(Long memberId) { - List playgrounds = playgroundRepository.findAll(); + public List findLocations( + Long memberId, + double startLatitude, + double endLatitude, + double startLongitude, + double endLongitude + ) { + List playgrounds = playgroundRepository.findAllByLatitudeBetweenAndLongitudeBetween( + startLatitude, + endLatitude, + startLongitude, + endLongitude + ); Optional playgroundMember = playgroundMemberRepository.findByMemberId(memberId); if (playgroundMember.isPresent()) { @@ -137,4 +149,14 @@ private List cutPetImagesCount(List petImageUrls) { } return petImageUrls; } + + public FindMyPlaygroundLocationResponse findMyPlaygroundLocation(Long memberId) { + PlaygroundMember playgroundMember = playgroundMemberRepository.getByMemberId(memberId); + Playground playground = playgroundMember.getPlayground(); + return new FindMyPlaygroundLocationResponse( + playground.getId(), + playground.getLocation().getLatitude(), + playground.getLocation().getLongitude() + ); + } } diff --git a/backend/src/test/java/com/happy/friendogly/docs/PlaygroundApiDocsTest.java b/backend/src/test/java/com/happy/friendogly/docs/PlaygroundApiDocsTest.java index 51014213e..1cac987c6 100644 --- a/backend/src/test/java/com/happy/friendogly/docs/PlaygroundApiDocsTest.java +++ b/backend/src/test/java/com/happy/friendogly/docs/PlaygroundApiDocsTest.java @@ -5,6 +5,7 @@ import static com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyDouble; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @@ -18,6 +19,7 @@ import com.epages.restdocs.apispec.ResourceSnippetParameters; import com.epages.restdocs.apispec.Schema; +import com.epages.restdocs.apispec.SimpleType; import com.happy.friendogly.member.domain.Member; import com.happy.friendogly.pet.domain.Gender; import com.happy.friendogly.pet.domain.Pet; @@ -29,6 +31,7 @@ import com.happy.friendogly.playground.dto.request.SavePlaygroundRequest; import com.happy.friendogly.playground.dto.request.UpdatePlaygroundArrivalRequest; import com.happy.friendogly.playground.dto.request.UpdatePlaygroundMemberMessageRequest; +import com.happy.friendogly.playground.dto.response.FindMyPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundDetailResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundSummaryResponse; @@ -221,12 +224,16 @@ void findAllLocation() throws Exception { new FindPlaygroundLocationResponse(4L, 37.5131474, 127.1042528, false) ); - when(playgroundQueryService.findLocations(anyLong())) + when(playgroundQueryService.findLocations(anyLong(),anyDouble(),anyDouble(),anyDouble(),anyDouble())) .thenReturn(response); mockMvc .perform(get("/playgrounds/locations") .header(HttpHeaders.AUTHORIZATION, getMemberToken()) + .queryParam("startLatitude", "37.5131474") + .queryParam("endLatitude", "37.5183316") + .queryParam("startLongitude", "127.0983182") + .queryParam("endLongitude", "127.1042528") ) .andDo(document("playgrounds/findLocations", getDocumentRequest(), @@ -234,6 +241,27 @@ void findAllLocation() throws Exception { resource(ResourceSnippetParameters.builder() .tag("Playground API") .summary("전체 놀이터 위치 조회 API") + .requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("로그인한 회원의 access token") + ) + .queryParameters( + parameterWithName("startLatitude") + .type(SimpleType.NUMBER) + .description("시작위도(default - 한국극단위도)") + .optional(), + parameterWithName("endLatitude") + .type(SimpleType.NUMBER) + .description("끝위도(default - 한국극단위도)") + .optional(), + parameterWithName("startLongitude") + .type(SimpleType.NUMBER) + .description("시작경도(default - 한국극단경도)") + .optional(), + parameterWithName("endLongitude") + .type(SimpleType.NUMBER) + .description("끝경도(default - 한국극단경도)") + .optional() + ) .responseFields( fieldWithPath("isSuccess").description("응답 성공 여부"), fieldWithPath("data.[].id").description("놀이터의 ID"), @@ -248,6 +276,41 @@ void findAllLocation() throws Exception { .andExpect(status().isOk()); } + @DisplayName("참여한 놀이터의 위치를 조회") + @Test + void findMyPlaygroundLocation() throws Exception { + + FindMyPlaygroundLocationResponse response = new FindMyPlaygroundLocationResponse(1L, 37.5173316, 127.1011661); + + when(playgroundQueryService.findMyPlaygroundLocation(anyLong())) + .thenReturn(response); + + mockMvc + .perform(get("/playgrounds/locations/mine") + .header(HttpHeaders.AUTHORIZATION, getMemberToken()) + ) + .andDo(document("playgrounds/findMyPlaygroundLocations", + getDocumentRequest(), + getDocumentResponse(), + resource(ResourceSnippetParameters.builder() + .tag("Playground API") + .summary("참여한 놀이터 위치 조회 API") + .requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("로그인한 회원의 access token") + ) + .responseFields( + fieldWithPath("isSuccess").description("응답 성공 여부"), + fieldWithPath("data.id").description("놀이터의 ID"), + fieldWithPath("data.latitude").description("놀이터의 위도"), + fieldWithPath("data.longitude").description("놀이터의 경도") + ) + .responseSchema(Schema.schema("MyPlaygroundLocationResponse")) + .build() + ) + )) + .andExpect(status().isOk()); + } + @DisplayName("놀이터의 참여 현황 요약 정보를 조회") @Test void findSummary() throws Exception { diff --git a/backend/src/test/java/com/happy/friendogly/playground/service/PlaygroundQueryServiceTest.java b/backend/src/test/java/com/happy/friendogly/playground/service/PlaygroundQueryServiceTest.java index 846c50c33..28fa766f6 100644 --- a/backend/src/test/java/com/happy/friendogly/playground/service/PlaygroundQueryServiceTest.java +++ b/backend/src/test/java/com/happy/friendogly/playground/service/PlaygroundQueryServiceTest.java @@ -9,6 +9,7 @@ import com.happy.friendogly.pet.domain.SizeType; import com.happy.friendogly.playground.domain.Playground; import com.happy.friendogly.playground.domain.PlaygroundMember; +import com.happy.friendogly.playground.dto.response.FindMyPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundDetailResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundLocationResponse; import com.happy.friendogly.playground.dto.response.FindPlaygroundSummaryResponse; @@ -112,7 +113,13 @@ void findLocations() { Playground playground = savePlayground(expectedLatitude, expectedLongitude); // when - List response = playgroundQueryService.findLocations(1L); + List response = playgroundQueryService.findLocations( + 1L, + 37.0, + 38.0, + 127.0, + 128.0 + ); // then assertAll( @@ -121,6 +128,29 @@ void findLocations() { ); } + @DisplayName("특정 범위내의 놀이터들의 위치를 조회할 수 있다.") + @Test + void findLocationsWithRange() { + // given + Playground insidePlayground = savePlayground(37.5173316, 127.1011661); + Playground outsidePlayground = savePlayground(38.5173316, 128.1011661); + + // when + List playgroundsLocation = playgroundQueryService.findLocations( + 1L, + 37.0, + 38.0, + 127.0, + 128.0 + ); + + // then + assertAll( + () -> assertThat(playgroundsLocation).hasSize(1), + () -> assertThat(playgroundsLocation.get(0).id()).isEqualTo(insidePlayground.getId()) + ); + } + @DisplayName("놀이터들의 위치를 조회할 때, 내가 참여했는 지 알 수있다(true)") @Test void findLocationsWithIsParticipatingTrue() { @@ -141,7 +171,13 @@ void findLocationsWithIsParticipatingTrue() { ); // when - List response = playgroundQueryService.findLocations(member1.getId()); + List response = playgroundQueryService.findLocations( + member1.getId(), + 37.0, + 38.0, + 127.0, + 128.0 + ); // then assertThat(response.get(0).isParticipating()).isEqualTo(true); @@ -157,12 +193,33 @@ void findLocationsWithIsParticipatingFalse() { savePlayground(); // when - List response = playgroundQueryService.findLocations(member1.getId()); + List response = playgroundQueryService.findLocations( + member1.getId(), + 37.0, + 38.0, + 127.0, + 128.0 + ); // then assertThat(response.get(0).isParticipating()).isEqualTo(false); } + @DisplayName("내가 참여한 놀이터의 위치를 조회할 수 있다.") + @Test + void findMyPlaygroundLocations() { + // given + Member member = saveMember("member1"); + Playground playground = savePlayground(); + savePlaygroundMember(playground, member); + + // when + FindMyPlaygroundLocationResponse myPlaygroundLocation = playgroundQueryService.findMyPlaygroundLocation(member.getId()); + + // then + assertThat(myPlaygroundLocation.id()).isEqualTo(playground.getId()); + } + @DisplayName("놀이터의 요약정보를 조회한다.") @Test void findSummary() {