test #20
|
@ -150,18 +150,14 @@ class AudioContentService(
|
|||
val theme = themeQueryRepository.findThemeByIdAndActive(id = request.themeId)
|
||||
?: throw SodaException("잘못된 테마입니다. 다시 선택해 주세요.")
|
||||
|
||||
if (request.price in 1..9) throw SodaException("콘텐츠의 최소금액은 10캔 입니다.")
|
||||
if (request.price <= 4) throw SodaException("콘텐츠의 최소금액은 5캔 입니다.")
|
||||
|
||||
// DB에 값 추가
|
||||
val audioContent = AudioContent(
|
||||
title = request.title,
|
||||
detail = request.detail,
|
||||
type = request.type,
|
||||
price = if (request.price < 0) {
|
||||
0
|
||||
} else {
|
||||
request.price
|
||||
},
|
||||
price = request.price,
|
||||
isAdult = request.isAdult,
|
||||
isGeneratePreview = if (request.type == AudioContentType.INDIVIDUAL) {
|
||||
request.isGeneratePreview
|
||||
|
@ -311,7 +307,7 @@ class AudioContentService(
|
|||
|
||||
// 크리에이터(유저) 정보
|
||||
val creatorId = audioContent.member!!.id!!
|
||||
val creator = explorerQueryRepository.getAccount(creatorId)
|
||||
val creator = explorerQueryRepository.getMember(creatorId)
|
||||
?: throw SodaException("없는 사용자 입니다.")
|
||||
|
||||
val notificationUserIds = explorerQueryRepository.getNotificationUserIds(creatorId)
|
||||
|
|
|
@ -42,7 +42,7 @@ data class Order(
|
|||
var audioContent: AudioContent? = null
|
||||
set(value) {
|
||||
can = if (type == OrderType.RENTAL) {
|
||||
ceil(value?.price!! * 0.7).toInt()
|
||||
ceil(value?.price!! * 0.6).toInt()
|
||||
} else {
|
||||
value?.price!!
|
||||
}
|
||||
|
|
|
@ -49,6 +49,16 @@ class ExplorerController(private val service: ExplorerService) {
|
|||
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")
|
||||
fun writeCheers(
|
||||
@RequestBody request: PostWriteCheersRequest,
|
||||
|
@ -86,4 +96,15 @@ class ExplorerController(private val service: ExplorerService) {
|
|||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
ApiResponse.ok(service.getFollowerList(creatorId, member, pageable))
|
||||
}
|
||||
|
||||
@GetMapping("/profile/{id}/cheers")
|
||||
fun getCreatorProfileCheers(
|
||||
@PathVariable("id") creatorId: Long,
|
||||
@RequestParam timezone: String,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
|
||||
pageable: Pageable
|
||||
) = run {
|
||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
ApiResponse.ok(service.getCreatorProfileCheers(creatorId, timezone, pageable))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import com.querydsl.core.types.dsl.Expressions
|
|||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
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.content.QAudioContent.audioContent
|
||||
import kr.co.vividnext.sodalive.explorer.follower.GetFollowerListDto
|
||||
|
@ -55,6 +57,59 @@ class ExplorerQueryRepository(
|
|||
.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(
|
||||
creatorId: Long,
|
||||
limit: Long,
|
||||
|
@ -161,55 +216,13 @@ class ExplorerQueryRepository(
|
|||
.fetch()
|
||||
}
|
||||
|
||||
fun getAccount(userId: Long): Member? {
|
||||
fun getMember(memberId: Long): Member? {
|
||||
return queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.id.eq(userId))
|
||||
.where(member.id.eq(memberId))
|
||||
.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> {
|
||||
val creator = queryFactory
|
||||
.selectFrom(member)
|
||||
|
|
|
@ -22,6 +22,9 @@ import org.springframework.context.ApplicationEventPublisher
|
|||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.temporal.TemporalAdjusters
|
||||
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
|
@ -164,7 +167,7 @@ class ExplorerService(
|
|||
|
||||
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)
|
||||
|
@ -175,7 +178,7 @@ class ExplorerService(
|
|||
val notificationRecipientCount = notificationUserIds.size
|
||||
|
||||
// 후원랭킹
|
||||
val userDonationRanking = queryRepository.getUserDonationRanking(
|
||||
val memberDonationRanking = queryRepository.getMemberDonationRanking(
|
||||
creatorId,
|
||||
10,
|
||||
withDonationCan = creatorId == member.id!!
|
||||
|
@ -234,7 +237,7 @@ class ExplorerService(
|
|||
isNotification = isNotification,
|
||||
notificationRecipientCount = notificationRecipientCount
|
||||
),
|
||||
userDonationRanking = userDonationRanking,
|
||||
userDonationRanking = memberDonationRanking,
|
||||
similarCreatorList = similarCreatorList,
|
||||
liveRoomList = liveRoomList,
|
||||
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),
|
||||
userDonationRanking = queryRepository.getMemberDonationRanking(
|
||||
creatorId,
|
||||
offset = pageable.offset,
|
||||
limit = pageable.pageSize.toLong(),
|
||||
withDonationCan = creatorId == member.id!!
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun getFollowerList(
|
||||
creatorId: Long,
|
||||
member: Member,
|
||||
|
@ -281,7 +331,7 @@ class ExplorerService(
|
|||
|
||||
@Transactional
|
||||
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)
|
||||
if (isBlocked) throw SodaException("${creator.nickname}님의 요청으로 팬토크 작성이 제한됩니다.")
|
||||
|
@ -303,6 +353,19 @@ class ExplorerService(
|
|||
cheersRepository.save(cheers)
|
||||
}
|
||||
|
||||
fun getCreatorProfileCheers(
|
||||
creatorId: Long,
|
||||
timezone: String,
|
||||
pageable: Pageable
|
||||
): GetCheersResponse {
|
||||
return queryRepository.getCheersList(
|
||||
creatorId = creatorId,
|
||||
timezone = timezone,
|
||||
offset = pageable.offset,
|
||||
limit = pageable.pageSize.toLong()
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun modifyCheers(request: PutWriteCheersRequest, member: Member) {
|
||||
val cheers = queryRepository.getCheers(request.cheersId, member.id!!)
|
||||
|
|
|
@ -4,7 +4,7 @@ import kr.co.vividnext.sodalive.content.GetAudioContentListItem
|
|||
|
||||
data class GetCreatorProfileResponse(
|
||||
val creator: CreatorResponse,
|
||||
val userDonationRanking: List<UserDonationRankingResponse>,
|
||||
val userDonationRanking: List<MemberDonationRankingResponse>,
|
||||
val similarCreatorList: List<SimilarCreatorResponse>,
|
||||
val liveRoomList: List<LiveRoomResponse>,
|
||||
val contentList: List<GetAudioContentListItem>,
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
package kr.co.vividnext.sodalive.explorer
|
||||
|
||||
data class GetDonationAllResponse(
|
||||
val accumulatedCansToday: Int,
|
||||
val accumulatedCansLastWeek: Int,
|
||||
val accumulatedCansThisMonth: Int,
|
||||
val totalCount: Int,
|
||||
val userDonationRanking: List<MemberDonationRankingResponse>
|
||||
)
|
||||
|
||||
data class MemberDonationRankingResponse(
|
||||
val userId: Long,
|
||||
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