Compare commits

..

No commits in common. "6d2f48f86df1246830d6ad482d4ad0fc1a6fd743" and "640f5ce6f5fdfbd9f5a79f8f09d0896ab0c89a7e" have entirely different histories.

8 changed files with 89 additions and 185 deletions

View File

@ -9,18 +9,17 @@ import org.springframework.stereotype.Repository
interface UseCanRepository : JpaRepository<UseCan, Long>, UseCanQueryRepository interface UseCanRepository : JpaRepository<UseCan, Long>, UseCanQueryRepository
interface UseCanQueryRepository { interface UseCanQueryRepository {
fun isExistCommunityPostOrdered(postId: Long, memberId: Long): Boolean fun isExistOrdered(postId: Long, memberId: Long): Boolean
} }
class UseCanQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : UseCanQueryRepository { class UseCanQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : UseCanQueryRepository {
override fun isExistCommunityPostOrdered(postId: Long, memberId: Long): Boolean { override fun isExistOrdered(postId: Long, memberId: Long): Boolean {
val useCanId = queryFactory.select(useCan.id) val useCanId = queryFactory.select(useCan.id)
.from(useCan) .from(useCan)
.where( .where(
useCan.member.id.eq(memberId) useCan.member.id.eq(memberId)
.and(useCan.isRefund.isFalse) .and(useCan.isRefund.isFalse)
.and(useCan.communityPost.id.eq(postId)) .and(useCan.communityPost.id.eq(postId))
.and(useCan.canUsage.eq(CanUsage.PAID_COMMUNITY_POST))
) )
.fetchFirst() .fetchFirst()

View File

@ -129,7 +129,6 @@ class CreatorCommunityController(private val service: CreatorCommunityService) {
comment = request.comment, comment = request.comment,
postId = request.postId, postId = request.postId,
parentId = request.parentId, parentId = request.parentId,
isSecret = request.isSecret,
member = member member = member
) )
) )
@ -159,7 +158,6 @@ class CreatorCommunityController(private val service: CreatorCommunityService) {
ApiResponse.ok( ApiResponse.ok(
service.getCommunityPostCommentList( service.getCommunityPostCommentList(
postId = postId, postId = postId,
memberId = member.id!!,
timezone = timezone, timezone = timezone,
offset = pageable.offset, offset = pageable.offset,
limit = pageable.pageSize.toLong() limit = pageable.pageSize.toLong()

View File

@ -28,8 +28,6 @@ interface CreatorCommunityQueryRepository {
fun getLatestPostListFromCreatorsYouFollow(memberId: Long, isAdult: Boolean): List<SelectCommunityPostResponse> fun getLatestPostListFromCreatorsYouFollow(memberId: Long, isAdult: Boolean): List<SelectCommunityPostResponse>
fun getCommunityPost(postId: Long, isAdult: Boolean): SelectCommunityPostResponse? fun getCommunityPost(postId: Long, isAdult: Boolean): SelectCommunityPostResponse?
fun isCommunityCreator(postId: Long, memberId: Long): Boolean
} }
class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CreatorCommunityQueryRepository { class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CreatorCommunityQueryRepository {
@ -197,17 +195,4 @@ class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFact
.where(where) .where(where)
.fetchFirst() .fetchFirst()
} }
override fun isCommunityCreator(postId: Long, memberId: Long): Boolean {
return queryFactory
.select(member.id)
.from(creatorCommunity)
.innerJoin(creatorCommunity.member, member)
.where(
creatorCommunity.id.eq(postId)
.and(creatorCommunity.isActive.isTrue)
.and(member.id.eq(memberId))
)
.fetchFirst() != null
}
} }

View File

@ -190,20 +190,15 @@ class CreatorCommunityService(
?: false ?: false
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(it.id) val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(it.id)
val commentCount = if (it.isCommentAvailable) { val commentCount = if (it.isCommentAvailable) {
commentRepository.totalCountCommentByPostId( commentRepository.totalCountCommentByPostId(postId = it.id)
postId = it.id,
memberId = memberId,
isContentCreator = it.creatorId == memberId
)
} else { } else {
0 0
} }
val commentList = if (it.isCommentAvailable) { val commentList = if (it.isCommentAvailable) {
commentRepository.findByPostId( commentRepository.findByPostId(
id = it.id, cloudFrontHost = imageHost,
memberId = memberId,
isContentCreator = it.creatorId == memberId,
timezone = timezone, timezone = timezone,
id = it.id,
offset = 0, offset = 0,
limit = 1 limit = 1
) )
@ -217,7 +212,7 @@ class CreatorCommunityService(
null null
} }
val existOrdered = useCanRepository.isExistCommunityPostOrdered(postId = it.id, memberId = memberId) val existOrdered = useCanRepository.isExistOrdered(postId = it.id, memberId = memberId)
val audioUrl = if ( val audioUrl = if (
( (
@ -268,20 +263,15 @@ class CreatorCommunityService(
val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id, memberId = memberId)?.isActive ?: false val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id, memberId = memberId)?.isActive ?: false
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id) val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id)
val commentCount = if (post.isCommentAvailable) { val commentCount = if (post.isCommentAvailable) {
commentRepository.totalCountCommentByPostId( commentRepository.totalCountCommentByPostId(postId = post.id)
postId = post.id,
memberId = memberId,
isContentCreator = post.creatorId == memberId
)
} else { } else {
0 0
} }
val commentList = if (post.isCommentAvailable) { val commentList = if (post.isCommentAvailable) {
commentRepository.findByPostId( commentRepository.findByPostId(
id = post.id, cloudFrontHost = imageHost,
memberId = memberId,
isContentCreator = post.creatorId == memberId,
timezone = timezone, timezone = timezone,
id = post.id,
offset = 0, offset = 0,
limit = 1 limit = 1
) )
@ -295,7 +285,7 @@ class CreatorCommunityService(
null null
} }
val existOrdered = useCanRepository.isExistCommunityPostOrdered(postId = post.id, memberId = memberId) val existOrdered = useCanRepository.isExistOrdered(postId = post.id, memberId = memberId)
val audioUrl = if ((post.price <= 0 || existOrdered) && post.audioPath != null) { val audioUrl = if ((post.price <= 0 || existOrdered) && post.audioPath != null) {
audioContentCloudFront.generateSignedURL( audioContentCloudFront.generateSignedURL(
@ -357,22 +347,11 @@ class CreatorCommunityService(
} }
@Transactional @Transactional
fun createCommunityPostComment( fun createCommunityPostComment(comment: String, postId: Long, parentId: Long?, member: Member) {
member: Member,
comment: String,
postId: Long,
parentId: Long? = null,
isSecret: Boolean = false
) {
val post = repository.findByIdOrNull(id = postId) val post = repository.findByIdOrNull(id = postId)
?: throw SodaException("잘못된 게시물 입니다.\n다시 시도해 주세요.") ?: throw SodaException("잘못된 게시물 입니다.\n다시 시도해 주세요.")
val isExistOrdered = useCanRepository.isExistCommunityPostOrdered(postId = postId, memberId = member.id!!)
if (isSecret && !isExistOrdered) { val postComment = CreatorCommunityComment(comment = comment)
throw SodaException("게시글을 구매 후 비밀댓글을 등록할 수 있습니다.")
}
val postComment = CreatorCommunityComment(comment = comment, isSecret = isSecret)
postComment.creatorCommunity = post postComment.creatorCommunity = post
postComment.member = member postComment.member = member
@ -411,25 +390,19 @@ class CreatorCommunityService(
fun getCommunityPostCommentList( fun getCommunityPostCommentList(
postId: Long, postId: Long,
memberId: Long,
timezone: String, timezone: String,
offset: Long, offset: Long,
limit: Long limit: Long
): GetCommunityPostCommentListResponse { ): GetCommunityPostCommentListResponse {
val commentList = commentRepository.findByPostId( val commentList = commentRepository.findByPostId(
id = postId, cloudFrontHost = imageHost,
memberId = memberId,
isContentCreator = repository.isCommunityCreator(postId, memberId),
timezone = timezone, timezone = timezone,
id = postId,
offset = offset, offset = offset,
limit = limit limit = limit
) )
val totalCount = commentRepository.totalCountCommentByPostId( val totalCount = commentRepository.totalCountCommentByPostId(postId = postId)
postId = postId,
memberId = memberId,
isContentCreator = repository.isCommunityCreator(postId, memberId)
)
return GetCommunityPostCommentListResponse(totalCount = totalCount, items = commentList) return GetCommunityPostCommentListResponse(totalCount = totalCount, items = commentList)
} }
@ -440,6 +413,7 @@ class CreatorCommunityService(
limit: Long limit: Long
): GetCommunityPostCommentListResponse { ): GetCommunityPostCommentListResponse {
val commentList = commentRepository.getCommunityCommentReplyList( val commentList = commentRepository.getCommunityCommentReplyList(
cloudFrontHost = imageHost,
commentId = commentId, commentId = commentId,
timezone = timezone, timezone = timezone,
offset = offset, offset = offset,
@ -469,20 +443,15 @@ class CreatorCommunityService(
likeRepository.findByPostIdAndMemberId(postId = it.id, memberId = memberId)?.isActive ?: false likeRepository.findByPostIdAndMemberId(postId = it.id, memberId = memberId)?.isActive ?: false
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(it.id) val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(it.id)
val commentCount = if (it.isCommentAvailable) { val commentCount = if (it.isCommentAvailable) {
commentRepository.totalCountCommentByPostId( commentRepository.totalCountCommentByPostId(postId = it.id)
postId = it.id,
memberId = memberId,
isContentCreator = it.creatorId == memberId
)
} else { } else {
0 0
} }
val commentList = if (it.isCommentAvailable) { val commentList = if (it.isCommentAvailable) {
commentRepository.findByPostId( commentRepository.findByPostId(
id = it.id, cloudFrontHost = imageHost,
memberId = memberId,
isContentCreator = it.creatorId == memberId,
timezone = timezone, timezone = timezone,
id = it.id,
offset = 0, offset = 0,
limit = 1 limit = 1
) )
@ -496,7 +465,7 @@ class CreatorCommunityService(
null null
} }
val existOrdered = useCanRepository.isExistCommunityPostOrdered(postId = it.id, memberId = memberId) val existOrdered = useCanRepository.isExistOrdered(postId = it.id, memberId = memberId)
it.toCommunityPostListResponse( it.toCommunityPostListResponse(
imageHost = imageHost, imageHost = imageHost,
@ -530,7 +499,7 @@ class CreatorCommunityService(
val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.member!!.id!!) val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.member!!.id!!)
if (isBlocked) throw SodaException("${post.member!!.nickname}님의 요청으로 접근이 제한됩니다.") if (isBlocked) throw SodaException("${post.member!!.nickname}님의 요청으로 접근이 제한됩니다.")
val existOrdered = useCanRepository.isExistCommunityPostOrdered(postId = postId, memberId = memberId) val existOrdered = useCanRepository.isExistOrdered(postId = postId, memberId = memberId)
if (!existOrdered) { if (!existOrdered) {
canPaymentService.spendCan( canPaymentService.spendCan(
@ -545,20 +514,15 @@ class CreatorCommunityService(
val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id!!, memberId = memberId)?.isActive ?: false val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id!!, memberId = memberId)?.isActive ?: false
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id!!) val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id!!)
val commentCount = if (post.isCommentAvailable) { val commentCount = if (post.isCommentAvailable) {
commentRepository.totalCountCommentByPostId( commentRepository.totalCountCommentByPostId(postId = post.id!!)
postId = post.id!!,
memberId = memberId,
isContentCreator = false
)
} else { } else {
0 0
} }
val commentList = if (post.isCommentAvailable) { val commentList = if (post.isCommentAvailable) {
commentRepository.findByPostId( commentRepository.findByPostId(
id = post.id!!, cloudFrontHost = imageHost,
memberId = memberId,
isContentCreator = false,
timezone = timezone, timezone = timezone,
id = post.id!!,
offset = 0, offset = 0,
limit = 1 limit = 1
) )

View File

@ -1,8 +1,3 @@
package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment
data class CreateCommunityPostCommentRequest( data class CreateCommunityPostCommentRequest(val comment: String, val postId: Long, val parentId: Long?)
val comment: String,
val postId: Long,
val parentId: Long?,
val isSecret: Boolean = false
)

View File

@ -14,7 +14,6 @@ import javax.persistence.OneToMany
data class CreatorCommunityComment( data class CreatorCommunityComment(
@Column(columnDefinition = "TEXT", nullable = false) @Column(columnDefinition = "TEXT", nullable = false)
var comment: String, var comment: String,
val isSecret: Boolean = false,
var isActive: Boolean = true var isActive: Boolean = true
) : BaseEntity() { ) : BaseEntity() {
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)

View File

@ -1,34 +1,29 @@
package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment
import org.springframework.beans.factory.annotation.Value
import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDateTime import java.time.ZoneId
import java.time.format.DateTimeFormatter
interface CreatorCommunityCommentRepository : interface CreatorCommunityCommentRepository :
JpaRepository<CreatorCommunityComment, Long>, CreatorCommunityCommentQueryRepository JpaRepository<CreatorCommunityComment, Long>, CreatorCommunityCommentQueryRepository
interface CreatorCommunityCommentQueryRepository { interface CreatorCommunityCommentQueryRepository {
fun findByPostId( fun findByPostId(
id: Long, cloudFrontHost: String,
memberId: Long,
isContentCreator: Boolean,
timezone: String, timezone: String,
id: Long,
offset: Long, offset: Long,
limit: Long limit: Long
): List<GetCommunityPostCommentListItem> ): List<GetCommunityPostCommentListItem>
fun commentReplyCountByCommentId(commentId: Long): Int fun commentReplyCountByCommentId(commentId: Long): Int
fun totalCountCommentByPostId( fun totalCountCommentByPostId(postId: Long): Int
postId: Long,
memberId: Long,
isContentCreator: Boolean
): Int
fun getCommunityCommentReplyList( fun getCommunityCommentReplyList(
cloudFrontHost: String,
commentId: Long, commentId: Long,
timezone: String, timezone: String,
offset: Long, offset: Long,
@ -37,64 +32,47 @@ interface CreatorCommunityCommentQueryRepository {
} }
class CreatorCommunityCommentQueryRepositoryImpl( class CreatorCommunityCommentQueryRepositoryImpl(
private val queryFactory: JPAQueryFactory, private val queryFactory: JPAQueryFactory
@Value("\${cloud.aws.cloud-front.host}")
private val imageHost: String
) : CreatorCommunityCommentQueryRepository { ) : CreatorCommunityCommentQueryRepository {
override fun findByPostId( override fun findByPostId(
id: Long, cloudFrontHost: String,
memberId: Long,
isContentCreator: Boolean,
timezone: String, timezone: String,
id: Long,
offset: Long, offset: Long,
limit: Long limit: Long
): List<GetCommunityPostCommentListItem> { ): List<GetCommunityPostCommentListItem> {
val formattedDate = Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
creatorCommunityComment.createdAt,
"UTC",
timezone
),
"%Y.%m.%d %W %h:%i %p"
)
var where = creatorCommunityComment.isActive.isTrue
.and(creatorCommunityComment.creatorCommunity.id.eq(id))
.and(creatorCommunityComment.parent.isNull)
if (!isContentCreator) {
where = where.and(
creatorCommunityComment.isSecret.isFalse
.or(creatorCommunityComment.member.id.eq(memberId))
)
}
return queryFactory return queryFactory
.select( .selectFrom(creatorCommunityComment)
QGetCommunityPostCommentListItem( .where(
creatorCommunityComment.id, creatorCommunityComment.isActive.isTrue
creatorCommunityComment.member.id, .and(creatorCommunityComment.creatorCommunity.id.eq(id))
creatorCommunityComment.member.nickname, .and(creatorCommunityComment.parent.isNull)
creatorCommunityComment.member.profileImage.prepend(imageHost),
creatorCommunityComment.comment,
formattedDate,
Expressions.constant(0)
)
) )
.from(creatorCommunityComment)
.where(where)
.offset(offset) .offset(offset)
.limit(limit) .limit(limit)
.orderBy(creatorCommunityComment.createdAt.desc()) .orderBy(creatorCommunityComment.createdAt.desc())
.fetch() .fetch()
.asSequence()
.map { .map {
it.replyCount = commentReplyCountByCommentId(it.id) val date = it.createdAt!!
it .atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of(timezone))
GetCommunityPostCommentListItem(
id = it.id!!,
writerId = it.member!!.id!!,
nickname = it.member!!.nickname,
profileUrl = if (it.member!!.profileImage != null) {
"$cloudFrontHost/${it.member!!.profileImage}"
} else {
"$cloudFrontHost/profile/default-profile.png"
},
comment = it.comment,
date = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd E hh:mm a")),
replyCount = commentReplyCountByCommentId(it.id!!)
)
} }
.toList()
} }
override fun commentReplyCountByCommentId(commentId: Long): Int { override fun commentReplyCountByCommentId(commentId: Long): Int {
@ -109,60 +87,27 @@ class CreatorCommunityCommentQueryRepositoryImpl(
.size .size
} }
override fun totalCountCommentByPostId( override fun totalCountCommentByPostId(postId: Long): Int {
postId: Long,
memberId: Long,
isContentCreator: Boolean
): Int {
var where = creatorCommunityComment.creatorCommunity.id.eq(postId)
.and(creatorCommunityComment.isActive.isTrue)
.and(creatorCommunityComment.parent.isNull)
if (!isContentCreator) {
where = where.and(
creatorCommunityComment.isSecret.isFalse
.or(creatorCommunityComment.member.id.eq(memberId))
)
}
return queryFactory.select(creatorCommunityComment.id) return queryFactory.select(creatorCommunityComment.id)
.from(creatorCommunityComment) .from(creatorCommunityComment)
.where(where) .where(
creatorCommunityComment.creatorCommunity.id.eq(postId)
.and(creatorCommunityComment.isActive.isTrue)
.and(creatorCommunityComment.parent.isNull)
)
.fetch() .fetch()
.size .size
} }
override fun getCommunityCommentReplyList( override fun getCommunityCommentReplyList(
cloudFrontHost: String,
commentId: Long, commentId: Long,
timezone: String, timezone: String,
offset: Long, offset: Long,
limit: Long limit: Long
): List<GetCommunityPostCommentListItem> { ): List<GetCommunityPostCommentListItem> {
val formattedDate = Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
creatorCommunityComment.createdAt,
"UTC",
timezone
),
"%Y.%m.%d %W %h:%i %p"
)
return queryFactory return queryFactory
.select( .selectFrom(creatorCommunityComment)
QGetCommunityPostCommentListItem(
creatorCommunityComment.id,
creatorCommunityComment.member.id,
creatorCommunityComment.member.nickname,
creatorCommunityComment.member.profileImage.prepend(imageHost),
creatorCommunityComment.comment,
formattedDate,
Expressions.constant(0)
)
)
.from(creatorCommunityComment)
.where( .where(
creatorCommunityComment.isActive.isTrue creatorCommunityComment.isActive.isTrue
.and(creatorCommunityComment.parent.isNotNull) .and(creatorCommunityComment.parent.isNotNull)
@ -172,5 +117,26 @@ class CreatorCommunityCommentQueryRepositoryImpl(
.limit(limit) .limit(limit)
.orderBy(creatorCommunityComment.createdAt.desc()) .orderBy(creatorCommunityComment.createdAt.desc())
.fetch() .fetch()
.asSequence()
.map {
val date = it.createdAt!!
.atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of(timezone))
GetCommunityPostCommentListItem(
id = it.id!!,
writerId = it.member!!.id!!,
nickname = it.member!!.nickname,
profileUrl = if (it.member!!.profileImage != null) {
"$cloudFrontHost/${it.member!!.profileImage}"
} else {
"$cloudFrontHost/profile/default-profile.png"
},
comment = it.comment,
date = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd E hh:mm a")),
replyCount = commentReplyCountByCommentId(it.id!!)
)
}
.toList()
} }
} }

View File

@ -1,18 +1,16 @@
package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment
import com.querydsl.core.annotations.QueryProjection
data class GetCommunityPostCommentListResponse( data class GetCommunityPostCommentListResponse(
val totalCount: Int, val totalCount: Int,
val items: List<GetCommunityPostCommentListItem> val items: List<GetCommunityPostCommentListItem>
) )
data class GetCommunityPostCommentListItem @QueryProjection constructor( data class GetCommunityPostCommentListItem(
val id: Long, val id: Long,
val writerId: Long, val writerId: Long,
val nickname: String, val nickname: String,
val profileUrl: String, val profileUrl: String,
val comment: String, val comment: String,
val date: String, val date: String,
var replyCount: Int val replyCount: Int
) )