Merge pull request '시그니처 후원 시간 추가' (#171) from test into main

Reviewed-on: #171
This commit is contained in:
klaus 2024-05-02 06:23:22 +00:00
commit db1a7a7fd6
9 changed files with 109 additions and 4 deletions

View File

@ -31,6 +31,7 @@ class CreatorAdminSignatureController(private val service: CreatorAdminSignature
@PostMapping @PostMapping
fun createSignature( fun createSignature(
@RequestParam("can") can: Int, @RequestParam("can") can: Int,
@RequestParam("time") time: Int,
@RequestParam("image") image: MultipartFile, @RequestParam("image") image: MultipartFile,
@RequestParam("isAdult", required = false) isAdult: Boolean = false, @RequestParam("isAdult", required = false) isAdult: Boolean = false,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
@ -38,7 +39,7 @@ class CreatorAdminSignatureController(private val service: CreatorAdminSignature
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok( ApiResponse.ok(
service.createSignature(can = can, image = image, isAdult = isAdult, memberId = member.id!!), service.createSignature(can = can, time = time, image = image, isAdult = isAdult, memberId = member.id!!),
"등록되었습니다." "등록되었습니다."
) )
} }
@ -47,13 +48,14 @@ class CreatorAdminSignatureController(private val service: CreatorAdminSignature
fun modifySignature( fun modifySignature(
@RequestParam("id") id: Long, @RequestParam("id") id: Long,
@RequestParam("can", required = false) can: Int?, @RequestParam("can", required = false) can: Int?,
@RequestParam("time", required = false) time: Int?,
@RequestParam("image", required = false) image: MultipartFile?, @RequestParam("image", required = false) image: MultipartFile?,
@RequestParam("isActive", required = false) isActive: Boolean?, @RequestParam("isActive", required = false) isActive: Boolean?,
@RequestParam("isAdult", required = false) isAdult: Boolean?, @RequestParam("isAdult", required = false) isAdult: Boolean?,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
if (can == null && image == null && isActive == null && isAdult == null) { if (can == null && time == null && image == null && isActive == null && isAdult == null) {
throw SodaException("변경사항이 없습니다.") throw SodaException("변경사항이 없습니다.")
} }
@ -61,6 +63,7 @@ class CreatorAdminSignatureController(private val service: CreatorAdminSignature
service.modifySignature( service.modifySignature(
id = id, id = id,
can = can, can = can,
time = time,
image = image, image = image,
isActive = isActive, isActive = isActive,
isAdult = isAdult, isAdult = isAdult,

View File

@ -40,6 +40,7 @@ class CreatorAdminSignatureQueryRepositoryImpl(
QGetSignatureListItem( QGetSignatureListItem(
signatureCan.id, signatureCan.id,
signatureCan.can, signatureCan.can,
signatureCan.time,
signatureCan.image.prepend("/").prepend(imageHost), signatureCan.image.prepend("/").prepend(imageHost),
signatureCan.isAdult, signatureCan.isAdult,
member.nickname member.nickname

View File

@ -37,11 +37,14 @@ class CreatorAdminSignatureService(
} }
@Transactional @Transactional
fun createSignature(can: Int, image: MultipartFile, memberId: Long, isAdult: Boolean) { fun createSignature(can: Int, time: Int, image: MultipartFile, memberId: Long, isAdult: Boolean) {
val member = memberRepository.findCreatorByIdOrNull(memberId = memberId) val member = memberRepository.findCreatorByIdOrNull(memberId = memberId)
?: throw SodaException("잘못된 접근입니다.") ?: throw SodaException("잘못된 접근입니다.")
val signatureCan = SignatureCan(can = can, isAdult = isAdult) if (can <= 0) throw SodaException("1캔 이상 설정할 수 있습니다.")
if (time < 3 || time > 20) throw SodaException("시간은 3초 이상 20초 이하로 설정할 수 있습니다.")
val signatureCan = SignatureCan(can = can, time = time, isAdult = isAdult)
signatureCan.creator = member signatureCan.creator = member
repository.save(signatureCan) repository.save(signatureCan)
@ -61,6 +64,7 @@ class CreatorAdminSignatureService(
fun modifySignature( fun modifySignature(
id: Long, id: Long,
can: Int?, can: Int?,
time: Int?,
image: MultipartFile?, image: MultipartFile?,
isActive: Boolean?, isActive: Boolean?,
memberId: Long, memberId: Long,
@ -70,9 +74,15 @@ class CreatorAdminSignatureService(
?: throw SodaException("잘못된 요청입니다.") ?: throw SodaException("잘못된 요청입니다.")
if (can != null) { if (can != null) {
if (can <= 0) throw SodaException("1캔 이상 설정할 수 있습니다.")
signatureCan.can = can signatureCan.can = can
} }
if (time != null) {
if (time < 3 || time > 20) throw SodaException("시간은 3초 이상 20초 이하로 설정할 수 있습니다.")
signatureCan.time = time
}
if (isActive != null) { if (isActive != null) {
signatureCan.isActive = isActive signatureCan.isActive = isActive
} }

View File

@ -10,6 +10,7 @@ data class GetSignatureListResponse(
data class GetSignatureListItem @QueryProjection constructor( data class GetSignatureListItem @QueryProjection constructor(
val id: Long, val id: Long,
val can: Int, val can: Int,
val time: Int,
val image: String, val image: String,
val isAdult: Boolean, val isAdult: Boolean,
val nickname: String val nickname: String

View File

@ -205,6 +205,16 @@ class LiveRoomController(
ApiResponse.ok(service.donation(request, member)) ApiResponse.ok(service.donation(request, member))
} }
@PostMapping("/donation/v2")
fun donationV2(
@RequestBody request: LiveRoomDonationRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.donationV2(request, member))
}
@PostMapping("/donation/refund/{id}") @PostMapping("/donation/refund/{id}")
fun refundDonation( fun refundDonation(
@PathVariable id: Long, @PathVariable id: Long,

View File

@ -33,6 +33,7 @@ import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationStatusResp
import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationTotalResponse import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationTotalResponse
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationMessage import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationMessage
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationRequest import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationRequest
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationResponse
import kr.co.vividnext.sodalive.live.room.info.GetRoomInfoResponse import kr.co.vividnext.sodalive.live.room.info.GetRoomInfoResponse
import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfo import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfo
import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfoRedisRepository import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfoRedisRepository
@ -1059,6 +1060,49 @@ class LiveRoomService(
) )
} }
@Transactional
fun donationV2(request: LiveRoomDonationRequest, member: Member): LiveRoomDonationResponse? {
val room = repository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.")
val host = room.member ?: throw SodaException("잘못된 요청입니다.")
if (host.role != MemberRole.CREATOR) {
throw SodaException("비비드넥스트와 계약한\n크리에이터에게만 후원을 하실 수 있습니다.")
}
canPaymentService.spendCan(
memberId = member.id!!,
needCan = request.can,
canUsage = CanUsage.DONATION,
liveRoom = room,
container = request.container
)
if (request.message.isNotBlank()) {
val lock = getOrCreateLock(memberId = member.id!!)
lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
roomInfo.addDonationMessage(
nickname = member.nickname,
can = request.can,
donationMessage = request.message
)
roomInfoRepository.save(roomInfo)
}
}
return signatureCanRepository.findByCreatorIdAndCan(
creatorId = host.id!!,
can = request.can,
imageHost = cloudFrontHost,
isAdult = room.isAdult
)
}
@Transactional @Transactional
fun refundDonation(roomId: Long, member: Member) { fun refundDonation(roomId: Long, member: Member) {
val donator = memberRepository.findByIdOrNull(member.id) val donator = memberRepository.findByIdOrNull(member.id)

View File

@ -0,0 +1,5 @@
package kr.co.vividnext.sodalive.live.room.donation
import com.querydsl.core.annotations.QueryProjection
data class LiveRoomDonationResponse @QueryProjection constructor(val imageUrl: String, val time: Int)

View File

@ -10,6 +10,7 @@ import javax.persistence.ManyToOne
@Entity @Entity
data class SignatureCan( data class SignatureCan(
var can: Int, var can: Int,
var time: Int = 7,
var isAdult: Boolean = false, var isAdult: Boolean = false,
var isActive: Boolean = true var isActive: Boolean = true
) : BaseEntity() { ) : BaseEntity() {

View File

@ -1,6 +1,8 @@
package kr.co.vividnext.sodalive.live.signature package kr.co.vividnext.sodalive.live.signature
import com.querydsl.jpa.impl.JPAQueryFactory import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationResponse
import kr.co.vividnext.sodalive.live.room.donation.QLiveRoomDonationResponse
import kr.co.vividnext.sodalive.live.signature.QSignatureCan.signatureCan import kr.co.vividnext.sodalive.live.signature.QSignatureCan.signatureCan
import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.JpaRepository
@ -8,6 +10,7 @@ interface SignatureCanRepository : JpaRepository<SignatureCan, Long>, SignatureC
interface SignatureCanQueryRepository { interface SignatureCanQueryRepository {
fun findImageByCreatorIdAndCan(creatorId: Long, can: Int, imageHost: String, isAdult: Boolean): String? fun findImageByCreatorIdAndCan(creatorId: Long, can: Int, imageHost: String, isAdult: Boolean): String?
fun findByCreatorIdAndCan(creatorId: Long, can: Int, imageHost: String, isAdult: Boolean): LiveRoomDonationResponse?
} }
class SignatureCanQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : SignatureCanQueryRepository { class SignatureCanQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : SignatureCanQueryRepository {
@ -27,4 +30,31 @@ class SignatureCanQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
.orderBy(signatureCan.isAdult.desc()) .orderBy(signatureCan.isAdult.desc())
.fetchFirst() .fetchFirst()
} }
override fun findByCreatorIdAndCan(
creatorId: Long,
can: Int,
imageHost: String,
isAdult: Boolean
): LiveRoomDonationResponse? {
var where = signatureCan.creator.id.eq(creatorId)
.and(signatureCan.can.eq(can))
.and(signatureCan.isActive.isTrue)
if (!isAdult) {
where = where.and(signatureCan.isAdult.isFalse())
}
return queryFactory
.select(
QLiveRoomDonationResponse(
signatureCan.image.prepend("/").prepend(imageHost),
signatureCan.time
)
)
.from(signatureCan)
.where(where)
.orderBy(signatureCan.isAdult.desc())
.fetchFirst()
}
} }