diff --git a/src/main/java/com/numberone/backend/domain/disaster/service/DisasterEventHandler.java b/src/main/java/com/numberone/backend/domain/disaster/service/DisasterEventHandler.java index 8bd9aece..056e2b02 100644 --- a/src/main/java/com/numberone/backend/domain/disaster/service/DisasterEventHandler.java +++ b/src/main/java/com/numberone/backend/domain/disaster/service/DisasterEventHandler.java @@ -34,16 +34,17 @@ public class DisasterEventHandler { private final NotificationRegionRepository notificationRegionRepository; private final NotificationDisasterRepository notificationDisasterRepository; - @Transactional(jakarta.transaction.Transactional.TxType.REQUIRES_NEW) @TransactionalEventListener - public void sendFcmMessagesByPresentLocation(DisasterEvent disasterEvent) { - log.info("[신규 재난 발생! Disaster event handler 가 동작합니다.]"); - log.info("[sendFcmMessagesByPresentLocation]"); - + public void sendFcmsPresentLocationAndOnboardingDisasterType(DisasterEvent disasterEvent) { + log.info(""" + [신규 재난 발생 이벤트 감지!] + 현재 재난 위치에 존재하면서, 발생한 재난 유형이 온보딩 때 선택한 재난 유형인 회원들에게 알림을 보냅니다. + 또한, 현재 재난위치에 존재하지는 않지만 온보딩을 통해 알림을 받고자 하는 지역 + 재난 유형이 발생한 경우에 대해서도 알림을 보냅니다. + 알람은 중복을 제거하여 발송됩니다. + """); String type = disasterEvent.getType().code2kor(); String disasterLocation = disasterEvent.getLocation(); - Long disasterNum = disasterEvent.getDisasterNum(); String title = String.format("[긴급] %s %s 발생", disasterLocation, type); String message = "대피로에 접속하여 행동요령을 확인하세요!"; @@ -56,8 +57,8 @@ public void sendFcmMessagesByPresentLocation(DisasterEvent disasterEvent) { memberId -> { List enableDisasterTypes = notificationDisasterRepository.findAllByMemberId(memberId) .stream().map(NotificationDisaster::getDisasterType).toList(); - return enableDisasterTypes.contains(disasterEvent.getType()); - }).map(memberId -> { + return enableDisasterTypes.contains(disasterEvent.getType()); + }).map(memberId -> { Member member = memberRepository.findById(memberId) .orElseThrow(NotFoundMemberException::new); NotificationEntity savedNotificationEntity = notificationRepository.save( @@ -80,8 +81,43 @@ public void sendFcmMessagesByPresentLocation(DisasterEvent disasterEvent) { log.info("현재 재난 위치에 있는, {} 재난 유형을 허용한 회원들에게 알림을 전송합니다.", type); fcmMessageProvider.sendFcmToMembers(fcmTokensByPresentLocationAndOnboardingDisasterType, title, message, NotificationTag.DISASTER); + // 온보딩때 선택한 지역에 대한 알림을 받고자 하는 회원 리스트를 필터링합니다. + // 이때 중복 알림 발송을 방지하기 위한 필터링 작업을 먼저 수행합니다. + List distinctMemberIdListByOnboardingRegions = memberRepository.findAll() + .stream().map(Member::getId) + .filter(id -> !memberIdListByPresentLocationAndOnboardingDisasterTypes.contains(id)) + .toList(); + log.info("회원이 재난문자 알림을 받고자 하는 지역에 대한 푸시알람을 중복을 제거하여 보냅니다."); + // 해당 회원의 온보딩 리스트 및 알림을 허용하는 재난 유형을 기준으로 알림을 보낸다. + List targetFcmsByOnboardingRegionsAndDisasterTypes = distinctMemberIdListByOnboardingRegions.stream() + .flatMap(memberId -> { + Member member = memberRepository.findById(memberId) + .orElseThrow(NotFoundMemberException::new); + boolean isMatched = notificationRegionRepository.findByMemberId(memberId) + .stream().anyMatch( + region -> region.getLocation().contains(disasterLocation) + ); + notificationRepository.save( + new NotificationEntity(member, disasterEvent.getType(), disasterEvent.getMessage(), true, disasterLocation) + ); + return isMatched ? Stream.of(member.getFcmToken()) : null; + }).filter(Objects::nonNull).toList(); + fcmMessageProvider.sendFcmToMembers(targetFcmsByOnboardingRegionsAndDisasterTypes, title, message, NotificationTag.DISASTER); + } + + @Transactional(jakarta.transaction.Transactional.TxType.REQUIRES_NEW) + @TransactionalEventListener + public void sendFcmToFriends(DisasterEvent disasterEvent) { + log.info(""" + [신규 재난 발생 이벤트 감지!] + 재난 지역에 위치하는 회원의 가족들에게 알림을 보냅니다! + """); + String disasterLocation = disasterEvent.getLocation(); + + // 현재 재난 위치에 있는 회원 아이디 리스트 + List memberIdListByOnlyPresentLocation = memberRepository.findAllByLocation(disasterLocation); log.info("위험 지역에 위치한 회원의 가족에게 알림을 보냅니다."); // 해당 회원의 가족에게 알림을 보낸다. String messageToFriend = ""; @@ -114,30 +150,6 @@ public void sendFcmMessagesByPresentLocation(DisasterEvent disasterEvent) { ); }); - // 온보딩때 선택한 지역에 대한 알림을 받고자 하는 회원 리스트를 필터링합니다. - // 이때 중복 알림 발송을 방지하기 위한 필터링 작업을 먼저 수행합니다. - List distinctMemberIdListByOnboardingRegions = memberRepository.findAll() - .stream().map(Member::getId) - .filter(id -> !memberIdListByPresentLocationAndOnboardingDisasterTypes.contains(id)) - .toList(); - - - log.info("회원이 재난문자 알림을 받고자 하는 지역에 대한 푸시알람을 중복을 제거하여 보냅니다."); - // 해당 회원의 온보딩 리스트 및 알림을 허용하는 재난 유형을 기준으로 알림을 보낸다. - List targetFcmsByOnboardingRegionsAndDisasterTypes = distinctMemberIdListByOnboardingRegions.stream() - .flatMap(memberId -> { - Member member = memberRepository.findById(memberId) - .orElseThrow(NotFoundMemberException::new); - boolean isMatched = notificationRegionRepository.findByMemberId(memberId) - .stream().anyMatch( - region -> region.getLocation().contains(disasterLocation) - ); - notificationRepository.save( - new NotificationEntity(member, disasterEvent.getType(), disasterEvent.getMessage(), true, disasterLocation) - ); - return isMatched ? Stream.of(member.getFcmToken()) : null; - }).filter(Objects::nonNull).toList(); - fcmMessageProvider.sendFcmToMembers(targetFcmsByOnboardingRegionsAndDisasterTypes, title, message, NotificationTag.DISASTER); - } + }