커뮤니티 게시글 구매 API
This commit is contained in:
parent
37853bdedd
commit
059d5260a9
|
@ -69,6 +69,7 @@ class CanService(private val repository: CanRepository) {
|
|||
|
||||
CanUsage.CHANGE_NICKNAME -> "닉네임 변경"
|
||||
CanUsage.ORDER_CONTENT -> "콘텐츠 구매"
|
||||
CanUsage.PAID_COMMUNITY_POST -> "게시글 보기"
|
||||
}
|
||||
|
||||
val createdAt = it.createdAt!!
|
||||
|
|
|
@ -15,6 +15,7 @@ import kr.co.vividnext.sodalive.can.use.UseCanRepository
|
|||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.content.AudioContent
|
||||
import kr.co.vividnext.sodalive.content.order.Order
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunity
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
|
@ -38,6 +39,7 @@ class CanPaymentService(
|
|||
liveRoom: LiveRoom? = null,
|
||||
order: Order? = null,
|
||||
audioContent: AudioContent? = null,
|
||||
communityPost: CreatorCommunity? = null,
|
||||
container: String
|
||||
) {
|
||||
val member = memberRepository.findByIdOrNull(id = memberId)
|
||||
|
@ -90,6 +92,10 @@ class CanPaymentService(
|
|||
recipientId = liveRoom.member!!.id!!
|
||||
useCan.room = liveRoom
|
||||
useCan.member = member
|
||||
} else if (canUsage == CanUsage.PAID_COMMUNITY_POST && communityPost != null) {
|
||||
recipientId = communityPost.member!!.id!!
|
||||
useCan.communityPost = communityPost
|
||||
useCan.member = member
|
||||
} else {
|
||||
throw SodaException("잘못된 요청입니다.")
|
||||
}
|
||||
|
|
|
@ -5,5 +5,6 @@ enum class CanUsage {
|
|||
DONATION,
|
||||
CHANGE_NICKNAME,
|
||||
ORDER_CONTENT,
|
||||
SPIN_ROULETTE
|
||||
SPIN_ROULETTE,
|
||||
PAID_COMMUNITY_POST
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity
|
||||
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.GetCommunityPostCommentListItem
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
|
@ -22,4 +23,37 @@ data class CreatorCommunity(
|
|||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "member_id", nullable = false)
|
||||
var member: Member? = null
|
||||
|
||||
fun toCommunityPostListResponse(
|
||||
imageHost: String,
|
||||
content: String,
|
||||
date: String,
|
||||
isLike: Boolean,
|
||||
existOrdered: Boolean,
|
||||
likeCount: Int,
|
||||
commentCount: Int,
|
||||
firstComment: GetCommunityPostCommentListItem?
|
||||
): GetCommunityPostListResponse {
|
||||
return GetCommunityPostListResponse(
|
||||
postId = id!!,
|
||||
creatorId = member!!.id!!,
|
||||
creatorNickname = member!!.nickname,
|
||||
creatorProfileUrl = "$imageHost/${member?.profileImage ?: "profile/default-profile.png"}",
|
||||
imageUrl = if (imagePath != null) {
|
||||
"$imageHost/$imagePath"
|
||||
} else {
|
||||
null
|
||||
},
|
||||
content = content,
|
||||
price = price,
|
||||
date = date,
|
||||
isCommentAvailable = isCommentAvailable,
|
||||
isAdult = false,
|
||||
isLike = isLike,
|
||||
existOrdered = existOrdered,
|
||||
likeCount = likeCount,
|
||||
commentCount = commentCount,
|
||||
firstComment = firstComment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,4 +195,22 @@ class CreatorCommunityController(private val service: CreatorCommunityService) {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
@PostMapping("/purchase")
|
||||
fun purchasePost(
|
||||
@RequestBody request: PurchasePostRequest,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
|
||||
ApiResponse.ok(
|
||||
service.purchasePost(
|
||||
postId = request.postId,
|
||||
memberId = member.id!!,
|
||||
timezone = request.timezone,
|
||||
isAdult = member.auth != null,
|
||||
container = request.container
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ interface CreatorCommunityQueryRepository {
|
|||
|
||||
fun findByIdAndActive(postId: Long, isAdult: Boolean): CreatorCommunity?
|
||||
fun getLatestPostListFromCreatorsYouFollow(memberId: Long, isAdult: Boolean): List<SelectCommunityPostResponse>
|
||||
|
||||
fun getCommunityPost(postId: Long, isAdult: Boolean): SelectCommunityPostResponse?
|
||||
}
|
||||
|
||||
class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CreatorCommunityQueryRepository {
|
||||
|
@ -146,4 +148,31 @@ class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFact
|
|||
.limit(10)
|
||||
.fetch()
|
||||
}
|
||||
|
||||
override fun getCommunityPost(postId: Long, isAdult: Boolean): SelectCommunityPostResponse? {
|
||||
var where = creatorCommunity.id.eq(postId)
|
||||
.and(creatorCommunity.isActive.isTrue)
|
||||
|
||||
if (!isAdult) {
|
||||
where = where.and(creatorCommunity.isAdult.isFalse)
|
||||
}
|
||||
|
||||
return queryFactory
|
||||
.select(
|
||||
QSelectCommunityPostResponse(
|
||||
creatorCommunity.id,
|
||||
creatorCommunity.member.id,
|
||||
creatorCommunity.member.nickname,
|
||||
creatorCommunity.member.profileImage.coalesce("profile/default_profile.png"),
|
||||
creatorCommunity.imagePath,
|
||||
creatorCommunity.content,
|
||||
creatorCommunity.createdAt,
|
||||
creatorCommunity.isCommentAvailable,
|
||||
creatorCommunity.price
|
||||
)
|
||||
)
|
||||
.from(creatorCommunity)
|
||||
.where(where)
|
||||
.fetchFirst()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity
|
|||
import com.amazonaws.services.s3.model.ObjectMetadata
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import kr.co.vividnext.sodalive.aws.s3.S3Uploader
|
||||
import kr.co.vividnext.sodalive.can.payment.CanPaymentService
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanRepository
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.CreatorCommunityComment
|
||||
|
@ -29,6 +31,8 @@ import java.time.LocalDateTime
|
|||
|
||||
@Service
|
||||
class CreatorCommunityService(
|
||||
private val canPaymentService: CanPaymentService,
|
||||
|
||||
private val repository: CreatorCommunityRepository,
|
||||
private val blockMemberRepository: BlockMemberRepository,
|
||||
private val likeRepository: CreatorCommunityLikeRepository,
|
||||
|
@ -152,7 +156,6 @@ class CreatorCommunityService(
|
|||
)
|
||||
|
||||
return postList
|
||||
.asSequence()
|
||||
.map {
|
||||
val isLike = likeRepository.findByPostIdAndMemberId(postId = it.id, memberId = memberId)?.isActive
|
||||
?: false
|
||||
|
@ -192,21 +195,10 @@ class CreatorCommunityService(
|
|||
it.content
|
||||
}
|
||||
|
||||
GetCommunityPostListResponse(
|
||||
postId = it.id,
|
||||
creatorId = it.creatorId,
|
||||
creatorNickname = it.creatorNickname,
|
||||
creatorProfileUrl = "$imageHost/${it.creatorProfileUrl}",
|
||||
imageUrl = if (it.imagePath != null) {
|
||||
"$imageHost/${it.imagePath}"
|
||||
} else {
|
||||
null
|
||||
},
|
||||
it.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
content = content,
|
||||
price = it.price,
|
||||
date = getTimeAgoString(it.date),
|
||||
isCommentAvailable = it.isCommentAvailable,
|
||||
isAdult = false,
|
||||
isLike = isLike,
|
||||
existOrdered = if (memberId == it.creatorId) {
|
||||
true
|
||||
|
@ -218,7 +210,6 @@ class CreatorCommunityService(
|
|||
firstComment = firstComment
|
||||
)
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
|
||||
fun getCommunityPostDetail(
|
||||
|
@ -227,16 +218,16 @@ class CreatorCommunityService(
|
|||
timezone: String,
|
||||
isAdult: Boolean
|
||||
): GetCommunityPostListResponse {
|
||||
val post = repository.findByIdAndActive(postId, isAdult = isAdult)
|
||||
val post = repository.getCommunityPost(postId, isAdult = isAdult)
|
||||
?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.")
|
||||
|
||||
val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.member!!.id!!)
|
||||
if (isBlocked) throw SodaException("${post.member!!.nickname}님의 요청으로 접근이 제한됩니다.")
|
||||
val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.creatorId)
|
||||
if (isBlocked) throw SodaException("${post.creatorNickname}님의 요청으로 접근이 제한됩니다.")
|
||||
|
||||
val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id!!, memberId = memberId)?.isActive ?: false
|
||||
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id!!)
|
||||
val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id, memberId = memberId)?.isActive ?: false
|
||||
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id)
|
||||
val commentCount = if (post.isCommentAvailable) {
|
||||
commentRepository.totalCountCommentByPostId(postId = post.id!!)
|
||||
commentRepository.totalCountCommentByPostId(postId = post.id)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
@ -244,7 +235,7 @@ class CreatorCommunityService(
|
|||
commentRepository.findByPostId(
|
||||
cloudFrontHost = imageHost,
|
||||
timezone = timezone,
|
||||
id = post.id!!,
|
||||
id = post.id,
|
||||
offset = 0,
|
||||
limit = 1
|
||||
)
|
||||
|
@ -258,9 +249,9 @@ class CreatorCommunityService(
|
|||
null
|
||||
}
|
||||
|
||||
val existOrdered = useCanRepository.isExistOrdered(postId = post.id!!, memberId = memberId)
|
||||
val existOrdered = useCanRepository.isExistOrdered(postId = post.id, memberId = memberId)
|
||||
|
||||
val content = if (post.price > 0 && memberId != post.member!!.id) {
|
||||
val content = if (post.price > 0 && memberId != post.creatorId) {
|
||||
if (existOrdered) {
|
||||
post.content
|
||||
} else {
|
||||
|
@ -270,27 +261,12 @@ class CreatorCommunityService(
|
|||
post.content
|
||||
}
|
||||
|
||||
return GetCommunityPostListResponse(
|
||||
postId = post.id!!,
|
||||
creatorId = post.member!!.id!!,
|
||||
creatorNickname = post.member!!.nickname,
|
||||
creatorProfileUrl = if (post.member!!.profileImage != null) {
|
||||
"$imageHost/${post.member!!.profileImage}"
|
||||
} else {
|
||||
"$imageHost/profile/default-profile.png"
|
||||
},
|
||||
imageUrl = if (post.imagePath != null) {
|
||||
"$imageHost/${post.imagePath!!}"
|
||||
} else {
|
||||
null
|
||||
},
|
||||
return post.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
content = content,
|
||||
price = post.price,
|
||||
date = getTimeAgoString(post.createdAt!!),
|
||||
isCommentAvailable = post.isCommentAvailable,
|
||||
isAdult = post.isAdult,
|
||||
date = getTimeAgoString(post.date),
|
||||
isLike = isLike,
|
||||
existOrdered = if (memberId == post.member!!.id!!) {
|
||||
existOrdered = if (memberId == post.creatorId) {
|
||||
true
|
||||
} else {
|
||||
existOrdered
|
||||
|
@ -420,7 +396,6 @@ class CreatorCommunityService(
|
|||
val postList = repository.getLatestPostListFromCreatorsYouFollow(memberId = memberId, isAdult = isAdult)
|
||||
|
||||
return postList
|
||||
.asSequence()
|
||||
.filter {
|
||||
!blockMemberRepository.isBlocked(
|
||||
blockedMemberId = memberId,
|
||||
|
@ -440,7 +415,7 @@ class CreatorCommunityService(
|
|||
commentRepository.findByPostId(
|
||||
cloudFrontHost = imageHost,
|
||||
timezone = timezone,
|
||||
id = it.id!!,
|
||||
id = it.id,
|
||||
offset = 0,
|
||||
limit = 1
|
||||
)
|
||||
|
@ -466,21 +441,10 @@ class CreatorCommunityService(
|
|||
it.content
|
||||
}
|
||||
|
||||
GetCommunityPostListResponse(
|
||||
postId = it.id,
|
||||
creatorId = it.creatorId,
|
||||
creatorNickname = it.creatorNickname,
|
||||
creatorProfileUrl = "$imageHost/${it.creatorProfileUrl}",
|
||||
imageUrl = if (it.imagePath != null) {
|
||||
"$imageHost/${it.imagePath}"
|
||||
} else {
|
||||
null
|
||||
},
|
||||
it.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
content = content,
|
||||
price = it.price,
|
||||
date = getTimeAgoString(it.date),
|
||||
isCommentAvailable = it.isCommentAvailable,
|
||||
isAdult = false,
|
||||
isLike = isLike,
|
||||
existOrdered = if (memberId == it.creatorId) {
|
||||
true
|
||||
|
@ -492,6 +456,68 @@ class CreatorCommunityService(
|
|||
firstComment = firstComment
|
||||
)
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun purchasePost(
|
||||
postId: Long,
|
||||
memberId: Long,
|
||||
timezone: String,
|
||||
isAdult: Boolean,
|
||||
container: String
|
||||
): GetCommunityPostListResponse {
|
||||
val post = repository.findByIdAndActive(postId, isAdult)
|
||||
?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.")
|
||||
|
||||
val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.member!!.id!!)
|
||||
if (isBlocked) throw SodaException("${post.member!!.nickname}님의 요청으로 접근이 제한됩니다.")
|
||||
|
||||
val existOrdered = useCanRepository.isExistOrdered(postId = postId, memberId = memberId)
|
||||
|
||||
if (!existOrdered) {
|
||||
canPaymentService.spendCan(
|
||||
memberId = memberId,
|
||||
needCan = post.price,
|
||||
canUsage = CanUsage.PAID_COMMUNITY_POST,
|
||||
communityPost = post,
|
||||
container = container
|
||||
)
|
||||
}
|
||||
|
||||
val isLike = likeRepository.findByPostIdAndMemberId(postId = post.id!!, memberId = memberId)?.isActive ?: false
|
||||
val likeCount = likeRepository.totalCountCommunityPostLikeByPostId(post.id!!)
|
||||
val commentCount = if (post.isCommentAvailable) {
|
||||
commentRepository.totalCountCommentByPostId(postId = post.id!!)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
val commentList = if (post.isCommentAvailable) {
|
||||
commentRepository.findByPostId(
|
||||
cloudFrontHost = imageHost,
|
||||
timezone = timezone,
|
||||
id = post.id!!,
|
||||
offset = 0,
|
||||
limit = 1
|
||||
)
|
||||
} else {
|
||||
listOf()
|
||||
}
|
||||
|
||||
val firstComment = if (post.isCommentAvailable && commentList.isNotEmpty()) {
|
||||
commentList[0]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return post.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
content = post.content,
|
||||
date = getTimeAgoString(post.createdAt!!),
|
||||
isLike = isLike,
|
||||
existOrdered = true,
|
||||
likeCount = likeCount,
|
||||
commentCount = commentCount,
|
||||
firstComment = firstComment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity
|
||||
|
||||
data class PurchasePostRequest(val postId: Long, val timezone: String, val container: String)
|
|
@ -1,6 +1,7 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.GetCommunityPostCommentListItem
|
||||
import java.time.LocalDateTime
|
||||
|
||||
data class SelectCommunityPostResponse @QueryProjection constructor(
|
||||
|
@ -13,4 +14,37 @@ data class SelectCommunityPostResponse @QueryProjection constructor(
|
|||
val date: LocalDateTime,
|
||||
val isCommentAvailable: Boolean,
|
||||
val price: Int
|
||||
)
|
||||
) {
|
||||
fun toCommunityPostListResponse(
|
||||
imageHost: String,
|
||||
content: String,
|
||||
date: String,
|
||||
isLike: Boolean,
|
||||
existOrdered: Boolean,
|
||||
likeCount: Int,
|
||||
commentCount: Int,
|
||||
firstComment: GetCommunityPostCommentListItem?
|
||||
): GetCommunityPostListResponse {
|
||||
return GetCommunityPostListResponse(
|
||||
postId = id,
|
||||
creatorId = creatorId,
|
||||
creatorNickname = creatorNickname,
|
||||
creatorProfileUrl = "$imageHost/$creatorProfileUrl",
|
||||
imageUrl = if (imagePath != null) {
|
||||
"$imageHost/$imagePath"
|
||||
} else {
|
||||
null
|
||||
},
|
||||
content = content,
|
||||
price = price,
|
||||
date = date,
|
||||
isCommentAvailable = isCommentAvailable,
|
||||
isAdult = false,
|
||||
isLike = isLike,
|
||||
existOrdered = existOrdered,
|
||||
likeCount = likeCount,
|
||||
commentCount = commentCount,
|
||||
firstComment = firstComment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue