Compare commits

..

No commits in common. "9abbb05ad8ec8b332f6f11b97ff348d694b33eb2" and "1ecaf69b0bd8ea18fd7eac13e1a812eb8a3e2cc9" have entirely different histories.

6 changed files with 83 additions and 101 deletions

View File

@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PostMapping
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
@ -33,6 +34,7 @@ class OrderController(private val service: OrderService) {
@GetMapping("/audio-content") @GetMapping("/audio-content")
fun getAudioContentOrderList( fun getAudioContentOrderList(
@RequestParam(value = "orderType", required = false) orderType: OrderType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable pageable: Pageable
) = run { ) = run {
@ -40,6 +42,7 @@ class OrderController(private val service: OrderService) {
ApiResponse.ok( ApiResponse.ok(
service.getAudioContentOrderList( service.getAudioContentOrderList(
orderType = orderType,
member = member, member = member,
offset = pageable.offset, offset = pageable.offset,
limit = pageable.pageSize.toLong() limit = pageable.pageSize.toLong()

View File

@ -6,8 +6,6 @@ import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
import kr.co.vividnext.sodalive.content.main.QGetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.QGetAudioContentMainItem
import kr.co.vividnext.sodalive.content.order.QOrder.order 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 kr.co.vividnext.sodalive.member.QMember.member
import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
@ -22,6 +20,7 @@ interface OrderQueryRepository {
fun isExistOrderedAndOrderType(memberId: Long, contentId: Long): Pair<Boolean, OrderType?> fun isExistOrderedAndOrderType(memberId: Long, contentId: Long): Pair<Boolean, OrderType?>
fun getAudioContentRemainingTime(memberId: Long, contentId: Long, timezone: String): String fun getAudioContentRemainingTime(memberId: Long, contentId: Long, timezone: String): String
fun getAudioContentOrderList( fun getAudioContentOrderList(
orderType: OrderType?,
dateTime: LocalDateTime, dateTime: LocalDateTime,
coverImageHost: String, coverImageHost: String,
memberId: Long, memberId: Long,
@ -29,7 +28,7 @@ interface OrderQueryRepository {
limit: Long = 10 limit: Long = 10
): List<GetAudioContentOrderListItem> ): List<GetAudioContentOrderListItem>
fun totalAudioContentOrderListCount(memberId: Long, dateTime: LocalDateTime): Int fun totalAudioContentOrderListCount(orderType: OrderType?, memberId: Long, dateTime: LocalDateTime): Int
fun getAudioContentMainOrderList( fun getAudioContentMainOrderList(
dateTime: LocalDateTime, dateTime: LocalDateTime,
coverImageHost: String, coverImageHost: String,
@ -39,7 +38,6 @@ interface OrderQueryRepository {
): List<GetAudioContentMainItem> ): List<GetAudioContentMainItem>
fun findOrderedContent(contentIdList: List<Long>, memberId: Long): List<Long> fun findOrderedContent(contentIdList: List<Long>, memberId: Long): List<Long>
fun findEndDateByContentId(contentIdList: List<Long>, memberId: Long): List<ContentIdAndEndDateData>
} }
@Repository @Repository
@ -120,22 +118,40 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde
} }
override fun getAudioContentOrderList( override fun getAudioContentOrderList(
orderType: OrderType?,
dateTime: LocalDateTime, dateTime: LocalDateTime,
coverImageHost: String, coverImageHost: String,
memberId: Long, memberId: Long,
offset: Long, offset: Long,
limit: Long limit: Long
): List<GetAudioContentOrderListItem> { ): List<GetAudioContentOrderListItem> {
val where = order.member.id.eq(memberId) var where = order.member.id.eq(memberId)
.and(order.isActive.isTrue) .and(order.isActive.isTrue)
.and(
order.type.eq(OrderType.KEEP) when (orderType) {
.or( OrderType.RENTAL -> {
order.type.eq(OrderType.RENTAL) where = where.and(
.and(order.startDate.before(dateTime)) order.type.eq(OrderType.RENTAL)
.and(order.endDate.after(dateTime)) .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))
)
)
}
}
return queryFactory return queryFactory
.select( .select(
@ -162,17 +178,34 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde
.fetch() .fetch()
} }
override fun totalAudioContentOrderListCount(memberId: Long, dateTime: LocalDateTime): Int { override fun totalAudioContentOrderListCount(orderType: OrderType?, memberId: Long, dateTime: LocalDateTime): Int {
val where = order.member.id.eq(memberId) var where = order.member.id.eq(memberId)
.and(order.isActive.isTrue) .and(order.isActive.isTrue)
.and(
order.type.eq(OrderType.KEEP) when (orderType) {
.or( OrderType.RENTAL -> {
order.type.eq(OrderType.RENTAL) where = where.and(
.and(order.startDate.before(dateTime)) order.type.eq(OrderType.RENTAL)
.and(order.endDate.after(dateTime)) .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))
)
)
}
}
return queryFactory.select(order.id) return queryFactory.select(order.id)
.from(order) .from(order)
@ -232,24 +265,9 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde
.innerJoin(order.audioContent, audioContent) .innerJoin(order.audioContent, audioContent)
.where( .where(
order.isActive.isTrue, order.isActive.isTrue,
order.endDate.isNull,
member.id.eq(memberId), 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() .fetch()
} }

View File

@ -90,15 +90,18 @@ class OrderService(
} }
fun getAudioContentOrderList( fun getAudioContentOrderList(
orderType: OrderType? = null,
member: Member, member: Member,
offset: Long, offset: Long,
limit: Long limit: Long
): GetAudioContentOrderListResponse { ): GetAudioContentOrderListResponse {
val totalCount = repository.totalAudioContentOrderListCount( val totalCount = repository.totalAudioContentOrderListCount(
orderType = orderType,
memberId = member.id!!, memberId = member.id!!,
dateTime = LocalDateTime.now() dateTime = LocalDateTime.now()
) )
val orderItems = repository.getAudioContentOrderList( val orderItems = repository.getAudioContentOrderList(
orderType = orderType,
dateTime = LocalDateTime.now(), dateTime = LocalDateTime.now(),
coverImageHost = audioContentCoverImageHost, coverImageHost = audioContentCoverImageHost,
memberId = member.id!!, memberId = member.id!!,

View File

@ -7,7 +7,6 @@ import kr.co.vividnext.sodalive.live.roulette.RedisIdGenerator
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.Member
import org.springframework.data.repository.findByIdOrNull import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@ -28,9 +27,10 @@ class AudioContentPlaylistService(
throw SodaException("플레이 리스트는 최대 10개까지 생성할 수 있습니다.") throw SodaException("플레이 리스트는 최대 10개까지 생성할 수 있습니다.")
} }
val contentIdAndOrderList = validateAndGetContentIdAndOrderList( // 콘텐츠 유효성 검사 (소장으로 구매한 콘텐츠 인가?)
contentIdAndOrderList = request.contentIdAndOrderList, validateContent(
member contentIdList = request.contentIdAndOrderList.map { it.contentId },
memberId = member.id!!
) )
val playlist = AudioContentPlaylist( val playlist = AudioContentPlaylist(
@ -38,34 +38,12 @@ class AudioContentPlaylistService(
memberId = member.id!!, memberId = member.id!!,
title = request.title, title = request.title,
desc = request.desc, desc = request.desc,
contentIdAndOrderList = contentIdAndOrderList contentIdAndOrderList = request.contentIdAndOrderList
) )
redisRepository.save(playlist) 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) { private fun validateContent(contentIdList: List<Long>, memberId: Long) {
if (contentIdList.isEmpty()) { if (contentIdList.isEmpty()) {
throw SodaException("콘텐츠를 1개 이상 추가하세요") throw SodaException("콘텐츠를 1개 이상 추가하세요")
@ -83,7 +61,7 @@ class AudioContentPlaylistService(
val notOrderedContentList = orderedContentMap.filterValues { !it }.keys val notOrderedContentList = orderedContentMap.filterValues { !it }.keys
if (notOrderedContentList.isNotEmpty()) { if (notOrderedContentList.isNotEmpty()) {
throw SodaException("대여/소장하지 않은 콘텐츠는 재생목록에 추가할 수 없습니다.") throw SodaException("소장하지 않은 콘텐츠는 재생목록에 추가할 수 없습니다.")
} }
} }
@ -99,15 +77,15 @@ class AudioContentPlaylistService(
throw SodaException("잘못된 요청입니다.") throw SodaException("잘못된 요청입니다.")
} }
val contentIdAndOrderList = validateAndGetContentIdAndOrderList( checkOrderedContent(
contentIdAndOrderList = request.contentIdAndOrderList, contentIdList = request.contentIdAndOrderList.map { it.contentId },
member memberId = member.id!!
) )
val updatePlaylist = playlist.copy( val updatePlaylist = playlist.copy(
title = request.title ?: playlist.title, title = request.title ?: playlist.title,
desc = request.desc ?: playlist.desc, desc = request.desc ?: playlist.desc,
contentIdAndOrderList = contentIdAndOrderList contentIdAndOrderList = request.contentIdAndOrderList
) )
redisRepository.save(updatePlaylist) redisRepository.save(updatePlaylist)
@ -120,22 +98,18 @@ class AudioContentPlaylistService(
return GetPlaylistsResponse( return GetPlaylistsResponse(
totalCount = playlists.size, totalCount = playlists.size,
items = playlists.map { playlist -> items = playlists.map {
val contentIdAndOrderList = playlist.contentIdAndOrderList.filter { val contentCount = it.contentIdAndOrderList.size
it.endDate == null || it.endDate!! > LocalDateTime.now()
}
val contentCount = contentIdAndOrderList.size
val coverImageUrl = if (contentCount > 0) { val coverImageUrl = if (contentCount > 0) {
audioContentRepository.getCoverImageById(id = contentIdAndOrderList[0].contentId) audioContentRepository.getCoverImageById(id = it.contentIdAndOrderList[0].contentId)
?: "" ?: ""
} else { } else {
"" ""
} }
GetPlaylistsItem( GetPlaylistsItem(
id = playlist.id, id = it.id,
title = playlist.title, title = it.title,
desc = playlist.desc ?: "", desc = it.desc ?: "",
contentCount = contentCount, contentCount = contentCount,
coverImageUrl = coverImageUrl coverImageUrl = coverImageUrl
) )
@ -168,15 +142,11 @@ class AudioContentPlaylistService(
.withZoneSameInstant(ZoneId.of("Asia/Seoul")) .withZoneSameInstant(ZoneId.of("Asia/Seoul"))
.format(dateTimeFormatter) .format(dateTimeFormatter)
val contentIdAndOrderList = playlist.contentIdAndOrderList.filter {
it.endDate == null || it.endDate!! > LocalDateTime.now()
}
val contentList = audioContentRepository.fetchContentForPlaylist( val contentList = audioContentRepository.fetchContentForPlaylist(
contentIdList = contentIdAndOrderList.map { it.contentId } contentIdList = playlist.contentIdAndOrderList.map { it.contentId }
) )
val orderMap = contentIdAndOrderList.sortedBy { it.order } val orderMap = playlist.contentIdAndOrderList.sortedBy { it.order }
.mapIndexed { index, item -> item.contentId to index } .mapIndexed { index, item -> item.contentId to index }
.toMap() .toMap()

View File

@ -1,9 +0,0 @@
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?
)

View File

@ -1,9 +1,6 @@
package kr.co.vividnext.sodalive.content.playlist package kr.co.vividnext.sodalive.content.playlist
import java.time.LocalDateTime
data class PlaylistContentIdAndOrder( data class PlaylistContentIdAndOrder(
val contentId: Long, val contentId: Long,
val order: Int, val order: Int
var endDate: LocalDateTime? = null
) )