| @@ -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() | ||||
|   | ||||
| @@ -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<Boolean, OrderType?> | ||||
|     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<GetAudioContentOrderListItem> | ||||
|  | ||||
|     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<GetAudioContentMainItem> | ||||
|  | ||||
|     fun findOrderedContent(contentIdList: List<Long>, memberId: Long): List<Long> | ||||
|     fun findEndDateByContentId(contentIdList: List<Long>, memberId: Long): List<ContentIdAndEndDateData> | ||||
| } | ||||
|  | ||||
| @Repository | ||||
| @@ -118,31 +120,15 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde | ||||
|     } | ||||
|  | ||||
|     override fun getAudioContentOrderList( | ||||
|         orderType: OrderType?, | ||||
|         dateTime: LocalDateTime, | ||||
|         coverImageHost: String, | ||||
|         memberId: Long, | ||||
|         offset: Long, | ||||
|         limit: Long | ||||
|     ): List<GetAudioContentOrderListItem> { | ||||
|         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( | ||||
|             .and( | ||||
|                 order.type.eq(OrderType.KEEP) | ||||
|                     .or( | ||||
|                         order.type.eq(OrderType.RENTAL) | ||||
| @@ -150,8 +136,6 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde | ||||
|                             .and(order.endDate.after(dateTime)) | ||||
|                     ) | ||||
|             ) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return queryFactory | ||||
|             .select( | ||||
| @@ -178,25 +162,10 @@ 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( | ||||
|             .and( | ||||
|                 order.type.eq(OrderType.KEEP) | ||||
|                     .or( | ||||
|                         order.type.eq(OrderType.RENTAL) | ||||
| @@ -204,8 +173,6 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde | ||||
|                             .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<Long>, memberId: Long): List<ContentIdAndEndDateData> { | ||||
|         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() | ||||
|     } | ||||
|   | ||||
| @@ -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!!, | ||||
|   | ||||
| @@ -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<PlaylistContentIdAndOrder>, | ||||
|         member: Member | ||||
|     ): List<PlaylistContentIdAndOrder> { | ||||
|         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<Long>, 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() | ||||
|  | ||||
|   | ||||
| @@ -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? | ||||
| ) | ||||
| @@ -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 | ||||
| ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user