From 711842f00d2cf2513eda5c7a299fb4184b786117 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 26 Jan 2024 23:36:17 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EA=B3=A0?= =?UTF-8?q?=EC=A0=95,=20=ED=95=B4=EC=A0=9C=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentController.kt | 22 +++++++++++++ .../sodalive/content/AudioContentService.kt | 30 +++++++++++++++++ .../sodalive/content/pin/PinContent.kt | 20 +++++++++++ .../content/pin/PinContentRepository.kt | 33 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContent.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContentRepository.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt index b8f8873..d86afd3 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt @@ -196,4 +196,26 @@ class AudioContentController(private val service: AudioContentService) { fun releaseContent() = run { ApiResponse.ok(service.releaseContent()) } + + @PostMapping("/pin-to-the-top/{id}") + @PreAuthorize("hasRole('CREATOR')") + fun pinToTheTop( + @PathVariable id: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(service.pinToTheTop(contentId = id, member = member)) + } + + @PutMapping("/unpin-at-the-top/{id}") + @PreAuthorize("hasRole('CREATOR')") + fun unpinAtTheTop( + @PathVariable id: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(service.unpinAtTheTop(contentId = id, member = member)) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt index 09a65f1..7d5e387 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt @@ -16,6 +16,8 @@ import kr.co.vividnext.sodalive.content.like.PutAudioContentLikeResponse import kr.co.vividnext.sodalive.content.main.GetAudioContentRanking import kr.co.vividnext.sodalive.content.order.OrderRepository import kr.co.vividnext.sodalive.content.order.OrderType +import kr.co.vividnext.sodalive.content.pin.PinContent +import kr.co.vividnext.sodalive.content.pin.PinContentRepository import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository import kr.co.vividnext.sodalive.extensions.convertLocalDateTime @@ -49,6 +51,7 @@ class AudioContentService( private val playbackTrackingRepository: PlaybackTrackingRepository, private val commentRepository: AudioContentCommentRepository, private val audioContentLikeRepository: AudioContentLikeRepository, + private val pinContentRepository: PinContentRepository, private val s3Uploader: S3Uploader, private val objectMapper: ObjectMapper, @@ -696,4 +699,31 @@ class AudioContentService( fun getContentRankingSortTypeList(): List { return listOf("매출", "댓글", "좋아요") } + + @Transactional + fun pinToTheTop(contentId: Long, member: Member) { + val audioContent = repository.findByIdAndCreatorId(contentId = contentId, creatorId = member.id!!) + ?: throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.") + + val pinContentList = pinContentRepository.getPinContentList(memberId = member.id!!) + val pinContent = if (pinContentList.size >= 3) { + pinContentList[0] + } else { + PinContent() + } + + pinContent.member = member + pinContent.content = audioContent + pinContentRepository.save(pinContent) + } + + @Transactional + fun unpinAtTheTop(contentId: Long, member: Member) { + val pinContent = pinContentRepository.findByContentIdAndMemberId( + contentId = contentId, + memberId = member.id!! + ) ?: throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.") + + pinContent.isActive = false + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContent.kt new file mode 100644 index 0000000..2d6fcc3 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContent.kt @@ -0,0 +1,20 @@ +package kr.co.vividnext.sodalive.content.pin + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.content.AudioContent +import kr.co.vividnext.sodalive.member.Member +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne + +@Entity +data class PinContent(var isActive: Boolean = true) : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + var member: Member? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "content_id", nullable = false) + var content: AudioContent? = null +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContentRepository.kt new file mode 100644 index 0000000..a33f642 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/pin/PinContentRepository.kt @@ -0,0 +1,33 @@ +package kr.co.vividnext.sodalive.content.pin + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.pin.QPinContent.pinContent +import org.springframework.data.jpa.repository.JpaRepository + +interface PinContentRepository : JpaRepository, PinContentQueryRepository + +interface PinContentQueryRepository { + fun getPinContentList(memberId: Long): List + + fun findByContentIdAndMemberId(contentId: Long, memberId: Long): PinContent? +} + +class PinContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : PinContentQueryRepository { + override fun getPinContentList(memberId: Long): List { + return queryFactory + .selectFrom(pinContent) + .where(pinContent.member.id.eq(memberId)) + .orderBy(pinContent.updatedAt.asc()) + .fetch() + } + + override fun findByContentIdAndMemberId(contentId: Long, memberId: Long): PinContent? { + return queryFactory + .selectFrom(pinContent) + .where( + pinContent.content.id.eq(contentId) + .and(pinContent.member.id.eq(memberId)) + ) + .fetchFirst() + } +}