From aaf0ab03ddf5d5d8e5cbf44e3b25838eaa7a2e26 Mon Sep 17 00:00:00 2001 From: HyungJu Date: Tue, 21 May 2024 14:14:21 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=B0=A9=20=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/model/CafeRoomAddressMap.kt | 7 +++++ .../domain/repository/CafeRoomRepository.kt | 5 ++++ .../domain/service/CafeRoomService.kt | 30 +++++++++++++++++++ .../jpa/repository/CafeRoomRepositoryImpl.kt | 29 ++++++++++++++++++ .../presenter/restapi/api/CafeRoomApi.kt | 5 ++++ .../presenter/restapi/api/CafeSearchApi.kt | 2 +- .../restapi/controller/CafeRoomController.kt | 5 ++++ .../response/CafeRoomAreaFilterResponse.kt | 20 +++++++++++++ 8 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/kr/nagaza/nagazaserver/domain/model/CafeRoomAddressMap.kt create mode 100644 src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/dto/response/CafeRoomAreaFilterResponse.kt diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/domain/model/CafeRoomAddressMap.kt b/src/main/kotlin/kr/nagaza/nagazaserver/domain/model/CafeRoomAddressMap.kt new file mode 100644 index 0000000..dc30007 --- /dev/null +++ b/src/main/kotlin/kr/nagaza/nagazaserver/domain/model/CafeRoomAddressMap.kt @@ -0,0 +1,7 @@ +package kr.nagaza.nagazaserver.domain.model + +data class CafeRoomAddressMap( + val address1: String, + val address2: String, + val count: Int, +) diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/domain/repository/CafeRoomRepository.kt b/src/main/kotlin/kr/nagaza/nagazaserver/domain/repository/CafeRoomRepository.kt index 6dd6bd9..653890f 100644 --- a/src/main/kotlin/kr/nagaza/nagazaserver/domain/repository/CafeRoomRepository.kt +++ b/src/main/kotlin/kr/nagaza/nagazaserver/domain/repository/CafeRoomRepository.kt @@ -1,6 +1,7 @@ package kr.nagaza.nagazaserver.domain.repository import kr.nagaza.nagazaserver.domain.model.CafeRoom +import kr.nagaza.nagazaserver.domain.model.CafeRoomAddressMap interface CafeRoomRepository { fun getAllRoomByCafeId(cafeId: String): List @@ -14,4 +15,8 @@ interface CafeRoomRepository { address2: String?, cafeId: String?, ): List + + fun getAll(): List + + fun getRoomCountGroupByAddress(): List } diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/domain/service/CafeRoomService.kt b/src/main/kotlin/kr/nagaza/nagazaserver/domain/service/CafeRoomService.kt index 4b1be70..5950bab 100644 --- a/src/main/kotlin/kr/nagaza/nagazaserver/domain/service/CafeRoomService.kt +++ b/src/main/kotlin/kr/nagaza/nagazaserver/domain/service/CafeRoomService.kt @@ -7,6 +7,7 @@ import kr.nagaza.nagazaserver.domain.model.CafeRoom import kr.nagaza.nagazaserver.domain.repository.CafeRepository import kr.nagaza.nagazaserver.domain.repository.CafeRoomRepository import kr.nagaza.nagazaserver.presenter.restapi.dto.request.RoomSearchQuery +import kr.nagaza.nagazaserver.presenter.restapi.dto.response.CafeRoomAreaFilterItem import org.springframework.stereotype.Service @Service @@ -35,4 +36,33 @@ class CafeRoomService( cafeId = cafeRoomSearchQuery.cafeId, ) } + + fun getRoomAreaFilters(): CafeRoomAreaFilterItem { + val res = cafeRoomRepository.getRoomCountGroupByAddress() + + val depth1 = + res.groupBy { it.address1 }.map { + CafeRoomAreaFilterItem( + name = it.key, + depth = 1, + count = it.value.size, + children = + it.value.map { depth2 -> + CafeRoomAreaFilterItem( + name = depth2.address2, + depth = 2, + count = depth2.count, + children = emptyList(), + ) + }, + ) + } + + return CafeRoomAreaFilterItem( + name = "전국", + depth = 0, + count = res.size, + children = depth1, + ) + } } diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/infrastructure/jpa/repository/CafeRoomRepositoryImpl.kt b/src/main/kotlin/kr/nagaza/nagazaserver/infrastructure/jpa/repository/CafeRoomRepositoryImpl.kt index faed2f5..a1320f2 100644 --- a/src/main/kotlin/kr/nagaza/nagazaserver/infrastructure/jpa/repository/CafeRoomRepositoryImpl.kt +++ b/src/main/kotlin/kr/nagaza/nagazaserver/infrastructure/jpa/repository/CafeRoomRepositoryImpl.kt @@ -4,6 +4,7 @@ import com.querydsl.jpa.impl.JPAQuery import jakarta.persistence.EntityManager import jakarta.persistence.PersistenceContext import kr.nagaza.nagazaserver.domain.model.CafeRoom +import kr.nagaza.nagazaserver.domain.model.CafeRoomAddressMap import kr.nagaza.nagazaserver.domain.repository.CafeRoomRepository import kr.nagaza.nagazaserver.infrastructure.jpa.entity.QCafeEntity import kr.nagaza.nagazaserver.infrastructure.jpa.entity.QCafeRoomEntity @@ -67,4 +68,32 @@ class CafeRoomRepositoryImpl( it.toModel() } } + + override fun getAll(): List { + return jpaCafeRoomRepository.findAll().map { + it.toModel() + } + } + + override fun getRoomCountGroupByAddress(): List { + val cafeRoomEntity = QCafeRoomEntity.cafeRoomEntity + val cafeEntity = QCafeEntity.cafeEntity + val result = + JPAQuery(entityManager) + .select(cafeEntity.addressOne, cafeEntity.addressTwo, cafeRoomEntity.count()) + .from(cafeRoomEntity) + .join(cafeEntity).on(cafeRoomEntity.cafeId.eq(cafeEntity.cafeId)) + .groupBy(cafeEntity.addressOne, cafeEntity.addressTwo) + .fetch() + + return result.filter { + it.get(cafeEntity.addressOne) != null && it.get(cafeEntity.addressTwo) != null + }.map { + CafeRoomAddressMap( + address1 = it.get(cafeEntity.addressOne)!!, + address2 = it.get(cafeEntity.addressTwo)!!, + count = it.get(cafeRoomEntity.count())?.toInt() ?: 0, + ) + } + } } diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeRoomApi.kt b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeRoomApi.kt index 0b0f625..c5d9285 100644 --- a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeRoomApi.kt +++ b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeRoomApi.kt @@ -2,6 +2,7 @@ package kr.nagaza.nagazaserver.presenter.restapi.api import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag +import kr.nagaza.nagazaserver.presenter.restapi.dto.response.CafeRoomAreaFilterItem import kr.nagaza.nagazaserver.presenter.restapi.dto.response.CafeRoomResponse import org.springframework.data.repository.query.Param import org.springframework.web.bind.annotation.GetMapping @@ -28,4 +29,8 @@ interface CafeRoomApi { fun getCafeRoom( @PathVariable roomId: String, ): CafeRoomResponse + + @Operation(summary = "카페 방 지역 필터", description = "카페 방 지역 필터 목록을 반환합니다.") + @GetMapping("/filter") + fun getCafeRoomAreaFilters(): CafeRoomAreaFilterItem } diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeSearchApi.kt b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeSearchApi.kt index 95f27da..e6206bb 100644 --- a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeSearchApi.kt +++ b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/api/CafeSearchApi.kt @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController @Tag(name = "카페 검색 API", description = "카페 검색 관련 API") @RestController -@RequestMapping("/v1/cafes/search") +@RequestMapping("/v1/cafes/rooms/search") interface CafeSearchApi { @Operation(summary = "카페 검색", description = "문자열로 카페를 검색합니다.") @GetMapping(params = ["q"]) diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/controller/CafeRoomController.kt b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/controller/CafeRoomController.kt index 5e65c21..da5d89b 100644 --- a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/controller/CafeRoomController.kt +++ b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/controller/CafeRoomController.kt @@ -3,6 +3,7 @@ package kr.nagaza.nagazaserver.presenter.restapi.controller import kr.nagaza.nagazaserver.domain.service.CafeRoomService import kr.nagaza.nagazaserver.presenter.restapi.api.CafeRoomApi import kr.nagaza.nagazaserver.presenter.restapi.dto.request.RoomSearchQuery +import kr.nagaza.nagazaserver.presenter.restapi.dto.response.CafeRoomAreaFilterItem import kr.nagaza.nagazaserver.presenter.restapi.dto.response.CafeRoomResponse import org.springframework.stereotype.Controller @@ -15,6 +16,10 @@ class CafeRoomController( .let(CafeRoomResponse::fromModel) } + override fun getCafeRoomAreaFilters(): CafeRoomAreaFilterItem { + return this.cafeRoomService.getRoomAreaFilters() + } + override fun searchRooms( queryString: String?, genre: String?, diff --git a/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/dto/response/CafeRoomAreaFilterResponse.kt b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/dto/response/CafeRoomAreaFilterResponse.kt new file mode 100644 index 0000000..c3ecf05 --- /dev/null +++ b/src/main/kotlin/kr/nagaza/nagazaserver/presenter/restapi/dto/response/CafeRoomAreaFilterResponse.kt @@ -0,0 +1,20 @@ +package kr.nagaza.nagazaserver.presenter.restapi.dto.response + +import com.fasterxml.jackson.annotation.JsonProperty +import io.swagger.v3.oas.annotations.media.Schema + +@Schema(description = "방 지역 필터 응답") +data class CafeRoomAreaFilterItem( + @JsonProperty("name") + @Schema(description = "지역 구분 이름", example = "서울시") + val name: String, + @JsonProperty("depth") + @Schema(description = "지역 구분 깊이 (0: 전체, 1: 시, 2: 구)", example = "1") + val depth: Int, + @JsonProperty("count") + @Schema(description = "해당 지역에 속한 방 수", example = "23") + val count: Int, + @JsonProperty("children") + @Schema(description = "하위 지역 목록", example = "[]") + val children: List, +)