From 00ce6d6a7a6c17913b47b92d5f81b8e401da663f Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 21 Jan 2025 16:19:36 +0900 Subject: [PATCH 01/14] =?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=83=AD=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/content/AdminContentController.kt | 3 ++ .../admin/content/AdminContentService.kt | 9 +++++- .../tab/AdminContentMainTabRepository.kt | 31 +++++++++++++++++++ .../content/main/tab/GetContentMainTabItem.kt | 8 +++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/tab/AdminContentMainTabRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetContentMainTabItem.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentController.kt index fa875fb..65ebb64 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentController.kt @@ -42,6 +42,9 @@ class AdminContentController(private val service: AdminContentService) { fun modifyAudioContent( @RequestBody request: UpdateAdminContentRequest ) = ApiResponse.ok(service.updateAudioContent(request)) + + @GetMapping("/main/tab") + fun getContentMainTabList() = ApiResponse.ok(service.getContentMainTabList()) } enum class ContentReleaseStatus { diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentService.kt index ebf0445..9733e46 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentService.kt @@ -1,9 +1,11 @@ package kr.co.vividnext.sodalive.admin.content import kr.co.vividnext.sodalive.admin.content.curation.AdminContentCurationRepository +import kr.co.vividnext.sodalive.admin.content.tab.AdminContentMainTabRepository import kr.co.vividnext.sodalive.admin.content.theme.AdminContentThemeRepository import kr.co.vividnext.sodalive.aws.cloudfront.AudioContentCloudFront import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.content.main.tab.GetContentMainTabItem import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service @@ -14,7 +16,8 @@ class AdminContentService( private val repository: AdminContentRepository, private val themeRepository: AdminContentThemeRepository, private val audioContentCloudFront: AudioContentCloudFront, - private val curationRepository: AdminContentCurationRepository + private val curationRepository: AdminContentCurationRepository, + private val contentMainTabRepository: AdminContentMainTabRepository ) { fun getAudioContentList(status: ContentReleaseStatus, pageable: Pageable): GetAdminContentListResponse { val totalCount = repository.getAudioContentTotalCount(status = status) @@ -118,4 +121,8 @@ class AdminContentService( audioContent.theme = theme } } + + fun getContentMainTabList(): List { + return contentMainTabRepository.findAllByActiveIsTrue() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/tab/AdminContentMainTabRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/tab/AdminContentMainTabRepository.kt new file mode 100644 index 0000000..38f690b --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/tab/AdminContentMainTabRepository.kt @@ -0,0 +1,31 @@ +package kr.co.vividnext.sodalive.admin.content.tab + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTab +import kr.co.vividnext.sodalive.content.main.tab.GetContentMainTabItem +import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab +import kr.co.vividnext.sodalive.content.main.tab.QGetContentMainTabItem +import org.springframework.data.jpa.repository.JpaRepository + +interface AdminContentMainTabRepository : JpaRepository, AdminContentMainTabQueryRepository + +interface AdminContentMainTabQueryRepository { + fun findAllByActiveIsTrue(): List +} + +class AdminContentMainTabQueryRepositoryImpl( + private val queryFactory: JPAQueryFactory +) : AdminContentMainTabQueryRepository { + override fun findAllByActiveIsTrue(): List { + return queryFactory + .select( + QGetContentMainTabItem( + audioContentMainTab.id, + audioContentMainTab.title + ) + ) + .from(audioContentMainTab) + .where(audioContentMainTab.isActive.isTrue) + .fetch() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetContentMainTabItem.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetContentMainTabItem.kt new file mode 100644 index 0000000..72b2b81 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetContentMainTabItem.kt @@ -0,0 +1,8 @@ +package kr.co.vividnext.sodalive.content.main.tab + +import com.querydsl.core.annotations.QueryProjection + +data class GetContentMainTabItem @QueryProjection constructor( + val tabId: Long, + val title: String +) From 8285589b10b2f02906cef87e829790f4244c2be9 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 21 Jan 2025 17:03:42 +0900 Subject: [PATCH 02/14] =?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=B0=B0=EB=84=88=20API=20-=20=ED=83=AD?= =?UTF-8?q?=EB=B3=84=20=EB=B0=B0=EB=84=88=20=EC=A1=B0=ED=9A=8C=20-=20?= =?UTF-8?q?=ED=83=AD=EB=B3=84=20=EB=B0=B0=EB=84=88=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../banner/AdminContentBannerController.kt | 5 ++++- .../banner/AdminContentBannerRepository.kt | 16 +++++++++++++--- .../content/banner/AdminContentBannerService.kt | 4 ++-- .../content/banner/CreateContentBannerRequest.kt | 1 + .../content/banner/UpdateContentBannerRequest.kt | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerController.kt index 1324585..249a8b2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerController.kt @@ -7,6 +7,7 @@ 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.RequestPart import org.springframework.web.bind.annotation.RestController import org.springframework.web.multipart.MultipartFile @@ -33,5 +34,7 @@ class AdminContentBannerController(private val service: AdminContentBannerServic ) = ApiResponse.ok(service.updateBannerOrders(request.ids), "수정되었습니다.") @GetMapping - fun getAudioContentMainBannerList() = ApiResponse.ok(service.getAudioContentMainBannerList()) + fun getAudioContentMainBannerList( + @RequestParam(value = "tabId", required = false) tabId: Long? = null + ) = ApiResponse.ok(service.getAudioContentMainBannerList(tabId = tabId)) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt index 14c1f25..77b1014 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt @@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.admin.content.banner import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner import kr.co.vividnext.sodalive.content.main.banner.QAudioContentBanner.audioContentBanner +import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series import kr.co.vividnext.sodalive.event.QEvent.event import kr.co.vividnext.sodalive.member.QMember.member @@ -14,7 +15,7 @@ import org.springframework.stereotype.Repository interface AdminContentBannerRepository : JpaRepository, AdminContentBannerQueryRepository interface AdminContentBannerQueryRepository { - fun getAudioContentMainBannerList(): List + fun getAudioContentMainBannerList(tabId: Long = 1): List } class AdminContentBannerQueryRepositoryImpl( @@ -22,7 +23,15 @@ class AdminContentBannerQueryRepositoryImpl( @Value("\${cloud.aws.cloud-front.host}") private val cloudFrontHost: String ) : AdminContentBannerQueryRepository { - override fun getAudioContentMainBannerList(): List { + override fun getAudioContentMainBannerList(tabId: Long): List { + var where = audioContentBanner.isActive.isTrue + + where = if (tabId <= 1L) { + where.and(audioContentMainTab.id.isNull) + } else { + where.and(audioContentMainTab.id.eq(tabId)) + } + return queryFactory .select( QGetAdminContentBannerResponse( @@ -43,7 +52,8 @@ class AdminContentBannerQueryRepositoryImpl( .leftJoin(audioContentBanner.event, event) .leftJoin(audioContentBanner.creator, member) .leftJoin(audioContentBanner.series, series) - .where(audioContentBanner.isActive.isTrue) + .leftJoin(audioContentBanner.tab, audioContentMainTab) + .where(where) .orderBy(audioContentBanner.orders.asc()) .fetch() } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt index 4fdddae..10a723e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt @@ -169,7 +169,7 @@ class AdminContentBannerService( } } - fun getAudioContentMainBannerList(): List { - return repository.getAudioContentMainBannerList() + fun getAudioContentMainBannerList(tabId: Long?): List { + return repository.getAudioContentMainBannerList(tabId = tabId ?: 1) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/CreateContentBannerRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/CreateContentBannerRequest.kt index ca9cb5e..e564206 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/CreateContentBannerRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/CreateContentBannerRequest.kt @@ -4,6 +4,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType data class CreateContentBannerRequest( val type: AudioContentBannerType, + val tabId: Long?, val eventId: Long?, val creatorId: Long?, val seriesId: Long?, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/UpdateContentBannerRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/UpdateContentBannerRequest.kt index fcbad72..4390788 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/UpdateContentBannerRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/UpdateContentBannerRequest.kt @@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType data class UpdateContentBannerRequest( val id: Long, val type: AudioContentBannerType?, + val tabId: Long?, val eventId: Long?, val creatorId: Long?, val seriesId: Long?, From 49a5e47f9dd2a76204e30ab51997f70a6a364801 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 21 Jan 2025 18:54:06 +0900 Subject: [PATCH 03/14] =?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=B0=B0=EB=84=88=20API=20-=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C,=20=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95=EC=8B=9C?= =?UTF-8?q?=20=ED=83=AD=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/banner/AdminContentBannerRepository.kt | 1 + .../content/banner/AdminContentBannerService.kt | 13 +++++++++++++ .../content/banner/GetAdminContentBannerResponse.kt | 1 + 3 files changed, 15 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt index 77b1014..00933fc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerRepository.kt @@ -36,6 +36,7 @@ class AdminContentBannerQueryRepositoryImpl( .select( QGetAdminContentBannerResponse( audioContentBanner.id, + audioContentBanner.tab.id.coalesce(1), audioContentBanner.type, audioContentBanner.thumbnailImage.prepend("/").prepend(cloudFrontHost), audioContentBanner.event.id, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt index 10a723e..3811632 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/AdminContentBannerService.kt @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.admin.content.banner import com.fasterxml.jackson.databind.ObjectMapper import kr.co.vividnext.sodalive.admin.content.series.AdminContentSeriesRepository +import kr.co.vividnext.sodalive.admin.content.tab.AdminContentMainTabRepository import kr.co.vividnext.sodalive.aws.s3.S3Uploader import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner @@ -22,6 +23,7 @@ class AdminContentBannerService( private val memberRepository: MemberRepository, private val seriesRepository: AdminContentSeriesRepository, private val eventRepository: EventRepository, + private val contentMainTabRepository: AdminContentMainTabRepository, private val objectMapper: ObjectMapper, @Value("\${cloud.aws.s3.bucket}") @@ -64,12 +66,19 @@ class AdminContentBannerService( null } + val tab = if (request.tabId !== null) { + contentMainTabRepository.findByIdOrNull(request.tabId) + } else { + null + } + val audioContentBanner = AudioContentBanner(type = request.type) audioContentBanner.link = request.link audioContentBanner.isAdult = request.isAdult audioContentBanner.event = event audioContentBanner.creator = creator audioContentBanner.series = series + audioContentBanner.tab = tab repository.save(audioContentBanner) val fileName = generateFileName() @@ -156,6 +165,10 @@ class AdminContentBannerService( audioContentBanner.type = request.type } + + if (request.tabId !== null) { + audioContentBanner.tab = contentMainTabRepository.findByIdOrNull(request.tabId) + } } @Transactional diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/GetAdminContentBannerResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/GetAdminContentBannerResponse.kt index bfd21d1..2ba9348 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/GetAdminContentBannerResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/banner/GetAdminContentBannerResponse.kt @@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType data class GetAdminContentBannerResponse @QueryProjection constructor( val id: Long, + val tabId: Long?, val type: AudioContentBannerType, val thumbnailImageUrl: String, val eventId: Long?, From e9e538168c737877049f586da265cbf7e17e8523 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 23 Jan 2025 19:33:17 +0900 Subject: [PATCH 04/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=93=B1=EB=A1=9D/=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=ED=83=AD=EA=B3=BC=20=EC=8B=9C=EB=A6=AC?= =?UTF-8?q?=EC=A6=88=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation/AdminContentCurationService.kt | 33 +++++++++++++++---- .../curation/AudioContentCurationRequest.kt | 6 +++- .../main/curation/AudioContentCuration.kt | 14 ++++++-- 3 files changed, 43 insertions(+), 10 deletions(-) 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 b6d0c14..67e7502 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 @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.admin.content.curation +import kr.co.vividnext.sodalive.admin.content.tab.AdminContentMainTabRepository import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration import org.springframework.data.repository.findByIdOrNull @@ -8,17 +9,23 @@ import org.springframework.transaction.annotation.Transactional @Service class AdminContentCurationService( - private val repository: AdminContentCurationRepository + private val repository: AdminContentCurationRepository, + private val contentMainTabRepository: AdminContentMainTabRepository ) { @Transactional fun createContentCuration(request: CreateContentCurationRequest) { - repository.save( - AudioContentCuration( - title = request.title, - description = request.description, - isAdult = request.isAdult - ) + val tab = contentMainTabRepository.findByIdOrNull(request.tabId) + ?: throw SodaException("잘못된 요청입니다.") + + val curation = AudioContentCuration( + title = request.title, + description = request.description, + isAdult = request.isAdult, + isSeries = request.isSeries ) + curation.tab = tab + + repository.save(curation) } @Transactional @@ -41,6 +48,18 @@ class AdminContentCurationService( if (request.isActive != null) { audioContentCuration.isActive = request.isActive } + + if (request.isSeries != null) { + audioContentCuration.isSeries = request.isSeries + } + + if (request.tabId != null) { + val tab = contentMainTabRepository.findByIdOrNull(request.tabId) + + if (tab != null) { + audioContentCuration.tab = tab + } + } } @Transactional diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AudioContentCurationRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AudioContentCurationRequest.kt index 49b46d7..b2ae35d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AudioContentCurationRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AudioContentCurationRequest.kt @@ -1,16 +1,20 @@ package kr.co.vividnext.sodalive.admin.content.curation data class CreateContentCurationRequest( + val tabId: Long, val title: String, val description: String, - val isAdult: Boolean + val isAdult: Boolean, + val isSeries: Boolean ) data class UpdateContentCurationRequest( val id: Long, + val tabId: Long?, val title: String?, val description: String?, val isAdult: Boolean?, + val isSeries: Boolean?, val isActive: Boolean? ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCuration.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCuration.kt index d5955cf..eeebc15 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCuration.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCuration.kt @@ -1,8 +1,12 @@ package kr.co.vividnext.sodalive.content.main.curation import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTab import javax.persistence.Column import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.OneToOne import javax.persistence.Table @Entity @@ -17,5 +21,11 @@ data class AudioContentCuration( @Column(nullable = false) var isActive: Boolean = true, @Column(nullable = false) - var orders: Int = 1 -) : BaseEntity() + var orders: Int = 1, + @Column(nullable = false) + var isSeries: Boolean = false +) : BaseEntity() { + @OneToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "tab_id", nullable = true) + var tab: AudioContentMainTab? = null +} From d95f95899c88d3276bfcb7d02bc230d964db0601 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 23 Jan 2025 19:46:54 +0900 Subject: [PATCH 05/14] =?UTF-8?q?=EC=8B=9C=EB=A6=AC=EC=A6=88=20-=20?= =?UTF-8?q?=EC=98=A4=EB=A6=AC=EC=A7=80=EB=84=90=20=EC=97=AC=EB=B6=80=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 --- .../co/vividnext/sodalive/creator/admin/content/series/Series.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt index 9e2d1d6..1bd336d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt @@ -43,6 +43,7 @@ data class Series( @CollectionTable(name = "series_published_days_of_week", joinColumns = [JoinColumn(name = "series_id")]) val publishedDaysOfWeek: MutableSet = mutableSetOf(), var isAdult: Boolean = false, + var isOriginal: Boolean = false, var isActive: Boolean = true, var orders: Int = 1 ) : BaseEntity() { From faf827de7101cdc15b6181ac6446aa3b9a812010 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 23 Jan 2025 22:18:00 +0900 Subject: [PATCH 06/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=A1=B0=ED=9A=8C=20-=20tabId?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=B4=EC=84=9C=20=ED=83=AD?= =?UTF-8?q?=EB=B3=84=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation/AdminContentCurationController.kt | 5 ++++- .../curation/AdminContentCurationRepository.kt | 12 +++++++++--- .../content/curation/AdminContentCurationService.kt | 4 ++-- .../curation/GetAdminContentCurationResponse.kt | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) 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 849697a..639aa3d 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 @@ -7,6 +7,7 @@ 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 @@ -29,5 +30,7 @@ class AdminContentCurationController(private val service: AdminContentCurationSe ) = ApiResponse.ok(service.updateContentCurationOrders(request.ids), "수정되었습니다.") @GetMapping - fun getContentCurationList() = ApiResponse.ok(service.getContentCurationList()) + fun getContentCurationList( + @RequestParam tabId: Long + ) = ApiResponse.ok(service.getContentCurationList(tabId = tabId)) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt index a24fa77..50cb950 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt @@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.admin.content.curation import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration +import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository @@ -12,7 +13,7 @@ interface AdminContentCurationRepository : AdminContentCurationQueryRepository interface AdminContentCurationQueryRepository { - fun getAudioContentCurationList(): List + fun getAudioContentCurationList(tabId: Long): List fun findByIdAndActive(id: Long): AudioContentCuration? } @@ -20,18 +21,23 @@ interface AdminContentCurationQueryRepository { class AdminContentCurationQueryRepositoryImpl( private val queryFactory: JPAQueryFactory ) : AdminContentCurationQueryRepository { - override fun getAudioContentCurationList(): List { + override fun getAudioContentCurationList(tabId: Long): List { return queryFactory .select( QGetAdminContentCurationResponse( audioContentCuration.id, + audioContentMainTab.id, audioContentCuration.title, audioContentCuration.description, audioContentCuration.isAdult ) ) .from(audioContentCuration) - .where(audioContentCuration.isActive.isTrue) + .innerJoin(audioContentCuration.tab, audioContentMainTab) + .where( + audioContentCuration.isActive.isTrue, + audioContentMainTab.id.eq(tabId) + ) .orderBy(audioContentCuration.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 67e7502..e914f08 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 @@ -73,7 +73,7 @@ class AdminContentCurationService( } } - fun getContentCurationList(): List { - return repository.getAudioContentCurationList() + fun getContentCurationList(tabId: Long): List { + return repository.getAudioContentCurationList(tabId = tabId) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt index 2938cfd..11a5559 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt @@ -4,6 +4,7 @@ import com.querydsl.core.annotations.QueryProjection data class GetAdminContentCurationResponse @QueryProjection constructor( val id: Long, + val tabId: Long, val title: String, val description: String, val isAdult: Boolean From de07b3d7de32b96afa9e9a8af2dbd415e78415e1 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 23 Jan 2025 22:38:52 +0900 Subject: [PATCH 07/14] =?UTF-8?q?=EC=95=B1=20=ED=81=90=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=A1=B0=ED=9A=8C=20-=20tab=EC=9D=B4=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=20=EC=95=88=EB=90=9C=20=ED=81=90=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=85=98=EB=A7=8C=20=EC=A1=B0=ED=9A=8C=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../co/vividnext/sodalive/content/AudioContentRepository.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 09063db..56ee40d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -15,6 +15,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner import kr.co.vividnext.sodalive.content.main.banner.QAudioContentBanner.audioContentBanner import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration +import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab import kr.co.vividnext.sodalive.content.order.QOrder.order import kr.co.vividnext.sodalive.content.pin.QPinContent.pinContent import kr.co.vividnext.sodalive.content.playlist.AudioContentPlaylistContent @@ -755,7 +756,8 @@ class AudioContentQueryRepositoryImpl( return queryFactory .selectFrom(audioContentCuration) - .where(where) + .innerJoin(audioContentCuration.tab, audioContentMainTab) + .where(where, audioContentMainTab.id.isNull) .offset(offset) .limit(limit) .orderBy(audioContentCuration.orders.asc()) From 8904ef224707e48b39951ed6c6304893730f1808 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 23 Jan 2025 22:46:06 +0900 Subject: [PATCH 08/14] =?UTF-8?q?=EC=95=B1=20=ED=81=90=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=A1=B0=ED=9A=8C=20-=20tab=EC=9D=B4=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=20=EC=95=88=EB=90=9C=20=ED=81=90=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=85=98=EB=A7=8C=20=EC=A1=B0=ED=9A=8C=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=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, 1 insertion(+), 1 deletion(-) 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 56ee40d..f1ac4e8 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -756,7 +756,7 @@ class AudioContentQueryRepositoryImpl( return queryFactory .selectFrom(audioContentCuration) - .innerJoin(audioContentCuration.tab, audioContentMainTab) + .leftJoin(audioContentCuration.tab, audioContentMainTab) .where(where, audioContentMainTab.id.isNull) .offset(offset) .limit(limit) From 155ea5c5e4c5522b8afa27ce0b1b28a112dffc30 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 24 Jan 2025 12:21:33 +0900 Subject: [PATCH 09/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=A1=B0=ED=9A=8C=20-=20?= =?UTF-8?q?=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=81=90=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/content/curation/AdminContentCurationRepository.kt | 3 ++- .../admin/content/curation/GetAdminContentCurationResponse.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt index 50cb950..f6dc40b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt @@ -29,7 +29,8 @@ class AdminContentCurationQueryRepositoryImpl( audioContentMainTab.id, audioContentCuration.title, audioContentCuration.description, - audioContentCuration.isAdult + audioContentCuration.isAdult, + audioContentCuration.isSeries ) ) .from(audioContentCuration) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt index 11a5559..a43364d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetAdminContentCurationResponse.kt @@ -7,5 +7,6 @@ data class GetAdminContentCurationResponse @QueryProjection constructor( val tabId: Long, val title: String, val description: String, - val isAdult: Boolean + val isAdult: Boolean, + val isSeries: Boolean ) From 705459ee907bfdb64cca5bec6e32239124777821 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 31 Jan 2025 21:58:31 +0900 Subject: [PATCH 10/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=95=84=EC=9D=B4=ED=85=9C=20-?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C,=20=EC=B6=94=EA=B0=80,=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C,=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EA=B2=80=EC=83=89,?= =?UTF-8?q?=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=EA=B2=80=EC=83=89=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 --- .../admin/content/AdminContentRepository.kt | 11 +++ .../curation/AddItemToCurationRequest.kt | 6 ++ .../AdminContentCurationController.kt | 27 +++++ .../AdminContentCurationItemRepository.kt | 46 +++++++++ .../AdminContentCurationRepository.kt | 99 ++++++++++++++++++- .../curation/AdminContentCurationService.kt | 69 ++++++++++++- .../curation/GetCurationItemResponse.kt | 12 +++ .../curation/RemoveItemInCurationRequest.kt | 6 ++ .../curation/SearchCurationItemResponse.kt | 9 ++ .../series/AdminContentSeriesRepository.kt | 11 +++ .../main/curation/AudioContentCurationItem.kt | 33 +++++++ 11 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationItemRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetCurationItemResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/RemoveItemInCurationRequest.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/SearchCurationItemResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationItem.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt index d01218d..3c402c2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt @@ -32,6 +32,7 @@ interface AdminAudioContentQueryRepository { ): List fun getHashTagList(audioContentId: Long): List + fun findByIdAndActiveTrue(audioContentId: Long): AudioContent? } class AdminAudioContentQueryRepositoryImpl( @@ -143,6 +144,16 @@ class AdminAudioContentQueryRepositoryImpl( .fetch() } + override fun findByIdAndActiveTrue(audioContentId: Long): AudioContent? { + return queryFactory + .select(audioContent) + .where( + audioContent.id.eq(audioContentId), + audioContent.isActive.isTrue + ) + .fetchFirst() + } + private fun formattedDateExpression( dateTime: DateTimePath, format: String = "%Y-%m-%d" diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt new file mode 100644 index 0000000..d344da7 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.admin.content.curation + +data class AddItemToCurationRequest( + val curationId: Long, + val contentIdList: List +) 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 639aa3d..aeb1863 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 @@ -33,4 +33,31 @@ class AdminContentCurationController(private val service: AdminContentCurationSe fun getContentCurationList( @RequestParam tabId: Long ) = ApiResponse.ok(service.getContentCurationList(tabId = tabId)) + + @GetMapping("/items") + fun getCurationItems( + @RequestParam curationId: Long + ) = ApiResponse.ok(service.getCurationItem(curationId = curationId)) + + @GetMapping("/search/content") + fun searchCurationContentItem( + @RequestParam curationId: Long, + @RequestParam searchWord: String + ) = ApiResponse.ok(service.searchCurationContentItem(curationId, searchWord)) + + @GetMapping("/search/series") + fun searchCurationSeriesItem( + @RequestParam curationId: Long, + @RequestParam searchWord: String + ) = ApiResponse.ok(service.searchCurationSeriesItem(curationId, searchWord)) + + @PostMapping("/add/item") + fun addItemToCuration(@RequestBody request: AddItemToCurationRequest) { + ApiResponse.ok(service.addItemToCuration(request), "큐레이션 아이템을 등록했습니다.") + } + + @PostMapping("/remove/item") + fun removeItemInCuration(@RequestBody request: RemoveItemInCurationRequest) { + ApiResponse.ok(service.removeItemInCuration(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 new file mode 100644 index 0000000..bcfe675 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationItemRepository.kt @@ -0,0 +1,46 @@ +package kr.co.vividnext.sodalive.admin.content.curation + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.QAudioContent.audioContent +import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationItem +import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration +import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCurationItem.audioContentCurationItem +import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series +import org.springframework.data.jpa.repository.JpaRepository + +interface AdminContentCurationItemRepository : + JpaRepository, + AdminContentCurationItemQueryRepository + +interface AdminContentCurationItemQueryRepository { + fun findByCurationIdAndSeriesId(curationId: Long, seriesId: Long?): AudioContentCurationItem? + fun findByCurationIdAndContentId(curationId: Long, contentId: Long?): AudioContentCurationItem? +} + +class AdminContentCurationItemQueryRepositoryImpl( + val queryFactory: JPAQueryFactory +) : AdminContentCurationItemQueryRepository { + override fun findByCurationIdAndSeriesId(curationId: Long, seriesId: Long?): AudioContentCurationItem? { + return queryFactory + .selectFrom(audioContentCurationItem) + .innerJoin(audioContentCurationItem.curation, audioContentCuration) + .innerJoin(audioContentCurationItem.series, series) + .where( + audioContentCurationItem.curation.id.eq(curationId), + audioContentCurationItem.series.id.eq(seriesId) + ) + .fetchFirst() + } + + override fun findByCurationIdAndContentId(curationId: Long, contentId: Long?): AudioContentCurationItem? { + return queryFactory + .selectFrom(audioContentCurationItem) + .innerJoin(audioContentCurationItem.curation, audioContentCuration) + .innerJoin(audioContentCurationItem.content, audioContent) + .where( + audioContentCurationItem.curation.id.eq(curationId), + audioContentCurationItem.content.id.eq(contentId) + ) + .fetchFirst() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt index f6dc40b..d0277eb 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AdminContentCurationRepository.kt @@ -1,9 +1,14 @@ package kr.co.vividnext.sodalive.admin.content.curation import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.QAudioContent.audioContent import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration +import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationItem import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration +import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCurationItem.audioContentCurationItem import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab +import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series +import org.springframework.beans.factory.annotation.Value import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository @@ -15,11 +20,18 @@ interface AdminContentCurationRepository : interface AdminContentCurationQueryRepository { fun getAudioContentCurationList(tabId: Long): List fun findByIdAndActive(id: Long): AudioContentCuration? + fun findByCurationIdAndItemId(curationId: Long, itemId: Long): AudioContentCurationItem? + fun getAudioContentCurationItemList(curationId: Long): List + fun searchCurationContentItem(curationId: Long, searchWord: String): List + fun searchCurationSeriesItem(curationId: Long, searchWord: String): List } @Repository class AdminContentCurationQueryRepositoryImpl( - private val queryFactory: JPAQueryFactory + private val queryFactory: JPAQueryFactory, + + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String ) : AdminContentCurationQueryRepository { override fun getAudioContentCurationList(tabId: Long): List { return queryFactory @@ -52,4 +64,89 @@ class AdminContentCurationQueryRepositoryImpl( ) .fetchFirst() } + + override fun findByCurationIdAndItemId(curationId: Long, itemId: Long): AudioContentCurationItem? { + return queryFactory.selectFrom(audioContentCurationItem) + .innerJoin(audioContentCurationItem.curation, audioContentCuration) + .where(audioContentCuration.id.eq(curationId), audioContentCurationItem.id.eq(itemId)) + .fetchFirst() + } + + override fun getAudioContentCurationItemList(curationId: Long): List { + return queryFactory + .select( + QGetCurationItemResponse( + audioContentCurationItem.id, + audioContent.title.coalesce(series.title), + audioContent.detail.coalesce(series.introduction), + audioContent.coverImage.coalesce(series.coverImage).prepend("/").prepend(imageHost), + audioContent.member.nickname.coalesce(series.member.nickname).coalesce(""), + audioContent.isAdult.coalesce(series.isAdult) + ) + ) + .from(audioContentCurationItem) + .innerJoin(audioContentCurationItem.curation, audioContentCuration) + .leftJoin(audioContentCurationItem.series, series) + .leftJoin(audioContentCurationItem.content, audioContent) + .where( + audioContentCuration.id.eq(curationId), + audioContentCurationItem.isActive.isTrue + ) + .fetch() + } + + override fun searchCurationContentItem( + curationId: Long, + searchWord: String + ): List { + return queryFactory + .select( + QSearchCurationItemResponse( + audioContent.id, + audioContent.title, + audioContent.coverImage.prepend("/").prepend(imageHost) + ) + ) + .from(audioContent) + .leftJoin(audioContentCurationItem) + .on( + audioContent.id.eq(audioContentCurationItem.content.id) + .and(audioContentCurationItem.curation.id.eq(curationId)) + ) + .where( + audioContent.duration.isNotNull + .and(audioContent.member.isNotNull) + .and(audioContent.isActive.isTrue) + .and(audioContent.title.contains(searchWord)) + .and(audioContentCurationItem.id.isNull) + ) + .fetch() + } + + override fun searchCurationSeriesItem( + curationId: Long, + searchWord: String + ): List { + return queryFactory + .select( + QSearchCurationItemResponse( + series.id, + series.title, + series.coverImage.prepend("/").prepend(imageHost) + ) + ) + .from(series) + .leftJoin(audioContentCurationItem) + .on( + series.id.eq(audioContentCurationItem.series.id) + .and(audioContentCurationItem.curation.id.eq(curationId)) + ) + .where( + series.isActive.isTrue + .and(series.member.isNotNull) + .and(series.title.contains(searchWord)) + .and(audioContentCurationItem.id.isNull) + ) + .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 e914f08..40a5404 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 @@ -1,8 +1,11 @@ package kr.co.vividnext.sodalive.admin.content.curation +import kr.co.vividnext.sodalive.admin.content.AdminContentRepository +import kr.co.vividnext.sodalive.admin.content.series.AdminContentSeriesRepository import kr.co.vividnext.sodalive.admin.content.tab.AdminContentMainTabRepository import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration +import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationItem import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -10,7 +13,10 @@ import org.springframework.transaction.annotation.Transactional @Service class AdminContentCurationService( private val repository: AdminContentCurationRepository, - private val contentMainTabRepository: AdminContentMainTabRepository + private val contentMainTabRepository: AdminContentMainTabRepository, + private val seriesRepository: AdminContentSeriesRepository, + private val contentRepository: AdminContentRepository, + private val contentCurationItemRepository: AdminContentCurationItemRepository ) { @Transactional fun createContentCuration(request: CreateContentCurationRequest) { @@ -76,4 +82,65 @@ class AdminContentCurationService( fun getContentCurationList(tabId: Long): List { return repository.getAudioContentCurationList(tabId = tabId) } + + fun getCurationItem(curationId: Long): List { + return repository.getAudioContentCurationItemList(curationId) + } + + fun searchCurationContentItem(curationId: Long, searchWord: String): List { + return repository.searchCurationContentItem(curationId, searchWord) + } + + fun searchCurationSeriesItem(curationId: Long, searchWord: String): List { + return repository.searchCurationSeriesItem(curationId, searchWord) + } + + @Transactional + fun addItemToCuration(request: AddItemToCurationRequest) { + // 큐레이션 조회 + val audioContentCuration = repository.findByIdOrNull(id = request.curationId) + ?: throw SodaException("잘못된 요청입니다.") + + if (audioContentCuration.isSeries) { + request.contentIdList.forEach { seriesId -> + val series = seriesRepository.findByIdAndActiveTrue(seriesId) + + if (series != null) { + val item = contentCurationItemRepository.findByCurationIdAndSeriesId( + curationId = request.curationId, + seriesId = series.id + ) ?: AudioContentCurationItem() + item.curation = audioContentCuration + item.series = series + item.isActive = true + contentCurationItemRepository.save(item) + } + } + } else { + request.contentIdList.forEach { contentId -> + val audioContent = contentRepository.findByIdAndActiveTrue(contentId) + + if (audioContent != null) { + val item = contentCurationItemRepository.findByCurationIdAndContentId( + curationId = request.curationId, + contentId = audioContent.id + ) ?: AudioContentCurationItem() + item.curation = audioContentCuration + item.content = audioContent + item.isActive = true + contentCurationItemRepository.save(item) + } + } + } + } + + @Transactional + fun removeItemInCuration(request: RemoveItemInCurationRequest) { + val audioContentCurationItem = repository.findByCurationIdAndItemId( + curationId = request.curationId, + itemId = request.itemId + ) + + audioContentCurationItem?.isActive = false + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetCurationItemResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetCurationItemResponse.kt new file mode 100644 index 0000000..b293643 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/GetCurationItemResponse.kt @@ -0,0 +1,12 @@ +package kr.co.vividnext.sodalive.admin.content.curation + +import com.querydsl.core.annotations.QueryProjection + +data class GetCurationItemResponse @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/admin/content/curation/RemoveItemInCurationRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/RemoveItemInCurationRequest.kt new file mode 100644 index 0000000..c9b108f --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/RemoveItemInCurationRequest.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.admin.content.curation + +data class RemoveItemInCurationRequest( + val curationId: Long, + val itemId: Long +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/SearchCurationItemResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/SearchCurationItemResponse.kt new file mode 100644 index 0000000..f373893 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/SearchCurationItemResponse.kt @@ -0,0 +1,9 @@ +package kr.co.vividnext.sodalive.admin.content.curation + +import com.querydsl.core.annotations.QueryProjection + +data class SearchCurationItemResponse @QueryProjection constructor( + val id: Long, + val title: String, + val coverImageUrl: String +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/AdminContentSeriesRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/AdminContentSeriesRepository.kt index c251e5b..3e4b7ea 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/AdminContentSeriesRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/AdminContentSeriesRepository.kt @@ -22,6 +22,7 @@ interface AdminContentSeriesQueryRepository { ): List fun searchSeriesList(searchWord: String): List + fun findByIdAndActiveTrue(seriesId: Long): Series? } class AdminContentSeriesQueryRepositoryImpl( @@ -97,4 +98,14 @@ class AdminContentSeriesQueryRepositoryImpl( .orderBy(series.id.desc()) .fetch() } + + override fun findByIdAndActiveTrue(seriesId: Long): Series? { + return queryFactory + .selectFrom(series) + .where( + series.id.eq(seriesId), + series.isActive.isTrue + ) + .fetchFirst() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationItem.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationItem.kt new file mode 100644 index 0000000..7eddaa4 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationItem.kt @@ -0,0 +1,33 @@ +package kr.co.vividnext.sodalive.content.main.curation + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.content.AudioContent +import kr.co.vividnext.sodalive.creator.admin.content.series.Series +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne +import javax.persistence.Table + +@Entity +@Table(name = "content_curation_item") +data class AudioContentCurationItem( + @Column(nullable = false) + var orders: Int = 1, + + @Column(nullable = false) + var isActive: Boolean = true +) : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "curation_id", nullable = false) + var curation: AudioContentCuration? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "content_id", nullable = true) + var content: AudioContent? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "series_id", nullable = true) + var series: Series? = null +} From 8f2ec7f4dda7c0124adcae4395a2a08c49ade12d Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 31 Jan 2025 22:50:27 +0900 Subject: [PATCH 11/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20Request=20-=20contentIdList=20->=20itemIdL?= =?UTF-8?q?ist=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/content/curation/AddItemToCurationRequest.kt | 2 +- .../admin/content/curation/AdminContentCurationService.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt index d344da7..938ad44 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/curation/AddItemToCurationRequest.kt @@ -2,5 +2,5 @@ package kr.co.vividnext.sodalive.admin.content.curation data class AddItemToCurationRequest( val curationId: Long, - val contentIdList: List + val itemIdList: List ) 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 40a5404..7135e27 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 @@ -102,7 +102,7 @@ class AdminContentCurationService( ?: throw SodaException("잘못된 요청입니다.") if (audioContentCuration.isSeries) { - request.contentIdList.forEach { seriesId -> + request.itemIdList.forEach { seriesId -> val series = seriesRepository.findByIdAndActiveTrue(seriesId) if (series != null) { @@ -117,7 +117,7 @@ class AdminContentCurationService( } } } else { - request.contentIdList.forEach { contentId -> + request.itemIdList.forEach { contentId -> val audioContent = contentRepository.findByIdAndActiveTrue(contentId) if (audioContent != null) { From 96b832983ae3f1dd3e55d51e632453e6fbd25de2 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 31 Jan 2025 23:06:03 +0900 Subject: [PATCH 12/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80/=EC=A0=9C=EA=B1=B0=20-=20return=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation/AdminContentCurationController.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 aeb1863..e065e62 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 @@ -52,12 +52,12 @@ class AdminContentCurationController(private val service: AdminContentCurationSe ) = ApiResponse.ok(service.searchCurationSeriesItem(curationId, searchWord)) @PostMapping("/add/item") - fun addItemToCuration(@RequestBody request: AddItemToCurationRequest) { - ApiResponse.ok(service.addItemToCuration(request), "큐레이션 아이템을 등록했습니다.") - } + fun addItemToCuration( + @RequestBody request: AddItemToCurationRequest + ) = ApiResponse.ok(service.addItemToCuration(request), "큐레이션 아이템을 등록했습니다.") @PostMapping("/remove/item") - fun removeItemInCuration(@RequestBody request: RemoveItemInCurationRequest) { - ApiResponse.ok(service.removeItemInCuration(request), "큐레이션 아이템을 제거했습니다.") - } + fun removeItemInCuration( + @RequestBody request: RemoveItemInCurationRequest + ) = ApiResponse.ok(service.removeItemInCuration(request), "큐레이션 아이템을 제거했습니다.") } From ce881506f997b5b4aa05d8f2f2a04940cca6aee9 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 31 Jan 2025 23:12:23 +0900 Subject: [PATCH 13/14] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EC=BD=98=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20sql=EC=97=90=20from=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/admin/content/AdminContentRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt index 3c402c2..8365b2b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/AdminContentRepository.kt @@ -146,7 +146,7 @@ class AdminAudioContentQueryRepositoryImpl( override fun findByIdAndActiveTrue(audioContentId: Long): AudioContent? { return queryFactory - .select(audioContent) + .selectFrom(audioContent) .where( audioContent.id.eq(audioContentId), audioContent.isActive.isTrue From 32a71664a469bdebabcdfc66aa59b78f7858a7da Mon Sep 17 00:00:00 2001 From: Klaus Date: Sat, 1 Feb 2025 00:08:37 +0900 Subject: [PATCH 14/14] =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EC=A0=95?= =?UTF-8?q?=EC=82=B0=20-=20=EC=BA=94=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=9C=20=EB=82=A0=EC=A7=9C=EB=A5=BC=20=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B3=84=EC=82=B0=20=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/admin/calculate/AdminCalculateQueryRepository.kt | 4 ++-- .../admin/calculate/CreatorAdminCalculateQueryRepository.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt index 026e9ec..47c243b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt @@ -41,8 +41,8 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .on(member.id.eq(creatorSettlementRatio.member.id)) .where( useCan.isRefund.isFalse - .and(liveRoom.beginDateTime.goe(startDate)) - .and(liveRoom.beginDateTime.loe(endDate)) + .and(useCan.createdAt.goe(startDate)) + .and(useCan.createdAt.loe(endDate)) ) .groupBy(liveRoom.id, useCan.canUsage, creatorSettlementRatio.liveSettlementRatio) .orderBy(member.nickname.desc(), liveRoom.id.desc(), useCan.canUsage.desc(), formattedDate.desc()) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt index 590e27a..bae92bc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt @@ -55,8 +55,8 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac .on(member.id.eq(creatorSettlementRatio.member.id)) .where( useCan.isRefund.isFalse - .and(liveRoom.beginDateTime.goe(startDate)) - .and(liveRoom.beginDateTime.loe(endDate)) + .and(useCan.createdAt.goe(startDate)) + .and(useCan.createdAt.loe(endDate)) .and(liveRoom.member.id.eq(memberId)) ) .groupBy(liveRoom.id, useCan.canUsage, creatorSettlementRatio.liveSettlementRatio)