[캡스톤] 기능 개발 - 알림 기능 - 로직2

이신행·2024년 6월 26일

capstone

목록 보기
11/15
post-thumbnail

이전 포스트의 내용

알림 기능 구분

송수진자의 역할에 따라 3가지의 알림으로 구분했습니다.

  1. 피보호자 → 보호자
    • 피보호자의 위치에 따라 자동으로 보호자에게 보내는 알림
    • 피보호자가 위험 상황에서 직접 보호자에게 보내는 알림
  2. 헬퍼 → 보호자
    • 헬퍼(주로 선생님)가 보호자에게 피보호자의 위치를 확인해주는 알림
  3. 보호자 → 주변 멤버
    • 보호자가 피보호자와 연락이 되지 않을 때, 피보호자의 주변 다른 멤버들에게 전송하는 알림

이 중에서 1번은 이전 포스트에 업로드했습니다.
2번부터 이번 포스트에서 이어집니다.

2. 헬퍼 → 보호자 (Confirm)

Confirm

학교나 학원 등의 보육 시설 선생님, 노인을 피보호자로 둘 경우 노인정 직원분들을 헬퍼로 설정할 수 있습니다.
헬퍼는 자신이 관리하는 피보호자의 [출발], [도착], [미확인](도착해야 하지만 확인되지 않는 경우)에 대한 알림을 보낼 수 있습니다.
단순히 알림을 보내는 로직이라 어렵지 않게 구현할 수 있습니다.

구현

가독성을 위해 일부 코드를 수정, 삭제했습니다. 코드 전문은 아래의 깃허브에서 확인하실 수 있습니다. (특히 optional null check 등의 예외 처리 + 알림을 저장하는 메서드)

Controller

@Transactional
@PostMapping("/send-confirm")
public ResponseEntity<Map<String, String>> sendConfirm(@RequestBody SendConfirmRequest dto) {
    Map<String, String> result = new HashMap<>();

    // 1. chidname 확인
    Child foundChild = memberService.findChildByChildName(dto.getChildName());
    Optional<Member> foundSender = memberRepository.findById(dto.getSenderId());
    // 2. 해당 child의 member에게 전송
    ArrayList<Member> foundMemberList = memberService.findAllParentByChild(foundChild);
    // helper가 helpinglist에 존재하는지 확인
    List<Helping> childHelpingList = foundChild.getHelpingList();

    boolean isSent = false;
    for (Helping helping : childHelpingList) {
        if(helping.getHelper().equals(foundSender.get())){
            // helper가 존재하면 confirm 전송
            isSent = sendConfirmToAllMember(foundMemberList, foundChild, helping, dto.getConfirmType());
        }
    }
    return addOkStatus(result);
}

@Transactional
public boolean sendConfirmToAllMember(ArrayList<Member> foundMemberList, Child foundChild, Helping helping, String confirmType) {
    for (Member member : foundMemberList) {
        if(! sendConfirmToMember(member, foundChild, helping, confirmType)){
            return false;
        }
    }
    return true;
}

@Transactional
public boolean sendConfirmToMember(Member receiverId, Child child, Helping helping, String confirmType) {
    Confirm confirm = confirmService.saveConfirm(receiverId, child, helping, confirmType);
    return confirmService.sendNotificationTo(receiverId.getMemberId(), confirm);
}

Service

public boolean sendNotificationTo(String receiverId, Confirm confirm){
    FCMNotificationDTO message = makeMessage(receiverId, confirm);
    return fcmService.SendNotificationByToken(message) != null;
}

3. 보호자 → 주변 멤버 (Emergency)

Emergency

피보호자가 확인되지 않을 때, 피보호자의 위치 주변에 있는 다른 멤버들에게 보호자가 보내는 알림입니다.
경찰청에서 실종 신고가 들어올때 보내는 안전 문자와 비슷한 개념으로 생각하시면 됩니다.
단순 알림 전송 아니라 알림을 보낼 사람(피보호자 주변 사람)을 찾는 로직을 필요로 하는 기능입니다.

구현

가독성을 위해 일부 코드를 수정, 삭제했습니다. 코드 전문은 아래의 깃허브에서 확인하실 수 있습니다. (특히 optional null check 등의 예외 처리 + 알림을 저장하는 메서드)

Controller

// 몇 km 이내의 사람들에게 알림을 보낼 것인지
static public final int DISTANCE = 1;

@Transactional
@PostMapping("/emergency")
public ResponseEntity<Map<String, String>> emergencyCall(@RequestBody EmergencyRequestDTO emergencyRequestDto) {
    Map<String, String> result = new HashMap<>();
    // 1. 반경 [] km내의 member들만 리스트업
    ArrayList<String> neighborMemberList
            = emergencyService.getNeighborMembers(emergencyRequestDto, DISTANCE);
    // 2. 반경 []km 내의 member 들에게 알림을 보냄
    if (! sendEmergencyToMembers(neighborMemberList, emergencyRequestDto)) {
        return addErrorStatus(result);
    }
    return addOkStatus(result);
}

@Transactional
public boolean sendEmergencyToMembers(ArrayList<String> neighborMemberList, EmergencyRequestDTO dto) {
    for (String memberId : neighborMemberList) {
        // 3. 알림을 전송 및 저장
        Emergency emergency = emergencyService.saveEmergency(memberId, dto);
        if (! emergencyService.sendNotificationTo(memberId, emergency)) {
            return false;
        }
    }
    return true;
}

Service

@Transactional
public boolean sendNotificationTo(String receiverId, Emergency emergency){
    FCMNotificationDTO message = makeMessage(receiverId, emergency);
    return fcmService.SendNotificationByToken(message) != null;
}

마무리

makeMessage 같은 기능은 모든 알림에 전반적으로 나타나는 메서드입니다.
이런 메서드를 AOP로 빼서 구현했다면 조금 더 수고를 덜었을 것이라 생각합니다.

추가적으로 Emergency 알림에 제보를 할 수 있도록 댓글 기능을 만들었습니다.
다음 포스트에서는 그에 대한 설명을 진행하도록 하겠습니다.

코드 깃허브

https://github.com/LeeShinHaeng/safeGuard

profile
언제나 Response 하는 Ability가 있는 서버를 만드는, Responsibility 있는 개발자가 되자

0개의 댓글