test #208
|
@ -111,6 +111,8 @@ interface AudioContentQueryRepository {
|
|||
fun getAudioContentCurationList(isAdult: Boolean, offset: Long, limit: Long): List<AudioContentCuration>
|
||||
|
||||
fun getNotReleaseContentId(): List<Long>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -27,6 +27,7 @@ class AudioContentCommentController(private val service: AudioContentCommentServ
|
|||
comment = request.comment,
|
||||
audioContentId = request.contentId,
|
||||
parentId = request.parentId,
|
||||
isSecret = request.isSecret,
|
||||
member = member
|
||||
)
|
||||
)
|
||||
|
@ -54,6 +55,7 @@ class AudioContentCommentController(private val service: AudioContentCommentServ
|
|||
ApiResponse.ok(
|
||||
service.getCommentList(
|
||||
audioContentId = audioContentId,
|
||||
memberId = member.id!!,
|
||||
timezone = timezone,
|
||||
pageable = pageable
|
||||
)
|
||||
|
|
|
@ -16,12 +16,14 @@ interface AudioContentCommentQueryRepository {
|
|||
fun findByContentId(
|
||||
cloudFrontHost: String,
|
||||
contentId: Long,
|
||||
memberId: Long,
|
||||
isContentCreator: Boolean,
|
||||
timezone: String,
|
||||
offset: Long,
|
||||
limit: Int
|
||||
): List<GetAudioContentCommentListItem>
|
||||
|
||||
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<GetAudioContentCommentListItem> {
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -90,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)
|
||||
}
|
||||
|
|
|
@ -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<GetAudioContentCommentListItem>
|
||||
)
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue