From 3b807543b72aa2b7ce1856a261a80d7566baa82f Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 26 Apr 2024 21:18:13 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=9C=EB=A6=AC=EC=A6=88=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=83=81=EC=84=B8=20API=20-=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/series/ContentSeriesController.kt | 18 ++++++ .../content/series/ContentSeriesRepository.kt | 10 ---- .../content/series/ContentSeriesService.kt | 44 ++++++++++++++- .../content/series/GetSeriesDetailResponse.kt | 14 +++-- .../content/ContentSeriesContentRepository.kt | 56 +++++++++++++++++++ .../content/GetSeriesContentListResponse.kt | 19 +++++++ 6 files changed, 143 insertions(+), 18 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/GetSeriesContentListResponse.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt index 946625e..13cdc3a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt @@ -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() + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt index e157180..345e4fb 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt @@ -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 fun getSeriesDetail(seriesId: Long, isAuth: Boolean): Series? - fun getPublishedDaysOfWeek(seriesId: Long): Set fun getKeywordList(seriesId: Long): List fun getSeriesContentMinMaxPrice(seriesId: Long): GetSeriesContentMinMaxPriceResponse } @@ -85,14 +83,6 @@ class ContentSeriesQueryRepositoryImpl( .fetchFirst() } - override fun getPublishedDaysOfWeek(seriesId: Long): Set { - return queryFactory - .select(series.publishedDaysOfWeek) - .from(series) - .where(series.id.eq(seriesId)) - .fetchFirst() - } - override fun getKeywordList(seriesId: Long): List { return queryFactory .select(hashTag.tag) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt index 6f96342..3e05ff2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt @@ -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): String { val dayOfWeekText = publishedDaysOfWeek.toList().sortedBy { it.ordinal } .map { diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/GetSeriesDetailResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/GetSeriesDetailResponse.kt index be90080..508c441 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/GetSeriesDetailResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/GetSeriesDetailResponse.kt @@ -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, - var publishedDaysOfWeek: String + val minPrice: Int, + val maxPrice: Int, + val keywordList: List, + val publishedDaysOfWeek: String, + val contentList: List, + val contentCount: Int ) { data class GetSeriesDetailCreator( val creatorId: Long, val nickname: String, val profileImage: String, - var isFollow: Boolean + val isFollow: Boolean ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/ContentSeriesContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/ContentSeriesContentRepository.kt index e8f955a..b757acc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/ContentSeriesContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/ContentSeriesContentRepository.kt @@ -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, C interface ContentSeriesContentQueryRepository { fun getContentCount(seriesId: Long, isAdult: Boolean): Int + fun getContentList( + seriesId: Long, + isAdult: Boolean, + imageHost: String, + offset: Long, + limit: Long + ): List + 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 { + 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, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/GetSeriesContentListResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/GetSeriesContentListResponse.kt new file mode 100644 index 0000000..00f774c --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/content/GetSeriesContentListResponse.kt @@ -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 +) + +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 +)