From 239516b98b5e2c935321c8cd9d2729037937c6d5 Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 11:54:08 +0900 Subject: [PATCH 01/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20-=20=ED=99=88,=20=EB=8B=A8=ED=8E=B8=20-=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=EB=B3=84=20=EC=9D=B8=EA=B8=B0=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=20-=20=EB=B3=B4=EC=9D=B4=EB=8A=94=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=20=EC=A1=B0=EA=B1=B4=20=EC=95=84=EB=9E=98=EC=99=80=20?= =?UTF-8?q?=EA=B0=99=EC=9D=B4=20=EB=B3=80=EA=B2=BD=20-=20=EC=9C=A0?= =?UTF-8?q?=EB=A3=8C=20=EC=BD=98=ED=85=90=EC=B8=A0=204=EA=B0=9C=20?= =?UTF-8?q?=EC=9D=B4=EC=83=81=20=EB=93=B1=EB=A1=9D=ED=95=9C=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=EC=9D=98=20=EC=A3=BC=EA=B0=84=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=20=ED=8C=90=EB=A7=A4=20=EA=B0=9C=EC=88=98=20Top=2020?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentService.kt | 2 +- .../tab/home/AudioContentMainTabHomeService.kt | 7 +++---- .../sodalive/rank/RankingRepository.kt | 18 +++++++++--------- .../vividnext/sodalive/rank/RankingService.kt | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt index 205951e..d14f065 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt @@ -69,7 +69,7 @@ class AudioContentMainTabContentService( // 이벤트 배너 val eventBannerList = eventService.getEventList(isAdult = isAdult) - val contentRankCreatorList = rankingService.fetchCreatorByContentRevenueRankTop20( + val contentRankCreatorList = rankingService.fetchCreatorBySellContentCountRankTop20( memberId = member.id!!, startDate = dailyRankingStartDate.minusDays(1), endDate = dailyRankingEndDate diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt index 1a1a0ec..8aed26d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt @@ -74,11 +74,10 @@ class AudioContentMainTabHomeService( /* 채널별 인기 콘텐츠 * - 콘텐츠를 4개 이상 등록한 채널 - * - 주간 콘텐츠 매출 Top 20 채널 - * - 해당 채널의 누적 매출 Top 2 - * - 해당 채널의 누적 판매 개수 Top 2 + * - 주간 콘텐츠 판매 개수 Top 20 채널 + * - 해당 채널의 누적 판매 개수 Top 4 */ - val contentRankCreatorList = rankingService.fetchCreatorByContentRevenueRankTop20( + val contentRankCreatorList = rankingService.fetchCreatorBySellContentCountRankTop20( memberId = member.id!!, startDate = startDate.minusDays(1), endDate = endDate diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index c0e9c65..5d6a605 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -336,7 +336,7 @@ class RankingRepository( .fetch() } - fun fetchCreatorByContentRevenueRankTop20( + fun fetchCreatorBySellContentCountRankTop20( memberId: Long, startDate: LocalDateTime, endDate: LocalDateTime @@ -350,9 +350,12 @@ class RankingRepository( .and(order.createdAt.goe(startDate)) .and(order.createdAt.lt(startDate)) - val where = member.isActive.isTrue + val memberCondition = member.isActive.isTrue .and(member.role.eq(MemberRole.CREATOR)) - .and(audioContent.isActive.isTrue) + .and(member.id.eq(audioContent.member.id)) + + val where = audioContent.isActive.isTrue + .and(audioContent.price.gt(0)) .and(audioContent.duration.isNotNull) .and(audioContent.limited.isNull) .and(blockMember.id.isNull) @@ -365,17 +368,14 @@ class RankingRepository( member.profileImage.prepend("/").prepend(imageHost) ) ) - .from(member) - .innerJoin(audioContent).on(member.id.eq(audioContent.member.id)) + .from(audioContent) + .innerJoin(member).on(memberCondition) .leftJoin(order).on(ordersCondition) .leftJoin(blockMember).on(blockMemberCondition) .where(where) .groupBy(member.id) .having(audioContent.id.count().goe(4)) - .orderBy( - order.can.sum().desc(), - Expressions.numberTemplate(Double::class.java, "function('rand')").asc() - ) + .orderBy(order.id.count().desc(), member.id.desc()) .offset(0) .limit(20) .fetch() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index 5f657d0..37db5fe 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -181,12 +181,12 @@ class RankingService( } } - fun fetchCreatorByContentRevenueRankTop20( + fun fetchCreatorBySellContentCountRankTop20( memberId: Long, startDate: LocalDateTime, endDate: LocalDateTime ): List { - return repository.fetchCreatorByContentRevenueRankTop20(memberId, startDate, endDate) + return repository.fetchCreatorBySellContentCountRankTop20(memberId, startDate, endDate) } fun fetchCreatorContentBySalesTop2( -- 2.40.1 From dc0902c5557a840f2313be748b0dda5228e8ea5a Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 12:07:21 +0900 Subject: [PATCH 02/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20-=20=EC=B1=84=EB=84=90=EB=B3=84=20=EC=9D=B8?= =?UTF-8?q?=EA=B8=B0=20=EC=BD=98=ED=85=90=EC=B8=A0=20-=20=ED=8C=90?= =?UTF-8?q?=EB=A7=A4=EA=B0=9C=EC=88=98=20=EC=88=9C=EC=9C=84=20Top2=20->=20?= =?UTF-8?q?Top4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tab/asmr/AudioContentMainTabAsmrService.kt | 4 ++-- .../content/AudioContentMainTabContentService.kt | 4 ++-- .../tab/home/AudioContentMainTabHomeService.kt | 14 ++------------ .../main/tab/home/GetContentMainTabHomeResponse.kt | 1 - .../replay/AudioContentMainTabLiveReplayService.kt | 4 ++-- .../vividnext/sodalive/rank/RankingRepository.kt | 4 ++-- .../co/vividnext/sodalive/rank/RankingService.kt | 4 ++-- 7 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt index 4ac40c4..bbb3a6e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt @@ -79,7 +79,7 @@ class AudioContentMainTabAsmrService( } val salesCountRankContentList = if (creatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesCountTop2( + rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorList[0].creatorId, isAdult = isAdult, theme = theme @@ -122,7 +122,7 @@ class AudioContentMainTabAsmrService( theme = theme ) - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult, theme = theme diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt index d14f065..c800664 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt @@ -85,7 +85,7 @@ class AudioContentMainTabContentService( } val salesCountRankContentList = if (contentRankCreatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesCountTop2( + rankingService.fetchCreatorContentBySalesCountTop4( creatorId = contentRankCreatorList[0].creatorId, isAdult = member.auth != null ) @@ -150,7 +150,7 @@ class AudioContentMainTabContentService( isAdult = isAdult ) - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt index 8aed26d..820b2e5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt @@ -83,17 +83,8 @@ class AudioContentMainTabHomeService( endDate = endDate ) - val salesRankContentList = if (contentRankCreatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesTop2( - creatorId = contentRankCreatorList[0].creatorId, - isAdult = member.auth != null - ) - } else { - emptyList() - } - val salesCountRankContentList = if (contentRankCreatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesCountTop2( + rankingService.fetchCreatorContentBySalesCountTop4( creatorId = contentRankCreatorList[0].creatorId, isAdult = member.auth != null ) @@ -110,7 +101,6 @@ class AudioContentMainTabHomeService( rankContentList = rankContentList, eventBannerList = eventBannerList, contentRankCreatorList = contentRankCreatorList, - salesRankContentList = salesRankContentList, salesCountRankContentList = salesCountRankContentList ) } @@ -121,7 +111,7 @@ class AudioContentMainTabHomeService( isAdult = isAdult ) - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt index db9b01f..24ae94d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt @@ -18,6 +18,5 @@ data class GetContentMainTabHomeResponse( val rankContentList: List, val eventBannerList: GetEventResponse, val contentRankCreatorList: List, - val salesRankContentList: List, val salesCountRankContentList: List ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt index d6d1164..80ba8c2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt @@ -79,7 +79,7 @@ class AudioContentMainTabLiveReplayService( } val salesCountRankContentList = if (creatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesCountTop2( + rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorList[0].creatorId, isAdult = isAdult, theme = theme @@ -122,7 +122,7 @@ class AudioContentMainTabLiveReplayService( theme = theme ) - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult, theme = theme diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 5d6a605..a7a4d44 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -429,7 +429,7 @@ class RankingRepository( .fetch() } - fun fetchCreatorContentBySalesCountTop2( + fun fetchCreatorContentBySalesCountTop4( creatorId: Long, isAdult: Boolean, theme: String @@ -473,7 +473,7 @@ class RankingRepository( .groupBy(audioContent.id) .orderBy(order.id.count().desc()) .offset(0) - .limit(2) + .limit(4) .fetch() } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index 37db5fe..2c98024 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -197,12 +197,12 @@ class RankingService( return repository.fetchCreatorContentBySalesTop2(creatorId, isAdult, theme) } - fun fetchCreatorContentBySalesCountTop2( + fun fetchCreatorContentBySalesCountTop4( creatorId: Long, isAdult: Boolean, theme: String = "" ): List { - return repository.fetchCreatorContentBySalesCountTop2(creatorId, isAdult, theme) + return repository.fetchCreatorContentBySalesCountTop4(creatorId, isAdult, theme) } fun fetchCreatorBySeriesRevenueRankTop20( -- 2.40.1 From f9c34d14c37f6833661f50441f335c4266d8af37 Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 12:15:02 +0900 Subject: [PATCH 03/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20-=20=EC=B1=84=EB=84=90=EB=B3=84=20**=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20-=20=EB=A7=A4=EC=B6=9C=20=EC=88=9C?= =?UTF-8?q?=EC=9C=84=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tab/GetPopularContentByCreatorResponse.kt | 8 ---- .../asmr/AudioContentMainTabAsmrService.kt | 31 ++---------- .../tab/asmr/GetContentMainTabAsmrResponse.kt | 1 - .../AudioContentMainTabContentService.kt | 25 +--------- .../GetContentMainTabContentResponse.kt | 1 - .../home/AudioContentMainTabHomeService.kt | 16 ++----- .../AudioContentMainTabLiveReplayService.kt | 31 ++---------- .../GetContentMainTabLiveReplayResponse.kt | 1 - .../sodalive/rank/RankingRepository.kt | 48 ------------------- .../vividnext/sodalive/rank/RankingService.kt | 8 ---- 10 files changed, 13 insertions(+), 157 deletions(-) delete mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt deleted file mode 100644 index 6f8cdc8..0000000 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package kr.co.vividnext.sodalive.content.main.tab - -import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem - -data class GetPopularContentByCreatorResponse( - val salesRankContentList: List, - val salesCountRankContentList: List -) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt index bbb3a6e..70eb0b0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt @@ -2,11 +2,11 @@ package kr.co.vividnext.sodalive.content.main.tab.asmr import kr.co.vividnext.sodalive.content.AudioContentRepository 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.AudioContentCurationQueryRepository import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse -import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.rank.RankingService @@ -68,16 +68,6 @@ class AudioContentMainTabAsmrService( minCount = 4 ) - val salesRankContentList = if (creatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesTop2( - creatorId = creatorList[0].creatorId, - isAdult = isAdult, - theme = theme - ) - } else { - emptyList() - } - val salesCountRankContentList = if (creatorList.isNotEmpty()) { rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorList[0].creatorId, @@ -107,30 +97,17 @@ class AudioContentMainTabAsmrService( newAsmrContentList = newAsmrContentList, rankAsmrContentList = rankAsmrContentList, creatorList = creatorList, - salesRankContentList = salesRankContentList, salesCountRankContentList = salesCountRankContentList, eventBannerList = eventBannerList, curationList = curationList ) } - fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { - val theme = "ASMR" - val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult, - theme = theme - ) - - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( - creatorId = creatorId, - isAdult = isAdult, - theme = theme - ) - - return GetPopularContentByCreatorResponse( - salesRankContentList = salesRankContentList, - salesCountRankContentList = salesCountRankContentList + theme = "ASMR" ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt index 9162e40..5e324f5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt @@ -13,7 +13,6 @@ data class GetContentMainTabAsmrResponse( val newAsmrContentList: List, val rankAsmrContentList: List, val creatorList: List, - val salesRankContentList: List, val salesCountRankContentList: List, val eventBannerList: GetEventResponse, val curationList: List diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt index c800664..22d67c7 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt @@ -5,7 +5,6 @@ import kr.co.vividnext.sodalive.content.ContentType import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService -import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member @@ -75,15 +74,6 @@ class AudioContentMainTabContentService( endDate = dailyRankingEndDate ) - val salesRankContentList = if (contentRankCreatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesTop2( - creatorId = contentRankCreatorList[0].creatorId, - isAdult = member.auth != null - ) - } else { - emptyList() - } - val salesCountRankContentList = if (contentRankCreatorList.isNotEmpty()) { rankingService.fetchCreatorContentBySalesCountTop4( creatorId = contentRankCreatorList[0].creatorId, @@ -100,7 +90,6 @@ class AudioContentMainTabContentService( rankSortTypeList = listOf("매출", "댓글", "좋아요"), rankContentList = rankContentList, contentRankCreatorList = contentRankCreatorList, - salesRankContentList = salesRankContentList, salesCountRankContentList = salesCountRankContentList, eventBannerList = eventBannerList ) @@ -144,20 +133,10 @@ class AudioContentMainTabContentService( ) } - fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { - val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult ) - - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( - creatorId = creatorId, - isAdult = isAdult - ) - - return GetPopularContentByCreatorResponse( - salesRankContentList = salesRankContentList, - salesCountRankContentList = salesCountRankContentList - ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt index 721e960..649363e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt @@ -14,7 +14,6 @@ data class GetContentMainTabContentResponse( val rankSortTypeList: List, val rankContentList: List, val contentRankCreatorList: List, - val salesRankContentList: List, val salesCountRankContentList: List, val eventBannerList: GetEventResponse ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt index 820b2e5..9eb9f3b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt @@ -1,7 +1,7 @@ package kr.co.vividnext.sodalive.content.main.tab.home +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService -import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.notice.ServiceNoticeService @@ -105,20 +105,10 @@ class AudioContentMainTabHomeService( ) } - fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { - val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult ) - - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( - creatorId = creatorId, - isAdult = isAdult - ) - - return GetPopularContentByCreatorResponse( - salesRankContentList = salesRankContentList, - salesCountRankContentList = salesCountRankContentList - ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt index 80ba8c2..daecdfb 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt @@ -2,11 +2,11 @@ package kr.co.vividnext.sodalive.content.main.tab.replay import kr.co.vividnext.sodalive.content.AudioContentRepository 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.AudioContentCurationQueryRepository import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse -import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.rank.RankingService @@ -68,16 +68,6 @@ class AudioContentMainTabLiveReplayService( minCount = 4 ) - val salesRankContentList = if (creatorList.isNotEmpty()) { - rankingService.fetchCreatorContentBySalesTop2( - creatorId = creatorList[0].creatorId, - isAdult = isAdult, - theme = theme - ) - } else { - emptyList() - } - val salesCountRankContentList = if (creatorList.isNotEmpty()) { rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorList[0].creatorId, @@ -107,30 +97,17 @@ class AudioContentMainTabLiveReplayService( newLiveReplayContentList = newLiveReplayContentList, rankLiveReplayContentList = rankLiveReplayContentList, creatorList = creatorList, - salesRankContentList = salesRankContentList, salesCountRankContentList = salesCountRankContentList, eventBannerList = eventBannerList, curationList = curationList ) } - fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { - val theme = "다시듣기" - val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchCreatorContentBySalesCountTop4( creatorId = creatorId, isAdult = isAdult, - theme = theme - ) - - val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop4( - creatorId = creatorId, - isAdult = isAdult, - theme = theme - ) - - return GetPopularContentByCreatorResponse( - salesRankContentList = salesRankContentList, - salesCountRankContentList = salesCountRankContentList + theme = "다시듣기" ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt index 05860b2..6991faf 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt @@ -13,7 +13,6 @@ data class GetContentMainTabLiveReplayResponse( val newLiveReplayContentList: List, val rankLiveReplayContentList: List, val creatorList: List, - val salesRankContentList: List, val salesCountRankContentList: List, val eventBannerList: GetEventResponse, val curationList: List diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index a7a4d44..9c3714d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -381,54 +381,6 @@ class RankingRepository( .fetch() } - fun fetchCreatorContentBySalesTop2( - creatorId: Long, - isAdult: Boolean, - theme: String - ): List { - var where = member.isActive.isTrue - .and(member.role.eq(MemberRole.CREATOR)) - .and(audioContent.isActive.isTrue) - .and(audioContent.duration.isNotNull) - .and(audioContent.limited.isNull) - .and(audioContentTheme.isActive.isTrue) - .and(order.isActive.isTrue) - .and(member.id.eq(creatorId)) - - if (!isAdult) { - where = where.and(series.isAdult.isFalse) - } - - if (theme.isNotBlank()) { - where = where.and(audioContentTheme.theme.eq(theme)) - } - - return queryFactory - .select( - QGetAudioContentRankingItem( - audioContent.id, - audioContent.title, - audioContent.coverImage.prepend("/").prepend(imageHost), - audioContentTheme.theme, - audioContent.price, - audioContent.duration, - member.id, - member.nickname, - member.profileImage.prepend("/").prepend(imageHost) - ) - ) - .from(order) - .innerJoin(order.audioContent, audioContent) - .innerJoin(audioContent.theme, audioContentTheme) - .innerJoin(audioContent.member, member) - .where(where) - .groupBy(audioContent.id) - .orderBy(order.can.sum().desc()) - .offset(0) - .limit(2) - .fetch() - } - fun fetchCreatorContentBySalesCountTop4( creatorId: Long, isAdult: Boolean, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index 2c98024..f7e907c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -189,14 +189,6 @@ class RankingService( return repository.fetchCreatorBySellContentCountRankTop20(memberId, startDate, endDate) } - fun fetchCreatorContentBySalesTop2( - creatorId: Long, - isAdult: Boolean, - theme: String = "" - ): List { - return repository.fetchCreatorContentBySalesTop2(creatorId, isAdult, theme) - } - fun fetchCreatorContentBySalesCountTop4( creatorId: Long, isAdult: Boolean, -- 2.40.1 From 5521f39cc5b3f4fe828844b401f78f56cee2b1df Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 12:22:34 +0900 Subject: [PATCH 04/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20-=20=EC=B1=84=EB=84=90=EB=B3=84=20**=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20-=20=EC=9C=A0=EB=A3=8C=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=EB=A7=8C=20=EA=B0=9C=EC=88=98=EC=97=90=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/main/tab/AudioContentMainTabRepository.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt index a5ef40a..0a1ec5d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt @@ -31,6 +31,7 @@ class AudioContentMainTabRepository( val where = member.isActive.isTrue .and(member.role.eq(MemberRole.CREATOR)) .and(audioContent.isActive.isTrue) + .and(audioContent.price.gt(0)) .and(audioContent.duration.isNotNull) .and(audioContent.limited.isNull) .and(audioContentTheme.isActive.isTrue) -- 2.40.1 From 3344757af80ddb019e05b896d72eebdb049b8b28 Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 12:30:17 +0900 Subject: [PATCH 05/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EB=AC=B4=EB=A3=8C=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=EA=B0=80=20?= =?UTF-8?q?=EB=A8=BC=EC=A0=80=20=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/main/tab/free/AudioContentMainTabFreeService.kt | 1 - 1 file changed, 1 deletion(-) 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 index df99edc..732f705 100644 --- 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 @@ -53,7 +53,6 @@ class AudioContentMainTabFreeService( val newFreeContentList = if (themeList.isNotEmpty()) { audioContentRepository.findByTheme( memberId = member.id!!, - theme = themeList[0], isAdult = member.auth != null, contentType = ContentType.ALL, offset = 0, -- 2.40.1 From b529d49e78e612a3e9ada75d668b7ee8d77f70b2 Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 20:22:57 +0900 Subject: [PATCH 06/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=95=8C=EB=9E=8C=20=ED=83=AD=20-=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EC=95=8C=EB=9E=8C=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20-=20=EC=A0=84=EC=B2=B4=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentRepository.kt | 39 +++++++++++++++++++ .../alarm/AudioContentMainTabAlarmService.kt | 14 +++++-- 2 files changed, 50 insertions(+), 3 deletions(-) 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 d0e30dc..22d289c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -81,6 +81,12 @@ interface AudioContentQueryRepository { limit: Long = 20 ): List + fun totalAlarmCountByTheme( + memberId: Long, + theme: List, + isAdult: Boolean = false + ): Int + fun totalCountByTheme( memberId: Long, theme: String = "", @@ -486,6 +492,39 @@ class AudioContentQueryRepositoryImpl( .fetch() } + override fun totalAlarmCountByTheme(memberId: Long, theme: List, isAdult: Boolean): Int { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + var where = audioContent.isActive.isTrue + .and(audioContent.duration.isNotNull) + .and( + audioContent.releaseDate.isNull + .or(audioContent.releaseDate.loe(LocalDateTime.now())) + .or(audioContent.member.id.eq(memberId)) + ) + .and(blockMember.id.isNull) + + if (!isAdult) { + where = where.and(audioContent.isAdult.isFalse) + } + + if (theme.isNotEmpty()) { + where = where.and(audioContentTheme.theme.`in`(theme)) + } + + return queryFactory + .select(audioContent.id) + .from(audioContent) + .innerJoin(audioContent.member, member) + .innerJoin(audioContent.theme, audioContentTheme) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .fetch() + .size + } + override fun totalCountByTheme(memberId: Long, theme: String, isAdult: Boolean, contentType: ContentType): Int { var where = audioContent.isActive.isTrue .and(audioContent.duration.isNotNull) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt index bac8749..53e9eb2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt @@ -1,7 +1,7 @@ package kr.co.vividnext.sodalive.content.main.tab.alarm import kr.co.vividnext.sodalive.content.AudioContentRepository -import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.GetNewContentAllResponse 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 @@ -86,7 +86,7 @@ class AudioContentMainTabAlarmService( member: Member, offset: Long, limit: Long - ): List { + ): GetNewContentAllResponse { val alarmThemeList = if (theme.isNotBlank()) { listOf(theme) } else { @@ -96,12 +96,20 @@ class AudioContentMainTabAlarmService( val memberId = member.id!! val isAdult = member.auth != null - return contentRepository.findAlarmContentByTheme( + val totalCount = contentRepository.totalAlarmCountByTheme( + memberId = memberId, + theme = alarmThemeList, + isAdult = isAdult + ) + + val items = contentRepository.findAlarmContentByTheme( memberId = memberId, theme = alarmThemeList, isAdult = isAdult, offset = offset, limit = limit ) + + return GetNewContentAllResponse(totalCount, items) } } -- 2.40.1 From fbfb951825522b7a944f1679c9665e44d66d897d Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 22:50:22 +0900 Subject: [PATCH 07/18] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=EB=A9=94=EC=9D=B8=20=ED=81=90=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=95=84=EC=9D=B4=ED=85=9C=20-=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation/AdminContentCurationController.kt | 5 +++++ .../AdminContentCurationItemRepository.kt | 2 ++ .../curation/AdminContentCurationService.kt | 15 +++++++++++++++ .../curation/UpdateCurationItemOrdersRequest.kt | 6 ++++++ 4 files changed, 28 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/UpdateCurationItemOrdersRequest.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationController.kt index 3bbe3ed..10c897d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationController.kt @@ -60,4 +60,9 @@ class AdminContentCurationController(private val service: AdminContentCurationSe fun removeItemInCuration( @RequestBody request: RemoveItemInCurationRequest ) = ApiResponse.ok(service.removeItemInCuration(request), "큐레이션 아이템을 제거했습니다.") + + @PutMapping("/orders/item") + fun updateItemInCurationOrders( + @RequestBody request: UpdateCurationItemOrdersRequest + ) = ApiResponse.ok(service.updateItemInCurationOrders(request), "수정되었습니다.") } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationItemRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationItemRepository.kt index 28bcc4d..bc1a5ee 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationItemRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationItemRepository.kt @@ -77,6 +77,7 @@ class AdminContentCurationItemQueryRepositoryImpl( audioContentCuration.id.eq(curationId), audioContentCurationItem.isActive.isTrue ) + .orderBy(audioContentCurationItem.orders.asc()) .fetch() } @@ -99,6 +100,7 @@ class AdminContentCurationItemQueryRepositoryImpl( audioContentCuration.id.eq(curationId), audioContentCurationItem.isActive.isTrue ) + .orderBy(audioContentCurationItem.orders.asc()) .fetch() } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationService.kt index 2d3427a..a9745f5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationService.kt @@ -150,4 +150,19 @@ class AdminContentCurationService( audioContentCurationItem?.isActive = false } + + @Transactional + fun updateItemInCurationOrders(request: UpdateCurationItemOrdersRequest) { + val ids = request.itemIds + for (index in ids.indices) { + val item = contentCurationItemRepository.findByCurationIdAndItemId( + curationId = request.curationId, + itemId = ids[index] + ) + + if (item != null) { + item.orders = index + 1 + } + } + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/UpdateCurationItemOrdersRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/UpdateCurationItemOrdersRequest.kt new file mode 100644 index 0000000..b1975ed --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/UpdateCurationItemOrdersRequest.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.admin.content.curation + +data class UpdateCurationItemOrdersRequest( + val curationId: Long, + val itemIds: List +) -- 2.40.1 From 51c4044e2f581ba3c3b1712791a0f87b27c1be9f Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 17 Feb 2025 23:34:58 +0900 Subject: [PATCH 08/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentService.kt | 23 ++++++++++++++++--- .../GetContentMainTabContentResponse.kt | 4 +++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt index 22d67c7..c38ad2c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt @@ -5,6 +5,8 @@ import kr.co.vividnext.sodalive.content.ContentType import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem 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.AudioContentCurationQueryRepository +import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member @@ -18,7 +20,8 @@ class AudioContentMainTabContentService( private val audioContentRepository: AudioContentRepository, private val audioContentThemeRepository: AudioContentThemeQueryRepository, private val rankingService: RankingService, - private val eventService: EventService + private val eventService: EventService, + private val curationRepository: AudioContentCurationQueryRepository ) { fun fetchData( isAdultContentVisible: Boolean, @@ -27,10 +30,11 @@ class AudioContentMainTabContentService( ): GetContentMainTabContentResponse { val memberId = member.id!! val isAdult = member.auth != null + val tabId = 3L // 단편 배너 val contentBannerList = bannerService.getBannerList( - tabId = 3, + tabId = tabId, memberId = memberId, isAdult = isAdult ) @@ -83,6 +87,18 @@ class AudioContentMainTabContentService( emptyList() } + val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) + .map { + GetContentCurationResponse( + title = it.title, + items = audioContentRepository.findAudioContentByCurationIdV2( + curationId = it.id!!, + memberId = memberId, + isAdult = isAdult + ) + ) + } + return GetContentMainTabContentResponse( bannerList = contentBannerList, contentThemeList = themeOfContentList, @@ -91,7 +107,8 @@ class AudioContentMainTabContentService( rankContentList = rankContentList, contentRankCreatorList = contentRankCreatorList, salesCountRankContentList = salesCountRankContentList, - eventBannerList = eventBannerList + eventBannerList = eventBannerList, + curationList = curationList ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt index 649363e..7451491 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt @@ -4,6 +4,7 @@ import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.GetAudioContentBannerResponse +import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse import kr.co.vividnext.sodalive.event.GetEventResponse data class GetContentMainTabContentResponse( @@ -15,5 +16,6 @@ data class GetContentMainTabContentResponse( val rankContentList: List, val contentRankCreatorList: List, val salesCountRankContentList: List, - val eventBannerList: GetEventResponse + val eventBannerList: GetEventResponse, + val curationList: List ) -- 2.40.1 From ab2f581c9f99baabfa1a627c9aba504fdc86a204 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 01:43:37 +0900 Subject: [PATCH 09/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EB=AC=B4=EB=A3=8C=20?= =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/AudioContent.kt | 1 + .../main/tab/AudioContentMainTabRepository.kt | 35 +++++++++++++++++++ .../free/AudioContentMainTabFreeController.kt | 15 ++++++++ .../free/AudioContentMainTabFreeService.kt | 18 ++++++++++ .../tab/free/GetContentMainTabFreeResponse.kt | 4 +++ .../sodalive/rank/RankingRepository.kt | 34 ++++++++++++++++++ .../vividnext/sodalive/rank/RankingService.kt | 4 +++ 7 files changed, 111 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt index 688ac4d..00d3eb3 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContent.kt @@ -32,6 +32,7 @@ data class AudioContent( var title: String, @Column(columnDefinition = "TEXT", nullable = false) var detail: String, + var playCount: Long = 0, var price: Int = 0, var releaseDate: LocalDateTime? = null, val limited: Int? = null, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt index 0a1ec5d..3604c0e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt @@ -60,4 +60,39 @@ class AudioContentMainTabRepository( .limit(20) .fetch() } + + fun findCreatorWithHasFreeContent(memberId: Long, minCount: Int): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + val where = member.isActive.isTrue + .and(member.role.eq(MemberRole.CREATOR)) + .and(audioContent.isActive.isTrue) + .and(audioContent.price.loe(0)) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + .and(blockMember.id.isNull) + + return queryFactory + .select( + QContentCreatorResponse( + member.id, + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) + ) + ) + .from(member) + .innerJoin(audioContent).on(member.id.eq(audioContent.member.id)) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .groupBy(member.id) + .having(audioContent.id.count().goe(minCount)) + .orderBy( + Expressions.numberTemplate(Double::class.java, "function('rand')").asc() + ) + .offset(0) + .limit(20) + .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 index 4c8fa63..2547d48 100644 --- 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 @@ -60,4 +60,19 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab ) ) } + + @GetMapping("/popular-content-by-creator") + fun getPopularContentByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getPopularContentByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } 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 index 732f705..0b1f9ea 100644 --- 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 @@ -3,20 +3,25 @@ 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.GetAudioContentMainItem +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.AudioContentCurationQueryRepository +import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository 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 kr.co.vividnext.sodalive.rank.RankingService import org.springframework.stereotype.Service @Service class AudioContentMainTabFreeService( + private val repository: AudioContentMainTabRepository, private val bannerService: AudioContentBannerService, private val recommendSeriesRepository: RecommendSeriesRepository, private val curationRepository: AudioContentCurationQueryRepository, private val contentRepository: AudioContentRepository, + private val rankingService: RankingService, private val audioContentRepository: AudioContentRepository, private val audioContentThemeRepository: AudioContentThemeQueryRepository ) { @@ -63,6 +68,13 @@ class AudioContentMainTabFreeService( emptyList() } + val creatorList = repository.findCreatorWithHasFreeContent(memberId, 4) + val playCountRankContentList = if (creatorList.isNotEmpty()) { + rankingService.fetchFreeContentByCreatorIdTop4(creatorList[0].creatorId, isAdult) + } else { + emptyList() + } + val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) .filter { it.title != "크리에이터 소개" } .map { @@ -86,6 +98,8 @@ class AudioContentMainTabFreeService( recommendSeriesList = recommendSeriesList, themeList = themeList, newFreeContentList = newFreeContentList, + creatorList = creatorList, + playCountRankContentList = playCountRankContentList, curationList = curationList ) } @@ -131,4 +145,8 @@ class AudioContentMainTabFreeService( isFree = true ) } + + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchFreeContentByCreatorIdTop4(creatorId, isAdult) + } } 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 index aed9911..e0035ad 100644 --- 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 @@ -1,6 +1,8 @@ package kr.co.vividnext.sodalive.content.main.tab.free +import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem 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 @@ -12,5 +14,7 @@ data class GetContentMainTabFreeResponse( val recommendSeriesList: List, val themeList: List, val newFreeContentList: List, + val creatorList: List, + val playCountRankContentList: List, val curationList: List ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 9c3714d..2d9a3ba 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -508,4 +508,38 @@ class RankingRepository( .limit(10) .fetch() } + + fun fetchFreeContentByCreatorIdTop4(creatorId: Long, isAdult: Boolean): List { + var where = member.isActive.isTrue + .and(member.id.eq(creatorId)) + .and(member.role.eq(MemberRole.CREATOR)) + .and(audioContent.isActive.isTrue) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + + if (!isAdult) { + where = where.and(series.isAdult.isFalse) + } + + return queryFactory + .select( + QGetAudioContentRankingItem( + audioContent.id, + audioContent.title, + audioContent.coverImage.prepend("/").prepend(imageHost), + audioContentTheme.theme, + audioContent.price, + audioContent.duration, + member.id, + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) + ) + ) + .from(audioContent) + .where(where) + .orderBy(audioContent.playCount.desc()) + .offset(0) + .limit(4) + .fetch() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index f7e907c..f94e672 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -209,4 +209,8 @@ class RankingService( val seriesList = repository.fetchCreatorSeriesBySales(creatorId = creatorId, isAdult = isAdult) return seriesToSeriesListItem(seriesList, isAdult) } + + fun fetchFreeContentByCreatorIdTop4(creatorId: Long, isAdult: Boolean): List { + return repository.fetchFreeContentByCreatorIdTop4(creatorId, isAdult) + } } -- 2.40.1 From 308127d044c7f5f21eaf13014c9337d89584e8a1 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 01:49:52 +0900 Subject: [PATCH 10/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EB=AC=B4=EB=A3=8C=20?= =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 2d9a3ba..1dd4352 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -516,6 +516,7 @@ class RankingRepository( .and(audioContent.isActive.isTrue) .and(audioContent.duration.isNotNull) .and(audioContent.limited.isNull) + .and(audioContent.price.loe(0)) if (!isAdult) { where = where.and(series.isAdult.isFalse) -- 2.40.1 From 43ea4191c300c4f9a89690276444bd4909531263 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 01:59:18 +0900 Subject: [PATCH 11/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=ED=85=8C=EB=A7=88=EC=99=80=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=AF=80?= =?UTF-8?q?=EB=A1=9C=20=ED=95=B4=EB=8B=B9=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=A1=B0=EC=9D=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 1dd4352..6e1b34c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -537,6 +537,8 @@ class RankingRepository( ) ) .from(audioContent) + .innerJoin(audioContent.theme, audioContentTheme) + .innerJoin(audioContent.member, member) .where(where) .orderBy(audioContent.playCount.desc()) .offset(0) -- 2.40.1 From e0565f7eed16d8bcdaba1da60e162468a4f8842e Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 15:27:39 +0900 Subject: [PATCH 12/18] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EB=8B=A8=ED=8E=B8=20?= =?UTF-8?q?-=20=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95,=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C,=20=EC=88=9C=EC=84=9C=EB=B3=80=EA=B2=BD=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...minContentHashTagCurationItemRepository.kt | 72 +++++++++++ .../tag/AdminHashTagCurationController.kt | 63 ++++++++++ .../tag/AdminHashTagCurationRepository.kt | 72 +++++++++++ .../tag/AdminHashTagCurationService.kt | 116 ++++++++++++++++++ .../tag/AudioContentHashTagCurationRequest.kt | 17 +++ .../GetAdminContentHashTagCurationResponse.kt | 9 ++ .../GetAdminHashTagCurationItemResponse.kt | 12 ++ .../curation/tag/ContentHashTagCuration.kt | 30 +++++ 8 files changed, 391 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminContentHashTagCurationItemRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationController.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AudioContentHashTagCurationRequest.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminContentHashTagCurationResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminHashTagCurationItemResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/tag/ContentHashTagCuration.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminContentHashTagCurationItemRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminContentHashTagCurationItemRepository.kt new file mode 100644 index 0000000..17173da --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminContentHashTagCurationItemRepository.kt @@ -0,0 +1,72 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.QAudioContent.audioContent +import kr.co.vividnext.sodalive.content.main.curation.tag.ContentHashTagCurationItem +import kr.co.vividnext.sodalive.content.main.curation.tag.QContentHashTagCuration.contentHashTagCuration +import kr.co.vividnext.sodalive.content.main.curation.tag.QContentHashTagCurationItem.contentHashTagCurationItem +import org.springframework.beans.factory.annotation.Value +import org.springframework.data.jpa.repository.JpaRepository + +interface AdminContentHashTagCurationItemRepository : + JpaRepository, + AdminContentHashTagCurationItemQueryRepository + +interface AdminContentHashTagCurationItemQueryRepository { + fun getContentHashTagCurationItemList(curationId: Long): List + fun findByCurationIdAndContentId(curationId: Long, contentId: Long?): ContentHashTagCurationItem? + fun findByCurationIdAndItemId(curationId: Long, itemId: Long): ContentHashTagCurationItem? +} + +class AdminContentHashTagCurationItemQueryRepositoryImpl( + val queryFactory: JPAQueryFactory, + + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String +) : AdminContentHashTagCurationItemQueryRepository { + override fun getContentHashTagCurationItemList(curationId: Long): List { + return queryFactory + .select( + QGetAdminHashTagCurationItemResponse( + contentHashTagCurationItem.id, + audioContent.title, + audioContent.detail, + audioContent.coverImage.prepend("/").prepend(imageHost), + audioContent.member.nickname.coalesce(""), + audioContent.isAdult + ) + ) + .from(contentHashTagCurationItem) + .innerJoin(contentHashTagCurationItem.curation, contentHashTagCuration) + .innerJoin(contentHashTagCurationItem.content, audioContent) + .where( + contentHashTagCuration.id.eq(curationId), + contentHashTagCurationItem.isActive.isTrue, + audioContent.isActive.isTrue + ) + .orderBy(contentHashTagCurationItem.orders.asc()) + .fetch() + } + + override fun findByCurationIdAndContentId(curationId: Long, contentId: Long?): ContentHashTagCurationItem? { + return queryFactory + .selectFrom(contentHashTagCurationItem) + .innerJoin(contentHashTagCurationItem.curation, contentHashTagCuration) + .innerJoin(contentHashTagCurationItem.content, audioContent) + .where( + contentHashTagCuration.id.eq(curationId), + audioContent.id.eq(contentId) + ) + .fetchFirst() + } + + override fun findByCurationIdAndItemId(curationId: Long, itemId: Long): ContentHashTagCurationItem? { + return queryFactory.selectFrom(contentHashTagCurationItem) + .innerJoin(contentHashTagCurationItem.curation, contentHashTagCuration) + .where( + contentHashTagCuration.id.eq(curationId), + contentHashTagCurationItem.id.eq(itemId) + ) + .fetchFirst() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationController.kt new file mode 100644 index 0000000..de905b7 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationController.kt @@ -0,0 +1,63 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +import kr.co.vividnext.sodalive.admin.content.curation.AddItemToCurationRequest +import kr.co.vividnext.sodalive.admin.content.curation.RemoveItemInCurationRequest +import kr.co.vividnext.sodalive.admin.content.curation.UpdateCurationItemOrdersRequest +import kr.co.vividnext.sodalive.common.ApiResponse +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/admin/audio-content/tag/curation") +@PreAuthorize("hasRole('ADMIN')") +class AdminHashTagCurationController(private val service: AdminHashTagCurationService) { + @GetMapping + fun getContentHashTagCurationList() = ApiResponse.ok(service.getContentHashTagCurationList()) + + @PostMapping + fun createContentHashTagCuration( + @RequestBody request: CreateContentHashTagCurationRequest + ) = ApiResponse.ok(service.createContentHashTagCuration(request)) + + @PutMapping + fun updateContentHashTagCuration( + @RequestBody request: UpdateContentHashTagCurationRequest + ) = ApiResponse.ok(service.updateContentHashTagCuration(request)) + + @PutMapping("/orders") + fun updateContentHashTagCurationOrders( + @RequestBody request: UpdateContentHashTagCurationOrderRequest + ) = ApiResponse.ok(service.updateContentHashTagCurationOrders(request.ids), "수정되었습니다.") + + @GetMapping("/items") + fun getHashTagCurationItemList( + @RequestParam curationId: Long + ) = ApiResponse.ok(service.getHashTagCurationItemList(curationId = curationId)) + + @GetMapping("/search/content") + fun searchHashTagCurationContentItem( + @RequestParam curationId: Long, + @RequestParam searchWord: String + ) = ApiResponse.ok(service.searchHashTagCurationContentItem(curationId, searchWord)) + + @PostMapping("/add/item") + fun addItemToHashTagCuration( + @RequestBody request: AddItemToCurationRequest + ) = ApiResponse.ok(service.addItemToHashTagCuration(request), "큐레이션 아이템을 등록했습니다.") + + @PutMapping("/remove/item") + fun removeItemInHashTagCuration( + @RequestBody request: RemoveItemInCurationRequest + ) = ApiResponse.ok(service.removeItemInHashTagCuration(request), "큐레이션 아이템을 제거했습니다.") + + @PutMapping("/orders/item") + fun updateItemInHashTagCurationOrders( + @RequestBody request: UpdateCurationItemOrdersRequest + ) = ApiResponse.ok(service.updateItemInHashTagCurationOrders(request), "수정되었습니다.") +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt new file mode 100644 index 0000000..d58329c --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt @@ -0,0 +1,72 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.admin.content.curation.QSearchCurationItemResponse +import kr.co.vividnext.sodalive.admin.content.curation.SearchCurationItemResponse +import kr.co.vividnext.sodalive.content.QAudioContent.audioContent +import kr.co.vividnext.sodalive.content.main.curation.tag.ContentHashTagCuration +import kr.co.vividnext.sodalive.content.main.curation.tag.QContentHashTagCuration.contentHashTagCuration +import kr.co.vividnext.sodalive.content.main.curation.tag.QContentHashTagCurationItem.contentHashTagCurationItem +import org.springframework.beans.factory.annotation.Value +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +interface AdminHashTagCurationRepository : + JpaRepository, + AdminHashTagCurationQueryRepository + +interface AdminHashTagCurationQueryRepository { + fun getContentHashTagCurationList(): List + fun searchHashTagCurationContentItem(curationId: Long, searchWord: String): List +} + +@Repository +class AdminHashTagCurationQueryRepositoryImpl( + private val queryFactory: JPAQueryFactory, + + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String +) : AdminHashTagCurationQueryRepository { + override fun getContentHashTagCurationList(): List { + return queryFactory + .select( + QGetAdminContentHashTagCurationResponse( + contentHashTagCuration.id, + contentHashTagCuration.tag, + contentHashTagCuration.isAdult + ) + ) + .from(contentHashTagCuration) + .where(contentHashTagCuration.isActive.isTrue) + .orderBy(contentHashTagCuration.orders.asc()) + .fetch() + } + + override fun searchHashTagCurationContentItem( + curationId: Long, + searchWord: String + ): List { + return queryFactory + .select( + QSearchCurationItemResponse( + audioContent.id, + audioContent.title, + audioContent.coverImage.prepend("/").prepend(imageHost) + ) + ) + .from(audioContent) + .leftJoin(contentHashTagCurationItem) + .on( + audioContent.id.eq(contentHashTagCurationItem.content.id) + .and(contentHashTagCurationItem.curation.id.eq(curationId)) + ) + .where( + audioContent.duration.isNotNull + .and(audioContent.member.isNotNull) + .and(audioContent.isActive.isTrue) + .and(audioContent.title.contains(searchWord)) + .and(contentHashTagCurationItem.id.isNull) + ) + .fetch() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt new file mode 100644 index 0000000..741d07d --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt @@ -0,0 +1,116 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +import kr.co.vividnext.sodalive.admin.content.curation.AddItemToCurationRequest +import kr.co.vividnext.sodalive.admin.content.curation.RemoveItemInCurationRequest +import kr.co.vividnext.sodalive.admin.content.curation.SearchCurationItemResponse +import kr.co.vividnext.sodalive.admin.content.curation.UpdateCurationItemOrdersRequest +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.content.AudioContentRepository +import kr.co.vividnext.sodalive.content.main.curation.tag.ContentHashTagCuration +import kr.co.vividnext.sodalive.content.main.curation.tag.ContentHashTagCurationItem +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class AdminHashTagCurationService( + private val repository: AdminHashTagCurationRepository, + private val itemRepository: AdminContentHashTagCurationItemRepository, + private val audioContentRepository: AudioContentRepository +) { + @Transactional + fun createContentHashTagCuration(request: CreateContentHashTagCurationRequest) { + repository.save( + ContentHashTagCuration( + tag = request.tag, + isAdult = request.isAdult + ) + ) + } + + @Transactional + fun updateContentHashTagCuration(request: UpdateContentHashTagCurationRequest) { + val hashTagCuration = repository.findByIdOrNull(id = request.id) + ?: throw SodaException("잘못된 요청입니다.") + + if (request.tag != null) { + hashTagCuration.tag = request.tag + } + + if (request.isAdult != null) { + hashTagCuration.isAdult = request.isAdult + } + + if (request.isActive != null) { + hashTagCuration.isActive = request.isActive + } + } + + @Transactional + fun updateContentHashTagCurationOrders(ids: List) { + for (index in ids.indices) { + val contentHashTagCuration = repository.findByIdOrNull(ids[index]) + + if (contentHashTagCuration != null) { + contentHashTagCuration.orders = index + 1 + } + } + } + + fun getContentHashTagCurationList(): List { + return repository.getContentHashTagCurationList() + } + + fun getHashTagCurationItemList(curationId: Long): List { + return itemRepository.getContentHashTagCurationItemList(curationId) + } + + fun searchHashTagCurationContentItem(curationId: Long, searchWord: String): List { + return repository.searchHashTagCurationContentItem(curationId, searchWord) + } + + @Transactional + fun addItemToHashTagCuration(request: AddItemToCurationRequest) { + val curation = repository.findByIdOrNull(id = request.curationId) + ?: throw SodaException("잘못된 요청입니다.") + + request.itemIdList.forEach { contentId -> + val audioContent = audioContentRepository.findByIdAndActive(contentId) + + if (audioContent != null) { + val item = itemRepository.findByCurationIdAndContentId( + curationId = request.curationId, + contentId = audioContent.id + ) ?: ContentHashTagCurationItem() + item.curation = curation + item.content = audioContent + itemRepository.save(item) + } + } + } + + @Transactional + fun removeItemInHashTagCuration(request: RemoveItemInCurationRequest) { + val item = itemRepository.findByCurationIdAndItemId( + curationId = request.curationId, + itemId = request.itemId + ) + + item?.isActive = false + } + + @Transactional + fun updateItemInHashTagCurationOrders(request: UpdateCurationItemOrdersRequest) { + val ids = request.itemIds + for (index in ids.indices) { + val item = itemRepository.findByCurationIdAndItemId( + curationId = request.curationId, + itemId = ids[index] + ) + + if (item != null) { + item.orders = index + 1 + } + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AudioContentHashTagCurationRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AudioContentHashTagCurationRequest.kt new file mode 100644 index 0000000..22970b6 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AudioContentHashTagCurationRequest.kt @@ -0,0 +1,17 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +data class CreateContentHashTagCurationRequest( + val tag: String, + val isAdult: Boolean +) + +data class UpdateContentHashTagCurationRequest( + val id: Long, + val tag: String?, + val isAdult: Boolean?, + val isActive: Boolean? +) + +data class UpdateContentHashTagCurationOrderRequest( + val ids: List +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminContentHashTagCurationResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminContentHashTagCurationResponse.kt new file mode 100644 index 0000000..c41daf6 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminContentHashTagCurationResponse.kt @@ -0,0 +1,9 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +import com.querydsl.core.annotations.QueryProjection + +data class GetAdminContentHashTagCurationResponse @QueryProjection constructor( + val id: Long, + val tag: String, + val isAdult: Boolean +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminHashTagCurationItemResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminHashTagCurationItemResponse.kt new file mode 100644 index 0000000..b42d042 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/GetAdminHashTagCurationItemResponse.kt @@ -0,0 +1,12 @@ +package kr.co.vividnext.sodalive.admin.content.curation.tag + +import com.querydsl.core.annotations.QueryProjection + +data class GetAdminHashTagCurationItemResponse @QueryProjection constructor( + val id: Long, + val title: String, + val desc: String, + val coverImageUrl: String, + val creatorNickname: String, + val isAdult: Boolean +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/tag/ContentHashTagCuration.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/tag/ContentHashTagCuration.kt new file mode 100644 index 0000000..f1acaf2 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/tag/ContentHashTagCuration.kt @@ -0,0 +1,30 @@ +package kr.co.vividnext.sodalive.content.main.curation.tag + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.content.AudioContent +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne + +@Entity +data class ContentHashTagCuration( + var tag: String, + var orders: Int = 1, + var isAdult: Boolean = false, + var isActive: Boolean = true +) : BaseEntity() + +@Entity +data class ContentHashTagCurationItem( + var orders: Int = 1, + var isActive: Boolean = true +) : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "curation_id", nullable = false) + var curation: ContentHashTagCuration? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "content_id", nullable = false) + var content: AudioContent? = null +} -- 2.40.1 From 93b05653686abbdc20f5a7534d815d1ca6e73fd8 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 16:19:59 +0900 Subject: [PATCH 13/18] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=20=ED=81=90=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20-=20=EB=8F=99=EC=9D=BC=ED=95=9C=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=EA=B0=80=20=EB=93=B1=EB=A1=9D=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20validation=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation/tag/AdminHashTagCurationRepository.kt | 9 +++++++++ .../content/curation/tag/AdminHashTagCurationService.kt | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt index d58329c..e6d300e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt @@ -18,6 +18,7 @@ interface AdminHashTagCurationRepository : interface AdminHashTagCurationQueryRepository { fun getContentHashTagCurationList(): List fun searchHashTagCurationContentItem(curationId: Long, searchWord: String): List + fun isExistsTag(tag: String): Boolean } @Repository @@ -69,4 +70,12 @@ class AdminHashTagCurationQueryRepositoryImpl( ) .fetch() } + + override fun isExistsTag(tag: String): Boolean { + return queryFactory + .select(contentHashTagCuration.id) + .from(contentHashTagCuration) + .where(contentHashTagCuration.tag.eq(tag)) + .fetch().isNotEmpty() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt index 741d07d..93915a3 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt @@ -20,6 +20,12 @@ class AdminHashTagCurationService( ) { @Transactional fun createContentHashTagCuration(request: CreateContentHashTagCurationRequest) { + val isExists = repository.isExistsTag(tag = request.tag.trim()) + + if (isExists) { + throw SodaException("이미 등록된 태그 입니다.") + } + repository.save( ContentHashTagCuration( tag = request.tag, -- 2.40.1 From 4370fef5d54902930bdb8e24247d0b8f2973f063 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 16:34:02 +0900 Subject: [PATCH 14/18] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=20=ED=81=90=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20-=20=EB=8F=99=EC=9D=BC=ED=95=9C=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=EA=B0=80=20=EB=93=B1=EB=A1=9D=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20validation=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/curation/tag/AdminHashTagCurationRepository.kt | 5 ++++- .../content/curation/tag/AdminHashTagCurationService.kt | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt index e6d300e..e892a00 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationRepository.kt @@ -75,7 +75,10 @@ class AdminHashTagCurationQueryRepositoryImpl( return queryFactory .select(contentHashTagCuration.id) .from(contentHashTagCuration) - .where(contentHashTagCuration.tag.eq(tag)) + .where( + contentHashTagCuration.tag.eq(tag), + contentHashTagCuration.isActive.isTrue + ) .fetch().isNotEmpty() } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt index 93915a3..cda9823 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt @@ -90,6 +90,7 @@ class AdminHashTagCurationService( ) ?: ContentHashTagCurationItem() item.curation = curation item.content = audioContent + item.isActive = true itemRepository.save(item) } } -- 2.40.1 From 03e1ef32719217a94e3b2d6c848249921599f486 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 17:05:28 +0900 Subject: [PATCH 15/18] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=20=ED=81=90=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D,=20=EC=88=98=EC=A0=95=20-=20=ED=83=9C=EA=B7=B8?= =?UTF-8?q?=EA=B0=80=20#=EC=9C=BC=EB=A1=9C=20=EC=8B=9C=EC=9E=91=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9C=BC=EB=A9=B4=20#=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation/tag/AdminHashTagCurationService.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt index cda9823..dc45006 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/tag/AdminHashTagCurationService.kt @@ -20,7 +20,12 @@ class AdminHashTagCurationService( ) { @Transactional fun createContentHashTagCuration(request: CreateContentHashTagCurationRequest) { - val isExists = repository.isExistsTag(tag = request.tag.trim()) + var tag = request.tag.trim() + if (!tag.startsWith("#")) { + tag = "#$tag" + } + + val isExists = repository.isExistsTag(tag = tag) if (isExists) { throw SodaException("이미 등록된 태그 입니다.") @@ -28,7 +33,7 @@ class AdminHashTagCurationService( repository.save( ContentHashTagCuration( - tag = request.tag, + tag = tag, isAdult = request.isAdult ) ) @@ -40,7 +45,12 @@ class AdminHashTagCurationService( ?: throw SodaException("잘못된 요청입니다.") if (request.tag != null) { - hashTagCuration.tag = request.tag + var tag = request.tag.trim() + if (!tag.startsWith("#")) { + tag = "#$tag" + } + + hashTagCuration.tag = tag } if (request.isAdult != null) { -- 2.40.1 From 7b957c673275c6a5b0a60ea7bdc96340ba546973 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 17:11:32 +0900 Subject: [PATCH 16/18] =?UTF-8?q?=EB=A0=88=EA=B1=B0=EC=8B=9C=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=EB=A9=94=EC=9D=B8=20-=20=EC=83=81?= =?UTF-8?q?=EB=8B=A8=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=B0=B0=EB=84=88=20?= =?UTF-8?q?-=20=ED=83=AD=EC=9D=B4=20=EC=A7=80=EC=A0=95=EB=90=98=EC=A7=80?= =?UTF-8?q?=20=EC=95=8A=EC=9D=80=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=B0=B0?= =?UTF-8?q?=EB=84=88=EB=A7=8C=20=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/vividnext/sodalive/content/AudioContentRepository.kt | 2 ++ 1 file changed, 2 insertions(+) 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 22d289c..1148ed8 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -698,6 +698,7 @@ class AudioContentQueryRepositoryImpl( override fun getAudioContentMainBannerList(isAdult: Boolean): List { var where = audioContentBanner.isActive.isTrue + .and(audioContentBanner.tab.isNull) if (!isAdult) { where = where.and(audioContentBanner.isAdult.isFalse) @@ -705,6 +706,7 @@ class AudioContentQueryRepositoryImpl( return queryFactory .selectFrom(audioContentBanner) + .leftJoin(audioContentBanner.tab, audioContentMainTab) .leftJoin(audioContentBanner.event, event) .leftJoin(audioContentBanner.creator, member) .where(where) -- 2.40.1 From 00c705085e6854068174417bf31ac854eba76498 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 19:19:52 +0900 Subject: [PATCH 17/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EB=8B=A8=ED=8E=B8=20?= =?UTF-8?q?API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentController.kt | 11 +++ .../AudioContentMainTabContentService.kt | 19 +++++ .../ContentMainTabTagCurationRepository.kt | 70 +++++++++++++++++++ .../ContentMainTabTagCurationService.kt | 15 ++++ .../GetContentMainTabContentResponse.kt | 2 + 5 files changed, 117 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationService.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt index f50efb8..3ecb4fa 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt @@ -82,4 +82,15 @@ class AudioContentMainTabContentController(private val service: AudioContentMain ) ) } + + @GetMapping("/recommend-content-by-tag") + fun getRecommendedContentByTag( + @RequestParam tag: String, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + ApiResponse.ok( + service.getRecommendedContentByTag(memberId = member.id!!, tag = tag) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt index c38ad2c..c968f8e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt @@ -21,6 +21,7 @@ class AudioContentMainTabContentService( private val audioContentThemeRepository: AudioContentThemeQueryRepository, private val rankingService: RankingService, private val eventService: EventService, + private val tagCurationService: ContentMainTabTagCurationService, private val curationRepository: AudioContentCurationQueryRepository ) { fun fetchData( @@ -87,6 +88,18 @@ class AudioContentMainTabContentService( emptyList() } + val tagList = if (isAdult) { + tagCurationService.getTagList(isAdult = isAdult) + } else { + emptyList() + } + + val tagCurationContentList = if (tagList.isNotEmpty()) { + tagCurationService.getTagCurationContentList(memberId = memberId, tag = tagList[0]) + } else { + emptyList() + } + val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) .map { GetContentCurationResponse( @@ -108,6 +121,8 @@ class AudioContentMainTabContentService( contentRankCreatorList = contentRankCreatorList, salesCountRankContentList = salesCountRankContentList, eventBannerList = eventBannerList, + tagList = tagList, + tagCurationContentList = tagCurationContentList, curationList = curationList ) } @@ -156,4 +171,8 @@ class AudioContentMainTabContentService( isAdult = isAdult ) } + + fun getRecommendedContentByTag(memberId: Long, tag: String): List { + return tagCurationService.getTagCurationContentList(memberId = memberId, tag = tag) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt new file mode 100644 index 0000000..4adc07e --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt @@ -0,0 +1,70 @@ +package kr.co.vividnext.sodalive.content.main.tab.content + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.QAudioContent.audioContent +import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.QGetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.curation.tag.QContentHashTagCuration.contentHashTagCuration +import kr.co.vividnext.sodalive.content.main.curation.tag.QContentHashTagCurationItem.contentHashTagCurationItem +import kr.co.vividnext.sodalive.member.QMember.member +import kr.co.vividnext.sodalive.member.block.QBlockMember.blockMember +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Repository + +@Repository +class ContentMainTabTagCurationRepository( + private val queryFactory: JPAQueryFactory, + + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String +) { + fun getTagList(isAdult: Boolean): List { + var where = contentHashTagCuration.isActive.isTrue + + if (!isAdult) { + where = where.and(contentHashTagCuration.isAdult.isFalse) + } + + return queryFactory + .select(contentHashTagCuration.tag) + .from(contentHashTagCuration) + .where(where) + .orderBy(contentHashTagCuration.orders.asc()) + .fetch() + } + + fun getTagCurationContentList(memberId: Long, tag: String): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + val where = audioContent.isActive.isTrue + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + .and(blockMember.id.isNull) + .and(contentHashTagCurationItem.isActive.isTrue) + .and(contentHashTagCuration.tag.eq(tag)) + + return queryFactory + .select( + QGetAudioContentMainItem( + audioContent.id, + audioContent.coverImage.prepend("/").prepend(imageHost), + audioContent.title, + member.id, + member.profileImage.prepend("/").prepend(imageHost), + member.nickname, + audioContent.price, + audioContent.duration + ) + ) + .from(contentHashTagCurationItem) + .innerJoin(contentHashTagCurationItem.curation, contentHashTagCuration) + .innerJoin(contentHashTagCurationItem.content, audioContent) + .innerJoin(audioContent.member, member) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .orderBy(contentHashTagCurationItem.orders.asc()) + .fetch() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationService.kt new file mode 100644 index 0000000..f95134d --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationService.kt @@ -0,0 +1,15 @@ +package kr.co.vividnext.sodalive.content.main.tab.content + +import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import org.springframework.stereotype.Service + +@Service +class ContentMainTabTagCurationService(private val repository: ContentMainTabTagCurationRepository) { + fun getTagList(isAdult: Boolean): List { + return repository.getTagList(isAdult = isAdult) + } + + fun getTagCurationContentList(memberId: Long, tag: String): List { + return repository.getTagCurationContentList(memberId = memberId, tag = tag) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt index 7451491..da16051 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt @@ -17,5 +17,7 @@ data class GetContentMainTabContentResponse( val contentRankCreatorList: List, val salesCountRankContentList: List, val eventBannerList: GetEventResponse, + val tagList: List, + val tagCurationContentList: List, val curationList: List ) -- 2.40.1 From 44e3eda145e3e55a1f623668400e567b7bb90680 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 18 Feb 2025 21:33:30 +0900 Subject: [PATCH 18/18] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EB=8B=A8=ED=8E=B8=20?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=20-=20=EC=BD=98=ED=85=90=EC=B8=A0=EA=B0=80?= =?UTF-8?q?=20=ED=95=98=EB=82=98=20=EC=9D=B4=EC=83=81=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=EB=90=98=EC=96=B4=20=EC=9E=88=EB=8A=94=20=ED=83=9C=EA=B7=B8?= =?UTF-8?q?=EB=A7=8C=20=EC=A1=B0=ED=9A=8C=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tab/content/ContentMainTabTagCurationRepository.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt index 4adc07e..3e7b85e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt @@ -20,6 +20,10 @@ class ContentMainTabTagCurationRepository( ) { fun getTagList(isAdult: Boolean): List { var where = contentHashTagCuration.isActive.isTrue + .and(audioContent.isActive.isTrue) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + .and(contentHashTagCurationItem.isActive.isTrue) if (!isAdult) { where = where.and(contentHashTagCuration.isAdult.isFalse) @@ -28,7 +32,12 @@ class ContentMainTabTagCurationRepository( return queryFactory .select(contentHashTagCuration.tag) .from(contentHashTagCuration) + .innerJoin(contentHashTagCurationItem) + .on(contentHashTagCurationItem.curation.id.eq(contentHashTagCuration.id)) + .innerJoin(contentHashTagCurationItem.content, audioContent) .where(where) + .groupBy(contentHashTagCuration.id) + .having(contentHashTagCurationItem.id.countDistinct().gt(0)) .orderBy(contentHashTagCuration.orders.asc()) .fetch() } -- 2.40.1