본문 바로가기
Spring Boot :

[FN] 신청서 상태 관리 API (신청서 승인, 거절, 취소)

by 밍코딩코 2025. 3. 28.

모임 신청과 신청서 조회는 모두 구현되었으니 이제 도착하거나 보낸 신청서의 상태를 관리하도록 구현해보자.

 

내가 신청한 신청서에 대해서는 "신청 취소, 닫기"와 같은 모달이 나타나야하고,

내 모임에 도착한 신청서에 대해서는 "신청 승인, 신청 거절, 닫기"와 같은 모달이 나타나야한다.

↑ 이 부분에 대해서는 프론트엔드 게시글에 정리 할 예정


백엔드에서 구현해야 할 기능

  1. Firestore database에 저장된 신청서의 상태를 변경하기
  2. 데이터베이스에서 취소, 거절된 신청서를 삭제하기
  3. 승인된 신청서는 모임(meetings) 컬렉션의 서브 컬렉션으로 맴버(members) 컬렉션에 신청자 정보 저장하기 + 마찬가지로 신청서(applications) 컬렉션에서는 신청서가 삭제되어야함
  4. 승인, 거절된 신청서에 대해서는 신청자에게 푸시 알림으로 신청서의 상태를 안내해줘야함

1. ApplicationController.java

REST API의 엔드 포인트를 정의할 ApplicationController.java를 생성

@RestController
@RequestMapping("/api/applications")
public class ApplicationController {

	private final ApplicationService applicationService;

    public ApplicationController(ApplicationService applicationService) {
        this.applicationService = applicationService;
    }

    @GetMapping("/{meetingId}/{applicationId}/status")
    public ResponseEntity<String> getApplicationStatus(
            @PathVariable String meetingId,
            @PathVariable String applicationId) {

        try {
            String status = applicationService.getApplicationStatus(meetingId, applicationId);
            return ResponseEntity.ok(status);
        } catch (ExecutionException | InterruptedException e) {
            return ResponseEntity.internalServerError().body("Error fetching status: " + e.getMessage());
        }
    }
  • meetingId와 applicationId를 받아서 요청을 처리함
  • ApplicationService의 getApplicationStatus 메서드를 호출하여 Firestore에서 신청서 상태를 조회함
  • ResponseEntity.ok(status) : 상태 조회 결과를 응답으로 반환
@PatchMapping("/{meetingId}/{applicationId}/status")
    public ResponseEntity<String> updateStatus(
            @PathVariable String meetingId,
            @PathVariable String applicationId,
            @RequestParam String status) {
  • Patch 요청으로 신청서의 상태를 변경하는 엔드포인트
  • status 값을 받아서 신청서의 상태를 변경한다.
@DeleteMapping("/{meetingId}/{applicationId}")
    public ResponseEntity<String> deleteApplication(
            @PathVariable String meetingId,
            @PathVariable String applicationId) {
  • Delete 요청으로 신청서를 삭제하는 엔트포인트

1. ApplicationService.java

Firebase와 상호작용하면서 실제 로직을 수행

@Service
public class ApplicationService {

    private final Firestore firestore;

    public ApplicationService(Firestore firestore) {
        this.firestore = firestore;
    }

    public String updateApplicationStatus(String meetingId, String applicationId, String status) throws ExecutionException, InterruptedException {
        DocumentReference docRef = firestore.collection("meetings")
                .document(meetingId)
                .collection("applications")
                .document(applicationId);

        docRef.update("status", status).get();
  • firestore.collection("meetings").document(meetingId)...  경로에 있는 Firestore 문서를 참조하여 해당 status값을 새 status값으로 업데이트
if ("approved".equals(status)) {
            moveApplicationToMembers(meetingId, applicationId);
        }
  • 만약 status가 approved 승인이라면 moveApplicationToMembers를 호출하여 신청서를 members 컬렉션으로 이동
public String getApplicationStatus(String meetingId, String applicationId) throws ExecutionException, InterruptedException {
    DocumentReference docRef = firestore.collection("meetings")
            .document(meetingId)
            .collection("applications")
            .document(applicationId);

    return docRef.get().get().getString("status");
  • Firestore에서 신청서 문서를 읽고, 그 안의 status 필드를 반환 (status 값 확인하기 위한)
public void deleteApplication(String meetingId, String applicationId) throws ExecutionException, InterruptedException {
    DocumentReference docRef = firestore.collection("meetings")
            .document(meetingId)
            .collection("applications")
            .document(applicationId);

    docRef.delete().get();
  • docRef.delete().get() : Firestore에서 해당 신청서 문서를 삭제
private void moveApplicationToMembers(String meetingId, String applicationId) throws ExecutionException, InterruptedException {
    DocumentReference applicationRef = firestore.collection("meetings")
            .document(meetingId)
            .collection("applications")
            .document(applicationId);

    DocumentSnapshot applicationSnapshot = applicationRef.get().get();
    if (!applicationSnapshot.exists()) {
        throw new RuntimeException("Application not found");
    }

    Map<String, Object> applicationData = applicationSnapshot.getData();
    if (applicationData == null) {
        throw new RuntimeException("Application data is null");
    }

    DocumentReference memberRef = firestore.collection("meetings")
            .document(meetingId)
            .collection("members")
            .document(applicationId);

    memberRef.set(applicationData).get();

    applicationRef.delete().get();
}
  • applicationRef.get().get() : 신청서 문서를 가져옴
  • if (!applicationSnapshot.exists()) : 신청서가 존재하지 않으면 예외 발생
  • Map<String, Object> applicationData = applicationSnapshot.getData(); : 신청서의 데이터를 Map 형태로 가져옴
  • memberRef.set(applicationData).get() : members 컬렉션에 해당 신청서 데이터를 저장
  • applicationRef.delete().get() : applications 컬렉션에서 해당 신청서를 삭제

 

구현 화면

 

도착한 신청서를 승인하면 정상적으로 모임 컬렉션의 서브 컬렉션으로 맴버 컬렉션이 생기고 신청자의 정보가 저장된다.

신청서를 취소, 거절하면 모임 컬렉션에 해당 신청서가 삭제되는 것도 구현 완료 

 

신청서 확인하는 페이지에 신청서 리스트 업데이트와 내 모임 페이지에서 가입된 모임을 출력하는 등 추가적인 내용은

다음 게시글에 정리하겠슴