From 45e8b0d15558a3adde6feaf1d7ce46f197132bc3 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 29 Aug 2024 22:41:30 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EB=93=B1=EB=A1=9D=20-=20=EB=B9=84=EB=B0=80=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/comment/AudioContentComment.kt | 1 + .../comment/AudioContentCommentController.kt | 1 + .../comment/AudioContentCommentService.kt | 21 +++++++++++++++++-- .../content/comment/RegisterCommentRequest.kt | 7 ++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentComment.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentComment.kt index 0f345e3..a84e468 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentComment.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentComment.kt @@ -18,6 +18,7 @@ data class AudioContentComment( var comment: String, @Column(nullable = true) var donationCan: Int? = null, + val isSecret: Boolean = false, var isActive: Boolean = true ) : BaseEntity() { @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt index dc153e2..d400c55 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt @@ -27,6 +27,7 @@ class AudioContentCommentController(private val service: AudioContentCommentServ comment = request.comment, audioContentId = request.contentId, parentId = request.parentId, + isSecret = request.isSecret, member = member ) ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt index d41e3d6..0daafc3 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.comment import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.content.AudioContentRepository +import kr.co.vividnext.sodalive.content.order.OrderRepository import kr.co.vividnext.sodalive.fcm.FcmEvent import kr.co.vividnext.sodalive.fcm.FcmEventType import kr.co.vividnext.sodalive.member.Member @@ -20,12 +21,19 @@ class AudioContentCommentService( private val blockMemberRepository: BlockMemberRepository, private val audioContentRepository: AudioContentRepository, private val applicationEventPublisher: ApplicationEventPublisher, + private val orderRepository: OrderRepository, @Value("\${cloud.aws.cloud-front.host}") private val cloudFrontHost: String ) { @Transactional - fun registerComment(member: Member, comment: String, audioContentId: Long, parentId: Long? = null) { + fun registerComment( + member: Member, + comment: String, + audioContentId: Long, + parentId: Long? = null, + isSecret: Boolean = false + ) { val audioContent = audioContentRepository.findByIdOrNull(id = audioContentId) ?: throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.") @@ -33,7 +41,16 @@ class AudioContentCommentService( val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = creator.id!!) if (isBlocked) throw SodaException("${creator.nickname}님의 요청으로 댓글쓰기가 제한됩니다.") - val audioContentComment = AudioContentComment(comment = comment) + val (isExistsAudioContent, _) = orderRepository.isExistOrderedAndOrderType( + memberId = member.id!!, + contentId = audioContent.id!! + ) + + if (isSecret && !isExistsAudioContent) { + throw SodaException("콘텐츠 구매 후 비밀댓글을 등록할 수 있습니다.") + } + + val audioContentComment = AudioContentComment(comment = comment, isSecret = isSecret) audioContentComment.audioContent = audioContent audioContentComment.member = member diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/RegisterCommentRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/RegisterCommentRequest.kt index df29747..a5fc8ac 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/RegisterCommentRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/RegisterCommentRequest.kt @@ -1,3 +1,8 @@ package kr.co.vividnext.sodalive.content.comment -data class RegisterCommentRequest(val comment: String, val contentId: Long, val parentId: Long?) +data class RegisterCommentRequest( + val comment: String, + val contentId: Long, + val parentId: Long?, + val isSecret: Boolean = false +) -- 2.40.1 From 93410af224044384f30cec5a682cd3ceddaa40cd Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 29 Aug 2024 23:40:44 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95=20-=20?= =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=ED=81=AC=EB=A6=AC=EC=97=90?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20-=20=EB=8C=93=EA=B8=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20-=20=EC=9D=BC=EB=B0=98=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20-=20=EA=B3=B5=EA=B0=9C=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20+=20=EB=82=B4=EA=B0=80=20=EC=93=B4=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentRepository.kt | 17 ++++++ .../sodalive/content/AudioContentService.kt | 14 ++++- .../comment/AudioContentCommentController.kt | 1 + .../comment/AudioContentCommentRepository.kt | 54 +++++++++++++------ .../comment/AudioContentCommentService.kt | 31 +++++++---- .../GetAudioContentCommentListResponse.kt | 5 +- .../order/GetAudioContentOrderListResponse.kt | 1 + .../sodalive/content/order/OrderRepository.kt | 1 + .../sodalive/content/order/OrderService.kt | 8 +-- 9 files changed, 101 insertions(+), 31 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt index 90f1b5f..e15c24a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -111,6 +111,8 @@ interface AudioContentQueryRepository { fun getAudioContentCurationList(isAdult: Boolean, offset: Long, limit: Long): List fun getNotReleaseContentId(): List + + fun isContentCreator(contentId: Long, memberId: Long): Boolean } @Repository @@ -721,4 +723,19 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) .where(where) .fetch() } + + override fun isContentCreator(contentId: Long, memberId: Long): Boolean { + val foundedContentId = queryFactory + .select(audioContent.id) + .from(audioContent) + .innerJoin(audioContent.member, member) + .where( + audioContent.isActive.isTrue + .and(audioContent.id.eq(contentId)) + .and(audioContent.member.id.eq(memberId)) + ) + .fetchOne() + + return foundedContentId != null && foundedContentId == contentId + } } 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 8af4c9f..37445a0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt @@ -492,6 +492,8 @@ class AudioContentService( commentRepository.findByContentId( cloudFrontHost = coverImageHost, contentId = audioContent.id!!, + memberId = member.id!!, + isContentCreator = creatorId == member.id!!, timezone = timezone, offset = 0, limit = 1 @@ -502,7 +504,11 @@ class AudioContentService( // 댓글 수 val commentCount = if (audioContent.isCommentAvailable) { - commentRepository.totalCountCommentByContentId(contentId = audioContent.id!!) + commentRepository.totalCountCommentByContentId( + contentId = audioContent.id!!, + memberId = member.id!!, + isContentCreator = creatorId == member.id!! + ) } else { 0 } @@ -666,7 +672,11 @@ class AudioContentService( val items = audioContentList .map { val commentCount = commentRepository - .totalCountCommentByContentId(it.contentId) + .totalCountCommentByContentId( + it.contentId, + memberId = member.id!!, + isContentCreator = creatorId == member.id!! + ) it.commentCount = commentCount val likeCount = audioContentLikeRepository diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt index d400c55..a68faa2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt @@ -55,6 +55,7 @@ class AudioContentCommentController(private val service: AudioContentCommentServ ApiResponse.ok( service.getCommentList( audioContentId = audioContentId, + memberId = member.id!!, timezone = timezone, pageable = pageable ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt index 5d0e9ce..c78cc03 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt @@ -16,12 +16,14 @@ interface AudioContentCommentQueryRepository { fun findByContentId( cloudFrontHost: String, contentId: Long, + memberId: Long, + isContentCreator: Boolean, timezone: String, offset: Long, limit: Int ): List - fun totalCountCommentByContentId(contentId: Long): Int + fun totalCountCommentByContentId(contentId: Long, memberId: Long, isContentCreator: Boolean): Int fun commentReplyCountByAudioContentCommentId(commentId: Long): Int fun getAudioContentCommentReplyList( cloudFrontHost: String, @@ -45,21 +47,32 @@ class AudioContentCommentQueryRepositoryImpl( override fun findByContentId( cloudFrontHost: String, contentId: Long, + memberId: Long, + isContentCreator: Boolean, timezone: String, offset: Long, limit: Int ): List { - return queryFactory.selectFrom(audioContentComment) - .where( - audioContentComment.audioContent.id.eq(contentId) - .and(audioContentComment.isActive.isTrue) - .and(audioContentComment.parent.isNull) + var where = audioContentComment.audioContent.id.eq(contentId) + .and(audioContentComment.isActive.isTrue) + .and(audioContentComment.parent.isNull) + + if (!isContentCreator) { + where = where.and( + audioContentComment.isSecret.isFalse + .or(audioContentComment.member.id.eq(memberId)) ) + } + + return queryFactory + .selectFrom(audioContentComment) + .innerJoin(audioContentComment.audioContent, audioContent) + .innerJoin(audioContentComment.member, member) + .where(where) .offset(offset) .limit(limit.toLong()) .orderBy(audioContentComment.createdAt.desc()) .fetch() - .asSequence() .map { val date = it.createdAt!! .atZone(ZoneId.of("UTC")) @@ -75,22 +88,32 @@ class AudioContentCommentQueryRepositoryImpl( "$cloudFrontHost/profile/default-profile.png" }, comment = it.comment, + isSecret = it.isSecret, donationCan = it.donationCan ?: 0, date = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd E hh:mm a")), replyCount = commentReplyCountByAudioContentCommentId(it.id!!) ) } - .toList() } - override fun totalCountCommentByContentId(contentId: Long): Int { - return queryFactory.select(audioContentComment.id) - .from(audioContentComment) - .where( - audioContentComment.audioContent.id.eq(contentId) - .and(audioContentComment.parent.isNull) - .and(audioContentComment.isActive.isTrue) + override fun totalCountCommentByContentId(contentId: Long, memberId: Long, isContentCreator: Boolean): Int { + var where = audioContentComment.audioContent.id.eq(contentId) + .and(audioContentComment.isActive.isTrue) + .and(audioContentComment.parent.isNull) + + if (!isContentCreator) { + where = where.and( + audioContentComment.isSecret.isFalse + .or(audioContentComment.member.id.eq(memberId)) ) + } + + return queryFactory + .select(audioContentComment.id) + .from(audioContentComment) + .innerJoin(audioContentComment.audioContent, audioContent) + .innerJoin(audioContentComment.member, member) + .where(where) .fetch() .size } @@ -140,6 +163,7 @@ class AudioContentCommentQueryRepositoryImpl( "$cloudFrontHost/profile/default-profile.png" }, comment = it.comment, + isSecret = it.isSecret, donationCan = it.donationCan ?: 0, date = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd E hh:mm a")), replyCount = 0 diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt index 0daafc3..632ad9f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt @@ -107,16 +107,27 @@ class AudioContentCommentService( } } - fun getCommentList(audioContentId: Long, timezone: String, pageable: Pageable): GetAudioContentCommentListResponse { - val commentList = - repository.findByContentId( - cloudFrontHost = cloudFrontHost, - contentId = audioContentId, - timezone = timezone, - offset = pageable.offset, - limit = pageable.pageSize - ) - val totalCount = repository.totalCountCommentByContentId(audioContentId) + fun getCommentList( + audioContentId: Long, + memberId: Long, + timezone: String, + pageable: Pageable + ): GetAudioContentCommentListResponse { + val isContentCreator = audioContentRepository.isContentCreator(audioContentId, memberId) + val commentList = repository.findByContentId( + cloudFrontHost = cloudFrontHost, + contentId = audioContentId, + memberId = memberId, + isContentCreator = isContentCreator, + timezone = timezone, + offset = pageable.offset, + limit = pageable.pageSize + ) + val totalCount = repository.totalCountCommentByContentId( + contentId = audioContentId, + memberId = memberId, + isContentCreator = isContentCreator + ) return GetAudioContentCommentListResponse(totalCount, commentList) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/GetAudioContentCommentListResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/GetAudioContentCommentListResponse.kt index bbdd725..2313d35 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/GetAudioContentCommentListResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/GetAudioContentCommentListResponse.kt @@ -1,16 +1,19 @@ package kr.co.vividnext.sodalive.content.comment +import com.querydsl.core.annotations.QueryProjection + data class GetAudioContentCommentListResponse( val totalCount: Int, val items: List ) -data class GetAudioContentCommentListItem( +data class GetAudioContentCommentListItem @QueryProjection constructor( val id: Long, val writerId: Long, val nickname: String, val profileUrl: String, val comment: String, + val isSecret: Boolean, val donationCan: Int, val date: String, val replyCount: Int diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/GetAudioContentOrderListResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/GetAudioContentOrderListResponse.kt index 52e72d9..a69ffc5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/GetAudioContentOrderListResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/GetAudioContentOrderListResponse.kt @@ -10,6 +10,7 @@ data class GetAudioContentOrderListResponse( data class GetAudioContentOrderListItem @QueryProjection constructor( val contentId: Long, val coverImageUrl: String, + val creatorId: Long, val creatorNickname: String, val title: String, val themeStr: String, 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 bcdce03..42ede81 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 @@ -126,6 +126,7 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde QGetAudioContentOrderListItem( audioContent.id, audioContent.coverImage.prepend("/").prepend(coverImageHost), + audioContent.member.id, audioContent.member.nickname, audioContent.title, audioContent.theme.theme, 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 06cba52..4826816 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 @@ -98,10 +98,13 @@ class OrderService( offset = offset, limit = limit ) - .asSequence() .map { val commentCount = audioContentCommentQueryRepository - .totalCountCommentByContentId(it.contentId) + .totalCountCommentByContentId( + it.contentId, + memberId = member.id!!, + isContentCreator = it.creatorId == member.id!! + ) val likeCount = audioContentLikeQueryRepository .totalCountAudioContentLike(it.contentId) @@ -110,7 +113,6 @@ class OrderService( it.likeCount = likeCount it } - .toList() return GetAudioContentOrderListResponse( totalCount = totalCount, -- 2.40.1