test #18
| @@ -85,7 +85,12 @@ class ChargeService( | ||||
|                     charge.payment?.status = PaymentStatus.COMPLETE | ||||
|                     member.charge(charge.chargeCan, charge.rewardCan, "pg") | ||||
|  | ||||
|                     applicationEventPublisher.publishEvent(ChargeSpringEvent(chargeId = charge.id!!, member = member)) | ||||
|                     applicationEventPublisher.publishEvent( | ||||
|                         ChargeSpringEvent( | ||||
|                             chargeId = charge.id!!, | ||||
|                             memberId = member.id!! | ||||
|                         ) | ||||
|                     ) | ||||
|                 } else { | ||||
|                     throw SodaException("결제정보에 오류가 있습니다.") | ||||
|                 } | ||||
| @@ -134,7 +139,12 @@ class ChargeService( | ||||
|                 charge.payment?.status = PaymentStatus.COMPLETE | ||||
|                 member.charge(charge.chargeCan, charge.rewardCan, "ios") | ||||
|  | ||||
|                 applicationEventPublisher.publishEvent(ChargeSpringEvent(chargeId = charge.id!!, member = member)) | ||||
|                 applicationEventPublisher.publishEvent( | ||||
|                     ChargeSpringEvent( | ||||
|                         chargeId = charge.id!!, | ||||
|                         memberId = member.id!! | ||||
|                     ) | ||||
|                 ) | ||||
|             } else { | ||||
|                 throw SodaException("결제정보에 오류가 있습니다.") | ||||
|             } | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.common.SodaException | ||||
| import kr.co.vividnext.sodalive.fcm.FcmEvent | ||||
| import kr.co.vividnext.sodalive.fcm.FcmEventType | ||||
| import kr.co.vividnext.sodalive.member.Member | ||||
| import kr.co.vividnext.sodalive.member.MemberRepository | ||||
| import kr.co.vividnext.sodalive.member.auth.AuthRepository | ||||
| import org.springframework.context.ApplicationEventPublisher | ||||
| import org.springframework.data.repository.findByIdOrNull | ||||
| @@ -22,25 +23,29 @@ import kotlin.math.round | ||||
| class ChargeEventService( | ||||
|     private val repository: ChargeEventRepository, | ||||
|     private val authRepository: AuthRepository, | ||||
|     private val memberRepository: MemberRepository, | ||||
|     private val chargeRepository: ChargeRepository, | ||||
|     private val chargeEventRepository: ChargeEventRepository, | ||||
|     private val applicationEventPublisher: ApplicationEventPublisher | ||||
| ) { | ||||
|     @Transactional | ||||
|     fun applyChargeEvent(chargeId: Long, member: Member) { | ||||
|     fun applyChargeEvent(chargeId: Long, memberId: Long) { | ||||
|         val charge = chargeRepository.findByIdOrNull(chargeId) | ||||
|             ?: throw SodaException("이벤트가 적용되지 않았습니다.") | ||||
|             ?: throw SodaException("이벤트가 적용되지 않았습니다.\n고객센터에 문의해 주세요.") | ||||
|  | ||||
|         val member = memberRepository.findByIdOrNull(memberId) | ||||
|             ?: throw SodaException("이벤트가 적용되지 않았습니다.\n고객센터에 문의해 주세요.") | ||||
|  | ||||
|         if (member.auth != null) { | ||||
|             val authDate = authRepository.getOldestCreatedAtByDi(member.auth!!.di) | ||||
|             val memberIds = authRepository.getMemberIdsByDi(member.auth!!.di) | ||||
|  | ||||
|             var chargeCount = 0 | ||||
|             for (memberId in memberIds) { | ||||
|                 chargeCount += chargeRepository.getChargeCountAfterDate(memberId = memberId, authDate) | ||||
|             for (id in memberIds) { | ||||
|                 chargeCount += chargeRepository.getChargeCountAfterDate(memberId = id, authDate) | ||||
|             } | ||||
|  | ||||
|             if (chargeCount > 0) { | ||||
|             if (chargeCount > 1) { | ||||
|                 applyOtherEvent(charge, member) | ||||
|             } else { | ||||
|                 applyFirstChargeEvent(charge, member) | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| package kr.co.vividnext.sodalive.can.charge.event | ||||
|  | ||||
| import kr.co.vividnext.sodalive.member.Member | ||||
| import org.springframework.context.event.EventListener | ||||
| import org.springframework.scheduling.annotation.Async | ||||
| import org.springframework.stereotype.Component | ||||
| import org.springframework.transaction.event.TransactionalEventListener | ||||
|  | ||||
| class ChargeSpringEvent( | ||||
|     val chargeId: Long, | ||||
|     val member: Member | ||||
|     val memberId: Long | ||||
| ) | ||||
|  | ||||
| @Component | ||||
| @@ -15,8 +14,8 @@ class ChargeSpringEventListener( | ||||
|     private val chargeEventService: ChargeEventService | ||||
| ) { | ||||
|     @Async | ||||
|     @EventListener | ||||
|     @TransactionalEventListener | ||||
|     fun applyChargeEvent(event: ChargeSpringEvent) { | ||||
|         chargeEventService.applyChargeEvent(event.chargeId, event.member) | ||||
|         chargeEventService.applyChargeEvent(event.chargeId, event.memberId) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -11,11 +11,14 @@ import kr.co.vividnext.sodalive.explorer.profile.CreatorCheers | ||||
| import kr.co.vividnext.sodalive.explorer.profile.CreatorCheersRepository | ||||
| import kr.co.vividnext.sodalive.explorer.profile.PostWriteCheersRequest | ||||
| import kr.co.vividnext.sodalive.explorer.profile.PutWriteCheersRequest | ||||
| import kr.co.vividnext.sodalive.fcm.FcmEvent | ||||
| import kr.co.vividnext.sodalive.fcm.FcmEventType | ||||
| import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailUser | ||||
| import kr.co.vividnext.sodalive.member.Member | ||||
| import kr.co.vividnext.sodalive.member.MemberRole | ||||
| import kr.co.vividnext.sodalive.member.MemberService | ||||
| import org.springframework.beans.factory.annotation.Value | ||||
| import org.springframework.context.ApplicationEventPublisher | ||||
| import org.springframework.data.domain.Pageable | ||||
| import org.springframework.stereotype.Service | ||||
| import org.springframework.transaction.annotation.Transactional | ||||
| @@ -28,6 +31,7 @@ class ExplorerService( | ||||
|     private val queryRepository: ExplorerQueryRepository, | ||||
|     private val cheersRepository: CreatorCheersRepository, | ||||
|     private val noticeRepository: ChannelNoticeRepository, | ||||
|     private val applicationEventPublisher: ApplicationEventPublisher, | ||||
|  | ||||
|     @Value("\${cloud.aws.cloud-front.host}") | ||||
|     private val cloudFrontHost: String | ||||
| @@ -318,5 +322,14 @@ class ExplorerService( | ||||
|         } else { | ||||
|             channelNotice.notice = notice | ||||
|         } | ||||
|  | ||||
|         applicationEventPublisher.publishEvent( | ||||
|             FcmEvent( | ||||
|                 type = FcmEventType.CHANGE_NOTICE, | ||||
|                 title = member.nickname, | ||||
|                 message = "공지를 등록했습니다.", | ||||
|                 creatorId = member.id!! | ||||
|             ) | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import org.springframework.scheduling.annotation.Async | ||||
| import org.springframework.stereotype.Component | ||||
|  | ||||
| enum class FcmEventType { | ||||
|     ALL, INDIVIDUAL, CREATE_LIVE, START_LIVE, UPLOAD_CONTENT, SEND_MESSAGE | ||||
|     ALL, INDIVIDUAL, CREATE_LIVE, START_LIVE, UPLOAD_CONTENT, SEND_MESSAGE, CHANGE_NOTICE | ||||
| } | ||||
|  | ||||
| class FcmEvent( | ||||
| @@ -156,6 +156,39 @@ class FcmSendListener( | ||||
|                     messageId = fcmEvent.messageId | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             FcmEventType.CHANGE_NOTICE -> { | ||||
|                 if (fcmEvent.creatorId != null) { | ||||
|                     val pushTokenList = memberRepository.getChangeNoticeRecipientPushTokens(fcmEvent.creatorId) | ||||
|  | ||||
|                     val iosPushTokens = pushTokenList["ios"] | ||||
|                     val aosPushToken = pushTokenList["aos"] | ||||
|  | ||||
|                     if (iosPushTokens != null) { | ||||
|                         for (tokens in iosPushTokens) { | ||||
|                             pushService.send( | ||||
|                                 tokens = tokens, | ||||
|                                 title = fcmEvent.title, | ||||
|                                 message = fcmEvent.message, | ||||
|                                 container = "ios", | ||||
|                                 creatorId = fcmEvent.creatorId | ||||
|                             ) | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (aosPushToken != null) { | ||||
|                         for (tokens in aosPushToken) { | ||||
|                             pushService.send( | ||||
|                                 tokens = tokens, | ||||
|                                 title = fcmEvent.title, | ||||
|                                 message = fcmEvent.message, | ||||
|                                 container = "aos", | ||||
|                                 creatorId = fcmEvent.creatorId | ||||
|                             ) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,8 @@ class FcmService { | ||||
|         container: String, | ||||
|         roomId: Long? = null, | ||||
|         messageId: Long? = null, | ||||
|         contentId: Long? = null | ||||
|         contentId: Long? = null, | ||||
|         creatorId: Long? = null | ||||
|     ) { | ||||
|         if (tokens.isNotEmpty()) { | ||||
|             logger.info("os: $container") | ||||
| @@ -52,6 +53,10 @@ class FcmService { | ||||
|                 multicastMessage.putData("content_id", contentId.toString()) | ||||
|             } | ||||
|  | ||||
|             if (creatorId != null) { | ||||
|                 multicastMessage.putData("channel_id", creatorId.toString()) | ||||
|             } | ||||
|  | ||||
|             val response = FirebaseMessaging.getInstance().sendEachForMulticast(multicastMessage.build()) | ||||
|             logger.info("보내기 성공: ${response.successCount}") | ||||
|             logger.info("보내기 실패: ${response.failureCount}") | ||||
|   | ||||
| @@ -40,6 +40,8 @@ interface MemberQueryRepository { | ||||
|     fun getIndividualRecipientPushTokens(recipients: List<Long>, isAuth: Boolean): Map<String, List<List<String>>> | ||||
|     fun getChangeNicknamePrice(memberId: Long): GetChangeNicknamePriceResponse | ||||
|     fun getMemberByEmail(email: String): Member? | ||||
|  | ||||
|     fun getChangeNoticeRecipientPushTokens(creatorId: Long): Map<String, List<List<String>>> | ||||
| } | ||||
|  | ||||
| @Repository | ||||
| @@ -244,4 +246,41 @@ class MemberQueryRepositoryImpl( | ||||
|             .where(member.email.eq(email)) | ||||
|             .fetchOne() | ||||
|     } | ||||
|  | ||||
|     override fun getChangeNoticeRecipientPushTokens(creatorId: Long): Map<String, List<List<String>>> { | ||||
|         val member = QMember.member | ||||
|         val creator = QMember.member | ||||
|  | ||||
|         val where = creatorFollowing.isActive.isTrue | ||||
|             .and(creatorFollowing.creator.id.eq(creatorId)) | ||||
|             .and(creatorFollowing.member.email.notIn("admin@sodalive.net")) | ||||
|             .and( | ||||
|                 creatorFollowing.member.id.notIn( | ||||
|                     blockMemberRepository.getBlockedMemberList(creatorId) | ||||
|                 ) | ||||
|             ) | ||||
|             .and(creatorFollowing.member.pushToken.isNotNull) | ||||
|  | ||||
|         val aosPushTokens = queryFactory | ||||
|             .select(creatorFollowing.member.pushToken) | ||||
|             .from(creatorFollowing) | ||||
|             .innerJoin(creatorFollowing.creator, creator) | ||||
|             .innerJoin(creatorFollowing.member, member) | ||||
|             .where(where.and(member.container.eq("aos"))) | ||||
|             .fetch() | ||||
|             .toSet() | ||||
|             .chunked(500) | ||||
|  | ||||
|         val iosPushTokens = queryFactory | ||||
|             .select(creatorFollowing.member.pushToken) | ||||
|             .from(creatorFollowing) | ||||
|             .innerJoin(creatorFollowing.creator, creator) | ||||
|             .innerJoin(creatorFollowing.member, member) | ||||
|             .where(where.and(member.container.eq("ios"))) | ||||
|             .fetch() | ||||
|             .toSet() | ||||
|             .chunked(500) | ||||
|  | ||||
|         return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens) | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user