후원랭킹 기간 선택 반영
프로필 업데이트에 후원랭킹 기간 선택을 추가하고 프로필 후원랭킹 조회가 선택한 기간을 사용한다
This commit is contained in:
@@ -24,6 +24,7 @@ import kr.co.vividnext.sodalive.i18n.Lang
|
|||||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||||
import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailUser
|
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.Member
|
||||||
import kr.co.vividnext.sodalive.member.MemberRole
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
import kr.co.vividnext.sodalive.member.MemberService
|
import kr.co.vividnext.sodalive.member.MemberService
|
||||||
@@ -215,6 +216,7 @@ class ExplorerService(
|
|||||||
val notificationUserIds = queryRepository.getNotificationUserIds(creatorId)
|
val notificationUserIds = queryRepository.getNotificationUserIds(creatorId)
|
||||||
val creatorFollowing = queryRepository.getCreatorFollowing(creatorId = creatorId, memberId = member.id!!)
|
val creatorFollowing = queryRepository.getCreatorFollowing(creatorId = creatorId, memberId = member.id!!)
|
||||||
val notificationRecipientCount = notificationUserIds.size
|
val notificationRecipientCount = notificationUserIds.size
|
||||||
|
val donationRankingPeriod = creatorAccount.donationRankingPeriod ?: DonationRankingPeriod.CUMULATIVE
|
||||||
|
|
||||||
// 후원랭킹
|
// 후원랭킹
|
||||||
val memberDonationRanking = if (
|
val memberDonationRanking = if (
|
||||||
@@ -223,7 +225,8 @@ class ExplorerService(
|
|||||||
donationRankingService.getMemberDonationRanking(
|
donationRankingService.getMemberDonationRanking(
|
||||||
creatorId = creatorId,
|
creatorId = creatorId,
|
||||||
limit = 10,
|
limit = 10,
|
||||||
withDonationCan = creatorId == member.id!!
|
withDonationCan = creatorId == member.id!!,
|
||||||
|
period = donationRankingPeriod
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
listOf()
|
listOf()
|
||||||
@@ -399,16 +402,23 @@ class ExplorerService(
|
|||||||
pageable: Pageable,
|
pageable: Pageable,
|
||||||
member: Member
|
member: Member
|
||||||
): GetDonationAllResponse {
|
): 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 currentDate = LocalDate.now().atTime(0, 0, 0)
|
||||||
val firstDayOfLastWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7)
|
val firstDayOfLastWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7)
|
||||||
val firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth())
|
val firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth())
|
||||||
|
|
||||||
val donationMemberTotal = donationRankingService.getMemberDonationRankingTotal(creatorId)
|
val donationMemberTotal = donationRankingService.getMemberDonationRankingTotal(
|
||||||
|
creatorId,
|
||||||
|
donationRankingPeriod
|
||||||
|
)
|
||||||
val donationRanking = donationRankingService.getMemberDonationRanking(
|
val donationRanking = donationRankingService.getMemberDonationRanking(
|
||||||
creatorId = creatorId,
|
creatorId = creatorId,
|
||||||
offset = pageable.offset,
|
offset = pageable.offset,
|
||||||
limit = pageable.pageSize.toLong(),
|
limit = pageable.pageSize.toLong(),
|
||||||
withDonationCan = creatorId == member.id!!
|
withDonationCan = creatorId == member.id!!,
|
||||||
|
period = donationRankingPeriod
|
||||||
)
|
)
|
||||||
|
|
||||||
return GetDonationAllResponse(
|
return GetDonationAllResponse(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package kr.co.vividnext.sodalive.explorer.profile
|
package kr.co.vividnext.sodalive.explorer.profile
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.querydsl.core.BooleanBuilder
|
||||||
import com.querydsl.core.annotations.QueryProjection
|
import com.querydsl.core.annotations.QueryProjection
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
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.can.use.QUseCanCalculate.useCanCalculate
|
||||||
import kr.co.vividnext.sodalive.member.QMember.member
|
import kr.co.vividnext.sodalive.member.QMember.member
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFactory) {
|
class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||||
fun getMemberDonationRanking(
|
fun getMemberDonationRanking(
|
||||||
creatorId: Long,
|
creatorId: Long,
|
||||||
offset: Long,
|
offset: Long,
|
||||||
limit: Long
|
limit: Long,
|
||||||
|
startDate: LocalDateTime? = null,
|
||||||
|
endDate: LocalDateTime? = null
|
||||||
): List<DonationRankingProjection> {
|
): List<DonationRankingProjection> {
|
||||||
val donationCan = useCan.rewardCan.add(useCan.can).sum()
|
val donationCan = useCan.rewardCan.add(useCan.can).sum()
|
||||||
return queryFactory
|
return queryFactory
|
||||||
@@ -38,6 +43,7 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
|||||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||||
)
|
)
|
||||||
|
.and(buildDateRangeCondition(startDate, endDate))
|
||||||
)
|
)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
@@ -46,7 +52,11 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
|||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
fun getMemberDonationRankingTotal(
|
||||||
|
creatorId: Long,
|
||||||
|
startDate: LocalDateTime? = null,
|
||||||
|
endDate: LocalDateTime? = null
|
||||||
|
): Int {
|
||||||
return queryFactory
|
return queryFactory
|
||||||
.select(member.id)
|
.select(member.id)
|
||||||
.from(useCanCalculate)
|
.from(useCanCalculate)
|
||||||
@@ -61,11 +71,32 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
|||||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||||
)
|
)
|
||||||
|
.and(buildDateRangeCondition(startDate, endDate))
|
||||||
)
|
)
|
||||||
.groupBy(member.id)
|
.groupBy(member.id)
|
||||||
.fetch()
|
.fetch()
|
||||||
.size
|
.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(
|
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.MemberDonationRankingListResponse
|
||||||
import kr.co.vividnext.sodalive.explorer.MemberDonationRankingResponse
|
import kr.co.vividnext.sodalive.explorer.MemberDonationRankingResponse
|
||||||
|
import kr.co.vividnext.sodalive.member.DonationRankingPeriod
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.data.redis.core.RedisTemplate
|
import org.springframework.data.redis.core.RedisTemplate
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
@@ -20,14 +22,22 @@ class CreatorDonationRankingService(
|
|||||||
@Value("\${cloud.aws.cloud-front.host}")
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
private val imageHost: String
|
private val imageHost: String
|
||||||
) {
|
) {
|
||||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
fun getMemberDonationRankingTotal(
|
||||||
val cacheKey = "creator_donation_ranking_member_total_v2:$creatorId"
|
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
|
val cachedTotal = redisTemplate.opsForValue().get(cacheKey) as? Int
|
||||||
if (cachedTotal != null) {
|
if (cachedTotal != null) {
|
||||||
return cachedTotal
|
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 now = LocalDateTime.now()
|
||||||
val nextMonday = now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).with(LocalTime.MIN)
|
val nextMonday = now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).with(LocalTime.MIN)
|
||||||
@@ -46,15 +56,27 @@ class CreatorDonationRankingService(
|
|||||||
creatorId: Long,
|
creatorId: Long,
|
||||||
offset: Long = 0,
|
offset: Long = 0,
|
||||||
limit: Long = 10,
|
limit: Long = 10,
|
||||||
withDonationCan: Boolean
|
withDonationCan: Boolean,
|
||||||
|
period: DonationRankingPeriod = DonationRankingPeriod.CUMULATIVE
|
||||||
): List<MemberDonationRankingResponse> {
|
): 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
|
val cachedData = redisTemplate.opsForValue().get(cacheKey) as? MemberDonationRankingListResponse
|
||||||
if (cachedData != null) {
|
if (cachedData != null) {
|
||||||
return cachedData.rankings
|
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 {
|
val result = memberDonationRanking.map {
|
||||||
MemberDonationRankingResponse(
|
MemberDonationRankingResponse(
|
||||||
@@ -77,4 +99,17 @@ class CreatorDonationRankingService(
|
|||||||
|
|
||||||
return result
|
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,
|
var isVisibleDonationRank: Boolean = true,
|
||||||
|
|
||||||
|
@Enumerated(value = EnumType.STRING)
|
||||||
|
var donationRankingPeriod: DonationRankingPeriod? = DonationRankingPeriod.CUMULATIVE,
|
||||||
|
|
||||||
var isActive: Boolean = true,
|
var isActive: Boolean = true,
|
||||||
|
|
||||||
var container: String = "web",
|
var container: String = "web",
|
||||||
@@ -178,3 +181,7 @@ enum class MemberRole {
|
|||||||
enum class MemberProvider {
|
enum class MemberProvider {
|
||||||
EMAIL, KAKAO, GOOGLE, APPLE, LINE
|
EMAIL, KAKAO, GOOGLE, APPLE, LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class DonationRankingPeriod {
|
||||||
|
WEEKLY, CUMULATIVE
|
||||||
|
}
|
||||||
|
|||||||
@@ -726,6 +726,10 @@ class MemberService(
|
|||||||
member.isVisibleDonationRank = profileUpdateRequest.isVisibleDonationRank
|
member.isVisibleDonationRank = profileUpdateRequest.isVisibleDonationRank
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (profileUpdateRequest.donationRankingPeriod != null) {
|
||||||
|
member.donationRankingPeriod = profileUpdateRequest.donationRankingPeriod
|
||||||
|
}
|
||||||
|
|
||||||
return ProfileResponse(member, cloudFrontHost, profileUpdateRequest.container)
|
return ProfileResponse(member, cloudFrontHost, profileUpdateRequest.container)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ data class ProfileUpdateRequest(
|
|||||||
val websiteUrl: String? = null,
|
val websiteUrl: String? = null,
|
||||||
val blogUrl: String? = null,
|
val blogUrl: String? = null,
|
||||||
val isVisibleDonationRank: Boolean? = null,
|
val isVisibleDonationRank: Boolean? = null,
|
||||||
|
val donationRankingPeriod: DonationRankingPeriod? = null,
|
||||||
val container: String
|
val container: String
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user