Skip to content

Commit

Permalink
refactor: 인기 셀럽 조회 시, 음식점 정보도 같이 포함되도록 수정 (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
TaeyeonRoyce authored Aug 13, 2024
1 parent 7a6111c commit 91a87f1
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.celuveat.celeb.adapter.`in`.rest

import com.celuveat.auth.adaptor.`in`.rest.Auth
import com.celuveat.auth.adaptor.`in`.rest.AuthContext
import com.celuveat.celeb.adapter.`in`.rest.response.BestCelebrityResponse
import com.celuveat.celeb.adapter.`in`.rest.response.CelebrityResponse
import com.celuveat.celeb.adapter.`in`.rest.response.SimpleCelebrityResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.enums.ParameterIn
Expand Down Expand Up @@ -53,5 +53,7 @@ interface CelebrityApi {

@Operation(summary = "인기 셀럽 조회")
@GetMapping("/interested")
fun readBestCelebrities(): List<SimpleCelebrityResponse>
fun readBestCelebrities(
@Auth auth: AuthContext,
): List<BestCelebrityResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.celuveat.celeb.adapter.`in`.rest

import com.celuveat.auth.adaptor.`in`.rest.Auth
import com.celuveat.auth.adaptor.`in`.rest.AuthContext
import com.celuveat.celeb.adapter.`in`.rest.response.BestCelebrityResponse
import com.celuveat.celeb.adapter.`in`.rest.response.CelebrityResponse
import com.celuveat.celeb.adapter.`in`.rest.response.SimpleCelebrityResponse
import com.celuveat.celeb.application.port.`in`.AddInterestedCelebrityUseCase
import com.celuveat.celeb.application.port.`in`.DeleteInterestedCelebrityUseCase
import com.celuveat.celeb.application.port.`in`.ReadBestCelebritiesUseCase
Expand Down Expand Up @@ -55,7 +55,11 @@ class CelebrityController(
}

@GetMapping("/best")
override fun readBestCelebrities(): List<SimpleCelebrityResponse> {
return readBestCelebritiesUseCase.readBestCelebrities().map { SimpleCelebrityResponse.from(it) }
override fun readBestCelebrities(
@Auth auth: AuthContext,
): List<BestCelebrityResponse> {
val optionalMemberId = auth.optionalMemberId()
val celebritiesResults = readBestCelebritiesUseCase.readBestCelebrities(optionalMemberId)
return celebritiesResults.map { BestCelebrityResponse.from(it) }
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.celuveat.celeb.adapter.`in`.rest.response

import com.celuveat.celeb.application.port.`in`.result.BestCelebrityResult
import com.celuveat.celeb.application.port.`in`.result.CelebrityResult
import com.celuveat.celeb.application.port.`in`.result.SimpleCelebrityResult
import com.celuveat.celeb.application.port.`in`.result.YoutubeContentResult
import com.celuveat.restaurant.adapter.`in`.rest.response.RestaurantPreviewResponse
import io.swagger.v3.oas.annotations.media.Schema

data class CelebrityResponse(
Expand Down Expand Up @@ -131,3 +133,23 @@ data class SimpleCelebrityResponse(
}
}
}

data class BestCelebrityResponse(
@Schema(
description = "연예인 정보",
)
val celebrity: SimpleCelebrityResponse,
@Schema(
description = "식당 정보",
)
val restaurants: List<RestaurantPreviewResponse>,
) {
companion object {
fun from(result: BestCelebrityResult): BestCelebrityResponse {
return BestCelebrityResponse(
celebrity = SimpleCelebrityResponse.from(result.celebrity),
restaurants = result.restaurants.map { RestaurantPreviewResponse.from(it) },
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CelebrityPersistenceAdapter(
.mapValues { (_, celebrityYoutubeContents) -> celebrityYoutubeContents.map { it.youtubeContent } }

override fun findBestCelebrities(): List<Celebrity> {
return celebrityJpaRepository.findAllBySubscriberCountDescTop15().map {
return celebrityJpaRepository.findAllBySubscriberCountDescTop10().map {
celebrityPersistenceMapper.toDomainWithoutYoutubeContent(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ interface CelebrityJpaRepository : JpaRepository<CelebrityJpaEntity, Long> {
FROM CelebrityYoutubeContentJpaEntity cyc
JOIN cyc.youtubeContent yc
JOIN cyc.celebrity c
ORDER BY yc.subscriberCount DESC LIMIT 15
ORDER BY yc.subscriberCount DESC LIMIT 10
""",
)
fun findAllBySubscriberCountDescTop15(): Set<CelebrityJpaEntity>
fun findAllBySubscriberCountDescTop10(): Set<CelebrityJpaEntity>
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,66 @@
package com.celuveat.celeb.application

import com.celuveat.celeb.application.port.`in`.ReadBestCelebritiesUseCase
import com.celuveat.celeb.application.port.`in`.ReadInterestedCelebritiesUseCase
import com.celuveat.celeb.application.port.`in`.result.BestCelebrityResult
import com.celuveat.celeb.application.port.`in`.result.CelebrityResult
import com.celuveat.celeb.application.port.`in`.result.SimpleCelebrityResult
import com.celuveat.celeb.application.port.out.ReadCelebritiesPort
import com.celuveat.celeb.application.port.out.ReadInterestedCelebritiesPort
import com.celuveat.restaurant.application.port.`in`.result.RestaurantPreviewResult
import com.celuveat.restaurant.application.port.out.ReadInterestedRestaurantPort
import com.celuveat.restaurant.application.port.out.ReadRestaurantPort
import com.celuveat.restaurant.domain.InterestedRestaurant
import com.celuveat.restaurant.domain.Restaurant
import org.springframework.stereotype.Service

@Service
class CelebrityQueryService(
private val readCelebritiesPort: ReadCelebritiesPort,
private val readRestaurantPort: ReadRestaurantPort,
private val readInterestedCelebritiesPort: ReadInterestedCelebritiesPort,
) : ReadInterestedCelebritiesUseCase {
private val readInterestedRestaurantPort: ReadInterestedRestaurantPort,
) : ReadInterestedCelebritiesUseCase, ReadBestCelebritiesUseCase {
override fun getInterestedCelebrities(memberId: Long): List<CelebrityResult> {
val celebrities = readInterestedCelebritiesPort.findInterestedCelebrities(memberId)
return celebrities.map { CelebrityResult.from(it.celebrity) }
}

override fun readBestCelebrities(memberId: Long?): List<BestCelebrityResult> {
val bestCelebrities = readCelebritiesPort.findBestCelebrities()
val restaurantsByCelebrity = bestCelebrities.associate {
it.id to readRestaurantPort.findVisitedRestaurantByCelebrity(
celebrityId = it.id,
page = 0,
size = 3
).contents
}
val interestedRestaurants = readInterestedRestaurants(memberId, restaurantsByCelebrity)

return bestCelebrities.map { celebrity ->
BestCelebrityResult(
celebrity = SimpleCelebrityResult.from(celebrity),
restaurants = restaurantsByCelebrity[celebrity.id]!!.map {
RestaurantPreviewResult.of(
restaurant = it,
liked = interestedRestaurants[it.id]?.let { true } ?: false
)
}
)
}
}

private fun readInterestedRestaurants(
memberId: Long?,
restaurantsByCelebrity: Map<Long, List<Restaurant>>
): Map<Long, InterestedRestaurant> {
val interestedRestaurants = memberId?.let {
val restaurantIds = restaurantsByCelebrity.values.flatten().map { it.id }
readInterestedRestaurantPort.findInterestedRestaurantsByIds(
memberId = it,
restaurantIds = restaurantIds
).associateBy { interested -> interested.restaurant.id }
} ?: emptyMap()
return interestedRestaurants
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ package com.celuveat.celeb.application

import com.celuveat.celeb.application.port.`in`.AddInterestedCelebrityUseCase
import com.celuveat.celeb.application.port.`in`.DeleteInterestedCelebrityUseCase
import com.celuveat.celeb.application.port.`in`.ReadBestCelebritiesUseCase
import com.celuveat.celeb.application.port.`in`.command.AddInterestedCelebrityCommand
import com.celuveat.celeb.application.port.`in`.command.DeleteInterestedCelebrityCommand
import com.celuveat.celeb.application.port.`in`.result.SimpleCelebrityResult
import com.celuveat.celeb.application.port.out.DeleteInterestedCelebrityPort
import com.celuveat.celeb.application.port.out.ReadCelebritiesPort
import com.celuveat.celeb.application.port.out.ReadInterestedCelebritiesPort
import com.celuveat.celeb.application.port.out.SaveInterestedCelebrityPort
import com.celuveat.celeb.exceptions.AlreadyInterestedCelebrityException
Expand All @@ -16,11 +13,10 @@ import org.springframework.stereotype.Service

@Service
class CelebrityService(
private val readCelebritiesPort: ReadCelebritiesPort,
private val readInterestedCelebritiesPort: ReadInterestedCelebritiesPort,
private val saveInterestedCelebrityPort: SaveInterestedCelebrityPort,
private val deleteInterestedCelebrityPort: DeleteInterestedCelebrityPort,
) : ReadBestCelebritiesUseCase, AddInterestedCelebrityUseCase, DeleteInterestedCelebrityUseCase {
) : AddInterestedCelebrityUseCase, DeleteInterestedCelebrityUseCase {
override fun addInterestedCelebrity(command: AddInterestedCelebrityCommand) {
throwWhen(
readInterestedCelebritiesPort.existsInterestedCelebrity(command.celebrityId, command.memberId),
Expand All @@ -31,9 +27,4 @@ class CelebrityService(
override fun deleteInterestedCelebrity(command: DeleteInterestedCelebrityCommand) {
deleteInterestedCelebrityPort.deleteInterestedCelebrity(command.celebrityId, command.memberId)
}

override fun readBestCelebrities(): List<SimpleCelebrityResult> {
val bestCelebrities = readCelebritiesPort.findBestCelebrities()
return bestCelebrities.map { SimpleCelebrityResult.from(it) }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.celuveat.celeb.application.port.`in`

import com.celuveat.celeb.application.port.`in`.result.SimpleCelebrityResult
import com.celuveat.celeb.application.port.`in`.result.BestCelebrityResult

interface ReadBestCelebritiesUseCase {
fun readBestCelebrities(): List<SimpleCelebrityResult>
fun readBestCelebrities(memberId: Long?): List<BestCelebrityResult>
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.celuveat.celeb.application.port.`in`.result

import com.celuveat.celeb.domain.Celebrity
import com.celuveat.restaurant.application.port.`in`.result.RestaurantPreviewResult

data class CelebrityResult(
val id: Long,
Expand Down Expand Up @@ -37,3 +38,8 @@ data class SimpleCelebrityResult(
}
}
}

data class BestCelebrityResult(
val celebrity: SimpleCelebrityResult,
val restaurants: List<RestaurantPreviewResult>,
)
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.celuveat.celeb.adapter.`in`.rest

import com.celuveat.auth.application.port.`in`.ExtractMemberIdUseCase
import com.celuveat.celeb.adapter.`in`.rest.response.SimpleCelebrityResponse
import com.celuveat.celeb.adapter.`in`.rest.response.BestCelebrityResponse
import com.celuveat.celeb.application.port.`in`.AddInterestedCelebrityUseCase
import com.celuveat.celeb.application.port.`in`.DeleteInterestedCelebrityUseCase
import com.celuveat.celeb.application.port.`in`.ReadBestCelebritiesUseCase
import com.celuveat.celeb.application.port.`in`.ReadInterestedCelebritiesUseCase
import com.celuveat.celeb.application.port.`in`.command.AddInterestedCelebrityCommand
import com.celuveat.celeb.application.port.`in`.command.DeleteInterestedCelebrityCommand
import com.celuveat.celeb.application.port.`in`.result.BestCelebrityResult
import com.celuveat.celeb.application.port.`in`.result.CelebrityResult
import com.celuveat.celeb.application.port.`in`.result.SimpleCelebrityResult
import com.celuveat.support.sut
import com.fasterxml.jackson.databind.ObjectMapper
import com.navercorp.fixturemonkey.kotlin.giveMeBuilder
Expand Down Expand Up @@ -96,11 +96,11 @@ class CelebrityControllerTest(
}

context("인기 셀럽을 조회 한다") {
val results = sut.giveMeBuilder<SimpleCelebrityResult>()
val results = sut.giveMeBuilder<BestCelebrityResult>()
.sampleList(3)
val response = results.map { SimpleCelebrityResponse.from(it) }
val response = results.map { BestCelebrityResponse.from(it) }
test("조회 성공") {
every { readBestCelebritiesUseCase.readBestCelebrities() } returns results
every { readBestCelebritiesUseCase.readBestCelebrities(null) } returns results

mockMvc.get("/celebrities/best").andExpect {
status { isOk() }
Expand Down

0 comments on commit 91a87f1

Please sign in to comment.