test #28

Merged
klaus merged 10 commits from test into main 2023-09-02 16:12:09 +00:00
9 changed files with 105 additions and 27 deletions

View File

@ -16,6 +16,7 @@ import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.AudioContent import kr.co.vividnext.sodalive.content.AudioContent
import kr.co.vividnext.sodalive.content.order.Order import kr.co.vividnext.sodalive.content.order.Order
import kr.co.vividnext.sodalive.live.room.LiveRoom import kr.co.vividnext.sodalive.live.room.LiveRoom
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.MemberRepository import kr.co.vividnext.sodalive.member.MemberRepository
import org.springframework.data.repository.findByIdOrNull import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -41,9 +42,9 @@ class CanPaymentService(
) { ) {
val member = memberRepository.findByIdOrNull(id = memberId) val member = memberRepository.findByIdOrNull(id = memberId)
?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.") ?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.")
val useRewardCan = spendRewardCan(memberId, needCan, container) val useRewardCan = spendRewardCan(member, needCan, container)
val useChargeCan = if (needCan - useRewardCan.total > 0) { val useChargeCan = if (needCan - useRewardCan.total > 0) {
spendChargeCan(memberId, needCan = needCan - useRewardCan.total, container = container) spendChargeCan(member, needCan = needCan - useRewardCan.total, container = container)
} else { } else {
null null
} }
@ -143,19 +144,19 @@ class CanPaymentService(
} }
} }
private fun spendRewardCan(memberId: Long, needCan: Int, container: String): TotalSpentCan { private fun spendRewardCan(member: Member, needCan: Int, container: String): TotalSpentCan {
return if (needCan > 0) { return if (needCan > 0) {
val member = memberRepository.findByIdOrNull(id = memberId)
?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.")
val spentCans = mutableListOf<SpentCan>() val spentCans = mutableListOf<SpentCan>()
var chargeId = 0L var chargeId = 0L
var total = 0 var total = 0
while (needCan - total > 0) { while (needCan - total > 0) {
val remainingNeedCan = needCan - total val remainingNeedCan = needCan - total
val charge = chargeRepository.getOldestChargeWhereRewardCanGreaterThan0(chargeId, memberId, container) val charge = chargeRepository.getOldestChargeWhereRewardCanGreaterThan0(
?: break chargeId,
member.id!!,
container
) ?: break
if (charge.rewardCan >= remainingNeedCan) { if (charge.rewardCan >= remainingNeedCan) {
charge.rewardCan -= remainingNeedCan charge.rewardCan -= remainingNeedCan
@ -184,9 +185,9 @@ class CanPaymentService(
) )
when (charge.payment!!.paymentGateway) { when (charge.payment!!.paymentGateway) {
PaymentGateway.PG -> member.pgRewardCan -= remainingNeedCan PaymentGateway.PG -> member.pgRewardCan -= charge.rewardCan
PaymentGateway.APPLE_IAP -> member.appleRewardCan -= remainingNeedCan PaymentGateway.APPLE_IAP -> member.appleRewardCan -= charge.rewardCan
PaymentGateway.GOOGLE_IAP -> member.googleRewardCan -= remainingNeedCan PaymentGateway.GOOGLE_IAP -> member.googleRewardCan -= charge.rewardCan
} }
charge.rewardCan = 0 charge.rewardCan = 0
@ -201,19 +202,19 @@ class CanPaymentService(
} }
} }
private fun spendChargeCan(memberId: Long, needCan: Int, container: String): TotalSpentCan { private fun spendChargeCan(member: Member, needCan: Int, container: String): TotalSpentCan {
return if (needCan > 0) { return if (needCan > 0) {
val member = memberRepository.findByIdOrNull(id = memberId)
?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.")
val spentCans = mutableListOf<SpentCan>() val spentCans = mutableListOf<SpentCan>()
var chargeId = 0L var chargeId = 0L
var total = 0 var total = 0
while (needCan - total > 0) { while (needCan - total > 0) {
val remainingNeedCan = needCan - total val remainingNeedCan = needCan - total
val charge = chargeRepository.getOldestChargeWhereChargeCanGreaterThan0(chargeId, memberId, container) val charge = chargeRepository.getOldestChargeWhereChargeCanGreaterThan0(
?: break chargeId,
member.id!!,
container
) ?: break
if (charge.chargeCan >= remainingNeedCan) { if (charge.chargeCan >= remainingNeedCan) {
charge.chargeCan -= remainingNeedCan charge.chargeCan -= remainingNeedCan
@ -242,9 +243,9 @@ class CanPaymentService(
) )
when (charge.payment!!.paymentGateway) { when (charge.payment!!.paymentGateway) {
PaymentGateway.PG -> member.pgChargeCan -= remainingNeedCan PaymentGateway.PG -> member.pgChargeCan -= charge.chargeCan
PaymentGateway.APPLE_IAP -> member.appleChargeCan -= remainingNeedCan PaymentGateway.APPLE_IAP -> member.appleChargeCan -= charge.chargeCan
PaymentGateway.GOOGLE_IAP -> member.pgChargeCan -= remainingNeedCan PaymentGateway.GOOGLE_IAP -> member.pgChargeCan -= charge.chargeCan
} }
charge.chargeCan = 0 charge.chargeCan = 0

View File

@ -14,7 +14,7 @@ class SodaExceptionHandler {
private val logger = LoggerFactory.getLogger(this::class.java) private val logger = LoggerFactory.getLogger(this::class.java)
@ExceptionHandler(SodaException::class) @ExceptionHandler(SodaException::class)
fun handleSudaException(e: SodaException) = run { fun handleSodaException(e: SodaException) = run {
logger.error("API error", e) logger.error("API error", e)
ApiResponse.error( ApiResponse.error(
message = e.message, message = e.message,

View File

@ -9,7 +9,8 @@ import org.springframework.transaction.annotation.Transactional
import org.springframework.transaction.event.TransactionalEventListener import org.springframework.transaction.event.TransactionalEventListener
enum class FcmEventType { enum class FcmEventType {
ALL, INDIVIDUAL, CREATE_LIVE, START_LIVE, UPLOAD_CONTENT, SEND_MESSAGE, CHANGE_NOTICE, CREATE_CONTENT_COMMENT ALL, INDIVIDUAL, CREATE_LIVE, START_LIVE, CANCEL_LIVE, UPLOAD_CONTENT, SEND_MESSAGE, CHANGE_NOTICE,
CREATE_CONTENT_COMMENT
} }
class FcmEvent( class FcmEvent(
@ -18,6 +19,7 @@ class FcmEvent(
val message: String, val message: String,
val container: String = "", val container: String = "",
val recipients: List<Long> = listOf(), val recipients: List<Long> = listOf(),
val recipientsMap: Map<String, List<List<String>>>? = null,
val isAuth: Boolean = false, val isAuth: Boolean = false,
val roomId: Long? = null, val roomId: Long? = null,
val contentId: Long? = null, val contentId: Long? = null,
@ -131,6 +133,34 @@ class FcmSendListener(
} }
} }
FcmEventType.CANCEL_LIVE -> {
if (fcmEvent.recipientsMap != null) {
val iosPushTokens = fcmEvent.recipientsMap["ios"]
val aosPushToken = fcmEvent.recipientsMap["aos"]
if (iosPushTokens != null) {
for (tokens in iosPushTokens) {
pushService.send(
tokens = tokens,
title = fcmEvent.title,
message = fcmEvent.message,
container = "ios"
)
}
}
if (aosPushToken != null) {
for (tokens in aosPushToken) {
pushService.send(
tokens = tokens,
title = fcmEvent.title,
message = fcmEvent.message,
container = "aos"
)
}
}
}
}
FcmEventType.UPLOAD_CONTENT -> { FcmEventType.UPLOAD_CONTENT -> {
if (fcmEvent.container.isNotBlank()) { if (fcmEvent.container.isNotBlank()) {
val pushTokens = memberRepository.getUploadContentNotificationRecipientPushTokens( val pushTokens = memberRepository.getUploadContentNotificationRecipientPushTokens(

View File

@ -113,6 +113,9 @@ class LiveRecommendRepository(
.orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc())
.limit(limit) .limit(limit)
.fetch() .fetch()
.asSequence()
.filter { !isBlocked(it.creatorId) }
.toList()
} }
fun getOnAirFollowingChannelList( fun getOnAirFollowingChannelList(
@ -188,6 +191,9 @@ class LiveRecommendRepository(
.orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc())
.limit(limit) .limit(limit)
.fetch() .fetch()
.asSequence()
.filter { !isBlocked(it.creatorId) }
.toList()
} }
fun getCreatorFollowingAllListTotalCount(memberId: Long, isBlocked: (Long) -> Boolean): Int { fun getCreatorFollowingAllListTotalCount(memberId: Long, isBlocked: (Long) -> Boolean): Int {

View File

@ -82,7 +82,8 @@ class LiveReservationQueryRepositoryImpl(private val queryFactory: JPAQueryFacto
.innerJoin(liveReservation.member, member) .innerJoin(liveReservation.member, member)
.innerJoin(liveReservation.room, liveRoom) .innerJoin(liveReservation.room, liveRoom)
.where( .where(
liveReservation.isActive.eq(active) liveRoom.isActive.isTrue
.and(liveReservation.isActive.eq(active))
.and(member.id.eq(memberId)) .and(member.id.eq(memberId))
) )
.fetch() .fetch()

View File

@ -1,6 +1,6 @@
package kr.co.vividnext.sodalive.live.room package kr.co.vividnext.sodalive.live.room
data class CreateSudaRoomRequest( data class CreateLiveRoomRequest(
val title: String, val title: String,
val content: String, val content: String,
val coverImageUrl: String? = null, val coverImageUrl: String? = null,

View File

@ -161,7 +161,7 @@ class LiveRoomService(
@Transactional @Transactional
fun createLiveRoom(coverImage: MultipartFile?, requestString: String, member: Member): CreateLiveRoomResponse { fun createLiveRoom(coverImage: MultipartFile?, requestString: String, member: Member): CreateLiveRoomResponse {
val request = objectMapper.readValue(requestString, CreateSudaRoomRequest::class.java) val request = objectMapper.readValue(requestString, CreateLiveRoomRequest::class.java)
if (request.coverImageUrl == null && coverImage == null) { if (request.coverImageUrl == null && coverImage == null) {
throw SodaException("커버이미지를 선택해 주세요.") throw SodaException("커버이미지를 선택해 주세요.")
} }
@ -474,7 +474,17 @@ class LiveRoomService(
} }
} }
val pushTokenListMap = memberRepository.getPushTokenFromReservationList(request.roomId)
reservationRepository.cancelReservation(roomId = room.id!!) reservationRepository.cancelReservation(roomId = room.id!!)
applicationEventPublisher.publishEvent(
FcmEvent(
type = FcmEventType.CANCEL_LIVE,
title = room.member!!.nickname,
message = "라이브 취소 : ${room.title}",
recipientsMap = pushTokenListMap
)
)
} }
@Transactional @Transactional
@ -594,7 +604,7 @@ class LiveRoomService(
val coverImagePath = s3Uploader.upload( val coverImagePath = s3Uploader.upload(
inputStream = coverImage.inputStream, inputStream = coverImage.inputStream,
bucket = coverImageBucket, bucket = coverImageBucket,
filePath = "suda_room_cover/${room.id}/$coverImageFileName", filePath = "live_room_cover/${room.id}/$coverImageFileName",
metadata = metadata metadata = metadata
) )

View File

@ -50,6 +50,7 @@ interface MemberQueryRepository {
fun getMemberByEmail(email: String): Member? fun getMemberByEmail(email: String): Member?
fun getChangeNoticeRecipientPushTokens(creatorId: Long): Map<String, List<List<String>>> fun getChangeNoticeRecipientPushTokens(creatorId: Long): Map<String, List<List<String>>>
fun getPushTokenFromReservationList(roomId: Long): Map<String, List<List<String>>>
} }
@Repository @Repository
@ -255,9 +256,11 @@ class MemberQueryRepositoryImpl(
) )
.from(message) .from(message)
.innerJoin(message.recipient, member) .innerJoin(message.recipient, member)
.innerJoin(member.notification, memberNotification)
.where( .where(
message.id.eq(messageId) message.id.eq(messageId)
.and(member.pushToken.isNotNull) .and(member.pushToken.isNotNull)
.and(memberNotification.message.isTrue)
) )
.fetchFirst() .fetchFirst()
} }
@ -356,4 +359,31 @@ class MemberQueryRepositoryImpl(
return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens) return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens)
} }
override fun getPushTokenFromReservationList(roomId: Long): Map<String, List<List<String>>> {
val where = liveRoom.id.eq(roomId)
.and(liveReservation.isActive.isTrue)
val aosPushTokens = queryFactory
.select(liveReservation.member.pushToken)
.from(liveReservation)
.innerJoin(liveReservation.room, liveRoom)
.innerJoin(liveReservation.member, member)
.where(where.and(member.container.eq("aos")))
.fetch()
.toSet()
.chunked(500)
val iosPushTokens = queryFactory
.select(liveReservation.member.pushToken)
.from(liveReservation)
.innerJoin(liveReservation.room, liveRoom)
.innerJoin(liveReservation.member, member)
.where(where.and(member.container.eq("ios")))
.fetch()
.toSet()
.chunked(500)
return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens)
}
} }

View File

@ -376,7 +376,7 @@ class MemberService(
) )
if (blockMember != null) { if (blockMember != null) {
blockMember.isActive = true blockMember.isActive = false
} }
} }