feat(creator-channel): 후원 탭 조회 서비스를 구현한다
This commit is contained in:
@@ -4,7 +4,6 @@ import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.v2.api.creator.channel.donation.application.CreatorChannelDonationFacade
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
@@ -13,7 +12,6 @@ import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@ConditionalOnProperty(name = ["creator-channel.donation-tab.enabled"], havingValue = "true")
|
||||
@RequestMapping("/api/v2/creator-channels")
|
||||
class CreatorChannelDonationController(
|
||||
private val creatorChannelDonationFacade: CreatorChannelDonationFacade
|
||||
|
||||
@@ -1,13 +1,39 @@
|
||||
package kr.co.vividnext.sodalive.v2.creator.channel.donation.application
|
||||
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.extensions.removeDeletedNicknamePrefix
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.member.DonationRankingPeriod
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.v2.common.domain.toCdnUrl
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.domain.CreatorChannelDonation
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.domain.CreatorChannelDonationQueryPolicy
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.domain.CreatorChannelDonationRanking
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.domain.CreatorChannelDonationTab
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationCreatorRecord
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationQueryPort
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationRankingPort
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationRankingRecord
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationRecord
|
||||
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
|
||||
class CreatorChannelDonationQueryService {
|
||||
@Transactional(readOnly = true)
|
||||
class CreatorChannelDonationQueryService(
|
||||
private val queryPortProvider: ObjectProvider<CreatorChannelDonationQueryPort>,
|
||||
private val rankingPort: CreatorChannelDonationRankingPort,
|
||||
private val queryPolicy: CreatorChannelDonationQueryPolicy,
|
||||
private val messageSource: SodaMessageSource,
|
||||
private val langContext: LangContext,
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val cloudFrontHost: String
|
||||
) {
|
||||
fun getDonationTab(
|
||||
creatorId: Long,
|
||||
viewer: Member,
|
||||
@@ -15,6 +41,73 @@ class CreatorChannelDonationQueryService {
|
||||
size: Int?,
|
||||
now: LocalDateTime
|
||||
): CreatorChannelDonationTab {
|
||||
throw SodaException(messageKey = "common.error.invalid_request")
|
||||
val donationPage = 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 fetchedDonations = queryPort.findChannelDonations(
|
||||
creatorId = creatorId,
|
||||
viewerId = viewerId,
|
||||
now = now,
|
||||
offset = donationPage.offset,
|
||||
limit = donationPage.fetchLimit
|
||||
)
|
||||
|
||||
return CreatorChannelDonationTab(
|
||||
donationCount = queryPort.countChannelDonations(creatorId, viewerId, now),
|
||||
rankings = findRankings(creator, viewerId),
|
||||
donations = queryPolicy.limitItems(fetchedDonations, donationPage).map { it.toDomain() },
|
||||
page = donationPage,
|
||||
hasNext = queryPolicy.hasNext(fetchedDonations, donationPage)
|
||||
)
|
||||
}
|
||||
|
||||
private fun validateCreatorRole(creator: CreatorChannelDonationCreatorRecord) {
|
||||
when (creator.role) {
|
||||
MemberRole.CREATOR -> return
|
||||
else -> throw SodaException(messageKey = "member.validation.creator_not_found")
|
||||
}
|
||||
}
|
||||
|
||||
private fun findRankings(
|
||||
creator: CreatorChannelDonationCreatorRecord,
|
||||
viewerId: Long
|
||||
): List<CreatorChannelDonationRanking> {
|
||||
val isViewerCreator = viewerId == creator.creatorId
|
||||
if (!isViewerCreator && !creator.isVisibleDonationRank) return emptyList()
|
||||
|
||||
return rankingPort.findTopRankings(
|
||||
creatorId = creator.creatorId,
|
||||
period = creator.donationRankingPeriod ?: DonationRankingPeriod.CUMULATIVE,
|
||||
withDonationCan = isViewerCreator
|
||||
).map { it.toDomain() }
|
||||
}
|
||||
|
||||
private fun CreatorChannelDonationRecord.toDomain() = CreatorChannelDonation(
|
||||
nickname = nickname.removeDeletedNicknamePrefix(),
|
||||
profileImageUrl = profileImagePath.toCdnUrl(cloudFrontHost) ?: defaultProfileImageUrl(),
|
||||
can = can,
|
||||
message = message.orEmpty(),
|
||||
createdAt = createdAt
|
||||
)
|
||||
|
||||
private fun CreatorChannelDonationRankingRecord.toDomain() = CreatorChannelDonationRanking(
|
||||
userId = userId,
|
||||
nickname = nickname,
|
||||
profileImage = profileImage,
|
||||
donationCan = donationCan
|
||||
)
|
||||
|
||||
private fun defaultProfileImageUrl(): String = "$cloudFrontHost/profile/default-profile.png"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user