후원랭킹 전체보기 API 추가
This commit is contained in:
parent
1629bc8bf7
commit
f25888c88e
|
@ -307,7 +307,7 @@ class AudioContentService(
|
||||||
|
|
||||||
// 크리에이터(유저) 정보
|
// 크리에이터(유저) 정보
|
||||||
val creatorId = audioContent.member!!.id!!
|
val creatorId = audioContent.member!!.id!!
|
||||||
val creator = explorerQueryRepository.getAccount(creatorId)
|
val creator = explorerQueryRepository.getMember(creatorId)
|
||||||
?: throw SodaException("없는 사용자 입니다.")
|
?: throw SodaException("없는 사용자 입니다.")
|
||||||
|
|
||||||
val notificationUserIds = explorerQueryRepository.getNotificationUserIds(creatorId)
|
val notificationUserIds = explorerQueryRepository.getNotificationUserIds(creatorId)
|
||||||
|
|
|
@ -49,6 +49,16 @@ class ExplorerController(private val service: ExplorerService) {
|
||||||
ApiResponse.ok(service.getCreatorProfile(creatorId, timezone, member))
|
ApiResponse.ok(service.getCreatorProfile(creatorId, timezone, member))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/profile/{id}/donation-rank")
|
||||||
|
fun getCreatorProfileDonationRanking(
|
||||||
|
@PathVariable("id") creatorId: Long,
|
||||||
|
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
|
||||||
|
pageable: Pageable
|
||||||
|
) = run {
|
||||||
|
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||||
|
ApiResponse.ok(service.getCreatorProfileDonationRanking(creatorId, pageable, member))
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/profile/cheers")
|
@PostMapping("/profile/cheers")
|
||||||
fun writeCheers(
|
fun writeCheers(
|
||||||
@RequestBody request: PostWriteCheersRequest,
|
@RequestBody request: PostWriteCheersRequest,
|
||||||
|
|
|
@ -6,6 +6,8 @@ import com.querydsl.core.types.dsl.Expressions
|
||||||
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
|
||||||
import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
|
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.UseCanCalculateStatus
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
|
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
|
||||||
import kr.co.vividnext.sodalive.explorer.follower.GetFollowerListDto
|
import kr.co.vividnext.sodalive.explorer.follower.GetFollowerListDto
|
||||||
|
@ -55,6 +57,59 @@ class ExplorerQueryRepository(
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getDonationCoinsDateRange(creatorId: Long, startDate: LocalDateTime, endDate: LocalDateTime): Int? {
|
||||||
|
val donationCoin = useCanCalculate.can.sum()
|
||||||
|
|
||||||
|
return queryFactory
|
||||||
|
.select(donationCoin)
|
||||||
|
.from(useCanCalculate)
|
||||||
|
.innerJoin(useCanCalculate.useCan, useCan)
|
||||||
|
.where(
|
||||||
|
useCanCalculate.status.eq(UseCanCalculateStatus.RECEIVED)
|
||||||
|
.and(useCan.isRefund.isFalse)
|
||||||
|
.and(useCanCalculate.recipientCreatorId.eq(creatorId))
|
||||||
|
.and(
|
||||||
|
useCanCalculate.createdAt.goe(
|
||||||
|
startDate
|
||||||
|
.atZone(ZoneId.of("Asia/Seoul"))
|
||||||
|
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||||
|
.toLocalDateTime()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.and(
|
||||||
|
useCanCalculate.createdAt.lt(
|
||||||
|
endDate
|
||||||
|
.atZone(ZoneId.of("Asia/Seoul"))
|
||||||
|
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||||
|
.toLocalDateTime()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.fetchOne()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
||||||
|
val creatorMember = QMember("creator")
|
||||||
|
val userMember = QMember("user")
|
||||||
|
|
||||||
|
val donation = useCan.rewardCan.add(useCan.can).sum()
|
||||||
|
return queryFactory
|
||||||
|
.select(userMember.id)
|
||||||
|
.from(useCan)
|
||||||
|
.join(useCan.room, liveRoom)
|
||||||
|
.join(liveRoom.member, creatorMember)
|
||||||
|
.join(useCan.member, userMember)
|
||||||
|
.where(
|
||||||
|
useCan.canUsage.eq(CanUsage.DONATION)
|
||||||
|
.and(useCan.isRefund.isFalse)
|
||||||
|
.and(creatorMember.id.eq(creatorId))
|
||||||
|
)
|
||||||
|
.groupBy(useCan.member.id)
|
||||||
|
.orderBy(donation.desc())
|
||||||
|
.fetch()
|
||||||
|
.size
|
||||||
|
}
|
||||||
|
|
||||||
fun getMemberDonationRanking(
|
fun getMemberDonationRanking(
|
||||||
creatorId: Long,
|
creatorId: Long,
|
||||||
limit: Long,
|
limit: Long,
|
||||||
|
@ -161,55 +216,13 @@ class ExplorerQueryRepository(
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAccount(userId: Long): Member? {
|
fun getMember(memberId: Long): Member? {
|
||||||
return queryFactory
|
return queryFactory
|
||||||
.selectFrom(member)
|
.selectFrom(member)
|
||||||
.where(member.id.eq(userId))
|
.where(member.id.eq(memberId))
|
||||||
.fetchFirst()
|
.fetchFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserDonationRanking(
|
|
||||||
creatorId: Long,
|
|
||||||
limit: Long,
|
|
||||||
offset: Long = 0,
|
|
||||||
withDonationCan: Boolean
|
|
||||||
): List<UserDonationRankingResponse> {
|
|
||||||
val creatorMember = QMember("creator")
|
|
||||||
val userMember = QMember("user")
|
|
||||||
|
|
||||||
val donation = useCan.rewardCan.add(useCan.can).sum()
|
|
||||||
return queryFactory
|
|
||||||
.select(userMember, donation)
|
|
||||||
.from(useCan)
|
|
||||||
.join(useCan.room, liveRoom)
|
|
||||||
.join(liveRoom.member, creatorMember)
|
|
||||||
.join(useCan.member, userMember)
|
|
||||||
.offset(offset)
|
|
||||||
.limit(limit)
|
|
||||||
.where(
|
|
||||||
useCan.canUsage.eq(CanUsage.DONATION)
|
|
||||||
.and(useCan.isRefund.isFalse)
|
|
||||||
.and(creatorMember.id.eq(creatorId))
|
|
||||||
)
|
|
||||||
.groupBy(useCan.member.id)
|
|
||||||
.orderBy(donation.desc(), userMember.id.desc())
|
|
||||||
.fetch()
|
|
||||||
.map {
|
|
||||||
val account = it.get(userMember)!!
|
|
||||||
val donationCan = it.get(donation)!!
|
|
||||||
UserDonationRankingResponse(
|
|
||||||
account.id!!,
|
|
||||||
account.nickname,
|
|
||||||
if (account.profileImage != null) {
|
|
||||||
"$cloudFrontHost/${account.profileImage}"
|
|
||||||
} else {
|
|
||||||
"$cloudFrontHost/profile/default-profile.png"
|
|
||||||
},
|
|
||||||
if (withDonationCan) donationCan else 0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSimilarCreatorList(creatorId: Long): List<SimilarCreatorResponse> {
|
fun getSimilarCreatorList(creatorId: Long): List<SimilarCreatorResponse> {
|
||||||
val creator = queryFactory
|
val creator = queryFactory
|
||||||
.selectFrom(member)
|
.selectFrom(member)
|
||||||
|
|
|
@ -22,6 +22,9 @@ import org.springframework.context.ApplicationEventPublisher
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.transaction.annotation.Transactional
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
import java.time.DayOfWeek
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.temporal.TemporalAdjusters
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
|
@ -164,7 +167,7 @@ class ExplorerService(
|
||||||
|
|
||||||
fun getCreatorProfile(creatorId: Long, timezone: String, member: Member): GetCreatorProfileResponse {
|
fun getCreatorProfile(creatorId: Long, timezone: String, member: Member): GetCreatorProfileResponse {
|
||||||
// 크리에이터(유저) 정보
|
// 크리에이터(유저) 정보
|
||||||
val creatorAccount = queryRepository.getAccount(creatorId) ?: throw SodaException("없는 사용자 입니다.")
|
val creatorAccount = queryRepository.getMember(creatorId) ?: throw SodaException("없는 사용자 입니다.")
|
||||||
|
|
||||||
// 차단된 사용자 체크
|
// 차단된 사용자 체크
|
||||||
val isBlocked = memberService.isBlocked(blockedMemberId = member.id!!, memberId = creatorId)
|
val isBlocked = memberService.isBlocked(blockedMemberId = member.id!!, memberId = creatorId)
|
||||||
|
@ -175,7 +178,7 @@ class ExplorerService(
|
||||||
val notificationRecipientCount = notificationUserIds.size
|
val notificationRecipientCount = notificationUserIds.size
|
||||||
|
|
||||||
// 후원랭킹
|
// 후원랭킹
|
||||||
val userDonationRanking = queryRepository.getUserDonationRanking(
|
val memberDonationRanking = queryRepository.getMemberDonationRanking(
|
||||||
creatorId,
|
creatorId,
|
||||||
10,
|
10,
|
||||||
withDonationCan = creatorId == member.id!!
|
withDonationCan = creatorId == member.id!!
|
||||||
|
@ -234,7 +237,7 @@ class ExplorerService(
|
||||||
isNotification = isNotification,
|
isNotification = isNotification,
|
||||||
notificationRecipientCount = notificationRecipientCount
|
notificationRecipientCount = notificationRecipientCount
|
||||||
),
|
),
|
||||||
userDonationRanking = userDonationRanking,
|
memberDonationRanking = memberDonationRanking,
|
||||||
similarCreatorList = similarCreatorList,
|
similarCreatorList = similarCreatorList,
|
||||||
liveRoomList = liveRoomList,
|
liveRoomList = liveRoomList,
|
||||||
contentList = contentList,
|
contentList = contentList,
|
||||||
|
@ -250,6 +253,53 @@ class ExplorerService(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getCreatorProfileDonationRanking(
|
||||||
|
creatorId: Long,
|
||||||
|
pageable: Pageable,
|
||||||
|
member: Member
|
||||||
|
): GetDonationAllResponse {
|
||||||
|
val currentDate = LocalDate.now().atTime(0, 0, 0)
|
||||||
|
val firstDayOfLastWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7)
|
||||||
|
val firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth())
|
||||||
|
|
||||||
|
return GetDonationAllResponse(
|
||||||
|
accumulatedCansToday = if (creatorId == member.id!!) {
|
||||||
|
queryRepository.getDonationCoinsDateRange(
|
||||||
|
creatorId,
|
||||||
|
currentDate,
|
||||||
|
currentDate.plusDays(1)
|
||||||
|
) ?: 0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
accumulatedCansLastWeek = if (creatorId == member.id!!) {
|
||||||
|
queryRepository.getDonationCoinsDateRange(
|
||||||
|
creatorId,
|
||||||
|
firstDayOfLastWeek,
|
||||||
|
firstDayOfLastWeek.plusDays(7)
|
||||||
|
) ?: 0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
accumulatedCansThisMonth = if (creatorId == member.id!!) {
|
||||||
|
queryRepository.getDonationCoinsDateRange(
|
||||||
|
creatorId,
|
||||||
|
firstDayOfMonth,
|
||||||
|
currentDate
|
||||||
|
) ?: 0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
totalCount = queryRepository.getMemberDonationRankingTotal(creatorId),
|
||||||
|
memberDonationRanking = queryRepository.getMemberDonationRanking(
|
||||||
|
creatorId,
|
||||||
|
offset = pageable.offset,
|
||||||
|
limit = pageable.pageSize.toLong(),
|
||||||
|
withDonationCan = creatorId == member.id!!
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun getFollowerList(
|
fun getFollowerList(
|
||||||
creatorId: Long,
|
creatorId: Long,
|
||||||
member: Member,
|
member: Member,
|
||||||
|
@ -281,7 +331,7 @@ class ExplorerService(
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
fun writeCheers(request: PostWriteCheersRequest, member: Member) {
|
fun writeCheers(request: PostWriteCheersRequest, member: Member) {
|
||||||
val creator = queryRepository.getAccount(request.creatorId) ?: throw SodaException("없는 사용자 입니다.")
|
val creator = queryRepository.getMember(request.creatorId) ?: throw SodaException("없는 사용자 입니다.")
|
||||||
|
|
||||||
val isBlocked = memberService.isBlocked(blockedMemberId = member.id!!, memberId = request.creatorId)
|
val isBlocked = memberService.isBlocked(blockedMemberId = member.id!!, memberId = request.creatorId)
|
||||||
if (isBlocked) throw SodaException("${creator.nickname}님의 요청으로 팬토크 작성이 제한됩니다.")
|
if (isBlocked) throw SodaException("${creator.nickname}님의 요청으로 팬토크 작성이 제한됩니다.")
|
||||||
|
|
|
@ -4,7 +4,7 @@ import kr.co.vividnext.sodalive.content.GetAudioContentListItem
|
||||||
|
|
||||||
data class GetCreatorProfileResponse(
|
data class GetCreatorProfileResponse(
|
||||||
val creator: CreatorResponse,
|
val creator: CreatorResponse,
|
||||||
val userDonationRanking: List<UserDonationRankingResponse>,
|
val memberDonationRanking: List<MemberDonationRankingResponse>,
|
||||||
val similarCreatorList: List<SimilarCreatorResponse>,
|
val similarCreatorList: List<SimilarCreatorResponse>,
|
||||||
val liveRoomList: List<LiveRoomResponse>,
|
val liveRoomList: List<LiveRoomResponse>,
|
||||||
val contentList: List<GetAudioContentListItem>,
|
val contentList: List<GetAudioContentListItem>,
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
package kr.co.vividnext.sodalive.explorer
|
package kr.co.vividnext.sodalive.explorer
|
||||||
|
|
||||||
|
data class GetDonationAllResponse(
|
||||||
|
val accumulatedCansToday: Int,
|
||||||
|
val accumulatedCansLastWeek: Int,
|
||||||
|
val accumulatedCansThisMonth: Int,
|
||||||
|
val totalCount: Int,
|
||||||
|
val memberDonationRanking: List<MemberDonationRankingResponse>
|
||||||
|
)
|
||||||
|
|
||||||
data class MemberDonationRankingResponse(
|
data class MemberDonationRankingResponse(
|
||||||
val userId: Long,
|
val userId: Long,
|
||||||
val nickname: String,
|
val nickname: String,
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.explorer
|
|
||||||
|
|
||||||
data class GetDonationAllResponse(
|
|
||||||
val accumulatedCansToday: Int,
|
|
||||||
val accumulatedCansLastWeek: Int,
|
|
||||||
val accumulatedCansThisMonth: Int,
|
|
||||||
val totalCount: Int,
|
|
||||||
val userDonationRanking: List<UserDonationRankingResponse>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class UserDonationRankingResponse(
|
|
||||||
val userId: Long,
|
|
||||||
val nickname: String,
|
|
||||||
val profileImage: String,
|
|
||||||
val donationCan: Int
|
|
||||||
)
|
|
Loading…
Reference in New Issue