diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt index 688ac4d..00d3eb3 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt @@ -32,6 +32,7 @@ data class AudioContent( var title: String, @Column(columnDefinition = "TEXT", nullable = false) var detail: String, + var playCount: Long = 0, var price: Int = 0, var releaseDate: LocalDateTime? = null, val limited: Int? = null, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt index 0a1ec5d..3604c0e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt @@ -60,4 +60,39 @@ class AudioContentMainTabRepository( .limit(20) .fetch() } + + fun findCreatorWithHasFreeContent(memberId: Long, minCount: Int): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + val where = member.isActive.isTrue + .and(member.role.eq(MemberRole.CREATOR)) + .and(audioContent.isActive.isTrue) + .and(audioContent.price.loe(0)) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + .and(blockMember.id.isNull) + + return queryFactory + .select( + QContentCreatorResponse( + member.id, + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) + ) + ) + .from(member) + .innerJoin(audioContent).on(member.id.eq(audioContent.member.id)) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .groupBy(member.id) + .having(audioContent.id.count().goe(minCount)) + .orderBy( + Expressions.numberTemplate(Double::class.java, "function('rand')").asc() + ) + .offset(0) + .limit(20) + .fetch() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt index 4c8fa63..2547d48 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt @@ -60,4 +60,19 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab ) ) } + + @GetMapping("/popular-content-by-creator") + fun getPopularContentByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getPopularContentByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt index 732f705..0b1f9ea 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt @@ -3,20 +3,25 @@ package kr.co.vividnext.sodalive.content.main.tab.free import kr.co.vividnext.sodalive.content.AudioContentRepository import kr.co.vividnext.sodalive.content.ContentType import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryRepository +import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse import kr.co.vividnext.sodalive.content.main.tab.RecommendSeriesRepository import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.member.Member +import kr.co.vividnext.sodalive.rank.RankingService import org.springframework.stereotype.Service @Service class AudioContentMainTabFreeService( + private val repository: AudioContentMainTabRepository, private val bannerService: AudioContentBannerService, private val recommendSeriesRepository: RecommendSeriesRepository, private val curationRepository: AudioContentCurationQueryRepository, private val contentRepository: AudioContentRepository, + private val rankingService: RankingService, private val audioContentRepository: AudioContentRepository, private val audioContentThemeRepository: AudioContentThemeQueryRepository ) { @@ -63,6 +68,13 @@ class AudioContentMainTabFreeService( emptyList() } + val creatorList = repository.findCreatorWithHasFreeContent(memberId, 4) + val playCountRankContentList = if (creatorList.isNotEmpty()) { + rankingService.fetchFreeContentByCreatorIdTop4(creatorList[0].creatorId, isAdult) + } else { + emptyList() + } + val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) .filter { it.title != "크리에이터 소개" } .map { @@ -86,6 +98,8 @@ class AudioContentMainTabFreeService( recommendSeriesList = recommendSeriesList, themeList = themeList, newFreeContentList = newFreeContentList, + creatorList = creatorList, + playCountRankContentList = playCountRankContentList, curationList = curationList ) } @@ -131,4 +145,8 @@ class AudioContentMainTabFreeService( isFree = true ) } + + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchFreeContentByCreatorIdTop4(creatorId, isAdult) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/GetContentMainTabFreeResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/GetContentMainTabFreeResponse.kt index aed9911..e0035ad 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/GetContentMainTabFreeResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/GetContentMainTabFreeResponse.kt @@ -1,6 +1,8 @@ package kr.co.vividnext.sodalive.content.main.tab.free +import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.GetAudioContentBannerResponse import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse import kr.co.vividnext.sodalive.content.main.tab.GetRecommendSeriesListResponse @@ -12,5 +14,7 @@ data class GetContentMainTabFreeResponse( val recommendSeriesList: List, val themeList: List, val newFreeContentList: List, + val creatorList: List, + val playCountRankContentList: List, val curationList: List ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 9c3714d..2d9a3ba 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -508,4 +508,38 @@ class RankingRepository( .limit(10) .fetch() } + + fun fetchFreeContentByCreatorIdTop4(creatorId: Long, isAdult: Boolean): List { + var where = member.isActive.isTrue + .and(member.id.eq(creatorId)) + .and(member.role.eq(MemberRole.CREATOR)) + .and(audioContent.isActive.isTrue) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + + if (!isAdult) { + where = where.and(series.isAdult.isFalse) + } + + return queryFactory + .select( + QGetAudioContentRankingItem( + audioContent.id, + audioContent.title, + audioContent.coverImage.prepend("/").prepend(imageHost), + audioContentTheme.theme, + audioContent.price, + audioContent.duration, + member.id, + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) + ) + ) + .from(audioContent) + .where(where) + .orderBy(audioContent.playCount.desc()) + .offset(0) + .limit(4) + .fetch() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index f7e907c..f94e672 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -209,4 +209,8 @@ class RankingService( val seriesList = repository.fetchCreatorSeriesBySales(creatorId = creatorId, isAdult = isAdult) return seriesToSeriesListItem(seriesList, isAdult) } + + fun fetchFreeContentByCreatorIdTop4(creatorId: Long, isAdult: Boolean): List { + return repository.fetchFreeContentByCreatorIdTop4(creatorId, isAdult) + } }