test #384
@@ -24,6 +24,7 @@ import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailUser
|
||||
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.member.MemberService
|
||||
@@ -215,6 +216,7 @@ class ExplorerService(
|
||||
val notificationUserIds = queryRepository.getNotificationUserIds(creatorId)
|
||||
val creatorFollowing = queryRepository.getCreatorFollowing(creatorId = creatorId, memberId = member.id!!)
|
||||
val notificationRecipientCount = notificationUserIds.size
|
||||
val donationRankingPeriod = creatorAccount.donationRankingPeriod ?: DonationRankingPeriod.CUMULATIVE
|
||||
|
||||
// 후원랭킹
|
||||
val memberDonationRanking = if (
|
||||
@@ -223,7 +225,8 @@ class ExplorerService(
|
||||
donationRankingService.getMemberDonationRanking(
|
||||
creatorId = creatorId,
|
||||
limit = 10,
|
||||
withDonationCan = creatorId == member.id!!
|
||||
withDonationCan = creatorId == member.id!!,
|
||||
period = donationRankingPeriod
|
||||
)
|
||||
} else {
|
||||
listOf()
|
||||
@@ -399,16 +402,23 @@ class ExplorerService(
|
||||
pageable: Pageable,
|
||||
member: Member
|
||||
): GetDonationAllResponse {
|
||||
val creatorAccount = queryRepository.getMember(creatorId)
|
||||
?: throw SodaException(messageKey = "member.validation.user_not_found")
|
||||
val donationRankingPeriod = creatorAccount.donationRankingPeriod ?: DonationRankingPeriod.CUMULATIVE
|
||||
val currentDate = LocalDate.now().atTime(0, 0, 0)
|
||||
val firstDayOfLastWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7)
|
||||
val firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth())
|
||||
|
||||
val donationMemberTotal = donationRankingService.getMemberDonationRankingTotal(creatorId)
|
||||
val donationMemberTotal = donationRankingService.getMemberDonationRankingTotal(
|
||||
creatorId,
|
||||
donationRankingPeriod
|
||||
)
|
||||
val donationRanking = donationRankingService.getMemberDonationRanking(
|
||||
creatorId = creatorId,
|
||||
offset = pageable.offset,
|
||||
limit = pageable.pageSize.toLong(),
|
||||
withDonationCan = creatorId == member.id!!
|
||||
withDonationCan = creatorId == member.id!!,
|
||||
period = donationRankingPeriod
|
||||
)
|
||||
|
||||
return GetDonationAllResponse(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package kr.co.vividnext.sodalive.explorer.profile
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.querydsl.core.BooleanBuilder
|
||||
import com.querydsl.core.annotations.QueryProjection
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
@@ -8,13 +9,17 @@ import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
|
||||
import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
|
||||
@Repository
|
||||
class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||
fun getMemberDonationRanking(
|
||||
creatorId: Long,
|
||||
offset: Long,
|
||||
limit: Long
|
||||
limit: Long,
|
||||
startDate: LocalDateTime? = null,
|
||||
endDate: LocalDateTime? = null
|
||||
): List<DonationRankingProjection> {
|
||||
val donationCan = useCan.rewardCan.add(useCan.can).sum()
|
||||
return queryFactory
|
||||
@@ -38,6 +43,7 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||
)
|
||||
.and(buildDateRangeCondition(startDate, endDate))
|
||||
)
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
@@ -46,7 +52,11 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
||||
.fetch()
|
||||
}
|
||||
|
||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
||||
fun getMemberDonationRankingTotal(
|
||||
creatorId: Long,
|
||||
startDate: LocalDateTime? = null,
|
||||
endDate: LocalDateTime? = null
|
||||
): Int {
|
||||
return queryFactory
|
||||
.select(member.id)
|
||||
.from(useCanCalculate)
|
||||
@@ -61,11 +71,32 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||
)
|
||||
.and(buildDateRangeCondition(startDate, endDate))
|
||||
)
|
||||
.groupBy(member.id)
|
||||
.fetch()
|
||||
.size
|
||||
}
|
||||
|
||||
private fun buildDateRangeCondition(
|
||||
startDate: LocalDateTime?,
|
||||
endDate: LocalDateTime?
|
||||
): BooleanBuilder {
|
||||
val condition = BooleanBuilder()
|
||||
if (startDate != null && endDate != null) {
|
||||
val startUtc = startDate
|
||||
.atZone(ZoneId.of("Asia/Seoul"))
|
||||
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||
.toLocalDateTime()
|
||||
val endUtc = endDate
|
||||
.atZone(ZoneId.of("Asia/Seoul"))
|
||||
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||
.toLocalDateTime()
|
||||
condition.and(useCanCalculate.createdAt.goe(startUtc))
|
||||
condition.and(useCanCalculate.createdAt.lt(endUtc))
|
||||
}
|
||||
return condition
|
||||
}
|
||||
}
|
||||
|
||||
data class DonationRankingProjection @QueryProjection constructor(
|
||||
|
||||
@@ -2,11 +2,13 @@ package kr.co.vividnext.sodalive.explorer.profile
|
||||
|
||||
import kr.co.vividnext.sodalive.explorer.MemberDonationRankingListResponse
|
||||
import kr.co.vividnext.sodalive.explorer.MemberDonationRankingResponse
|
||||
import kr.co.vividnext.sodalive.member.DonationRankingPeriod
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.data.redis.core.RedisTemplate
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Duration
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.temporal.ChronoUnit
|
||||
@@ -20,14 +22,22 @@ class CreatorDonationRankingService(
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val imageHost: String
|
||||
) {
|
||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
||||
val cacheKey = "creator_donation_ranking_member_total_v2:$creatorId"
|
||||
fun getMemberDonationRankingTotal(
|
||||
creatorId: Long,
|
||||
period: DonationRankingPeriod = DonationRankingPeriod.CUMULATIVE
|
||||
): Int {
|
||||
val cacheKey = "creator_donation_ranking_member_total_v2:$creatorId:$period"
|
||||
val cachedTotal = redisTemplate.opsForValue().get(cacheKey) as? Int
|
||||
if (cachedTotal != null) {
|
||||
return cachedTotal
|
||||
}
|
||||
|
||||
val total = repository.getMemberDonationRankingTotal(creatorId)
|
||||
val weeklyDateRange = getWeeklyDateRange(period)
|
||||
val total = if (weeklyDateRange == null) {
|
||||
repository.getMemberDonationRankingTotal(creatorId)
|
||||
} else {
|
||||
repository.getMemberDonationRankingTotal(creatorId, weeklyDateRange.first, weeklyDateRange.second)
|
||||
}
|
||||
|
||||
val now = LocalDateTime.now()
|
||||
val nextMonday = now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).with(LocalTime.MIN)
|
||||
@@ -46,15 +56,27 @@ class CreatorDonationRankingService(
|
||||
creatorId: Long,
|
||||
offset: Long = 0,
|
||||
limit: Long = 10,
|
||||
withDonationCan: Boolean
|
||||
withDonationCan: Boolean,
|
||||
period: DonationRankingPeriod = DonationRankingPeriod.CUMULATIVE
|
||||
): List<MemberDonationRankingResponse> {
|
||||
val cacheKey = "creator_donation_ranking_v2:$creatorId:$offset:$limit:$withDonationCan"
|
||||
val cacheKey = "creator_donation_ranking_v2:$creatorId:$period:$offset:$limit:$withDonationCan"
|
||||
val cachedData = redisTemplate.opsForValue().get(cacheKey) as? MemberDonationRankingListResponse
|
||||
if (cachedData != null) {
|
||||
return cachedData.rankings
|
||||
}
|
||||
|
||||
val memberDonationRanking = repository.getMemberDonationRanking(creatorId, offset, limit)
|
||||
val weeklyDateRange = getWeeklyDateRange(period)
|
||||
val memberDonationRanking = if (weeklyDateRange == null) {
|
||||
repository.getMemberDonationRanking(creatorId, offset, limit)
|
||||
} else {
|
||||
repository.getMemberDonationRanking(
|
||||
creatorId,
|
||||
offset,
|
||||
limit,
|
||||
weeklyDateRange.first,
|
||||
weeklyDateRange.second
|
||||
)
|
||||
}
|
||||
|
||||
val result = memberDonationRanking.map {
|
||||
MemberDonationRankingResponse(
|
||||
@@ -77,4 +99,17 @@ class CreatorDonationRankingService(
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getWeeklyDateRange(period: DonationRankingPeriod): Pair<LocalDateTime, LocalDateTime>? {
|
||||
if (period != DonationRankingPeriod.WEEKLY) {
|
||||
return null
|
||||
}
|
||||
|
||||
val currentDate = LocalDate.now()
|
||||
val lastWeekMonday = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusWeeks(1)
|
||||
val startDate = lastWeekMonday.atStartOfDay()
|
||||
val endDate = startDate.plusDays(7)
|
||||
|
||||
return startDate to endDate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ data class Member(
|
||||
|
||||
var isVisibleDonationRank: Boolean = true,
|
||||
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
var donationRankingPeriod: DonationRankingPeriod? = DonationRankingPeriod.CUMULATIVE,
|
||||
|
||||
var isActive: Boolean = true,
|
||||
|
||||
var container: String = "web",
|
||||
@@ -178,3 +181,7 @@ enum class MemberRole {
|
||||
enum class MemberProvider {
|
||||
EMAIL, KAKAO, GOOGLE, APPLE, LINE
|
||||
}
|
||||
|
||||
enum class DonationRankingPeriod {
|
||||
WEEKLY, CUMULATIVE
|
||||
}
|
||||
|
||||
@@ -726,6 +726,10 @@ class MemberService(
|
||||
member.isVisibleDonationRank = profileUpdateRequest.isVisibleDonationRank
|
||||
}
|
||||
|
||||
if (profileUpdateRequest.donationRankingPeriod != null) {
|
||||
member.donationRankingPeriod = profileUpdateRequest.donationRankingPeriod
|
||||
}
|
||||
|
||||
return ProfileResponse(member, cloudFrontHost, profileUpdateRequest.container)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,5 +14,6 @@ data class ProfileUpdateRequest(
|
||||
val websiteUrl: String? = null,
|
||||
val blogUrl: String? = null,
|
||||
val isVisibleDonationRank: Boolean? = null,
|
||||
val donationRankingPeriod: DonationRankingPeriod? = null,
|
||||
val container: String
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user