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.content.ContentType
|
||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.rank.ContentRankingSortType
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
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.AudioContentMainItem
|
||||||
import kr.co.vividnext.sodalive.content.AudioContentService
|
import kr.co.vividnext.sodalive.content.AudioContentService
|
||||||
import kr.co.vividnext.sodalive.content.ContentType
|
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.banner.AudioContentBannerService
|
||||||
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationService
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationService
|
||||||
import kr.co.vividnext.sodalive.content.series.ContentSeriesService
|
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.Member
|
||||||
import kr.co.vividnext.sodalive.member.MemberService
|
import kr.co.vividnext.sodalive.member.MemberService
|
||||||
import kr.co.vividnext.sodalive.query.recommend.RecommendChannelQueryService
|
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.RankingRepository
|
||||||
import kr.co.vividnext.sodalive.rank.RankingService
|
import kr.co.vividnext.sodalive.rank.RankingService
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
@@ -153,7 +155,7 @@ class HomeService(
|
|||||||
contentType = contentType,
|
contentType = contentType,
|
||||||
startDate = startDate.minusDays(1),
|
startDate = startDate.minusDays(1),
|
||||||
endDate = endDate,
|
endDate = endDate,
|
||||||
sortType = "매출"
|
sort = ContentRankingSortType.REVENUE
|
||||||
)
|
)
|
||||||
|
|
||||||
val recommendChannelList = recommendChannelService.getRecommendChannel(
|
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 {
|
private fun getDayOfWeekByTimezone(timezone: String): SeriesPublishedDaysOfWeek {
|
||||||
val systemTime = LocalDateTime.now()
|
val systemTime = LocalDateTime.now()
|
||||||
val zoneId = ZoneId.of(timezone)
|
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)
|
.innerJoin(audioContent.theme, audioContentTheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"판매량" -> {
|
||||||
|
select
|
||||||
|
.from(order)
|
||||||
|
.innerJoin(order.audioContent, audioContent)
|
||||||
|
.innerJoin(audioContent.member, member)
|
||||||
|
.innerJoin(audioContent.theme, audioContentTheme)
|
||||||
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
select
|
select
|
||||||
.from(order)
|
.from(order)
|
||||||
@@ -184,6 +192,18 @@ class RankingRepository(
|
|||||||
.orderBy(audioContentLike.id.count().desc(), audioContent.createdAt.asc())
|
.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 -> {
|
else -> {
|
||||||
select
|
select
|
||||||
.where(
|
.where(
|
||||||
|
|||||||
@@ -76,6 +76,38 @@ class RankingService(
|
|||||||
return contentList
|
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(
|
fun getSeriesRanking(
|
||||||
memberId: Long?,
|
memberId: Long?,
|
||||||
isAdult: Boolean,
|
isAdult: Boolean,
|
||||||
|
|||||||
Reference in New Issue
Block a user