feat(recommendation): 추천 배너 언어 필터를 적용한다
This commit is contained in:
@@ -5,8 +5,8 @@ import kr.co.vividnext.sodalive.member.Member
|
|||||||
private val FORCED_KR_MEMBER_IDS = setOf(16L, 17L, 17958L, 44144L)
|
private val FORCED_KR_MEMBER_IDS = setOf(16L, 17L, 17958L, 44144L)
|
||||||
private val FORCED_JP_MEMBER_IDS = setOf(2L, 29721L, 32050L, 37543L, 40850L)
|
private val FORCED_JP_MEMBER_IDS = setOf(2L, 29721L, 32050L, 37543L, 40850L)
|
||||||
|
|
||||||
fun resolveCountryCodeWithForcedMapping(member: Member, requestCountryCode: String?): String {
|
fun resolveCountryCodeWithForcedMapping(member: Member?, requestCountryCode: String?): String {
|
||||||
val memberId = member.id
|
val memberId = member?.id
|
||||||
if (memberId != null && FORCED_KR_MEMBER_IDS.contains(memberId)) {
|
if (memberId != null && FORCED_KR_MEMBER_IDS.contains(memberId)) {
|
||||||
return "KR"
|
return "KR"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ class MemberContentPreferenceService(
|
|||||||
return getStoredPreference(member).isAdult
|
return getStoredPreference(member).isAdult
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveCountryCode(member: Member): String {
|
fun resolveCountryCode(member: Member?): String {
|
||||||
requireMemberId(member)
|
if (member != null) requireMemberId(member)
|
||||||
return resolveCountryCodeWithForcedMapping(member, countryContext.countryCode)
|
return resolveCountryCodeWithForcedMapping(member, countryContext.countryCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.api.home.application
|
package kr.co.vividnext.sodalive.v2.api.home.application
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.event.EventItem
|
import kr.co.vividnext.sodalive.event.EventItem
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||||
import kr.co.vividnext.sodalive.v2.api.common.dto.RecommendationBannerResponse
|
import kr.co.vividnext.sodalive.v2.api.common.dto.RecommendationBannerResponse
|
||||||
@@ -46,6 +47,7 @@ class HomeRecommendationFacade(
|
|||||||
return runCatching {
|
return runCatching {
|
||||||
val now = LocalDateTime.now()
|
val now = LocalDateTime.now()
|
||||||
val includeAdult = resolveAdultVisibility(member)
|
val includeAdult = resolveAdultVisibility(member)
|
||||||
|
val bannerLang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||||
|
|
||||||
HomeRecommendationResponse(
|
HomeRecommendationResponse(
|
||||||
lives = queryService.findLiveRecommendations(
|
lives = queryService.findLiveRecommendations(
|
||||||
@@ -56,7 +58,8 @@ class HomeRecommendationFacade(
|
|||||||
banners = queryService.findHomeBanners(
|
banners = queryService.findHomeBanners(
|
||||||
limit = HOME_BANNER_LIMIT,
|
limit = HOME_BANNER_LIMIT,
|
||||||
memberId = member?.id,
|
memberId = member?.id,
|
||||||
includeAdultBanners = includeAdult
|
includeAdultBanners = includeAdult,
|
||||||
|
lang = bannerLang
|
||||||
)
|
)
|
||||||
.map { RecommendationBannerResponse.from(it.toBanner()) },
|
.map { RecommendationBannerResponse.from(it.toBanner()) },
|
||||||
recentlyActiveCreators = queryService.findRecentlyActiveCreators(
|
recentlyActiveCreators = queryService.findRecentlyActiveCreators(
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
|
|||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeriesContent.seriesContent
|
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeriesContent.seriesContent
|
||||||
import kr.co.vividnext.sodalive.event.EventItem
|
import kr.co.vividnext.sodalive.event.EventItem
|
||||||
import kr.co.vividnext.sodalive.event.QEvent.event
|
import kr.co.vividnext.sodalive.event.QEvent.event
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.member.QMember
|
import kr.co.vividnext.sodalive.member.QMember
|
||||||
import kr.co.vividnext.sodalive.member.QMember.member
|
import kr.co.vividnext.sodalive.member.QMember.member
|
||||||
import kr.co.vividnext.sodalive.member.block.QBlockMember
|
import kr.co.vividnext.sodalive.member.block.QBlockMember
|
||||||
@@ -40,7 +41,12 @@ class DefaultAudioRecommendationQueryRepository(
|
|||||||
@Value("\${cloud.aws.cloud-front.host}")
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
private val cloudFrontHost: String
|
private val cloudFrontHost: String
|
||||||
) : AudioRecommendationQueryRepository {
|
) : AudioRecommendationQueryRepository {
|
||||||
override fun findBanners(limit: Int, memberId: Long?, canViewAdultContent: Boolean): List<RecommendationBanner> {
|
override fun findBanners(
|
||||||
|
limit: Int,
|
||||||
|
memberId: Long?,
|
||||||
|
canViewAdultContent: Boolean,
|
||||||
|
lang: Lang
|
||||||
|
): List<RecommendationBanner> {
|
||||||
val bannerCreator = QMember("audioRecommendationBannerCreator")
|
val bannerCreator = QMember("audioRecommendationBannerCreator")
|
||||||
val seriesOwner = QMember("audioRecommendationSeriesOwner")
|
val seriesOwner = QMember("audioRecommendationSeriesOwner")
|
||||||
val randomTieBreaker = Expressions.numberTemplate(Double::class.java, "function('rand')")
|
val randomTieBreaker = Expressions.numberTemplate(Double::class.java, "function('rand')")
|
||||||
@@ -64,6 +70,7 @@ class DefaultAudioRecommendationQueryRepository(
|
|||||||
.where(
|
.where(
|
||||||
audioContentBanner.isActive.isTrue,
|
audioContentBanner.isActive.isTrue,
|
||||||
audioContentBanner.tab.id.eq(2L),
|
audioContentBanner.tab.id.eq(2L),
|
||||||
|
audioContentBanner.lang.eq(lang),
|
||||||
adultBannerCondition(canViewAdultContent),
|
adultBannerCondition(canViewAdultContent),
|
||||||
activeBannerTargetCondition(memberId, bannerCreator, seriesOwner)
|
activeBannerTargetCondition(memberId, bannerCreator, seriesOwner)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.content.recommendation.application
|
package kr.co.vividnext.sodalive.v2.content.recommendation.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||||
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioCard
|
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioCard
|
||||||
@@ -24,6 +25,7 @@ class AudioRecommendationQueryService(
|
|||||||
val canViewAdultContent = canViewAdultContent(member)
|
val canViewAdultContent = canViewAdultContent(member)
|
||||||
val visibility = if (canViewAdultContent) AudioRecommendationVisibility.ALL else AudioRecommendationVisibility.SAFE
|
val visibility = if (canViewAdultContent) AudioRecommendationVisibility.ALL else AudioRecommendationVisibility.SAFE
|
||||||
val memberId = member?.id
|
val memberId = member?.id
|
||||||
|
val bannerLang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||||
val newAndHotSectionType = newAndHotSectionType(visibility)
|
val newAndHotSectionType = newAndHotSectionType(visibility)
|
||||||
val mostCommentedSectionType = mostCommentedSectionType(visibility)
|
val mostCommentedSectionType = mostCommentedSectionType(visibility)
|
||||||
val recommendedAudioSectionType = recommendedAudioSectionType(visibility)
|
val recommendedAudioSectionType = recommendedAudioSectionType(visibility)
|
||||||
@@ -44,7 +46,7 @@ class AudioRecommendationQueryService(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return AudioRecommendations(
|
return AudioRecommendations(
|
||||||
banners = queryPort.findBanners(BANNER_LIMIT, memberId, canViewAdultContent),
|
banners = queryPort.findBanners(BANNER_LIMIT, memberId, canViewAdultContent, bannerLang),
|
||||||
originalSeries = queryPort.findOriginalSeries(ORIGINAL_SERIES_LIMIT, memberId, canViewAdultContent, now),
|
originalSeries = queryPort.findOriginalSeries(ORIGINAL_SERIES_LIMIT, memberId, canViewAdultContent, now),
|
||||||
latestAudios = queryPort.findLatestAudios(LATEST_AUDIO_LIMIT, memberId, canViewAdultContent, now),
|
latestAudios = queryPort.findLatestAudios(LATEST_AUDIO_LIMIT, memberId, canViewAdultContent, now),
|
||||||
newAndHotAudios = queryPort.findAudioCardsByIds(
|
newAndHotAudios = queryPort.findAudioCardsByIds(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.content.recommendation.port.out
|
package kr.co.vividnext.sodalive.v2.content.recommendation.port.out
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.v2.common.domain.RecommendationBanner
|
import kr.co.vividnext.sodalive.v2.common.domain.RecommendationBanner
|
||||||
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioCard
|
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioCard
|
||||||
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioRecommendationVisibility
|
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioRecommendationVisibility
|
||||||
@@ -9,7 +10,12 @@ import kr.co.vividnext.sodalive.v2.recommendation.port.out.RecommendationSnapsho
|
|||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
interface AudioRecommendationQueryPort {
|
interface AudioRecommendationQueryPort {
|
||||||
fun findBanners(limit: Int, memberId: Long?, canViewAdultContent: Boolean): List<RecommendationBanner>
|
fun findBanners(
|
||||||
|
limit: Int,
|
||||||
|
memberId: Long?,
|
||||||
|
canViewAdultContent: Boolean,
|
||||||
|
lang: Lang = Lang.KO
|
||||||
|
): List<RecommendationBanner>
|
||||||
fun findOriginalSeries(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<OriginalSeries>
|
fun findOriginalSeries(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<OriginalSeries>
|
||||||
fun findLatestAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard>
|
fun findLatestAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard>
|
||||||
fun findFreeAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard>
|
fun findFreeAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import kr.co.vividnext.sodalive.event.QEvent.event
|
|||||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.QCreatorCommunity.creatorCommunity
|
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.QCreatorCommunity.creatorCommunity
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment
|
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.like.QCreatorCommunityLike.creatorCommunityLike
|
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.like.QCreatorCommunityLike.creatorCommunityLike
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
|
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
|
||||||
import kr.co.vividnext.sodalive.member.MemberKind
|
import kr.co.vividnext.sodalive.member.MemberKind
|
||||||
import kr.co.vividnext.sodalive.member.MemberRole
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
@@ -88,7 +89,8 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
override fun findHomeBanners(
|
override fun findHomeBanners(
|
||||||
limit: Int,
|
limit: Int,
|
||||||
memberId: Long?,
|
memberId: Long?,
|
||||||
includeAdultBanners: Boolean
|
includeAdultBanners: Boolean,
|
||||||
|
lang: Lang
|
||||||
): List<HomeBannerRecommendationRecord> {
|
): List<HomeBannerRecommendationRecord> {
|
||||||
val bannerCreator = QMember("bannerCreator")
|
val bannerCreator = QMember("bannerCreator")
|
||||||
val seriesOwner = QMember("seriesOwner")
|
val seriesOwner = QMember("seriesOwner")
|
||||||
@@ -116,6 +118,7 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
.where(
|
.where(
|
||||||
audioContentBanner.isActive.isTrue,
|
audioContentBanner.isActive.isTrue,
|
||||||
audioContentBanner.tab.isNull,
|
audioContentBanner.tab.isNull,
|
||||||
|
audioContentBanner.lang.eq(lang),
|
||||||
includeAdultBannerCondition(includeAdultBanners),
|
includeAdultBannerCondition(includeAdultBanners),
|
||||||
activeBannerTargetCondition(memberId, bannerCreator, seriesOwner)
|
activeBannerTargetCondition(memberId, bannerCreator, seriesOwner)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.recommendation.application
|
package kr.co.vividnext.sodalive.v2.recommendation.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
||||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendationSnapshotWindowPolicy
|
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendationSnapshotWindowPolicy
|
||||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
||||||
@@ -44,9 +45,10 @@ class HomeRecommendationQueryService(
|
|||||||
fun findHomeBanners(
|
fun findHomeBanners(
|
||||||
limit: Int = DEFAULT_BANNER_LIMIT,
|
limit: Int = DEFAULT_BANNER_LIMIT,
|
||||||
memberId: Long? = null,
|
memberId: Long? = null,
|
||||||
includeAdultBanners: Boolean = false
|
includeAdultBanners: Boolean = false,
|
||||||
|
lang: Lang = Lang.KO
|
||||||
): List<HomeBannerRecommendationRecord> {
|
): List<HomeBannerRecommendationRecord> {
|
||||||
return queryPort.findHomeBanners(limit, memberId, includeAdultBanners)
|
return queryPort.findHomeBanners(limit, memberId, includeAdultBanners, lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findRecentlyActiveCreators(
|
fun findRecentlyActiveCreators(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.recommendation.port.out
|
package kr.co.vividnext.sodalive.v2.recommendation.port.out
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@@ -14,7 +15,8 @@ interface HomeRecommendationQueryPort {
|
|||||||
fun findHomeBanners(
|
fun findHomeBanners(
|
||||||
limit: Int,
|
limit: Int,
|
||||||
memberId: Long? = null,
|
memberId: Long? = null,
|
||||||
includeAdultBanners: Boolean = false
|
includeAdultBanners: Boolean = false,
|
||||||
|
lang: Lang = Lang.KO
|
||||||
): List<HomeBannerRecommendationRecord>
|
): List<HomeBannerRecommendationRecord>
|
||||||
|
|
||||||
fun findRecentlyActiveCreators(
|
fun findRecentlyActiveCreators(
|
||||||
|
|||||||
@@ -207,6 +207,22 @@ class MemberContentPreferenceIntegrationTest @Autowired constructor(
|
|||||||
assertEquals("KR", service.resolveCountryCode(member))
|
assertEquals("KR", service.resolveCountryCode(member))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("비로그인 사용자의 국가 코드는 접속 국가 헤더를 정규화하고 없으면 KR로 계산된다")
|
||||||
|
fun shouldResolveCountryCodeForAnonymousUser() {
|
||||||
|
countryContext.setCountryCode("JP")
|
||||||
|
assertEquals("JP", service.resolveCountryCode(null))
|
||||||
|
|
||||||
|
countryContext.setCountryCode(" jp ")
|
||||||
|
assertEquals("JP", service.resolveCountryCode(null))
|
||||||
|
|
||||||
|
countryContext.setCountryCode(null)
|
||||||
|
assertEquals("KR", service.resolveCountryCode(null))
|
||||||
|
|
||||||
|
countryContext.setCountryCode(" ")
|
||||||
|
assertEquals("KR", service.resolveCountryCode(null))
|
||||||
|
}
|
||||||
|
|
||||||
private fun saveMember(seed: String): Member {
|
private fun saveMember(seed: String): Member {
|
||||||
return memberRepository.saveAndFlush(
|
return memberRepository.saveAndFlush(
|
||||||
Member(
|
Member(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.api.home.application
|
package kr.co.vividnext.sodalive.v2.api.home.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||||
import kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService
|
import kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService
|
||||||
@@ -56,6 +57,27 @@ class HomeRecommendationFacadeTest {
|
|||||||
assertTrue(queryPort.bannerIncludeAdultBanners)
|
assertTrue(queryPort.bannerIncludeAdultBanners)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("홈 추천은 JP 국가 판정이면 JA 배너 조회를 요청한다")
|
||||||
|
fun shouldPassJaToHomeBannerQueryForJapan() {
|
||||||
|
val member = Member(password = "password", nickname = "jp-member").apply { id = 11L }
|
||||||
|
Mockito.doReturn("JP").`when`(preferenceService).resolveCountryCode(member)
|
||||||
|
|
||||||
|
facade.getHomeRecommendations(member)
|
||||||
|
|
||||||
|
assertTrue(queryPort.bannerLang == Lang.JA)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("홈 추천은 JP 이외 국가 판정이면 KO 배너 조회를 요청한다")
|
||||||
|
fun shouldPassKoToHomeBannerQueryForNonJapan() {
|
||||||
|
Mockito.doReturn("KR").`when`(preferenceService).resolveCountryCode(null)
|
||||||
|
|
||||||
|
facade.getHomeRecommendations(null)
|
||||||
|
|
||||||
|
assertTrue(queryPort.bannerLang == Lang.KO)
|
||||||
|
}
|
||||||
|
|
||||||
private fun firstAudio(price: Int, isPointAvailable: Boolean): HomeFirstAudioContentRecord {
|
private fun firstAudio(price: Int, isPointAvailable: Boolean): HomeFirstAudioContentRecord {
|
||||||
return HomeFirstAudioContentRecord(
|
return HomeFirstAudioContentRecord(
|
||||||
contentId = price.toLong() + 1,
|
contentId = price.toLong() + 1,
|
||||||
@@ -74,6 +96,7 @@ class HomeRecommendationFacadeTest {
|
|||||||
private class FakeHomeRecommendationQueryPort : HomeRecommendationQueryPort {
|
private class FakeHomeRecommendationQueryPort : HomeRecommendationQueryPort {
|
||||||
var firstAudioContents: List<HomeFirstAudioContentRecord> = emptyList()
|
var firstAudioContents: List<HomeFirstAudioContentRecord> = emptyList()
|
||||||
var bannerIncludeAdultBanners: Boolean = false
|
var bannerIncludeAdultBanners: Boolean = false
|
||||||
|
var bannerLang: Lang? = null
|
||||||
|
|
||||||
override fun findLiveRecommendations(
|
override fun findLiveRecommendations(
|
||||||
offset: Long,
|
offset: Long,
|
||||||
@@ -85,9 +108,11 @@ class HomeRecommendationFacadeTest {
|
|||||||
override fun findHomeBanners(
|
override fun findHomeBanners(
|
||||||
limit: Int,
|
limit: Int,
|
||||||
memberId: Long?,
|
memberId: Long?,
|
||||||
includeAdultBanners: Boolean
|
includeAdultBanners: Boolean,
|
||||||
|
lang: Lang
|
||||||
): List<HomeBannerRecommendationRecord> {
|
): List<HomeBannerRecommendationRecord> {
|
||||||
bannerIncludeAdultBanners = includeAdultBanners
|
bannerIncludeAdultBanners = includeAdultBanners
|
||||||
|
bannerLang = lang
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTab
|
|||||||
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
|
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
|
||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
|
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
|
||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesContent
|
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesContent
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.MemberRole
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
import kr.co.vividnext.sodalive.member.block.BlockMember
|
import kr.co.vividnext.sodalive.member.block.BlockMember
|
||||||
@@ -96,6 +97,38 @@ class DefaultAudioRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
assertEquals(visibleCreator.id, safeBanners.first().creatorId)
|
assertEquals(visibleCreator.id, safeBanners.first().creatorId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("콘텐츠 추천 배너는 언어 필터를 limit보다 먼저 적용한다")
|
||||||
|
fun shouldFilterBannersByLangBeforeLimit() {
|
||||||
|
val recommendationTab = saveContentRecommendationTab()
|
||||||
|
val koBanner = saveBanner(
|
||||||
|
"ko-audio-banner.png",
|
||||||
|
AudioContentBannerType.LINK,
|
||||||
|
1,
|
||||||
|
link = "https://ko.test",
|
||||||
|
tab = recommendationTab,
|
||||||
|
lang = Lang.KO
|
||||||
|
)
|
||||||
|
val jaBanner = saveBanner(
|
||||||
|
"ja-audio-banner.png",
|
||||||
|
AudioContentBannerType.LINK,
|
||||||
|
2,
|
||||||
|
link = "https://ja.test",
|
||||||
|
tab = recommendationTab,
|
||||||
|
lang = Lang.JA
|
||||||
|
)
|
||||||
|
flushAndClear()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
listOf("https://cdn.test/${koBanner.thumbnailImage}"),
|
||||||
|
repository.findBanners(1, null, false, Lang.KO).map { it.imageUrl }
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf("https://cdn.test/${jaBanner.thumbnailImage}"),
|
||||||
|
repository.findBanners(1, null, false, Lang.JA).map { it.imageUrl }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("오리지널 시리즈는 활성 원본 시리즈를 최신순으로 반환하고 성인/차단 조건을 적용한다")
|
@DisplayName("오리지널 시리즈는 활성 원본 시리즈를 최신순으로 반환하고 성인/차단 조건을 적용한다")
|
||||||
fun shouldFindOriginalSeriesWithVisibilityConditions() {
|
fun shouldFindOriginalSeriesWithVisibilityConditions() {
|
||||||
@@ -404,11 +437,13 @@ class DefaultAudioRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
isAdult: Boolean = false,
|
isAdult: Boolean = false,
|
||||||
creator: Member? = null,
|
creator: Member? = null,
|
||||||
link: String? = null,
|
link: String? = null,
|
||||||
tab: AudioContentMainTab? = null
|
tab: AudioContentMainTab? = null,
|
||||||
|
lang: Lang = Lang.KO
|
||||||
): AudioContentBanner {
|
): AudioContentBanner {
|
||||||
val banner = AudioContentBanner(
|
val banner = AudioContentBanner(
|
||||||
thumbnailImage = thumbnailImage,
|
thumbnailImage = thumbnailImage,
|
||||||
type = type,
|
type = type,
|
||||||
|
lang = lang,
|
||||||
isAdult = isAdult,
|
isAdult = isAdult,
|
||||||
isActive = isActive,
|
isActive = isActive,
|
||||||
orders = orders
|
orders = orders
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.content.recommendation.application
|
package kr.co.vividnext.sodalive.v2.content.recommendation.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.MemberRole
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||||
@@ -77,7 +78,7 @@ class AudioRecommendationQueryServiceTest {
|
|||||||
0,
|
0,
|
||||||
AudioRecommendationQueryService.RECOMMENDED_AUDIO_LIMIT
|
AudioRecommendationQueryService.RECOMMENDED_AUDIO_LIMIT
|
||||||
)
|
)
|
||||||
Mockito.verify(queryPort).findBanners(AudioRecommendationQueryService.BANNER_LIMIT, null, false)
|
Mockito.verify(queryPort).findBanners(AudioRecommendationQueryService.BANNER_LIMIT, null, false, Lang.KO)
|
||||||
Mockito.verify(queryPort).findLatestAudios(
|
Mockito.verify(queryPort).findLatestAudios(
|
||||||
eqValue(AudioRecommendationQueryService.LATEST_AUDIO_LIMIT),
|
eqValue(AudioRecommendationQueryService.LATEST_AUDIO_LIMIT),
|
||||||
Mockito.isNull(),
|
Mockito.isNull(),
|
||||||
@@ -140,6 +141,7 @@ class AudioRecommendationQueryServiceTest {
|
|||||||
fun shouldUseStoredPreferenceForMemberAdultVisibility() {
|
fun shouldUseStoredPreferenceForMemberAdultVisibility() {
|
||||||
val member = member(id = 10L)
|
val member = member(id = 10L)
|
||||||
Mockito.doReturn(true).`when`(preferenceService).canViewAdultContent(member)
|
Mockito.doReturn(true).`when`(preferenceService).canViewAdultContent(member)
|
||||||
|
Mockito.doReturn("JP").`when`(preferenceService).resolveCountryCode(member)
|
||||||
stubFallback(
|
stubFallback(
|
||||||
RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL,
|
RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL,
|
||||||
0,
|
0,
|
||||||
@@ -150,6 +152,7 @@ class AudioRecommendationQueryServiceTest {
|
|||||||
service.getRecommendations(member)
|
service.getRecommendations(member)
|
||||||
|
|
||||||
Mockito.verify(preferenceService).canViewAdultContent(member)
|
Mockito.verify(preferenceService).canViewAdultContent(member)
|
||||||
|
Mockito.verify(queryPort).findBanners(AudioRecommendationQueryService.BANNER_LIMIT, member.id, true, Lang.JA)
|
||||||
Mockito.verify(preferenceService, Mockito.never()).initializeDefaultPreference(member)
|
Mockito.verify(preferenceService, Mockito.never()).initializeDefaultPreference(member)
|
||||||
verifyFallback(
|
verifyFallback(
|
||||||
RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL,
|
RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL,
|
||||||
|
|||||||
@@ -262,6 +262,23 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
assertEquals(listOf(homeBanner.thumbnailImage), banners.map { it.thumbnailImage })
|
assertEquals(listOf(homeBanner.thumbnailImage), banners.map { it.thumbnailImage })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("홈 배너는 언어 필터를 limit보다 먼저 적용한다")
|
||||||
|
fun shouldFilterHomeBannersByLangBeforeLimit() {
|
||||||
|
val koBanner = saveBanner("ko-home-banner.png", AudioContentBannerType.LINK, 1, true, lang = Lang.KO)
|
||||||
|
val jaBanner = saveBanner("ja-home-banner.png", AudioContentBannerType.LINK, 2, true, lang = Lang.JA)
|
||||||
|
flushAndClear()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
listOf(koBanner.thumbnailImage),
|
||||||
|
repository.findHomeBanners(limit = 1, lang = Lang.KO).map { it.thumbnailImage }
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(jaBanner.thumbnailImage),
|
||||||
|
repository.findHomeBanners(limit = 1, lang = Lang.JA).map { it.thumbnailImage }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("홈 배너는 성인 콘텐츠 조회가 불가능하면 비성인 배너만 반환한다")
|
@DisplayName("홈 배너는 성인 콘텐츠 조회가 불가능하면 비성인 배너만 반환한다")
|
||||||
fun shouldExcludeAdultHomeBannersWhenAdultContentIsNotVisible() {
|
fun shouldExcludeAdultHomeBannersWhenAdultContentIsNotVisible() {
|
||||||
@@ -2693,12 +2710,13 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
event: Event? = null,
|
event: Event? = null,
|
||||||
series: Series? = null,
|
series: Series? = null,
|
||||||
tab: AudioContentMainTab? = null,
|
tab: AudioContentMainTab? = null,
|
||||||
link: String? = null
|
link: String? = null,
|
||||||
|
lang: Lang = Lang.KO
|
||||||
): AudioContentBanner {
|
): AudioContentBanner {
|
||||||
val banner = AudioContentBanner(
|
val banner = AudioContentBanner(
|
||||||
thumbnailImage = thumbnailImage,
|
thumbnailImage = thumbnailImage,
|
||||||
type = type,
|
type = type,
|
||||||
lang = Lang.KO,
|
lang = lang,
|
||||||
isAdult = isAdult,
|
isAdult = isAdult,
|
||||||
isActive = isActive,
|
isActive = isActive,
|
||||||
orders = orders
|
orders = orders
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.recommendation.application
|
package kr.co.vividnext.sodalive.v2.recommendation.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.i18n.Lang
|
||||||
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
||||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
||||||
import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeAiCharacterRecommendationRecord
|
import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeAiCharacterRecommendationRecord
|
||||||
@@ -93,6 +94,16 @@ class HomeRecommendationQueryServiceTest {
|
|||||||
assertEquals(20, port.bannerLimit)
|
assertEquals(20, port.bannerLimit)
|
||||||
assertEquals(100L, port.bannerMemberId)
|
assertEquals(100L, port.bannerMemberId)
|
||||||
assertEquals(true, port.bannerIncludeAdultBanners)
|
assertEquals(true, port.bannerIncludeAdultBanners)
|
||||||
|
assertEquals(Lang.KO, port.bannerLang)
|
||||||
|
assertEquals(port.banners, banners)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("홈 배너 추천은 언어 조건을 조회 포트에 위임한다")
|
||||||
|
fun shouldDelegateHomeBannerLang() {
|
||||||
|
val banners = service.findHomeBanners(lang = Lang.JA)
|
||||||
|
|
||||||
|
assertEquals(Lang.JA, port.bannerLang)
|
||||||
assertEquals(port.banners, banners)
|
assertEquals(port.banners, banners)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,6 +977,7 @@ class HomeRecommendationQueryServiceTest {
|
|||||||
var bannerLimit: Int? = null
|
var bannerLimit: Int? = null
|
||||||
var bannerMemberId: Long? = null
|
var bannerMemberId: Long? = null
|
||||||
var bannerIncludeAdultBanners: Boolean? = null
|
var bannerIncludeAdultBanners: Boolean? = null
|
||||||
|
var bannerLang: Lang? = null
|
||||||
var activeCreatorLimit: Int? = null
|
var activeCreatorLimit: Int? = null
|
||||||
var activeCreatorMemberId: Long? = null
|
var activeCreatorMemberId: Long? = null
|
||||||
var activeCreatorIncludeAdultActivities: Boolean? = null
|
var activeCreatorIncludeAdultActivities: Boolean? = null
|
||||||
@@ -1068,11 +1080,13 @@ class HomeRecommendationQueryServiceTest {
|
|||||||
override fun findHomeBanners(
|
override fun findHomeBanners(
|
||||||
limit: Int,
|
limit: Int,
|
||||||
memberId: Long?,
|
memberId: Long?,
|
||||||
includeAdultBanners: Boolean
|
includeAdultBanners: Boolean,
|
||||||
|
lang: Lang
|
||||||
): List<HomeBannerRecommendationRecord> {
|
): List<HomeBannerRecommendationRecord> {
|
||||||
bannerLimit = limit
|
bannerLimit = limit
|
||||||
bannerMemberId = memberId
|
bannerMemberId = memberId
|
||||||
bannerIncludeAdultBanners = includeAdultBanners
|
bannerIncludeAdultBanners = includeAdultBanners
|
||||||
|
bannerLang = lang
|
||||||
return banners
|
return banners
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user