| @@ -41,8 +41,8 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { | |||||||
|             .on(member.id.eq(creatorSettlementRatio.member.id)) |             .on(member.id.eq(creatorSettlementRatio.member.id)) | ||||||
|             .where( |             .where( | ||||||
|                 useCan.isRefund.isFalse |                 useCan.isRefund.isFalse | ||||||
|                     .and(liveRoom.beginDateTime.goe(startDate)) |                     .and(useCan.createdAt.goe(startDate)) | ||||||
|                     .and(liveRoom.beginDateTime.loe(endDate)) |                     .and(useCan.createdAt.loe(endDate)) | ||||||
|             ) |             ) | ||||||
|             .groupBy(liveRoom.id, useCan.canUsage, creatorSettlementRatio.liveSettlementRatio) |             .groupBy(liveRoom.id, useCan.canUsage, creatorSettlementRatio.liveSettlementRatio) | ||||||
|             .orderBy(member.nickname.desc(), liveRoom.id.desc(), useCan.canUsage.desc(), formattedDate.desc()) |             .orderBy(member.nickname.desc(), liveRoom.id.desc(), useCan.canUsage.desc(), formattedDate.desc()) | ||||||
|   | |||||||
| @@ -42,6 +42,9 @@ class AdminContentController(private val service: AdminContentService) { | |||||||
|     fun modifyAudioContent( |     fun modifyAudioContent( | ||||||
|         @RequestBody request: UpdateAdminContentRequest |         @RequestBody request: UpdateAdminContentRequest | ||||||
|     ) = ApiResponse.ok(service.updateAudioContent(request)) |     ) = ApiResponse.ok(service.updateAudioContent(request)) | ||||||
|  |  | ||||||
|  |     @GetMapping("/main/tab") | ||||||
|  |     fun getContentMainTabList() = ApiResponse.ok(service.getContentMainTabList()) | ||||||
| } | } | ||||||
|  |  | ||||||
| enum class ContentReleaseStatus { | enum class ContentReleaseStatus { | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ interface AdminAudioContentQueryRepository { | |||||||
|     ): List<GetAdminContentListItem> |     ): List<GetAdminContentListItem> | ||||||
|  |  | ||||||
|     fun getHashTagList(audioContentId: Long): List<String> |     fun getHashTagList(audioContentId: Long): List<String> | ||||||
|  |     fun findByIdAndActiveTrue(audioContentId: Long): AudioContent? | ||||||
| } | } | ||||||
|  |  | ||||||
| class AdminAudioContentQueryRepositoryImpl( | class AdminAudioContentQueryRepositoryImpl( | ||||||
| @@ -143,6 +144,16 @@ class AdminAudioContentQueryRepositoryImpl( | |||||||
|             .fetch() |             .fetch() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override fun findByIdAndActiveTrue(audioContentId: Long): AudioContent? { | ||||||
|  |         return queryFactory | ||||||
|  |             .selectFrom(audioContent) | ||||||
|  |             .where( | ||||||
|  |                 audioContent.id.eq(audioContentId), | ||||||
|  |                 audioContent.isActive.isTrue | ||||||
|  |             ) | ||||||
|  |             .fetchFirst() | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private fun formattedDateExpression( |     private fun formattedDateExpression( | ||||||
|         dateTime: DateTimePath<LocalDateTime>, |         dateTime: DateTimePath<LocalDateTime>, | ||||||
|         format: String = "%Y-%m-%d" |         format: String = "%Y-%m-%d" | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
| package kr.co.vividnext.sodalive.admin.content | package kr.co.vividnext.sodalive.admin.content | ||||||
|  |  | ||||||
| import kr.co.vividnext.sodalive.admin.content.curation.AdminContentCurationRepository | 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.admin.content.theme.AdminContentThemeRepository | ||||||
| import kr.co.vividnext.sodalive.aws.cloudfront.AudioContentCloudFront | import kr.co.vividnext.sodalive.aws.cloudfront.AudioContentCloudFront | ||||||
| import kr.co.vividnext.sodalive.common.SodaException | 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.domain.Pageable | ||||||
| import org.springframework.data.repository.findByIdOrNull | import org.springframework.data.repository.findByIdOrNull | ||||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||||
| @@ -14,7 +16,8 @@ class AdminContentService( | |||||||
|     private val repository: AdminContentRepository, |     private val repository: AdminContentRepository, | ||||||
|     private val themeRepository: AdminContentThemeRepository, |     private val themeRepository: AdminContentThemeRepository, | ||||||
|     private val audioContentCloudFront: AudioContentCloudFront, |     private val audioContentCloudFront: AudioContentCloudFront, | ||||||
|     private val curationRepository: AdminContentCurationRepository |     private val curationRepository: AdminContentCurationRepository, | ||||||
|  |     private val contentMainTabRepository: AdminContentMainTabRepository | ||||||
| ) { | ) { | ||||||
|     fun getAudioContentList(status: ContentReleaseStatus, pageable: Pageable): GetAdminContentListResponse { |     fun getAudioContentList(status: ContentReleaseStatus, pageable: Pageable): GetAdminContentListResponse { | ||||||
|         val totalCount = repository.getAudioContentTotalCount(status = status) |         val totalCount = repository.getAudioContentTotalCount(status = status) | ||||||
| @@ -118,4 +121,8 @@ class AdminContentService( | |||||||
|             audioContent.theme = theme |             audioContent.theme = theme | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fun getContentMainTabList(): List<GetContentMainTabItem> { | ||||||
|  |         return contentMainTabRepository.findAllByActiveIsTrue() | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping | |||||||
| import org.springframework.web.bind.annotation.PutMapping | import org.springframework.web.bind.annotation.PutMapping | ||||||
| import org.springframework.web.bind.annotation.RequestBody | import org.springframework.web.bind.annotation.RequestBody | ||||||
| import org.springframework.web.bind.annotation.RequestMapping | 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.RequestPart | ||||||
| import org.springframework.web.bind.annotation.RestController | import org.springframework.web.bind.annotation.RestController | ||||||
| import org.springframework.web.multipart.MultipartFile | import org.springframework.web.multipart.MultipartFile | ||||||
| @@ -33,5 +34,7 @@ class AdminContentBannerController(private val service: AdminContentBannerServic | |||||||
|     ) = ApiResponse.ok(service.updateBannerOrders(request.ids), "수정되었습니다.") |     ) = ApiResponse.ok(service.updateBannerOrders(request.ids), "수정되었습니다.") | ||||||
|  |  | ||||||
|     @GetMapping |     @GetMapping | ||||||
|     fun getAudioContentMainBannerList() = ApiResponse.ok(service.getAudioContentMainBannerList()) |     fun getAudioContentMainBannerList( | ||||||
|  |         @RequestParam(value = "tabId", required = false) tabId: Long? = null | ||||||
|  |     ) = ApiResponse.ok(service.getAudioContentMainBannerList(tabId = tabId)) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.admin.content.banner | |||||||
| import com.querydsl.jpa.impl.JPAQueryFactory | import com.querydsl.jpa.impl.JPAQueryFactory | ||||||
| import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner | 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.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.creator.admin.content.series.QSeries.series | ||||||
| import kr.co.vividnext.sodalive.event.QEvent.event | import kr.co.vividnext.sodalive.event.QEvent.event | ||||||
| import kr.co.vividnext.sodalive.member.QMember.member | import kr.co.vividnext.sodalive.member.QMember.member | ||||||
| @@ -14,7 +15,7 @@ import org.springframework.stereotype.Repository | |||||||
| interface AdminContentBannerRepository : JpaRepository<AudioContentBanner, Long>, AdminContentBannerQueryRepository | interface AdminContentBannerRepository : JpaRepository<AudioContentBanner, Long>, AdminContentBannerQueryRepository | ||||||
|  |  | ||||||
| interface AdminContentBannerQueryRepository { | interface AdminContentBannerQueryRepository { | ||||||
|     fun getAudioContentMainBannerList(): List<GetAdminContentBannerResponse> |     fun getAudioContentMainBannerList(tabId: Long = 1): List<GetAdminContentBannerResponse> | ||||||
| } | } | ||||||
|  |  | ||||||
| class AdminContentBannerQueryRepositoryImpl( | class AdminContentBannerQueryRepositoryImpl( | ||||||
| @@ -22,11 +23,20 @@ class AdminContentBannerQueryRepositoryImpl( | |||||||
|     @Value("\${cloud.aws.cloud-front.host}") |     @Value("\${cloud.aws.cloud-front.host}") | ||||||
|     private val cloudFrontHost: String |     private val cloudFrontHost: String | ||||||
| ) : AdminContentBannerQueryRepository { | ) : AdminContentBannerQueryRepository { | ||||||
|     override fun getAudioContentMainBannerList(): List<GetAdminContentBannerResponse> { |     override fun getAudioContentMainBannerList(tabId: Long): List<GetAdminContentBannerResponse> { | ||||||
|  |         var where = audioContentBanner.isActive.isTrue | ||||||
|  |  | ||||||
|  |         where = if (tabId <= 1L) { | ||||||
|  |             where.and(audioContentMainTab.id.isNull) | ||||||
|  |         } else { | ||||||
|  |             where.and(audioContentMainTab.id.eq(tabId)) | ||||||
|  |         } | ||||||
|  |  | ||||||
|         return queryFactory |         return queryFactory | ||||||
|             .select( |             .select( | ||||||
|                 QGetAdminContentBannerResponse( |                 QGetAdminContentBannerResponse( | ||||||
|                     audioContentBanner.id, |                     audioContentBanner.id, | ||||||
|  |                     audioContentBanner.tab.id.coalesce(1), | ||||||
|                     audioContentBanner.type, |                     audioContentBanner.type, | ||||||
|                     audioContentBanner.thumbnailImage.prepend("/").prepend(cloudFrontHost), |                     audioContentBanner.thumbnailImage.prepend("/").prepend(cloudFrontHost), | ||||||
|                     audioContentBanner.event.id, |                     audioContentBanner.event.id, | ||||||
| @@ -43,7 +53,8 @@ class AdminContentBannerQueryRepositoryImpl( | |||||||
|             .leftJoin(audioContentBanner.event, event) |             .leftJoin(audioContentBanner.event, event) | ||||||
|             .leftJoin(audioContentBanner.creator, member) |             .leftJoin(audioContentBanner.creator, member) | ||||||
|             .leftJoin(audioContentBanner.series, series) |             .leftJoin(audioContentBanner.series, series) | ||||||
|             .where(audioContentBanner.isActive.isTrue) |             .leftJoin(audioContentBanner.tab, audioContentMainTab) | ||||||
|  |             .where(where) | ||||||
|             .orderBy(audioContentBanner.orders.asc()) |             .orderBy(audioContentBanner.orders.asc()) | ||||||
|             .fetch() |             .fetch() | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.admin.content.banner | |||||||
|  |  | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper | import com.fasterxml.jackson.databind.ObjectMapper | ||||||
| import kr.co.vividnext.sodalive.admin.content.series.AdminContentSeriesRepository | 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.aws.s3.S3Uploader | ||||||
| import kr.co.vividnext.sodalive.common.SodaException | import kr.co.vividnext.sodalive.common.SodaException | ||||||
| import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner | import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner | ||||||
| @@ -22,6 +23,7 @@ class AdminContentBannerService( | |||||||
|     private val memberRepository: MemberRepository, |     private val memberRepository: MemberRepository, | ||||||
|     private val seriesRepository: AdminContentSeriesRepository, |     private val seriesRepository: AdminContentSeriesRepository, | ||||||
|     private val eventRepository: EventRepository, |     private val eventRepository: EventRepository, | ||||||
|  |     private val contentMainTabRepository: AdminContentMainTabRepository, | ||||||
|     private val objectMapper: ObjectMapper, |     private val objectMapper: ObjectMapper, | ||||||
|  |  | ||||||
|     @Value("\${cloud.aws.s3.bucket}") |     @Value("\${cloud.aws.s3.bucket}") | ||||||
| @@ -64,12 +66,19 @@ class AdminContentBannerService( | |||||||
|             null |             null | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         val tab = if (request.tabId !== null) { | ||||||
|  |             contentMainTabRepository.findByIdOrNull(request.tabId) | ||||||
|  |         } else { | ||||||
|  |             null | ||||||
|  |         } | ||||||
|  |  | ||||||
|         val audioContentBanner = AudioContentBanner(type = request.type) |         val audioContentBanner = AudioContentBanner(type = request.type) | ||||||
|         audioContentBanner.link = request.link |         audioContentBanner.link = request.link | ||||||
|         audioContentBanner.isAdult = request.isAdult |         audioContentBanner.isAdult = request.isAdult | ||||||
|         audioContentBanner.event = event |         audioContentBanner.event = event | ||||||
|         audioContentBanner.creator = creator |         audioContentBanner.creator = creator | ||||||
|         audioContentBanner.series = series |         audioContentBanner.series = series | ||||||
|  |         audioContentBanner.tab = tab | ||||||
|         repository.save(audioContentBanner) |         repository.save(audioContentBanner) | ||||||
|  |  | ||||||
|         val fileName = generateFileName() |         val fileName = generateFileName() | ||||||
| @@ -156,6 +165,10 @@ class AdminContentBannerService( | |||||||
|  |  | ||||||
|             audioContentBanner.type = request.type |             audioContentBanner.type = request.type | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (request.tabId !== null) { | ||||||
|  |             audioContentBanner.tab = contentMainTabRepository.findByIdOrNull(request.tabId) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Transactional |     @Transactional | ||||||
| @@ -169,7 +182,7 @@ class AdminContentBannerService( | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fun getAudioContentMainBannerList(): List<GetAdminContentBannerResponse> { |     fun getAudioContentMainBannerList(tabId: Long?): List<GetAdminContentBannerResponse> { | ||||||
|         return repository.getAudioContentMainBannerList() |         return repository.getAudioContentMainBannerList(tabId = tabId ?: 1) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType | |||||||
|  |  | ||||||
| data class CreateContentBannerRequest( | data class CreateContentBannerRequest( | ||||||
|     val type: AudioContentBannerType, |     val type: AudioContentBannerType, | ||||||
|  |     val tabId: Long?, | ||||||
|     val eventId: Long?, |     val eventId: Long?, | ||||||
|     val creatorId: Long?, |     val creatorId: Long?, | ||||||
|     val seriesId: Long?, |     val seriesId: Long?, | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType | |||||||
|  |  | ||||||
| data class GetAdminContentBannerResponse @QueryProjection constructor( | data class GetAdminContentBannerResponse @QueryProjection constructor( | ||||||
|     val id: Long, |     val id: Long, | ||||||
|  |     val tabId: Long?, | ||||||
|     val type: AudioContentBannerType, |     val type: AudioContentBannerType, | ||||||
|     val thumbnailImageUrl: String, |     val thumbnailImageUrl: String, | ||||||
|     val eventId: Long?, |     val eventId: Long?, | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType | |||||||
| data class UpdateContentBannerRequest( | data class UpdateContentBannerRequest( | ||||||
|     val id: Long, |     val id: Long, | ||||||
|     val type: AudioContentBannerType?, |     val type: AudioContentBannerType?, | ||||||
|  |     val tabId: Long?, | ||||||
|     val eventId: Long?, |     val eventId: Long?, | ||||||
|     val creatorId: Long?, |     val creatorId: Long?, | ||||||
|     val seriesId: Long?, |     val seriesId: Long?, | ||||||
|   | |||||||
| @@ -0,0 +1,6 @@ | |||||||
|  | package kr.co.vividnext.sodalive.admin.content.curation | ||||||
|  |  | ||||||
|  | data class AddItemToCurationRequest( | ||||||
|  |     val curationId: Long, | ||||||
|  |     val itemIdList: List<Long> | ||||||
|  | ) | ||||||
| @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping | |||||||
| import org.springframework.web.bind.annotation.PutMapping | import org.springframework.web.bind.annotation.PutMapping | ||||||
| import org.springframework.web.bind.annotation.RequestBody | import org.springframework.web.bind.annotation.RequestBody | ||||||
| import org.springframework.web.bind.annotation.RequestMapping | import org.springframework.web.bind.annotation.RequestMapping | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam | ||||||
| import org.springframework.web.bind.annotation.RestController | import org.springframework.web.bind.annotation.RestController | ||||||
|  |  | ||||||
| @RestController | @RestController | ||||||
| @@ -29,5 +30,34 @@ class AdminContentCurationController(private val service: AdminContentCurationSe | |||||||
|     ) = ApiResponse.ok(service.updateContentCurationOrders(request.ids), "수정되었습니다.") |     ) = ApiResponse.ok(service.updateContentCurationOrders(request.ids), "수정되었습니다.") | ||||||
|  |  | ||||||
|     @GetMapping |     @GetMapping | ||||||
|     fun getContentCurationList() = ApiResponse.ok(service.getContentCurationList()) |     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), "큐레이션 아이템을 제거했습니다.") | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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<AudioContentCurationItem, Long>, | ||||||
|  |     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() | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,8 +1,14 @@ | |||||||
| package kr.co.vividnext.sodalive.admin.content.curation | package kr.co.vividnext.sodalive.admin.content.curation | ||||||
|  |  | ||||||
| import com.querydsl.jpa.impl.JPAQueryFactory | 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.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.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.data.jpa.repository.JpaRepository | ||||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||||
|  |  | ||||||
| @@ -12,26 +18,39 @@ interface AdminContentCurationRepository : | |||||||
|     AdminContentCurationQueryRepository |     AdminContentCurationQueryRepository | ||||||
|  |  | ||||||
| interface AdminContentCurationQueryRepository { | interface AdminContentCurationQueryRepository { | ||||||
|     fun getAudioContentCurationList(): List<GetAdminContentCurationResponse> |     fun getAudioContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> | ||||||
|     fun findByIdAndActive(id: Long): AudioContentCuration? |     fun findByIdAndActive(id: Long): AudioContentCuration? | ||||||
|  |     fun findByCurationIdAndItemId(curationId: Long, itemId: Long): AudioContentCurationItem? | ||||||
|  |     fun getAudioContentCurationItemList(curationId: Long): List<GetCurationItemResponse> | ||||||
|  |     fun searchCurationContentItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse> | ||||||
|  |     fun searchCurationSeriesItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse> | ||||||
| } | } | ||||||
|  |  | ||||||
| @Repository | @Repository | ||||||
| class AdminContentCurationQueryRepositoryImpl( | class AdminContentCurationQueryRepositoryImpl( | ||||||
|     private val queryFactory: JPAQueryFactory |     private val queryFactory: JPAQueryFactory, | ||||||
|  |  | ||||||
|  |     @Value("\${cloud.aws.cloud-front.host}") | ||||||
|  |     private val imageHost: String | ||||||
| ) : AdminContentCurationQueryRepository { | ) : AdminContentCurationQueryRepository { | ||||||
|     override fun getAudioContentCurationList(): List<GetAdminContentCurationResponse> { |     override fun getAudioContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> { | ||||||
|         return queryFactory |         return queryFactory | ||||||
|             .select( |             .select( | ||||||
|                 QGetAdminContentCurationResponse( |                 QGetAdminContentCurationResponse( | ||||||
|                     audioContentCuration.id, |                     audioContentCuration.id, | ||||||
|  |                     audioContentMainTab.id, | ||||||
|                     audioContentCuration.title, |                     audioContentCuration.title, | ||||||
|                     audioContentCuration.description, |                     audioContentCuration.description, | ||||||
|                     audioContentCuration.isAdult |                     audioContentCuration.isAdult, | ||||||
|  |                     audioContentCuration.isSeries | ||||||
|                 ) |                 ) | ||||||
|             ) |             ) | ||||||
|             .from(audioContentCuration) |             .from(audioContentCuration) | ||||||
|             .where(audioContentCuration.isActive.isTrue) |             .innerJoin(audioContentCuration.tab, audioContentMainTab) | ||||||
|  |             .where( | ||||||
|  |                 audioContentCuration.isActive.isTrue, | ||||||
|  |                 audioContentMainTab.id.eq(tabId) | ||||||
|  |             ) | ||||||
|             .orderBy(audioContentCuration.orders.asc()) |             .orderBy(audioContentCuration.orders.asc()) | ||||||
|             .fetch() |             .fetch() | ||||||
|     } |     } | ||||||
| @@ -45,4 +64,89 @@ class AdminContentCurationQueryRepositoryImpl( | |||||||
|             ) |             ) | ||||||
|             .fetchFirst() |             .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<GetCurationItemResponse> { | ||||||
|  |         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<SearchCurationItemResponse> { | ||||||
|  |         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<SearchCurationItemResponse> { | ||||||
|  |         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() | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,24 +1,37 @@ | |||||||
| package kr.co.vividnext.sodalive.admin.content.curation | 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.common.SodaException | ||||||
| import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration | 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.data.repository.findByIdOrNull | ||||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||||
| import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||||
|  |  | ||||||
| @Service | @Service | ||||||
| class AdminContentCurationService( | class AdminContentCurationService( | ||||||
|     private val repository: AdminContentCurationRepository |     private val repository: AdminContentCurationRepository, | ||||||
|  |     private val contentMainTabRepository: AdminContentMainTabRepository, | ||||||
|  |     private val seriesRepository: AdminContentSeriesRepository, | ||||||
|  |     private val contentRepository: AdminContentRepository, | ||||||
|  |     private val contentCurationItemRepository: AdminContentCurationItemRepository | ||||||
| ) { | ) { | ||||||
|     @Transactional |     @Transactional | ||||||
|     fun createContentCuration(request: CreateContentCurationRequest) { |     fun createContentCuration(request: CreateContentCurationRequest) { | ||||||
|         repository.save( |         val tab = contentMainTabRepository.findByIdOrNull(request.tabId) | ||||||
|             AudioContentCuration( |             ?: throw SodaException("잘못된 요청입니다.") | ||||||
|                 title = request.title, |  | ||||||
|                 description = request.description, |         val curation = AudioContentCuration( | ||||||
|                 isAdult = request.isAdult |             title = request.title, | ||||||
|             ) |             description = request.description, | ||||||
|  |             isAdult = request.isAdult, | ||||||
|  |             isSeries = request.isSeries | ||||||
|         ) |         ) | ||||||
|  |         curation.tab = tab | ||||||
|  |  | ||||||
|  |         repository.save(curation) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Transactional |     @Transactional | ||||||
| @@ -41,6 +54,18 @@ class AdminContentCurationService( | |||||||
|         if (request.isActive != null) { |         if (request.isActive != null) { | ||||||
|             audioContentCuration.isActive = request.isActive |             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 |     @Transactional | ||||||
| @@ -54,7 +79,68 @@ class AdminContentCurationService( | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fun getContentCurationList(): List<GetAdminContentCurationResponse> { |     fun getContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> { | ||||||
|         return repository.getAudioContentCurationList() |         return repository.getAudioContentCurationList(tabId = tabId) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun getCurationItem(curationId: Long): List<GetCurationItemResponse> { | ||||||
|  |         return repository.getAudioContentCurationItemList(curationId) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun searchCurationContentItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse> { | ||||||
|  |         return repository.searchCurationContentItem(curationId, searchWord) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun searchCurationSeriesItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse> { | ||||||
|  |         return repository.searchCurationSeriesItem(curationId, searchWord) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Transactional | ||||||
|  |     fun addItemToCuration(request: AddItemToCurationRequest) { | ||||||
|  |         // 큐레이션 조회 | ||||||
|  |         val audioContentCuration = repository.findByIdOrNull(id = request.curationId) | ||||||
|  |             ?: throw SodaException("잘못된 요청입니다.") | ||||||
|  |  | ||||||
|  |         if (audioContentCuration.isSeries) { | ||||||
|  |             request.itemIdList.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.itemIdList.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 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,16 +1,20 @@ | |||||||
| package kr.co.vividnext.sodalive.admin.content.curation | package kr.co.vividnext.sodalive.admin.content.curation | ||||||
|  |  | ||||||
| data class CreateContentCurationRequest( | data class CreateContentCurationRequest( | ||||||
|  |     val tabId: Long, | ||||||
|     val title: String, |     val title: String, | ||||||
|     val description: String, |     val description: String, | ||||||
|     val isAdult: Boolean |     val isAdult: Boolean, | ||||||
|  |     val isSeries: Boolean | ||||||
| ) | ) | ||||||
|  |  | ||||||
| data class UpdateContentCurationRequest( | data class UpdateContentCurationRequest( | ||||||
|     val id: Long, |     val id: Long, | ||||||
|  |     val tabId: Long?, | ||||||
|     val title: String?, |     val title: String?, | ||||||
|     val description: String?, |     val description: String?, | ||||||
|     val isAdult: Boolean?, |     val isAdult: Boolean?, | ||||||
|  |     val isSeries: Boolean?, | ||||||
|     val isActive: Boolean? |     val isActive: Boolean? | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,9 @@ import com.querydsl.core.annotations.QueryProjection | |||||||
|  |  | ||||||
| data class GetAdminContentCurationResponse @QueryProjection constructor( | data class GetAdminContentCurationResponse @QueryProjection constructor( | ||||||
|     val id: Long, |     val id: Long, | ||||||
|  |     val tabId: Long, | ||||||
|     val title: String, |     val title: String, | ||||||
|     val description: String, |     val description: String, | ||||||
|     val isAdult: Boolean |     val isAdult: Boolean, | ||||||
|  |     val isSeries: Boolean | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -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 | ||||||
|  | ) | ||||||
| @@ -0,0 +1,6 @@ | |||||||
|  | package kr.co.vividnext.sodalive.admin.content.curation | ||||||
|  |  | ||||||
|  | data class RemoveItemInCurationRequest( | ||||||
|  |     val curationId: Long, | ||||||
|  |     val itemId: Long | ||||||
|  | ) | ||||||
| @@ -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 | ||||||
|  | ) | ||||||
| @@ -22,6 +22,7 @@ interface AdminContentSeriesQueryRepository { | |||||||
|     ): List<GetAdminSeriesListItem> |     ): List<GetAdminSeriesListItem> | ||||||
|  |  | ||||||
|     fun searchSeriesList(searchWord: String): List<GetAdminSearchSeriesListItem> |     fun searchSeriesList(searchWord: String): List<GetAdminSearchSeriesListItem> | ||||||
|  |     fun findByIdAndActiveTrue(seriesId: Long): Series? | ||||||
| } | } | ||||||
|  |  | ||||||
| class AdminContentSeriesQueryRepositoryImpl( | class AdminContentSeriesQueryRepositoryImpl( | ||||||
| @@ -97,4 +98,14 @@ class AdminContentSeriesQueryRepositoryImpl( | |||||||
|             .orderBy(series.id.desc()) |             .orderBy(series.id.desc()) | ||||||
|             .fetch() |             .fetch() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override fun findByIdAndActiveTrue(seriesId: Long): Series? { | ||||||
|  |         return queryFactory | ||||||
|  |             .selectFrom(series) | ||||||
|  |             .where( | ||||||
|  |                 series.id.eq(seriesId), | ||||||
|  |                 series.isActive.isTrue | ||||||
|  |             ) | ||||||
|  |             .fetchFirst() | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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<AudioContentMainTab, Long>, AdminContentMainTabQueryRepository | ||||||
|  |  | ||||||
|  | interface AdminContentMainTabQueryRepository { | ||||||
|  |     fun findAllByActiveIsTrue(): List<GetContentMainTabItem> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class AdminContentMainTabQueryRepositoryImpl( | ||||||
|  |     private val queryFactory: JPAQueryFactory | ||||||
|  | ) : AdminContentMainTabQueryRepository { | ||||||
|  |     override fun findAllByActiveIsTrue(): List<GetContentMainTabItem> { | ||||||
|  |         return queryFactory | ||||||
|  |             .select( | ||||||
|  |                 QGetContentMainTabItem( | ||||||
|  |                     audioContentMainTab.id, | ||||||
|  |                     audioContentMainTab.title | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |             .from(audioContentMainTab) | ||||||
|  |             .where(audioContentMainTab.isActive.isTrue) | ||||||
|  |             .fetch() | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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.banner.QAudioContentBanner.audioContentBanner | ||||||
| import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration | 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.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.order.QOrder.order | ||||||
| import kr.co.vividnext.sodalive.content.pin.QPinContent.pinContent | import kr.co.vividnext.sodalive.content.pin.QPinContent.pinContent | ||||||
| import kr.co.vividnext.sodalive.content.playlist.AudioContentPlaylistContent | import kr.co.vividnext.sodalive.content.playlist.AudioContentPlaylistContent | ||||||
| @@ -755,7 +756,8 @@ class AudioContentQueryRepositoryImpl( | |||||||
|  |  | ||||||
|         return queryFactory |         return queryFactory | ||||||
|             .selectFrom(audioContentCuration) |             .selectFrom(audioContentCuration) | ||||||
|             .where(where) |             .leftJoin(audioContentCuration.tab, audioContentMainTab) | ||||||
|  |             .where(where, audioContentMainTab.id.isNull) | ||||||
|             .offset(offset) |             .offset(offset) | ||||||
|             .limit(limit) |             .limit(limit) | ||||||
|             .orderBy(audioContentCuration.orders.asc()) |             .orderBy(audioContentCuration.orders.asc()) | ||||||
|   | |||||||
| @@ -1,8 +1,12 @@ | |||||||
| package kr.co.vividnext.sodalive.content.main.curation | package kr.co.vividnext.sodalive.content.main.curation | ||||||
|  |  | ||||||
| import kr.co.vividnext.sodalive.common.BaseEntity | import kr.co.vividnext.sodalive.common.BaseEntity | ||||||
|  | import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTab | ||||||
| import javax.persistence.Column | import javax.persistence.Column | ||||||
| import javax.persistence.Entity | import javax.persistence.Entity | ||||||
|  | import javax.persistence.FetchType | ||||||
|  | import javax.persistence.JoinColumn | ||||||
|  | import javax.persistence.OneToOne | ||||||
| import javax.persistence.Table | import javax.persistence.Table | ||||||
|  |  | ||||||
| @Entity | @Entity | ||||||
| @@ -17,5 +21,11 @@ data class AudioContentCuration( | |||||||
|     @Column(nullable = false) |     @Column(nullable = false) | ||||||
|     var isActive: Boolean = true, |     var isActive: Boolean = true, | ||||||
|     @Column(nullable = false) |     @Column(nullable = false) | ||||||
|     var orders: Int = 1 |     var orders: Int = 1, | ||||||
| ) : BaseEntity() |     @Column(nullable = false) | ||||||
|  |     var isSeries: Boolean = false | ||||||
|  | ) : BaseEntity() { | ||||||
|  |     @OneToOne(fetch = FetchType.EAGER) | ||||||
|  |     @JoinColumn(name = "tab_id", nullable = true) | ||||||
|  |     var tab: AudioContentMainTab? = null | ||||||
|  | } | ||||||
|   | |||||||
| @@ -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 | ||||||
|  | } | ||||||
| @@ -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 | ||||||
|  | ) | ||||||
| @@ -55,8 +55,8 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac | |||||||
|             .on(member.id.eq(creatorSettlementRatio.member.id)) |             .on(member.id.eq(creatorSettlementRatio.member.id)) | ||||||
|             .where( |             .where( | ||||||
|                 useCan.isRefund.isFalse |                 useCan.isRefund.isFalse | ||||||
|                     .and(liveRoom.beginDateTime.goe(startDate)) |                     .and(useCan.createdAt.goe(startDate)) | ||||||
|                     .and(liveRoom.beginDateTime.loe(endDate)) |                     .and(useCan.createdAt.loe(endDate)) | ||||||
|                     .and(liveRoom.member.id.eq(memberId)) |                     .and(liveRoom.member.id.eq(memberId)) | ||||||
|             ) |             ) | ||||||
|             .groupBy(liveRoom.id, useCan.canUsage, creatorSettlementRatio.liveSettlementRatio) |             .groupBy(liveRoom.id, useCan.canUsage, creatorSettlementRatio.liveSettlementRatio) | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ data class Series( | |||||||
|     @CollectionTable(name = "series_published_days_of_week", joinColumns = [JoinColumn(name = "series_id")]) |     @CollectionTable(name = "series_published_days_of_week", joinColumns = [JoinColumn(name = "series_id")]) | ||||||
|     val publishedDaysOfWeek: MutableSet<SeriesPublishedDaysOfWeek> = mutableSetOf(), |     val publishedDaysOfWeek: MutableSet<SeriesPublishedDaysOfWeek> = mutableSetOf(), | ||||||
|     var isAdult: Boolean = false, |     var isAdult: Boolean = false, | ||||||
|  |     var isOriginal: Boolean = false, | ||||||
|     var isActive: Boolean = true, |     var isActive: Boolean = true, | ||||||
|     var orders: Int = 1 |     var orders: Int = 1 | ||||||
| ) : BaseEntity() { | ) : BaseEntity() { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user