feat(chat-character): 보온 주간 차트 콘텐츠 정렬 기준 추가
- 매출, 판매량, 댓글 수, 좋아요 수, 후원
This commit is contained in:
@@ -4,6 +4,7 @@ import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.content.ContentType
|
||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.rank.ContentRankingSortType
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
@@ -79,4 +80,28 @@ class HomeController(private val service: HomeService) {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 콘텐츠 랭킹 엔드포인트
|
||||
@GetMapping("/content-ranking")
|
||||
fun getContentRanking(
|
||||
@RequestParam("sort", required = false) sort: ContentRankingSortType? = null,
|
||||
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
|
||||
@RequestParam("contentType", required = false) contentType: ContentType? = null,
|
||||
@RequestParam("offset", required = false) offset: Long? = null,
|
||||
@RequestParam("limit", required = false) limit: Long? = null,
|
||||
@RequestParam("theme", required = false) theme: String? = null,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
ApiResponse.ok(
|
||||
service.getContentRankingBySort(
|
||||
sort = sort ?: ContentRankingSortType.REVENUE,
|
||||
isAdultContentVisible = isAdultContentVisible ?: true,
|
||||
contentType = contentType ?: ContentType.ALL,
|
||||
offset = offset,
|
||||
limit = limit,
|
||||
theme = theme,
|
||||
member = member
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService
|
||||
import kr.co.vividnext.sodalive.content.AudioContentMainItem
|
||||
import kr.co.vividnext.sodalive.content.AudioContentService
|
||||
import kr.co.vividnext.sodalive.content.ContentType
|
||||
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.AudioContentCurationService
|
||||
import kr.co.vividnext.sodalive.content.series.ContentSeriesService
|
||||
@@ -18,6 +19,7 @@ import kr.co.vividnext.sodalive.live.room.LiveRoomStatus
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberService
|
||||
import kr.co.vividnext.sodalive.query.recommend.RecommendChannelQueryService
|
||||
import kr.co.vividnext.sodalive.rank.ContentRankingSortType
|
||||
import kr.co.vividnext.sodalive.rank.RankingRepository
|
||||
import kr.co.vividnext.sodalive.rank.RankingService
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
@@ -153,7 +155,7 @@ class HomeService(
|
||||
contentType = contentType,
|
||||
startDate = startDate.minusDays(1),
|
||||
endDate = endDate,
|
||||
sortType = "매출"
|
||||
sort = ContentRankingSortType.REVENUE
|
||||
)
|
||||
|
||||
val recommendChannelList = recommendChannelService.getRecommendChannel(
|
||||
@@ -277,6 +279,40 @@ class HomeService(
|
||||
)
|
||||
}
|
||||
|
||||
fun getContentRankingBySort(
|
||||
sort: ContentRankingSortType,
|
||||
isAdultContentVisible: Boolean,
|
||||
contentType: ContentType,
|
||||
offset: Long?,
|
||||
limit: Long?,
|
||||
theme: String?,
|
||||
member: Member?
|
||||
): List<GetAudioContentRankingItem> {
|
||||
val memberId = member?.id
|
||||
val isAdult = member?.auth != null && isAdultContentVisible
|
||||
|
||||
val currentDateTime = LocalDateTime.now()
|
||||
val startDate = currentDateTime
|
||||
.withHour(15)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
.minusWeeks(1)
|
||||
.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
||||
val endDate = startDate.plusDays(6)
|
||||
|
||||
return rankingService.getContentRanking(
|
||||
memberId = memberId,
|
||||
isAdult = isAdult,
|
||||
contentType = contentType,
|
||||
startDate = startDate.minusDays(1),
|
||||
endDate = endDate,
|
||||
offset = offset ?: 0,
|
||||
limit = limit ?: 12,
|
||||
sort = sort,
|
||||
theme = theme ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun getDayOfWeekByTimezone(timezone: String): SeriesPublishedDaysOfWeek {
|
||||
val systemTime = LocalDateTime.now()
|
||||
val zoneId = ZoneId.of(timezone)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package kr.co.vividnext.sodalive.rank
|
||||
|
||||
/**
|
||||
* 콘텐츠 랭킹 정렬 기준
|
||||
*/
|
||||
enum class ContentRankingSortType {
|
||||
// 매출: order.can.sum.desc
|
||||
REVENUE,
|
||||
|
||||
// 판매량: order.id.count.desc
|
||||
SALES_COUNT,
|
||||
|
||||
// 댓글 수: audioContentComment.id.count.desc
|
||||
COMMENT_COUNT,
|
||||
|
||||
// 좋아요 수: audioContentLike.id.count.desc
|
||||
LIKE_COUNT,
|
||||
|
||||
// 후원: audioContentComment.donationCan.sum.desc
|
||||
DONATION
|
||||
}
|
||||
@@ -132,6 +132,14 @@ class RankingRepository(
|
||||
.innerJoin(audioContent.theme, audioContentTheme)
|
||||
}
|
||||
|
||||
"판매량" -> {
|
||||
select
|
||||
.from(order)
|
||||
.innerJoin(order.audioContent, audioContent)
|
||||
.innerJoin(audioContent.member, member)
|
||||
.innerJoin(audioContent.theme, audioContentTheme)
|
||||
}
|
||||
|
||||
else -> {
|
||||
select
|
||||
.from(order)
|
||||
@@ -184,6 +192,18 @@ class RankingRepository(
|
||||
.orderBy(audioContentLike.id.count().desc(), audioContent.createdAt.asc())
|
||||
}
|
||||
|
||||
"판매량" -> {
|
||||
select
|
||||
.where(
|
||||
where
|
||||
.and(order.isActive.isTrue)
|
||||
.and(order.createdAt.goe(startDate))
|
||||
.and(order.createdAt.lt(endDate))
|
||||
)
|
||||
.groupBy(audioContent.id)
|
||||
.orderBy(order.id.count().desc(), audioContent.createdAt.asc())
|
||||
}
|
||||
|
||||
else -> {
|
||||
select
|
||||
.where(
|
||||
|
||||
@@ -76,6 +76,38 @@ class RankingService(
|
||||
return contentList
|
||||
}
|
||||
|
||||
private fun toSortString(sort: ContentRankingSortType): String = when (sort) {
|
||||
ContentRankingSortType.REVENUE -> "매출"
|
||||
ContentRankingSortType.SALES_COUNT -> "판매량"
|
||||
ContentRankingSortType.COMMENT_COUNT -> "댓글"
|
||||
ContentRankingSortType.LIKE_COUNT -> "좋아요"
|
||||
ContentRankingSortType.DONATION -> "후원"
|
||||
}
|
||||
|
||||
fun getContentRanking(
|
||||
memberId: Long?,
|
||||
isAdult: Boolean,
|
||||
contentType: ContentType,
|
||||
startDate: LocalDateTime,
|
||||
endDate: LocalDateTime,
|
||||
offset: Long = 0,
|
||||
limit: Long = 12,
|
||||
sort: ContentRankingSortType,
|
||||
theme: String = ""
|
||||
): List<GetAudioContentRankingItem> {
|
||||
return getContentRanking(
|
||||
memberId = memberId,
|
||||
isAdult = isAdult,
|
||||
contentType = contentType,
|
||||
startDate = startDate,
|
||||
endDate = endDate,
|
||||
offset = offset,
|
||||
limit = limit,
|
||||
sortType = toSortString(sort),
|
||||
theme = theme
|
||||
)
|
||||
}
|
||||
|
||||
fun getSeriesRanking(
|
||||
memberId: Long?,
|
||||
isAdult: Boolean,
|
||||
|
||||
Reference in New Issue
Block a user