콘텐츠 메인 - 순위 정렬(매출, 후원, 댓글, 좋아요) 추가
This commit is contained in:
		| @@ -19,6 +19,9 @@ import org.springframework.web.bind.annotation.RequestParam | ||||
| import org.springframework.web.bind.annotation.RequestPart | ||||
| import org.springframework.web.bind.annotation.RestController | ||||
| import org.springframework.web.multipart.MultipartFile | ||||
| import java.time.DayOfWeek | ||||
| import java.time.LocalDateTime | ||||
| import java.time.temporal.TemporalAdjusters | ||||
|  | ||||
| @RestController | ||||
| @RequestMapping("/audio-content") | ||||
| @@ -152,15 +155,29 @@ class AudioContentController(private val service: AudioContentService) { | ||||
|     @GetMapping("/ranking") | ||||
|     fun getAudioContentRanking( | ||||
|         @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, | ||||
|         @RequestParam("sortType") sortType: String, | ||||
|         pageable: Pageable | ||||
|     ) = run { | ||||
|         if (member == null) throw SodaException("로그인 정보를 확인해주세요.") | ||||
|  | ||||
|         val currentDateTime = LocalDateTime.now() | ||||
|         val startDate = currentDateTime | ||||
|             .withHour(15) | ||||
|             .withMinute(0) | ||||
|             .withSecond(0) | ||||
|             .minusWeeks(1) | ||||
|             .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)) | ||||
|         val endDate = startDate | ||||
|             .plusDays(7) | ||||
|  | ||||
|         ApiResponse.ok( | ||||
|             service.getAudioContentRanking( | ||||
|                 member = member, | ||||
|                 isAdult = member.auth != null, | ||||
|                 startDate = startDate, | ||||
|                 endDate = endDate, | ||||
|                 offset = pageable.offset, | ||||
|                 limit = pageable.pageSize.toLong() | ||||
|                 limit = pageable.pageSize.toLong(), | ||||
|                 sortType = sortType | ||||
|             ) | ||||
|         ) | ||||
|     } | ||||
|   | ||||
| @@ -2,8 +2,11 @@ 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.comment.QAudioContentComment.audioContentComment | ||||
| import kr.co.vividnext.sodalive.content.like.QAudioContentLike.audioContentLike | ||||
| import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem | ||||
| import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem | ||||
| import kr.co.vividnext.sodalive.content.main.GetNewContentUploadCreator | ||||
| @@ -88,7 +91,8 @@ interface AudioContentQueryRepository { | ||||
|         startDate: LocalDateTime, | ||||
|         endDate: LocalDateTime, | ||||
|         offset: Long = 0, | ||||
|         limit: Long = 12 | ||||
|         limit: Long = 12, | ||||
|         sortType: String = "매출" | ||||
|     ): List<GetAudioContentRankingItem> | ||||
| } | ||||
|  | ||||
| @@ -443,11 +447,11 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) | ||||
|         startDate: LocalDateTime, | ||||
|         endDate: LocalDateTime, | ||||
|         offset: Long, | ||||
|         limit: Long | ||||
|         limit: Long, | ||||
|         sortType: String | ||||
|     ): List<GetAudioContentRankingItem> { | ||||
|         var where = order.createdAt.goe(startDate) | ||||
|             .and(order.createdAt.lt(endDate)) | ||||
|             .and(audioContent.isActive.isTrue) | ||||
|         var where = audioContent.isActive.isTrue | ||||
|             .and(audioContent.member.id.ne(648)) | ||||
|             .and(audioContent.member.isNotNull) | ||||
|             .and(audioContent.duration.isNotNull) | ||||
|             .and(audioContent.member.isActive.isTrue) | ||||
| @@ -457,7 +461,7 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) | ||||
|             where = where.and(audioContent.isAdult.isFalse) | ||||
|         } | ||||
|  | ||||
|         return queryFactory | ||||
|         var select = queryFactory | ||||
|             .select( | ||||
|                 QGetAudioContentRankingItem( | ||||
|                     audioContent.id, | ||||
| @@ -470,13 +474,70 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) | ||||
|                     member.nickname | ||||
|                 ) | ||||
|             ) | ||||
|             .from(order) | ||||
|             .innerJoin(order.audioContent, audioContent) | ||||
|             .innerJoin(audioContent.member, member) | ||||
|             .innerJoin(audioContent.theme, audioContentTheme) | ||||
|             .where(where) | ||||
|             .groupBy(audioContent.id) | ||||
|             .orderBy(order.can.sum().desc(), audioContent.createdAt.asc()) | ||||
|  | ||||
|         select = when (sortType) { | ||||
|             "후원" -> { | ||||
|                 select | ||||
|                     .from(useCan) | ||||
|                     .innerJoin(useCan.audioContent, audioContent) | ||||
|                     .innerJoin(audioContent.member, member) | ||||
|                     .innerJoin(audioContent.theme, audioContentTheme) | ||||
|                     .where( | ||||
|                         where | ||||
|                             .and(audioContentComment.createdAt.goe(startDate)) | ||||
|                             .and(audioContentComment.createdAt.lt(endDate)) | ||||
|                     ) | ||||
|                     .groupBy(audioContent.id) | ||||
|                     .orderBy(useCan.can.add(useCan.rewardCan).sum().desc(), audioContent.createdAt.asc()) | ||||
|             } | ||||
|  | ||||
|             "댓글" -> { | ||||
|                 select | ||||
|                     .from(audioContentComment) | ||||
|                     .innerJoin(audioContentComment.audioContent, audioContent) | ||||
|                     .innerJoin(audioContentComment.audioContent.member, member) | ||||
|                     .innerJoin(audioContentComment.audioContent.theme, audioContentTheme) | ||||
|                     .where( | ||||
|                         where | ||||
|                             .and(audioContentComment.createdAt.goe(startDate)) | ||||
|                             .and(audioContentComment.createdAt.lt(endDate)) | ||||
|                     ) | ||||
|                     .groupBy(audioContentComment.audioContent.id) | ||||
|                     .orderBy(audioContentComment.id.count().desc(), audioContent.createdAt.asc()) | ||||
|             } | ||||
|  | ||||
|             "좋아요" -> { | ||||
|                 select | ||||
|                     .from(audioContentLike) | ||||
|                     .innerJoin(audioContentLike.audioContent, audioContent) | ||||
|                     .innerJoin(audioContentLike.audioContent.member, member) | ||||
|                     .innerJoin(audioContentLike.audioContent.theme, audioContentTheme) | ||||
|                     .where( | ||||
|                         where | ||||
|                             .and(audioContentLike.createdAt.goe(startDate)) | ||||
|                             .and(audioContentLike.createdAt.lt(endDate)) | ||||
|                     ) | ||||
|                     .groupBy(audioContentLike.audioContent.id) | ||||
|                     .orderBy(audioContentLike.id.count().desc(), audioContent.createdAt.asc()) | ||||
|             } | ||||
|  | ||||
|             else -> { | ||||
|                 select | ||||
|                     .from(order) | ||||
|                     .innerJoin(order.audioContent, audioContent) | ||||
|                     .innerJoin(audioContent.member, member) | ||||
|                     .innerJoin(audioContent.theme, audioContentTheme) | ||||
|                     .where( | ||||
|                         where | ||||
|                             .and(order.createdAt.goe(startDate)) | ||||
|                             .and(order.createdAt.lt(endDate)) | ||||
|                     ) | ||||
|                     .groupBy(audioContent.id) | ||||
|                     .orderBy(order.can.sum().desc(), audioContent.createdAt.asc()) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return select | ||||
|             .offset(offset) | ||||
|             .limit(limit) | ||||
|             .fetch() | ||||
|   | ||||
| @@ -24,17 +24,16 @@ import kr.co.vividnext.sodalive.member.Member | ||||
| import kr.co.vividnext.sodalive.member.block.BlockMemberRepository | ||||
| import kr.co.vividnext.sodalive.utils.generateFileName | ||||
| import org.springframework.beans.factory.annotation.Value | ||||
| import org.springframework.cache.annotation.Cacheable | ||||
| import org.springframework.context.ApplicationEventPublisher | ||||
| import org.springframework.data.repository.findByIdOrNull | ||||
| import org.springframework.stereotype.Service | ||||
| import org.springframework.transaction.annotation.Transactional | ||||
| import org.springframework.web.multipart.MultipartFile | ||||
| import java.text.SimpleDateFormat | ||||
| import java.time.DayOfWeek | ||||
| import java.time.LocalDateTime | ||||
| import java.time.ZoneId | ||||
| import java.time.format.DateTimeFormatter | ||||
| import java.time.temporal.TemporalAdjusters | ||||
| import java.util.Locale | ||||
|  | ||||
| @Service | ||||
| @@ -72,11 +71,10 @@ class AudioContentService( | ||||
|         ) | ||||
|  | ||||
|         if (audioContentLike == null) { | ||||
|             audioContentLike = AudioContentLike( | ||||
|                 memberId = member.id!!, | ||||
|                 contentId = request.contentId | ||||
|             ) | ||||
|             audioContentLike = AudioContentLike(memberId = member.id!!) | ||||
|  | ||||
|             val audioContent = repository.findByIdAndActive(request.contentId) | ||||
|             audioContentLike.audioContent = audioContent | ||||
|             audioContentLikeRepository.save(audioContentLike) | ||||
|         } else { | ||||
|             audioContentLike.isActive = !audioContentLike.isActive | ||||
| @@ -579,21 +577,19 @@ class AudioContentService( | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Cacheable( | ||||
|         cacheNames = ["cache_ttl_3_days"], | ||||
|         key = "'contentRanking:' + ':' +" + | ||||
|             "#isAdult + ':' + #startDate + ':' + #endDate + ':' + #sortType + ':' + #offset + ':' + #limit" | ||||
|     ) | ||||
|     fun getAudioContentRanking( | ||||
|         member: Member, | ||||
|         isAdult: Boolean, | ||||
|         startDate: LocalDateTime, | ||||
|         endDate: LocalDateTime, | ||||
|         offset: Long, | ||||
|         limit: Long | ||||
|         limit: Long, | ||||
|         sortType: String = "매출" | ||||
|     ): GetAudioContentRanking { | ||||
|         val currentDateTime = LocalDateTime.now() | ||||
|         val startDate = currentDateTime | ||||
|             .withHour(15) | ||||
|             .withMinute(0) | ||||
|             .withSecond(0) | ||||
|             .minusWeeks(1) | ||||
|             .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)) | ||||
|         val endDate = startDate | ||||
|             .plusDays(7) | ||||
|  | ||||
|         val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일") | ||||
|         val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일") | ||||
|  | ||||
| @@ -602,9 +598,10 @@ class AudioContentService( | ||||
|                 cloudfrontHost = coverImageHost, | ||||
|                 startDate = startDate.minusDays(1), | ||||
|                 endDate = endDate.minusDays(1), | ||||
|                 isAdult = member.auth != null, | ||||
|                 isAdult = isAdult, | ||||
|                 offset = offset, | ||||
|                 limit = limit | ||||
|                 limit = limit, | ||||
|                 sortType = sortType | ||||
|             ) | ||||
|  | ||||
|         return GetAudioContentRanking( | ||||
| @@ -613,4 +610,8 @@ class AudioContentService( | ||||
|             items = contentRankingItemList | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fun getContentRankingSortTypeList(): List<String> { | ||||
|         return listOf("매출", "후원", "댓글", "좋아요") | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,20 +1,21 @@ | ||||
| package kr.co.vividnext.sodalive.content.like | ||||
|  | ||||
| import kr.co.vividnext.sodalive.content.AudioContent | ||||
| import java.time.LocalDateTime | ||||
| import javax.persistence.Entity | ||||
| import javax.persistence.FetchType | ||||
| import javax.persistence.GeneratedValue | ||||
| import javax.persistence.GenerationType | ||||
| import javax.persistence.Id | ||||
| import javax.persistence.JoinColumn | ||||
| import javax.persistence.ManyToOne | ||||
| import javax.persistence.PrePersist | ||||
| import javax.persistence.PreUpdate | ||||
| import javax.persistence.Table | ||||
|  | ||||
| @Entity | ||||
| @Table(name = "content_like") | ||||
| data class AudioContentLike( | ||||
|     val memberId: Long, | ||||
|     val contentId: Long | ||||
| ) { | ||||
| data class AudioContentLike(val memberId: Long) { | ||||
|     @Id | ||||
|     @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||
|     var id: Long? = null | ||||
| @@ -34,4 +35,8 @@ data class AudioContentLike( | ||||
|     } | ||||
|  | ||||
|     var isActive = true | ||||
|  | ||||
|     @ManyToOne(fetch = FetchType.LAZY) | ||||
|     @JoinColumn(name = "content_id", nullable = false) | ||||
|     var audioContent: AudioContent? = null | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,7 @@ class AudioContentLikeQueryRepositoryImpl(private val queryFactory: JPAQueryFact | ||||
|             .selectFrom(audioContentLike) | ||||
|             .where( | ||||
|                 audioContentLike.memberId.eq(memberId) | ||||
|                     .and(audioContentLike.contentId.eq(contentId)) | ||||
|                     .and(audioContentLike.audioContent.id.eq(contentId)) | ||||
|             ) | ||||
|             .fetchFirst() | ||||
|     } | ||||
| @@ -30,7 +30,7 @@ class AudioContentLikeQueryRepositoryImpl(private val queryFactory: JPAQueryFact | ||||
|             .select(audioContentLike.id) | ||||
|             .from(audioContentLike) | ||||
|             .where( | ||||
|                 audioContentLike.contentId.eq(contentId) | ||||
|                 audioContentLike.audioContent.id.eq(contentId) | ||||
|                     .and(audioContentLike.isActive.isTrue) | ||||
|             ) | ||||
|             .fetch() | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package kr.co.vividnext.sodalive.content.main | ||||
|  | ||||
| import kr.co.vividnext.sodalive.content.AudioContentRepository | ||||
| import kr.co.vividnext.sodalive.content.AudioContentService | ||||
| import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType | ||||
| import kr.co.vividnext.sodalive.content.main.banner.GetAudioContentBannerResponse | ||||
| import kr.co.vividnext.sodalive.content.main.curation.GetAudioContentCurationResponse | ||||
| @@ -15,12 +16,12 @@ import org.springframework.data.domain.Pageable | ||||
| import org.springframework.stereotype.Service | ||||
| import java.time.DayOfWeek | ||||
| import java.time.LocalDateTime | ||||
| import java.time.format.DateTimeFormatter | ||||
| import java.time.temporal.TemporalAdjusters | ||||
|  | ||||
| @Service | ||||
| class AudioContentMainService( | ||||
|     private val repository: AudioContentRepository, | ||||
|     private val audioContentService: AudioContentService, | ||||
|     private val blockMemberRepository: BlockMemberRepository, | ||||
|     private val orderService: OrderService, | ||||
|     private val audioContentThemeRepository: AudioContentThemeQueryRepository, | ||||
| @@ -66,7 +67,14 @@ class AudioContentMainService( | ||||
|             .withSecond(0) | ||||
|         val endDate = startDate.plusDays(7) | ||||
|  | ||||
|         val contentRanking = getContentRanking(isAdult = isAdult, startDate = startDate, endDate = endDate) | ||||
|         val contentRankingSortTypeList = audioContentService.getContentRankingSortTypeList() | ||||
|         val contentRanking = audioContentService.getAudioContentRanking( | ||||
|             isAdult = isAdult, | ||||
|             startDate = startDate, | ||||
|             endDate = endDate, | ||||
|             offset = 0, | ||||
|             limit = 12 | ||||
|         ) | ||||
|  | ||||
|         return GetAudioContentMainResponse( | ||||
|             newContentUploadCreatorList = newContentUploadCreatorList, | ||||
| @@ -75,6 +83,7 @@ class AudioContentMainService( | ||||
|             themeList = themeList, | ||||
|             newContentList = newContentList, | ||||
|             curationList = curationList, | ||||
|             contentRankingSortTypeList = contentRankingSortTypeList, | ||||
|             contentRanking = contentRanking | ||||
|         ) | ||||
|     } | ||||
| @@ -192,27 +201,4 @@ class AudioContentMainService( | ||||
|             } | ||||
|             .filter { it.contents.isNotEmpty() } | ||||
|             .toList() | ||||
|  | ||||
|     @Cacheable( | ||||
|         cacheNames = ["cache_ttl_3_days"], | ||||
|         key = "'contentRanking:' + ':' + #isAdult + ':' + #startDate + ':' + #endDate" | ||||
|     ) | ||||
|     fun getContentRanking(isAdult: Boolean, startDate: LocalDateTime, endDate: LocalDateTime): GetAudioContentRanking { | ||||
|         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 | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -10,5 +10,6 @@ data class GetAudioContentMainResponse( | ||||
|     val themeList: List<String>, | ||||
|     val newContentList: List<GetAudioContentMainItem>, | ||||
|     val curationList: List<GetAudioContentCurationResponse>, | ||||
|     val contentRankingSortTypeList: List<String>, | ||||
|     val contentRanking: GetAudioContentRanking | ||||
| ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user