From 00e4fefc8f9e21fe06ae52fa162ee5b678afcd6b Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 18 Dec 2024 03:22:13 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EB=AA=A9=EB=A1=9D=20-=20?= =?UTF-8?q?orderType=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/order/OrderController.kt | 3 - .../sodalive/content/order/OrderRepository.kt | 76 +++++-------------- .../sodalive/content/order/OrderService.kt | 3 - 3 files changed, 20 insertions(+), 62 deletions(-) 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..6b31b77 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 @@ -20,7 +20,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 +27,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, @@ -118,40 +117,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 +159,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) 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!!, -- 2.40.1 From 36052f034ace4e8e2fc3afbf6a9a21b13c31b3a8 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 18 Dec 2024 06:18:36 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EC=9E=AC=EC=83=9D=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D/=EC=88=98=EC=A0=95=20-=20=EB=93=B1=EB=A1=9D/?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=8B=9C=20=EB=A7=8C=EB=A3=8C=20=EB=82=A0?= =?UTF-8?q?=EC=A7=9C=20=EC=8B=9C=EA=B0=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/order/OrderRepository.kt | 22 +++++++++- .../playlist/AudioContentPlaylistService.kt | 41 ++++++++++++++----- .../playlist/ContentIdAndEndDateData.kt | 9 ++++ .../playlist/PlaylistContentIdAndOrder.kt | 5 ++- 4 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/ContentIdAndEndDateData.kt 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 6b31b77..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 @@ -37,6 +39,7 @@ interface OrderQueryRepository { ): List fun findOrderedContent(contentIdList: List, memberId: Long): List + fun findEndDateByContentId(contentIdList: List, memberId: Long): List } @Repository @@ -229,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/playlist/AudioContentPlaylistService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/playlist/AudioContentPlaylistService.kt index 46ccf02..3b23c67 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 @@ -27,10 +27,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 +37,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 +82,7 @@ class AudioContentPlaylistService( val notOrderedContentList = orderedContentMap.filterValues { !it }.keys if (notOrderedContentList.isNotEmpty()) { - throw SodaException("소장하지 않은 콘텐츠는 재생목록에 추가할 수 없습니다.") + throw SodaException("대여/소장하지 않은 콘텐츠는 재생목록에 추가할 수 없습니다.") } } @@ -77,15 +98,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) 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 ) -- 2.40.1 From 0c4dc7e5df49199990a5bba8bb77378d2d669aa2 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 18 Dec 2024 06:39:10 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=EC=9E=AC=EC=83=9D=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8,=20=EC=83=81=EC=84=B8=20-=20?= =?UTF-8?q?=EB=8C=80=EC=97=AC=EA=B0=80=20=EB=A7=8C=EB=A3=8C=EB=90=9C=20?= =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=EB=A5=BC=20=EC=A0=9C=EC=99=B8?= =?UTF-8?q?=ED=95=98=EA=B3=A0=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 --- .../playlist/AudioContentPlaylistService.kt | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) 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 3b23c67..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 @@ -119,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 ) @@ -163,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() -- 2.40.1