시리즈 리스트 상세 API

- 콘텐츠 리스트 추가
This commit is contained in:
Klaus 2024-04-26 21:18:13 +09:00
parent 0350f86322
commit 3b807543b7
6 changed files with 143 additions and 18 deletions

View File

@ -46,4 +46,22 @@ class ContentSeriesController(private val service: ContentSeriesService) {
service.getSeriesDetail(seriesId = id, member = member)
)
}
@GetMapping("/{id}/content")
fun getSeriesContentList(
@PathVariable id: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(
service.getSeriesContentList(
seriesId = id,
member = member,
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)
)
}
}

View File

@ -8,7 +8,6 @@ import kr.co.vividnext.sodalive.content.series.content.QGetSeriesContentMinMaxPr
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeriesContent.seriesContent
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
import kr.co.vividnext.sodalive.creator.admin.content.series.keyword.QSeriesKeyword.seriesKeyword
import org.springframework.data.jpa.repository.JpaRepository
@ -25,7 +24,6 @@ interface ContentSeriesQueryRepository {
): List<Series>
fun getSeriesDetail(seriesId: Long, isAuth: Boolean): Series?
fun getPublishedDaysOfWeek(seriesId: Long): Set<SeriesPublishedDaysOfWeek>
fun getKeywordList(seriesId: Long): List<String>
fun getSeriesContentMinMaxPrice(seriesId: Long): GetSeriesContentMinMaxPriceResponse
}
@ -85,14 +83,6 @@ class ContentSeriesQueryRepositoryImpl(
.fetchFirst()
}
override fun getPublishedDaysOfWeek(seriesId: Long): Set<SeriesPublishedDaysOfWeek> {
return queryFactory
.select(series.publishedDaysOfWeek)
.from(series)
.where(series.id.eq(seriesId))
.fetchFirst()
}
override fun getKeywordList(seriesId: Long): List<String> {
return queryFactory
.select(hashTag.tag)

View File

@ -1,7 +1,10 @@
package kr.co.vividnext.sodalive.content.series
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.order.OrderRepository
import kr.co.vividnext.sodalive.content.order.OrderType
import kr.co.vividnext.sodalive.content.series.content.ContentSeriesContentRepository
import kr.co.vividnext.sodalive.content.series.content.GetSeriesContentListResponse
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesSortType
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesState
@ -16,6 +19,7 @@ import java.time.format.DateTimeFormatter
@Service
class ContentSeriesService(
private val repository: ContentSeriesRepository,
private val orderRepository: OrderRepository,
private val explorerQueryRepository: ExplorerQueryRepository,
private val seriesContentRepository: ContentSeriesContentRepository,
@ -97,7 +101,9 @@ class ContentSeriesService(
val rentalMinPrice = (minMaxPrice.minPrice * 0.7).toInt()
val rentalMaxPrice = (minMaxPrice.maxPrice * 0.7).toInt()
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val seriesContentList = getSeriesContentList(seriesId = seriesId, member = member, offset = 0, limit = 5)
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy.MM.dd")
return GetSeriesDetailResponse(
seriesId = seriesId,
title = series.title,
@ -124,11 +130,43 @@ class ContentSeriesService(
minPrice = minPrice,
maxPrice = maxPrice,
keywordList = keywordList,
publishedDaysOfWeek = publishedDaysOfWeekText(series.publishedDaysOfWeek)
publishedDaysOfWeek = publishedDaysOfWeekText(series.publishedDaysOfWeek),
contentList = seriesContentList.items,
contentCount = seriesContentList.totalCount
)
}
fun getSeriesContentList(seriesId: Long, member: Member, offset: Long, limit: Long): GetSeriesContentListResponse {
val isAdult = member.auth != null
val totalCount = seriesContentRepository.getContentCount(seriesId, isAdult = isAdult)
val contentList = seriesContentRepository.getContentList(
seriesId = seriesId,
isAdult = isAdult,
imageHost = coverImageHost,
offset = offset,
limit = limit
)
.map {
val (isExistsAudioContent, orderType) = orderRepository.isExistOrderedAndOrderType(
memberId = member.id!!,
contentId = it.contentId
)
if (isExistsAudioContent) {
if (orderType == OrderType.RENTAL) {
it.isRented = true
} else {
it.isOwned = true
}
}
it
}
return GetSeriesContentListResponse(totalCount, contentList)
}
private fun publishedDaysOfWeekText(publishedDaysOfWeek: Set<SeriesPublishedDaysOfWeek>): String {
val dayOfWeekText = publishedDaysOfWeek.toList().sortedBy { it.ordinal }
.map {

View File

@ -1,5 +1,7 @@
package kr.co.vividnext.sodalive.content.series
import kr.co.vividnext.sodalive.content.series.content.GetSeriesContentListItem
data class GetSeriesDetailResponse(
val seriesId: Long,
val title: String,
@ -14,15 +16,17 @@ data class GetSeriesDetailResponse(
var rentalMinPrice: Int,
var rentalMaxPrice: Int,
val rentalPeriod: Int,
var minPrice: Int,
var maxPrice: Int,
var keywordList: List<String>,
var publishedDaysOfWeek: String
val minPrice: Int,
val maxPrice: Int,
val keywordList: List<String>,
val publishedDaysOfWeek: String,
val contentList: List<GetSeriesContentListItem>,
val contentCount: Int
) {
data class GetSeriesDetailCreator(
val creatorId: Long,
val nickname: String,
val profileImage: String,
var isFollow: Boolean
val isFollow: Boolean
)
}

View File

@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.content.series.content
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
@ -12,6 +13,14 @@ interface ContentSeriesContentRepository : JpaRepository<SeriesContent, Long>, C
interface ContentSeriesContentQueryRepository {
fun getContentCount(seriesId: Long, isAdult: Boolean): Int
fun getContentList(
seriesId: Long,
isAdult: Boolean,
imageHost: String,
offset: Long,
limit: Long
): List<GetSeriesContentListItem>
fun isNewContent(seriesId: Long, isAdult: Boolean, fromDate: LocalDateTime, nowDate: LocalDateTime): Boolean
}
@ -36,6 +45,53 @@ class ContentSeriesContentQueryRepositoryImpl(
.size
}
override fun getContentList(
seriesId: Long,
isAdult: Boolean,
imageHost: String,
offset: Long,
limit: Long
): List<GetSeriesContentListItem> {
var where = series.id.eq(seriesId)
.and(audioContent.isActive.isTrue)
.and(audioContent.duration.isNotNull)
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
}
val formattedDate = Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
audioContent.releaseDate,
"UTC",
"Asia/Seoul"
),
"%y.%m.%d"
)
return queryFactory
.select(
QGetSeriesContentListItem(
audioContent.id,
audioContent.title,
audioContent.coverImage.prepend("/").prepend(imageHost),
formattedDate,
audioContent.duration,
audioContent.price,
Expressions.asBoolean(false),
Expressions.asBoolean(false)
)
)
.from(seriesContent)
.innerJoin(seriesContent.series, series)
.innerJoin(seriesContent.content, audioContent)
.where(where)
.fetch()
}
override fun isNewContent(
seriesId: Long,
isAdult: Boolean,

View File

@ -0,0 +1,19 @@
package kr.co.vividnext.sodalive.content.series.content
import com.querydsl.core.annotations.QueryProjection
data class GetSeriesContentListResponse(
val totalCount: Int,
val items: List<GetSeriesContentListItem>
)
data class GetSeriesContentListItem @QueryProjection constructor(
val contentId: Long,
val title: String,
val coverImage: String,
val releaseDate: String,
val duration: String,
val price: Int,
var isRented: Boolean,
var isOwned: Boolean
)