From 9be78062bef125441e8c0ce259f24d55920ac7ae Mon Sep 17 00:00:00 2001 From: Klaus Date: Sat, 8 Feb 2025 02:40:25 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20-=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentRepository.kt | 10 +- .../AudioContentCurationQueryRepository.kt | 22 +++++ .../main/tab/RecommendSeriesRepository.kt | 27 ++++++ .../free/AudioContentMainTabFreeController.kt | 22 +++++ .../free/AudioContentMainTabFreeService.kt | 91 +++++++++++++++++++ .../tab/free/GetContentMainTabFreeResponse.kt | 16 ++++ 6 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/GetContentMainTabFreeResponse.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt index 980ab66..f855b57 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -68,7 +68,8 @@ interface AudioContentQueryRepository { isAdult: Boolean = false, contentType: ContentType, offset: Long = 0, - limit: Long = 20 + limit: Long = 20, + isFree: Boolean = false ): List fun totalCountByTheme( @@ -339,7 +340,8 @@ class AudioContentQueryRepositoryImpl( isAdult: Boolean, contentType: ContentType, offset: Long, - limit: Long + limit: Long, + isFree: Boolean ): List { val blockMemberCondition = blockMember.member.id.eq(member.id) .and(blockMember.isActive.isTrue) @@ -383,6 +385,10 @@ class AudioContentQueryRepositoryImpl( where = where.and(audioContentTheme.theme.eq(theme)) } + if (isFree) { + where = where.and(audioContent.price.loe(0)) + } + return queryFactory .select( QGetAudioContentMainItem( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt index 84b63ed..28c6985 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt @@ -105,4 +105,26 @@ class AudioContentCurationQueryRepository(private val queryFactory: JPAQueryFact .orderBy(audioContentCuration.orders.asc()) .fetch() } + + fun findByContentMainTabIdAndTitle( + tabId: Long, + title: String, + isAdult: Boolean, + offset: Long = 0, + limit: Long = 12 + ): List { + var where = audioContentCuration.isActive.isTrue + .and(audioContentMainTab.id.eq(tabId)) + + if (!isAdult) { + where = where.and(audioContentCuration.isAdult.isFalse) + } + + return queryFactory + .selectFrom(audioContentCuration) + .innerJoin(audioContentCuration.tab, audioContentMainTab) + .where(where) + .orderBy(audioContentCuration.orders.asc()) + .fetch() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt index 4375d96..b17a583 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt @@ -40,4 +40,31 @@ class RecommendSeriesRepository( .orderBy(recommendSeries.orders.asc()) .fetch() } + + fun getRecommendSeriesList(isAdult: Boolean): List { + var where = recommendSeries.isActive.isTrue + .and(recommendSeries.isFree.isTrue) + .and(series.isActive.isTrue) + + if (!isAdult) { + where = where.and(series.isAdult.isFalse) + } + + return queryFactory + .select( + QGetRecommendSeriesListResponse( + series.id, + series.title, + recommendSeries.imagePath.prepend("/").prepend(imageHost), + member.id, + member.nickname + ) + ) + .from(recommendSeries) + .innerJoin(recommendSeries.series, series) + .innerJoin(series.member, member) + .where(where) + .orderBy(recommendSeries.orders.asc()) + .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 new file mode 100644 index 0000000..e356865 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt @@ -0,0 +1,22 @@ +package kr.co.vividnext.sodalive.content.main.tab.free + +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.member.Member +import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/v2/audio-content/main/series") +class AudioContentMainTabFreeController(private val service: AudioContentMainTabFreeService) { + @GetMapping + fun fetchContentMainFree( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(service.fetchData(member)) + } +} 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 new file mode 100644 index 0000000..b64a2ab --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt @@ -0,0 +1,91 @@ +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.banner.AudioContentBannerService +import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryRepository +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 org.springframework.stereotype.Service + +@Service +class AudioContentMainTabFreeService( + private val bannerService: AudioContentBannerService, + private val recommendSeriesRepository: RecommendSeriesRepository, + private val curationRepository: AudioContentCurationQueryRepository, + private val contentRepository: AudioContentRepository, + private val audioContentRepository: AudioContentRepository, + private val audioContentThemeRepository: AudioContentThemeQueryRepository +) { + fun fetchData(member: Member): GetContentMainTabFreeResponse { + val isAdult = member.auth != null + val memberId = member.id!! + val tabId = 7L + + val contentBannerList = bannerService.getBannerList( + tabId = tabId, + memberId = memberId, + isAdult = isAdult + ) + + val introduceCreator = curationRepository.findByContentMainTabIdAndTitle( + tabId = tabId, + title = "크리에이터 소개", + isAdult = isAdult + ) + .map { + GetContentCurationResponse( + title = it.title, + items = contentRepository.findAudioContentByCurationId( + curationId = it.id!!, + isAdult = isAdult, + contentType = ContentType.ALL + ) + ) + } + + val recommendSeriesList = recommendSeriesRepository.getRecommendSeriesList(isAdult = isAdult) + + val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult) + val newFreeContentList = if (themeList.isNotEmpty()) { + audioContentRepository.findByTheme( + memberId = member.id!!, + theme = themeList[0], + isAdult = member.auth != null, + contentType = ContentType.ALL, + offset = 0, + limit = 10, + isFree = true + ) + } else { + emptyList() + } + + val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) + .map { + GetContentCurationResponse( + title = it.title, + items = contentRepository.findAudioContentByCurationId( + curationId = it.id!!, + isAdult = isAdult, + contentType = ContentType.ALL + ) + ) + } + + return GetContentMainTabFreeResponse( + contentBannerList = contentBannerList, + introduceCreator = if (introduceCreator.isNotEmpty()) { + introduceCreator[0] + } else { + null + }, + recommendSeriesList = recommendSeriesList, + themeList = themeList, + newFreeContentList = newFreeContentList, + curationList = curationList + ) + } +} 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 new file mode 100644 index 0000000..aed9911 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/GetContentMainTabFreeResponse.kt @@ -0,0 +1,16 @@ +package kr.co.vividnext.sodalive.content.main.tab.free + +import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +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 + +data class GetContentMainTabFreeResponse( + val tabId: Long = 7, + val contentBannerList: List, + val introduceCreator: GetContentCurationResponse?, + val recommendSeriesList: List, + val themeList: List, + val newFreeContentList: List, + val curationList: List +)