예약 관리 | 예약 취소 API 구현

Faithful Dev·2025년 3월 15일

매장 예약 서비스

목록 보기
10/15

구현한 기능

  • 사용자가 본인의 예약을 취소할 수 있는 API
  • 파트너(점장)가 매장의 예약을 취소할 수 있는 API
  • 예약 취소 시 상태를 CANCELLED로 변경하는 로직
  • 적절한 권한 체크(본인 예약 또는 파트너 소유 매장의 예약만 취소 가능)
  • 이미 취소되었거나 방문 확인/완료된 예약은 취소할 수 없도록 제한

코드 스냅샷

ReservationService.java

/**
 * 예약 취소 메서드
 *
 * @param reservationId 예약 ID
 * @param actorId 액터 ID (사용자 또는 파트너)
 * @param isPartner 파트너 여부
 * @return 취소된 예약 정보
 */
@Transactional
public ReservationDto.ReservationInfoResponse cancelReservation(Long reservationId, Long actorId, boolean isPartner) {
    Reservation reservation = reservationRepository.findById(reservationId)
            .orElseThrow(() -> new CustomException(ErrorCode.RESERVATION_NOT_FOUND));
    
    // 예약 취소 권한 확인
    validateCancellationPermission(reservation, actorId, isPartner);
    
    // 이미 취소된 예약인지 확인
    if (reservation.getStatus() == ReservationStatus.CANCELLED) {
        throw new CustomException(ErrorCode.INVALID_REQUEST, "이미 취소된 예약입니다.");
    }
    
    // 이미 도착 확인되었거나 완료된 예약인지 확인
    if (reservation.getStatus() == ReservationStatus.ARRIVED || 
        reservation.getStatus() == ReservationStatus.COMPLETED) {
        throw new CustomException(ErrorCode.RESERVATION_NOT_ALLOWED, "이미 방문 확인되었거나 완료된 예약은 취소할 수 없습니다.");
    }
    
    // 예약 상태를 취소로 변경
    reservation.setStatus(ReservationStatus.CANCELLED);
    Reservation cancelledReservation = reservationRepository.save(reservation);
    
    return converToReservationInfoResponse(cancelledReservation);
}

ReservationController.java

/**
 * 예약 취소 API
 * 사용자 또는 파트너(점장)가 예약을 취소
 *
 * @param reservationId 예약 ID
 * @return 취소된 예약 정보 응답
 */
@PatchMapping("/{reservationId}/cancel")
public ResponseEntity<ApiResponse<ReservationDto.ReservationInfoResponse>> cancelReservation(
        @PathVariable Long reservationId
) {
    String currentUserEmail = authenticationUtil.getCurrentUserEmail();
    Long currentUserId = authenticationUtil.getCurrentUserId();
    
    // 파트너 여부 확인
    Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext()
            .getAuthentication().getAuthorities();
    boolean isPartner = authorities.stream()
            .anyMatch(auth -> auth.getAuthority().equals("ROLE_PARTNER"));
    
    ReservationDto.ReservationInfoResponse response = 
            reservationService.cancelReservation(reservationId, currentUserId, isPartner);
    
    return ResponseEntity.ok(ApiResponse.success("예약이 성공적으로 취소되었습니다.", response));
}

Postman 테스트


구현 예정

  • 도착 확인 API(키오스크 연동)
  • 도착 상태 업데이트 API(예약 상태 변경)
profile
Turning Vision into Reality.

0개의 댓글