diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt index fd3a937..602e82e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt @@ -16,6 +16,7 @@ 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.live.room.LiveRoom +import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.MemberRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service @@ -41,9 +42,9 @@ class CanPaymentService( ) { val member = memberRepository.findByIdOrNull(id = memberId) ?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.") - val useRewardCan = spendRewardCan(memberId, needCan, container) + val useRewardCan = spendRewardCan(member, needCan, container) val useChargeCan = if (needCan - useRewardCan.total > 0) { - spendChargeCan(memberId, needCan = needCan - useRewardCan.total, container = container) + spendChargeCan(member, needCan = needCan - useRewardCan.total, container = container) } else { 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) { - val member = memberRepository.findByIdOrNull(id = memberId) - ?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.") - val spentCans = mutableListOf() var chargeId = 0L var total = 0 while (needCan - total > 0) { val remainingNeedCan = needCan - total - val charge = chargeRepository.getOldestChargeWhereRewardCanGreaterThan0(chargeId, memberId, container) - ?: break + val charge = chargeRepository.getOldestChargeWhereRewardCanGreaterThan0( + chargeId, + member.id!!, + container + ) ?: break if (charge.rewardCan >= remainingNeedCan) { charge.rewardCan -= remainingNeedCan @@ -184,9 +185,9 @@ class CanPaymentService( ) when (charge.payment!!.paymentGateway) { - PaymentGateway.PG -> member.pgRewardCan -= remainingNeedCan - PaymentGateway.APPLE_IAP -> member.appleRewardCan -= remainingNeedCan - PaymentGateway.GOOGLE_IAP -> member.googleRewardCan -= remainingNeedCan + PaymentGateway.PG -> member.pgRewardCan -= charge.rewardCan + PaymentGateway.APPLE_IAP -> member.appleRewardCan -= charge.rewardCan + PaymentGateway.GOOGLE_IAP -> member.googleRewardCan -= charge.rewardCan } 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) { - val member = memberRepository.findByIdOrNull(id = memberId) - ?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.") - val spentCans = mutableListOf() var chargeId = 0L var total = 0 while (needCan - total > 0) { val remainingNeedCan = needCan - total - val charge = chargeRepository.getOldestChargeWhereChargeCanGreaterThan0(chargeId, memberId, container) - ?: break + val charge = chargeRepository.getOldestChargeWhereChargeCanGreaterThan0( + chargeId, + member.id!!, + container + ) ?: break if (charge.chargeCan >= remainingNeedCan) { charge.chargeCan -= remainingNeedCan @@ -242,9 +243,9 @@ class CanPaymentService( ) when (charge.payment!!.paymentGateway) { - PaymentGateway.PG -> member.pgChargeCan -= remainingNeedCan - PaymentGateway.APPLE_IAP -> member.appleChargeCan -= remainingNeedCan - PaymentGateway.GOOGLE_IAP -> member.pgChargeCan -= remainingNeedCan + PaymentGateway.PG -> member.pgChargeCan -= charge.chargeCan + PaymentGateway.APPLE_IAP -> member.appleChargeCan -= charge.chargeCan + PaymentGateway.GOOGLE_IAP -> member.pgChargeCan -= charge.chargeCan } charge.chargeCan = 0 diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt b/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt index 4b9aa7f..65c1599 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt @@ -14,7 +14,7 @@ class SodaExceptionHandler { private val logger = LoggerFactory.getLogger(this::class.java) @ExceptionHandler(SodaException::class) - fun handleSudaException(e: SodaException) = run { + fun handleSodaException(e: SodaException) = run { logger.error("API error", e) ApiResponse.error( message = e.message, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt index e766c32..bd8d174 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt @@ -9,7 +9,8 @@ import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.event.TransactionalEventListener 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( @@ -18,6 +19,7 @@ class FcmEvent( val message: String, val container: String = "", val recipients: List = listOf(), + val recipientsMap: Map>>? = null, val isAuth: Boolean = false, val roomId: 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 -> { if (fcmEvent.container.isNotBlank()) { val pushTokens = memberRepository.getUploadContentNotificationRecipientPushTokens( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt index 0f147df..e6ece32 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt @@ -113,6 +113,9 @@ class LiveRecommendRepository( .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) .limit(limit) .fetch() + .asSequence() + .filter { !isBlocked(it.creatorId) } + .toList() } fun getOnAirFollowingChannelList( @@ -188,6 +191,9 @@ class LiveRecommendRepository( .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) .limit(limit) .fetch() + .asSequence() + .filter { !isBlocked(it.creatorId) } + .toList() } fun getCreatorFollowingAllListTotalCount(memberId: Long, isBlocked: (Long) -> Boolean): Int { diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/reservation/LiveReservationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/reservation/LiveReservationRepository.kt index 4191d46..b161730 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/reservation/LiveReservationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/reservation/LiveReservationRepository.kt @@ -82,7 +82,8 @@ class LiveReservationQueryRepositoryImpl(private val queryFactory: JPAQueryFacto .innerJoin(liveReservation.member, member) .innerJoin(liveReservation.room, liveRoom) .where( - liveReservation.isActive.eq(active) + liveRoom.isActive.isTrue + .and(liveReservation.isActive.eq(active)) .and(member.id.eq(memberId)) ) .fetch() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/CreateSudaRoomRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/CreateLiveRoomRequest.kt similarity index 92% rename from src/main/kotlin/kr/co/vividnext/sodalive/live/room/CreateSudaRoomRequest.kt rename to src/main/kotlin/kr/co/vividnext/sodalive/live/room/CreateLiveRoomRequest.kt index 2df98d8..22b5468 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/CreateSudaRoomRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/CreateLiveRoomRequest.kt @@ -1,6 +1,6 @@ package kr.co.vividnext.sodalive.live.room -data class CreateSudaRoomRequest( +data class CreateLiveRoomRequest( val title: String, val content: String, val coverImageUrl: String? = null, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt index b470dd1..528abc9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt @@ -161,7 +161,7 @@ class LiveRoomService( @Transactional 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) { throw SodaException("커버이미지를 선택해 주세요.") } @@ -474,7 +474,17 @@ class LiveRoomService( } } + val pushTokenListMap = memberRepository.getPushTokenFromReservationList(request.roomId) reservationRepository.cancelReservation(roomId = room.id!!) + + applicationEventPublisher.publishEvent( + FcmEvent( + type = FcmEventType.CANCEL_LIVE, + title = room.member!!.nickname, + message = "라이브 취소 : ${room.title}", + recipientsMap = pushTokenListMap + ) + ) } @Transactional @@ -594,7 +604,7 @@ class LiveRoomService( val coverImagePath = s3Uploader.upload( inputStream = coverImage.inputStream, bucket = coverImageBucket, - filePath = "suda_room_cover/${room.id}/$coverImageFileName", + filePath = "live_room_cover/${room.id}/$coverImageFileName", metadata = metadata ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt index 3a60039..806240e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt @@ -50,6 +50,7 @@ interface MemberQueryRepository { fun getMemberByEmail(email: String): Member? fun getChangeNoticeRecipientPushTokens(creatorId: Long): Map>> + fun getPushTokenFromReservationList(roomId: Long): Map>> } @Repository @@ -255,9 +256,11 @@ class MemberQueryRepositoryImpl( ) .from(message) .innerJoin(message.recipient, member) + .innerJoin(member.notification, memberNotification) .where( message.id.eq(messageId) .and(member.pushToken.isNotNull) + .and(memberNotification.message.isTrue) ) .fetchFirst() } @@ -356,4 +359,31 @@ class MemberQueryRepositoryImpl( return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens) } + + override fun getPushTokenFromReservationList(roomId: Long): Map>> { + 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) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt index 42e33c2..9b788bc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt @@ -376,7 +376,7 @@ class MemberService( ) if (blockMember != null) { - blockMember.isActive = true + blockMember.isActive = false } }