Merge pull request 'test' (#53) from test into main

Reviewed-on: #53
This commit is contained in:
klaus 2023-10-24 10:42:10 +00:00
commit 7dfaa36024
9 changed files with 255 additions and 20 deletions

View File

@ -35,6 +35,7 @@ data class AudioContent(
@Enumerated(value = EnumType.STRING)
val type: AudioContentType = AudioContentType.INDIVIDUAL,
val isGeneratePreview: Boolean = true,
var isOnlyRental: Boolean = false,
var isAdult: Boolean = false,
var isCommentAvailable: Boolean = true
) : BaseEntity() {

View File

@ -2,7 +2,6 @@ package kr.co.vividnext.sodalive.content
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.QBundleAudioContent.bundleAudioContent
import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
@ -78,6 +77,9 @@ interface AudioContentQueryRepository {
fun getAudioContentMainBannerList(isAdult: Boolean): List<AudioContentBanner>
fun getAudioContentCurations(isAdult: Boolean): List<AudioContentCuration>
fun getAudioContentCurationList(isAdult: Boolean, offset: Long = 0, limit: Long = 10): List<AudioContentCuration>
fun findAudioContentByCurationId(
curationId: Long,
cloudfrontHost: String,
@ -337,10 +339,6 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
.fetch()
}
@Cacheable(
value = ["getNewContentUploadCreatorList"],
cacheManager = "cacheManager"
)
override fun getNewContentUploadCreatorList(
cloudfrontHost: String,
isAdult: Boolean
@ -410,6 +408,30 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
.fetch()
}
override fun getAudioContentCurationList(
isAdult: Boolean,
offset: Long,
limit: Long
): List<AudioContentCuration> {
var where = audioContentCuration.isActive.isTrue
if (!isAdult) {
where = where.and(audioContentCuration.isAdult.isFalse)
}
return queryFactory
.selectFrom(audioContentCuration)
.where(where)
.orderBy(audioContentCuration.orders.asc())
.offset(offset)
.limit(limit)
.fetch()
}
@Cacheable(
value = ["findAudioContentByCurationId"],
cacheManager = "cacheManager"
)
override fun findAudioContentByCurationId(
curationId: Long,
cloudfrontHost: String,
@ -459,12 +481,13 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
offset: Long,
limit: Long
): List<GetAudioContentRankingItem> {
var where = audioContent.isActive.isTrue
var where = order.createdAt.goe(startDate)
.and(order.createdAt.lt(endDate))
.and(audioContent.isActive.isTrue)
.and(audioContent.member.isNotNull)
.and(audioContent.duration.isNotNull)
.and(audioContent.member.isActive.isTrue)
.and(useCan.createdAt.goe(startDate))
.and(useCan.createdAt.lt(endDate))
.and(audioContentTheme.isActive.isTrue)
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
@ -483,8 +506,7 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
member.nickname
)
)
.from(useCan)
.innerJoin(useCan.order, order)
.from(order)
.innerJoin(order.audioContent, audioContent)
.innerJoin(audioContent.member, member)
.innerJoin(audioContent.theme, audioContentTheme)

View File

@ -176,6 +176,7 @@ class AudioContentService(
} else {
false
},
isOnlyRental = request.isOnlyRental,
isCommentAvailable = request.isCommentAvailable
)
audioContent.theme = theme
@ -486,6 +487,7 @@ class AudioContentService(
duration = audioContent.duration ?: "",
isAdult = audioContent.isAdult,
isMosaic = audioContent.isAdult && member.auth == null,
isOnlyRental = audioContent.isOnlyRental,
existOrdered = isExistsBundleAudioContent || isExistsAudioContent,
orderType = orderType,
remainingTime = remainingTime,

View File

@ -8,6 +8,7 @@ data class CreateAudioContentRequest(
val themeId: Long = 0,
val isAdult: Boolean = false,
val isGeneratePreview: Boolean = true,
val isOnlyRental: Boolean = false,
val isCommentAvailable: Boolean = false,
val type: AudioContentType = AudioContentType.INDIVIDUAL,
val childIds: List<Long>? = null,

View File

@ -16,6 +16,7 @@ data class GetAudioContentDetailResponse(
val duration: String,
val isAdult: Boolean,
val isMosaic: Boolean,
val isOnlyRental: Boolean,
val existOrdered: Boolean,
val orderType: OrderType?,
val remainingTime: String?,

View File

@ -23,6 +23,33 @@ class AudioContentMainController(private val service: AudioContentMainService) {
ApiResponse.ok(service.getMain(member = member))
}
@GetMapping("/new-content-upload-creator")
fun getNewContentUploadCreatorList(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.getNewContentUploadCreatorList(member = member))
}
@GetMapping("/banner-list")
fun getAudioContentMainBannerList(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.getAudioContentMainBannerList(member = member))
}
@GetMapping("/order-list")
fun getAudioContentMainOrderList(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.getAudioContentMainOrderList(member = member))
}
@GetMapping("/new")
fun getNewContentByTheme(
@RequestParam("theme") theme: String,
@ -53,4 +80,29 @@ class AudioContentMainController(private val service: AudioContentMainService) {
ApiResponse.ok(service.getNewContentFor2WeeksByTheme(theme, member, pageable))
}
@GetMapping("/curation-list")
fun getAudioContentMainCurationList(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(
service.getAudioContentMainCurationList(
member,
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)
)
}
@GetMapping("/content-ranking")
fun getAudioContentMainContentRanking(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.getAudioContentMainContentRanking(member))
}
}

View File

