feat(creator-channel): 시리즈 탭 조회 서비스를 추가한다
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
package kr.co.vividnext.sodalive.v2.creator.channel.series.application
|
||||
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesState
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.isAdultVisibleByPolicy
|
||||
import kr.co.vividnext.sodalive.v2.common.domain.toCdnUrl
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.domain.CreatorChannelSeries
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.domain.CreatorChannelSeriesQueryPolicy
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.domain.CreatorChannelSeriesTab
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.port.out.CreatorChannelSeriesCreatorRecord
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.port.out.CreatorChannelSeriesQueryPort
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.port.out.CreatorChannelSeriesRecord
|
||||
import org.springframework.beans.factory.ObjectProvider
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
class CreatorChannelSeriesQueryService(
|
||||
private val queryPortProvider: ObjectProvider<CreatorChannelSeriesQueryPort>,
|
||||
private val queryPolicy: CreatorChannelSeriesQueryPolicy,
|
||||
private val memberContentPreferenceService: MemberContentPreferenceService,
|
||||
private val messageSource: SodaMessageSource,
|
||||
private val langContext: LangContext,
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val cloudFrontHost: String
|
||||
) {
|
||||
fun getSeriesTab(
|
||||
creatorId: Long,
|
||||
viewer: Member,
|
||||
sort: String?,
|
||||
page: Int?,
|
||||
size: Int?,
|
||||
now: LocalDateTime = LocalDateTime.now()
|
||||
): CreatorChannelSeriesTab {
|
||||
val resolvedSort = queryPolicy.resolveSort(sort)
|
||||
val seriesPage = queryPolicy.createPage(page, size)
|
||||
val queryPort = queryPortProvider.getObject()
|
||||
val viewerId = viewer.id!!
|
||||
val creator = queryPort.findCreator(creatorId, viewerId)
|
||||
?: throw SodaException(messageKey = "member.validation.user_not_found")
|
||||
|
||||
if (queryPort.existsBlockedBetween(viewerId, creatorId)) {
|
||||
val messageTemplate = messageSource
|
||||
.getMessage("explorer.creator.blocked_access", langContext.lang)
|
||||
.orEmpty()
|
||||
throw SodaException(message = String.format(messageTemplate, creator.nickname))
|
||||
}
|
||||
|
||||
validateCreatorRole(creator)
|
||||
|
||||
val preference = memberContentPreferenceService.getStoredPreference(viewer)
|
||||
val canViewAdultContent = isAdultVisibleByPolicy(viewer, preference.isAdultContentVisible)
|
||||
val locale = langContext.lang.code
|
||||
val fetchedSeries = queryPort.findSeries(
|
||||
creatorId = creatorId,
|
||||
viewerId = viewerId,
|
||||
now = now,
|
||||
canViewAdultContent = canViewAdultContent,
|
||||
sort = resolvedSort,
|
||||
locale = locale,
|
||||
offset = seriesPage.offset,
|
||||
limit = seriesPage.fetchLimit
|
||||
)
|
||||
|
||||
return CreatorChannelSeriesTab(
|
||||
seriesCount = queryPort.countSeries(
|
||||
creatorId = creatorId,
|
||||
now = now,
|
||||
canViewAdultContent = canViewAdultContent
|
||||
),
|
||||
series = queryPolicy.limitItems(fetchedSeries, seriesPage).map { it.toDomain(creatorId, viewerId, locale) },
|
||||
sort = resolvedSort,
|
||||
page = seriesPage,
|
||||
hasNext = queryPolicy.hasNext(fetchedSeries, seriesPage)
|
||||
)
|
||||
}
|
||||
|
||||
private fun validateCreatorRole(creator: CreatorChannelSeriesCreatorRecord) {
|
||||
when (creator.role) {
|
||||
MemberRole.CREATOR -> return
|
||||
else -> throw SodaException(messageKey = "member.validation.creator_not_found")
|
||||
}
|
||||
}
|
||||
|
||||
private fun CreatorChannelSeriesRecord.toDomain(creatorId: Long, viewerId: Long, locale: String): CreatorChannelSeries {
|
||||
val isCreatorSelf = viewerId == creatorId
|
||||
val domainPurchasedContentCount = if (isCreatorSelf) null else purchasedContentCount
|
||||
val domainPaidContentCount = if (isCreatorSelf) null else paidContentCount
|
||||
return CreatorChannelSeries(
|
||||
seriesId = seriesId,
|
||||
title = title,
|
||||
coverImageUrl = coverImagePath.toCdnUrl(cloudFrontHost),
|
||||
publishedDaysOfWeek = queryPolicy.publishedDaysOfWeekText(publishedDaysOfWeek, locale),
|
||||
isOriginal = isOriginal,
|
||||
isAdult = isAdult,
|
||||
isProceeding = state == SeriesState.PROCEEDING,
|
||||
contentCount = contentCount,
|
||||
purchasedContentCount = domainPurchasedContentCount,
|
||||
paidContentCount = domainPaidContentCount,
|
||||
purchasedPaidContentRate = if (isCreatorSelf) {
|
||||
null
|
||||
} else {
|
||||
queryPolicy.purchaseRate(domainPaidContentCount ?: 0, domainPurchasedContentCount ?: 0)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user