diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderController.kt index 889e6ed..89c1e08 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderController.kt @@ -9,7 +9,6 @@ import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping 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 @@ -34,7 +33,6 @@ class OrderController(private val service: OrderService) { @GetMapping("/audio-content") fun getAudioContentOrderList( - @RequestParam(value = "orderType", required = false) orderType: OrderType? = null, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, pageable: Pageable ) = run { @@ -42,7 +40,6 @@ class OrderController(private val service: OrderService) { ApiResponse.ok( service.getAudioContentOrderList( - orderType = orderType, member = member, offset = pageable.offset, limit = pageable.pageSize.toLong() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderRepository.kt index 4c7887b..e900de8 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderRepository.kt @@ -6,6 +6,8 @@ import kr.co.vividnext.sodalive.content.QAudioContent.audioContent import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.QGetAudioContentMainItem import kr.co.vividnext.sodalive.content.order.QOrder.order +import kr.co.vividnext.sodalive.content.playlist.ContentIdAndEndDateData +import kr.co.vividnext.sodalive.content.playlist.QContentIdAndEndDateData import kr.co.vividnext.sodalive.member.QMember.member import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository @@ -20,7 +22,6 @@ interface OrderQueryRepository { fun isExistOrderedAndOrderType(memberId: Long, contentId: Long): Pair fun getAudioContentRemainingTime(memberId: Long, contentId: Long, timezone: String): String fun getAudioContentOrderList( - orderType: OrderType?, dateTime: LocalDateTime, coverImageHost: String, memberId: Long, @@ -28,7 +29,7 @@ interface OrderQueryRepository { limit: Long = 10 ): List - fun totalAudioContentOrderListCount(orderType: OrderType?, memberId: Long, dateTime: LocalDateTime): Int + fun totalAudioContentOrderListCount(memberId: Long, dateTime: LocalDateTime): Int fun getAudioContentMainOrderList( dateTime: LocalDateTime, coverImageHost: String, @@ -38,6 +39,7 @@ interface OrderQueryRepository { ): List fun findOrderedContent(contentIdList: List, memberId: Long): List + fun findEndDateByContentId(contentIdList: List, memberId: Long): List } @Repository @@ -118,40 +120,22 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde } override fun getAudioContentOrderList( - orderType: OrderType?, dateTime: LocalDateTime, coverImageHost: String, memberId: Long, offset: Long, limit: Long ): List { - var where = order.member.id.eq(memberId) + val where = order.member.id.eq(memberId) .and(order.isActive.isTrue) - - when (orderType) { - OrderType.RENTAL -> { - where = where.and( - order.type.eq(OrderType.RENTAL) - .and(order.startDate.before(dateTime)) - .and(order.endDate.after(dateTime)) - ) - } - - OrderType.KEEP -> { - where = where.and(order.type.eq(OrderType.KEEP)) - } - - null -> { - where = where.and( - order.type.eq(OrderType.KEEP) - .or( - order.type.eq(OrderType.RENTAL) - .and(order.startDate.before(dateTime)) - .and(order.endDate.after(dateTime)) - ) - ) - } - } + .and( + order.type.eq(OrderType.KEEP) + .or( + order.type.eq(OrderType.RENTAL) + .and(order.startDate.before(dateTime)) + .and(order.endDate.after(dateTime)) + ) + ) return queryFactory .select( @@ -178,34 +162,17 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde .fetch() } - override fun totalAudioContentOrderListCount(orderType: OrderType?, memberId: Long, dateTime: LocalDateTime): Int { - var where = order.member.id.eq(memberId) + override fun totalAudioContentOrderListCount(memberId: Long, dateTime: LocalDateTime): Int { + val where = order.member.id.eq(memberId) .and(order.isActive.isTrue) - - when (orderType) { - OrderType.RENTAL -> { - where = where.and( - order.type.eq(OrderType.RENTAL) - .and(order.startDate.before(dateTime)) - .and(order.endDate.after(dateTime)) - ) - } - - OrderType.KEEP -> { - where = where.and(order.type.eq(OrderType.KEEP)) - } - - null -> { - where = where.and( - order.type.eq(OrderType.KEEP) - .or( - order.type.eq(OrderType.RENTAL) - .and(order.startDate.before(dateTime)) - .and(order.endDate.after(dateTime)) - ) - ) - } - } + .and( + order.type.eq(OrderType.KEEP) + .or( + order.type.eq(OrderType.RENTAL) + .and(order.startDate.before(dateTime)) + .and(order.endDate.after(dateTime)) + ) + ) return queryFactory.select(order.id) .from(order) @@ -265,9 +232,24 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde .innerJoin(order.audioContent, audioContent) .where( order.isActive.isTrue, - order.endDate.isNull, member.id.eq(memberId), - audioContent.id.`in`(contentIdList) + audioContent.id.`in`(contentIdList), + order.endDate.isNull.or(order.endDate.after(LocalDateTime.now())) + ) + .fetch() + } + + override fun findEndDateByContentId(contentIdList: List, memberId: Long): List { + return queryFactory + .select(QContentIdAndEndDateData(audioContent.id, order.endDate)) + .from(order) + .innerJoin(order.member, member) + .innerJoin(order.audioContent, audioContent) + .where( + order.isActive.isTrue, + member.id.eq(memberId), + audioContent.id.`in`(contentIdList), + order.endDate.isNull.or(order.endDate.after(LocalDateTime.now())) ) .fetch() } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt index 620aaaa..630b22a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt @@ -90,18 +90,15 @@ class OrderService( } fun getAudioContentOrderList( - orderType: OrderType? = null, member: Member, offset: Long, limit: Long ): GetAudioContentOrderListResponse { val totalCount = repository.totalAudioContentOrderListCount( - orderType = orderType, memberId = member.id!!, dateTime = LocalDateTime.now() ) val orderItems = repository.getAudioContentOrderList( - orderType = orderType, dateTime = LocalDateTime.now(), coverImageHost = audioContentCoverImageHost, memberId = member.id!!, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/AudioContentPlaylistService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/AudioContentPlaylistService.kt index 46ccf02..f224ab0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/AudioContentPlaylistService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/AudioContentPlaylistService.kt @@ -7,6 +7,7 @@ import kr.co.vividnext.sodalive.live.roulette.RedisIdGenerator import kr.co.vividnext.sodalive.member.Member import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter @@ -27,10 +28,9 @@ class AudioContentPlaylistService( throw SodaException("플레이 리스트는 최대 10개까지 생성할 수 있습니다.") } - // 콘텐츠 유효성 검사 (소장으로 구매한 콘텐츠 인가?) - validateContent( - contentIdList = request.contentIdAndOrderList.map { it.contentId }, - memberId = member.id!! + val contentIdAndOrderList = validateAndGetContentIdAndOrderList( + contentIdAndOrderList = request.contentIdAndOrderList, + member ) val playlist = AudioContentPlaylist( @@ -38,12 +38,34 @@ class AudioContentPlaylistService( memberId = member.id!!, title = request.title, desc = request.desc, - contentIdAndOrderList = request.contentIdAndOrderList + contentIdAndOrderList = contentIdAndOrderList ) redisRepository.save(playlist) } + private fun validateAndGetContentIdAndOrderList( + contentIdAndOrderList: List, + member: Member + ): List { + validateContent( + contentIdList = contentIdAndOrderList.map { it.contentId }, + memberId = member.id!! + ) + + val contentIdAndEndDate = orderRepository.findEndDateByContentId( + contentIdList = contentIdAndOrderList.map { it.contentId }, + memberId = member.id!! + ) + + val contentIdAndEndDateMap = contentIdAndEndDate.associate { it.contentId to it.endDate } + + return contentIdAndOrderList.map { + it.endDate = contentIdAndEndDateMap[it.contentId] + it + } + } + private fun validateContent(contentIdList: List, memberId: Long) { if (contentIdList.isEmpty()) { throw SodaException("콘텐츠를 1개 이상 추가하세요") @@ -61,7 +83,7 @@ class AudioContentPlaylistService( val notOrderedContentList = orderedContentMap.filterValues { !it }.keys if (notOrderedContentList.isNotEmpty()) { - throw SodaException("소장하지 않은 콘텐츠는 재생목록에 추가할 수 없습니다.") + throw SodaException("대여/소장하지 않은 콘텐츠는 재생목록에 추가할 수 없습니다.") } } @@ -77,15 +99,15 @@ class AudioContentPlaylistService( throw SodaException("잘못된 요청입니다.") } - checkOrderedContent( - contentIdList = request.contentIdAndOrderList.map { it.contentId }, - memberId = member.id!! + val contentIdAndOrderList = validateAndGetContentIdAndOrderList( + contentIdAndOrderList = request.contentIdAndOrderList, + member ) val updatePlaylist = playlist.copy( title = request.title ?: playlist.title, desc = request.desc ?: playlist.desc, - contentIdAndOrderList = request.contentIdAndOrderList + contentIdAndOrderList = contentIdAndOrderList ) redisRepository.save(updatePlaylist) @@ -98,18 +120,22 @@ class AudioContentPlaylistService( return GetPlaylistsResponse( totalCount = playlists.size, - items = playlists.map { - val contentCount = it.contentIdAndOrderList.size + items = playlists.map { playlist -> + val contentIdAndOrderList = playlist.contentIdAndOrderList.filter { + it.endDate == null || it.endDate!! > LocalDateTime.now() + } + + val contentCount = contentIdAndOrderList.size val coverImageUrl = if (contentCount > 0) { - audioContentRepository.getCoverImageById(id = it.contentIdAndOrderList[0].contentId) + audioContentRepository.getCoverImageById(id = contentIdAndOrderList[0].contentId) ?: "" } else { "" } GetPlaylistsItem( - id = it.id, - title = it.title, - desc = it.desc ?: "", + id = playlist.id, + title = playlist.title, + desc = playlist.desc ?: "", contentCount = contentCount, coverImageUrl = coverImageUrl ) @@ -142,11 +168,15 @@ class AudioContentPlaylistService( .withZoneSameInstant(ZoneId.of("Asia/Seoul")) .format(dateTimeFormatter) + val contentIdAndOrderList = playlist.contentIdAndOrderList.filter { + it.endDate == null || it.endDate!! > LocalDateTime.now() + } + val contentList = audioContentRepository.fetchContentForPlaylist( - contentIdList = playlist.contentIdAndOrderList.map { it.contentId } + contentIdList = contentIdAndOrderList.map { it.contentId } ) - val orderMap = playlist.contentIdAndOrderList.sortedBy { it.order } + val orderMap = contentIdAndOrderList.sortedBy { it.order } .mapIndexed { index, item -> item.contentId to index } .toMap() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/ContentIdAndEndDateData.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/ContentIdAndEndDateData.kt new file mode 100644 index 0000000..5d89a49 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/ContentIdAndEndDateData.kt @@ -0,0 +1,9 @@ +package kr.co.vividnext.sodalive.content.playlist + +import com.querydsl.core.annotations.QueryProjection +import java.time.LocalDateTime + +data class ContentIdAndEndDateData @QueryProjection constructor( + val contentId: Long, + val endDate: LocalDateTime? +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/PlaylistContentIdAndOrder.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/PlaylistContentIdAndOrder.kt index 2e0d558..dbc8196 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/PlaylistContentIdAndOrder.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/PlaylistContentIdAndOrder.kt @@ -1,6 +1,9 @@ package kr.co.vividnext.sodalive.content.playlist +import java.time.LocalDateTime + data class PlaylistContentIdAndOrder( val contentId: Long, - val order: Int + val order: Int, + var endDate: LocalDateTime? = null )