@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.event.EventItem
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
import org.springframework.beans.factory.annotation.Value
import org.springframework.cache.annotation.Cacheable
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.time.DayOfWeek
@ -168,6 +169,87 @@ class AudioContentMainService(
)
}
@Cacheable(
value = ["getNewContentUploadCreatorList"],
cacheManager = "cacheManager"
)
fun getNewContentUploadCreatorList(member: Member): List<GetNewContentUploadCreator> {
val isAdult = member.auth != null
// 2주일 이내에 콘텐츠를 올린 크리에이터 20명 조회
return repository.getNewContentUploadCreatorList(
cloudfrontHost = imageHost,
isAdult = isAdult
)
.asSequence()
.filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) }
.toList()
}
@Cacheable(
value = ["getAudioContentMainBannerList"],
cacheManager = "cacheManager"
)
fun getAudioContentMainBannerList(member: Member): List<GetAudioContentBannerResponse> {
val isAdult = member.auth != null
return repository
.getAudioContentMainBannerList(isAdult = isAdult)
.asSequence()
.filter {
if (it.type == AudioContentBannerType.CREATOR && it.creator != null) {
!blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creator!!.id!!)
} else {
true
}
}
.map {
GetAudioContentBannerResponse(
type = it.type,
thumbnailImageUrl = "$imageHost/${it.thumbnailImage}",
eventItem = if (it.type == AudioContentBannerType.EVENT && it.event != null) {
EventItem(
id = it.event!!.id!!,
thumbnailImageUrl = if (!it.event!!.thumbnailImage.startsWith("https://")) {
"$imageHost/${it.event!!.thumbnailImage}"
} else {
it.event!!.thumbnailImage
},
detailImageUrl = if (
it.event!!.detailImage != null &&
!it.event!!.detailImage!!.startsWith("https://")
) {
"$imageHost/${it.event!!.detailImage}"
} else {
it.event!!.detailImage
},
popupImageUrl = null,
link = it.event!!.link,
title = it.event!!.title,
isPopup = false
)
} else {
null
},
creatorId = if (it.type == AudioContentBannerType.CREATOR && it.creator != null) {
it.creator!!.id
} else {
null
},
link = it.link
)
}
.toList()
}
fun getAudioContentMainOrderList(member: Member): List<GetAudioContentMainItem> {
return orderService
.getAudioContentMainOrderList(
member = member,
limit = 20
)
}
fun getThemeList(member: Member): List<String> {
return audioContentThemeRepository.getActiveThemeOfContent(isAdult = member.auth != null)
}
@ -197,4 +279,77 @@ class AudioContentMainService(
return GetNewContentAllResponse(totalCount, items)
}
@Cacheable(
value = ["getAudioContentMainCurationList"],
cacheManager = "cacheManager"
)
fun getAudioContentMainCurationList(
member: Member,
offset: Long,
limit: Long
): List<GetAudioContentCurationResponse> {
val isAdult = member.auth != null
return repository
.getAudioContentCurationList(
isAdult = isAdult,
offset = offset,
limit = limit
)
.asSequence()
.map {
GetAudioContentCurationResponse(
curationId = it.id!!,
title = it.title,
description = it.description,
contents = repository.findAudioContentByCurationId(
curationId = it.id!!,
cloudfrontHost = imageHost,
isAdult = isAdult
)
.asSequence()
.filter { content ->
!blockMemberRepository.isBlocked(
blockedMemberId = member.id!!,
memberId = content.creatorId
)
}
.toList()
)
}
.filter { it.contents.isNotEmpty() }
.toList()
}
fun getAudioContentMainContentRanking(member: Member): GetAudioContentRanking {
val isAdult = member.auth != null
val currentDateTime = LocalDateTime.now()
val startDate = currentDateTime
.minusWeeks(1)
.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
.withHour(15)
.withMinute(0)
.withSecond(0)
val endDate = startDate
.plusDays(7)
val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일")
val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일")
val contentRankingItemList = repository
.getAudioContentRanking(
cloudfrontHost = imageHost,
startDate = startDate.minusDays(1),
endDate = endDate.minusDays(1),
isAdult = isAdult
)
return GetAudioContentRanking(
startDate = startDate.format(startDateFormatter),
endDate = endDate.minusDays(1).format(endDateFormatter),
contentRankingItemList
)
}
}

View File

@ -1,13 +1,14 @@
package kr.co.vividnext.sodalive.content.main
import com.fasterxml.jackson.annotation.JsonProperty
import com.querydsl.core.annotations.QueryProjection
data class GetAudioContentMainItem @QueryProjection constructor(
val contentId: Long,
val coverImageUrl: String,
val title: String,
val isAdult: Boolean,
val creatorId: Long,
val creatorProfileImageUrl: String,
val creatorNickname: String
@JsonProperty("contentId") val contentId: Long,
@JsonProperty("coverImageUrl") val coverImageUrl: String,
@JsonProperty("title") val title: String,
@JsonProperty("adult") val isAdult: Boolean,
@JsonProperty("creatorId") val creatorId: Long,
@JsonProperty("creatorProfileImageUrl") val creatorProfileImageUrl: String,
@JsonProperty("creatorNickname") val creatorNickname: String
)

View File

@ -41,8 +41,8 @@ data class Order(
@JoinColumn(name = "content_id", nullable = false)
var audioContent: AudioContent? = null
set(value) {
can = if (type == OrderType.RENTAL) {
ceil(value?.price!! * 0.6).toInt()
can = if (type == OrderType.RENTAL && !value?.isOnlyRental!!) {
ceil(value.price * 0.6).toInt()
} else {
value?.price!!
}
@ -52,7 +52,7 @@ data class Order(
override fun prePersist() {
super.prePersist()
if (type == OrderType.RENTAL) {
endDate = startDate.plusDays(7)
endDate = startDate.plusDays(15)
}
}
}