호텔 예약 프로그램(2)

2023. 10. 26. 19:35Java/project

호텔 예약 프로그램
  • System.out.println()형태로 호텔 예약 프로그램을 만듭니다.
  • UUID, LocalDateTime 사용
  • 블랙리스트 패턴을 사용한 정규 표현식 사용

 

 맡은 역할 : 예약 프로세스

   1. ViewManagement.java

       - 아직 출력화면과 메서드들을 ViewManagement.java에서 관리하고 있음.

       - makeReservation(selectDate) // 날짜 입력 로직

       - checkRoom(selectNumber, selectDate) // room확인 및 예약 진행 로직

       - reservationOrCancel(finalCheck) // 해당 사항을 최종적으로 묻는 로직

       - hotel.checkCustomerName(customerName, selectRoomNumber) // 예약자 이름 로직

       - makeReservation(selectDate) // 날짜 입력 로직

       - checkBlackPhoneNumber(customerPhoneNumber) // 예약자가 블랙리스트인지 확인 로직

       - hotel.checkMoney(customerMoney, selectRoomPrice, selectDate) // 고객의 돈과 룸 예약 돈의 비교 로직

       - 해당 메서드들은 switch문에서 관리하고 있으며 추후 변경예정

package com.nbc.hotel.model;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Scanner;

import com.nbc.hotel.util.RoomNumberInvalidException;

public class ViewManagement {
    private static final Scanner sc = new Scanner(System.in);
    
    private Hotel hotel;
 
    private int roomNumber = 1;
    
    public ViewManagement() {
    	
    }
    
    public ViewManagement(Hotel hotel) {
        this.hotel = hotel;  // 생성자를 통해 Hotel 객체를 주입받음
    }
    
    public void setHotel(Hotel hotel) {
        this.hotel = hotel;
    }
    
    // role : admin, user처리는 팀원과 상의 후 처리 예정
    public void test() {
    	try {
    		System.out.println("호텔을 예약하시겠습니까? ");
        	System.out.println("1. 예약 2. 취소 3. 조회");
        	int select = sc.nextInt();
        	switch(select) {
        	case 1:
        		// 입력단 예외 상황 해결을 위해 makeReservation()으로 옮김
        		System.out.println("날짜를 입력해주세요 : ");
        		String selectDate = sc.next();
            	makeReservation(selectDate);
            	// 날짜 입력 로직 
            	
            	System.out.println("============================");
            	System.out.println("선택하고 싶은 방을 골라주세요 : ");
            	int selectRoomNumber = sc.nextInt();
            	checkRoom(selectRoomNumber, selectDate);
            	// room 확인 및 예약 진행 로직
            	
            	System.out.println("=====1. 예약하기 2. 취소하기=====");
            	int finalCheck = sc.nextInt();
            	reservationOrCancel(finalCheck);
            	// 해당 사항으로 최종확인 여부를 물음
            	
            	System.out.println("예약자 성함을 알려주세요 : ");
            	String customerName = sc.next();
            	hotel.checkCustomerName(customerName, selectRoomNumber);
            	// 예약자 이름 확인 로직
            	
            	System.out.println("예약자 전화번호를 입력해주세요 : (010-****-****만 가능)");
        		String customerPhoneNumber = sc.next();
            	boolean checkBlackList = hotel.checkBlackListPhoneNumber(customerPhoneNumber);

            	if(checkBlackList) {
            		// 예약자가 블랙리스트인 사용자
            		break;
            	}else {
            		// 예약자가 블랙리스트 아닌 사용자
                	System.out.println(customerName+"님의 소지 금액을 입력해주세요 : ");
            		double customerMoney = sc.nextLong();
            		double selectRoomPrice = hotel.getRooms().get(selectRoomNumber-1).getPrice();
            		hotel.checkMoney(customerMoney, selectRoomPrice, selectDate);
            		// 돈 확인
            	}
            	// 블랙리스트 조회 및 돈 확인 
        		break;
        	case 2:
        		// 예약 조회
        		break;
        	case 3:
        		// 예약 취소
        		break;
        	default :
        		System.out.println("잘못된 입력입니다. 다시 시도해주세요");
        		break;
        	}
    	}catch(Exception e) {
    		e.printStackTrace();
    	}
    }
    
    public void makeReservation(String selectDate) {
    	try {
            // selectDate의 유효성을 검사합니다.
            if (!isValidDate(selectDate)) {
                // 만약 날짜를 파싱해서 제대로된 yyyy-MM-dd가 들어가지 않을때
                throw new IllegalArgumentException("유효하지 않은 날짜 형식입니다.");
            }
        } catch (IllegalArgumentException e) {
            System.out.println("예외 발생: " + e.getMessage());
            System.out.println("=========다시 실행합니다=========");
            test();
        }
    	System.out.println("============================");
    	System.out.println("해당 날짜 : "+ selectDate+" 방 예약");
    	System.out.println("============================");
    	roomNumber = 1;
    	 
    	hotel.getRooms().stream().forEach((room)-> {
    	    int roomSize = room.getSize().intValue();
    	    System.out.println(roomNumber + ". " + "size: " + roomSize + " price: $" + room.getPrice());
    	    roomNumber++;
    	});
    }
    
    private boolean isValidDate(String selectDate) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        // 날짜 검사 결과를 저장할 변수입니다.
        dateFormat.setLenient(false);
        // yyyy-MM-dd형식에 맞는지
        try {
            Date parsedDate = dateFormat.parse(selectDate);
            // 입력된 날짜를 LocalDate로 변환
            LocalDate selectedDate = LocalDate.parse(selectDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            // 현재 날짜와 비교
            LocalDate currentDate = LocalDate.now();
            // 입력된 날짜가 현재 날짜 이전이면 유효하지 않음
            if (selectedDate.isBefore(currentDate)) {
                return false;
            }

            return true;
        } catch (ParseException e) {
            return false;
        }
    }
    
    public void checkRoom(int selectRoomNumber, String selectDate) {
        try {
            if (selectRoomNumber < 1 || selectRoomNumber > hotel.getRooms().size()) {
                throw new RoomNumberInvalidException("잘못된 방 번호입니다.");
            }

            Integer selectRoomSize = hotel.getRooms().get(selectRoomNumber - 1).getSize().intValue();
            Double selectRoomPrice = hotel.getRooms().get(selectRoomNumber - 1).getPrice();
            System.out.println("=========" + selectDate + "=========");
            System.out.println(selectRoomNumber + ". size : " + selectRoomSize + " price : $" + selectRoomPrice);
        } catch (RoomNumberInvalidException e) {
            System.out.println("예외 발생: " + e.getMessage());
            System.out.println("예약 페이지로 다시 돌아갑니다.");
            System.out.println("============================");
            test();
        }
    }


    
    public void reservationOrCancel(int finalCheck) {
    	switch(finalCheck) {
		case 1:
			return;
		case 2:
			System.out.println("예약을 취소하셨습니다.");
			System.out.println("예약 페이지로 다시 돌아갑니다.");
            System.out.println("============================");
            test();
			break;
		default : 
			System.out.println("잘못된 입력을 하여 예약 페이지로 다시 돌아갑니다.");
            System.out.println("============================");
            test();
			break;
		}
    }
}

 

  2. Reservation.java

       - LocalDate reservationDate // 예약 날짜

       - LocalDateTime reservationDate2 // 예약 당

       - hasMoney(Customer customer, double selectRoomPrice) 고객의 돈이 방 예약 가격 비교 로직

         finalReservation(String selectDate, List <Reservation> reservations) // 예약 정보를 getter, setter를 통해 저장

       - receipt() // 해당 예약 상황 출력

package com.nbc.hotel.model;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

public class Reservation {
	private UUID uuid;
	private Room room;
	private String customerName;
	private String customerPhoneNumber;
	private LocalDate reservationDate;
	private LocalDateTime reservationDate2;
	
	public Reservation() {
		
	}
	
	public Reservation(UUID uuid, Room room, String customerName, String customerPhoneNumber, LocalDate reservationDate, LocalDateTime reservationDate2) {
		this.uuid = uuid;
		this.room = room;
		this.customerName = customerName;
		this.customerPhoneNumber = customerPhoneNumber;
		this.reservationDate = reservationDate;
		this.reservationDate2 = reservationDate2;
	}
	
	public UUID getUUID() {
		return this.uuid;
	}
	
	public void setUUID(UUID uuid) {
		this.uuid = uuid;
	}
	
	
	public Room getRoom() {
		return this.room;
	}
	
	public void setRoom(Room room) {
		this.room = room;
	}
	
	public String getCustomerName() {
		return this.customerName;
	}
	
	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getCustomerPhoneNumber() {
		return this.customerPhoneNumber;
	}
	
	public void setCustomerPhoneNumber(String customerPhoneNumber) {
		this.customerPhoneNumber = customerPhoneNumber;
	}
	public LocalDate getReservationDate() {
		return this.reservationDate;
	}
	
	public void setReservationDate(LocalDate reservationDate) {
		this.reservationDate = reservationDate;
	}
	
	public LocalDateTime getReservationDate2() {
		return this.reservationDate2;
	}
	
	public void setReservationDate2(LocalDateTime reservationDate2) {
		this.reservationDate2 = reservationDate2;
	}
	
	public void finalReservation(String selectDate, List<Reservation> reservations) {
		System.out.println(getCustomerName()+"님 예약 완료되셨습니다.");
		System.out.println(getCustomerName()+"님 예약 번호는"+getUUID()+"입니다.");
		LocalDate testTime = reservationDate(selectDate);
		setReservationDate(testTime);
		
		LocalDateTime localTime = LocalDateTime.now();
		setReservationDate2(localTime);
		reservationListSave(reservations);
		receipt();
		// 예약 완료
	}
	
    public LocalDate reservationDate(String selectDate) {
    	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    	LocalDate ld = LocalDate.parse(selectDate, formatter);
    	// 원하는 값은 여기까지 잘됨
        // LocalDateTime dateTime = LocalDateTime.of(ld, LocalTime.now());
        // t~~~까지 붙히고 있다.
        return ld;
        // localDate
    }
    
    public boolean hasMoney(Customer customer, double selectRoomPrice) {
    	boolean isTrue = true;
    	if(customer.getMoney() < selectRoomPrice) {
    		System.out.println(customer.getName()+"님의 금액이 부족합니다.");
    		isTrue = false;
    		// 고객이 가진 금액이 적음
    	}
    	return isTrue;
    	// 고객이 가진 금액이 더 많거나 같음
    }
    
    public void reservationListSave(List<Reservation> reservations) {
    	reservations.add(this);
    	// 현재 저장된 객체를 add
    	/*reservations.stream().forEach((reservation)-> {
    		System.out.println(
    				"현재 예약 목록 테스트 : "
    				+reservation.getCustomerName()
    				+" "
    				+reservation.getCustomerPhoneNumber());
    	});*/
    	String test = receipt();
    	System.out.println(test);
    }
    
    public String receipt() {
        StringBuilder receipt = new StringBuilder();
        
        receipt.append("=============receipt=============");
        receipt.append("\nname : ").append(getCustomerName());
        receipt.append("\nphoneNumber : ").append(getCustomerPhoneNumber());
        receipt.append("\nReservation Date : ").append(getReservationDate());
        receipt.append("\nReservation Day : ").append(getReservationDate2());
        receipt.append("\nreservationUUID : ").append(getUUID());
        receipt.append("\nreservationPrice : ").append(getRoom().getPrice());
        receipt.append("\nroomSize : ").append(getRoom().getSize());
        receipt.append("\n================================");
        
        return receipt.toString();
    }

}

 

   3. Room.java

     - 변경점 없음

package com.nbc.hotel.model;

import java.util.List;
import java.util.UUID;

public class Room {
	Double size;
	Double price;
	
	List<Reservation> reservations;
	
	public Room(Double size, Double price) {
		this.size = size;
		this.price = price;
	}
	
	public Double getSize() {
		return this.size;
	}
	
	public Double getPrice() {
		return this.price;
	}
	
	public void addReservation() {
		
	}
	
	public void removeReservation(UUID uuid) {
		
	}
}

 

  4. Customer.java

     - 변경점 없음

package com.nbc.hotel.model;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class Customer {

	private Role role;
	private String name;
	private String phoneNumber;
	private Double money;
	private List<UUID> reservationIds = new ArrayList<>();;
	
	public Customer() {

	}
	
	public Customer(Role role, String name, String phoneNumber, Double money, List<UUID> reservationIds) {
		this.role = role;
		this.name = name;
		this.phoneNumber = phoneNumber;
		this.money = money;
		this.reservationIds = reservationIds;
	}
	
	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public Double getMoney() {
		return money;
	}

	public void setMoney(Double money) {
		this.money = money;
	}

	public List<UUID> getReservationIds() {
		return reservationIds;
	}

	public void setReservationIds(List<UUID> reservationIds) {
		this.reservationIds = reservationIds;
	}

	public void addReservationId(UUID uuid) {
	    this.reservationIds.add(uuid);
	}
}

 

 

   5. Hotel.java

     - 블랙리스트 패턴 추가

     - checkBlackListPhoneNumber() // ViewManagement.java에서 설명과 같음

     - checkCustomerName() // 예약자의 이름에 특수문자와 같은 이상한 정규표현이 있는지 확인 로직

     - checkMoeny() // ViewManagement.java에서 설명과 같음

package com.nbc.hotel.model;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Hotel {
	private List<Room> rooms = new ArrayList<>();				
    // 현재 방목록
	private List<Reservation> reservations = new ArrayList<>();	
    // 현재 예약목록
	private Double money;										
    // 총자산
	
	private int roomNumber = 1;
	
	Reservation reservation = new Reservation();
	Customer customer = new Customer();
	
	private ViewManagement viewManagement;
	
	private final String BLACKLISTPHONENUMBER_PATTERN = "010-2222-\\d+";
    private Pattern blacklistPattern = Pattern.compile(BLACKLISTPHONENUMBER_PATTERN);
    // 010-2222에 해당하는 모든 숫자조합은 블랙리스트패턴에 걸려서 호텔 서비스를 활용 불가합니다.
    
	public Hotel() {
		rooms.add(new Room(1.0,90.0));
		rooms.add(new Room(1.0,110.0));
		rooms.add(new Room(1.0,130.0));
		rooms.add(new Room(1.0,190.0));
		
		rooms.add(new Room(2.0,140.0));
		rooms.add(new Room(2.0,160.0));
		rooms.add(new Room(2.0,200.0));
		rooms.add(new Room(2.0,220.0));
	}
	
	public Hotel(ViewManagement viewManagement) {
		this.viewManagement = viewManagement;
	}
	
	public void setViewManagement(ViewManagement viewManagement) {
		this.viewManagement = viewManagement;
	}
	
	
	public List<Room> getRooms(){
		return this.rooms;
	}
	
	public List<Reservation> getReservations() {
		return reservations;
	}

	public void setReservations(List<Reservation> reservations) {
		this.reservations = reservations;
	}

	UUID reservation(String customerName, String customerPhoneNumber) {
		return null;
	}
	
	List<Reservation> findAllReservations(){
		return null;
	}
	
	Reservation findReservationByUUID(UUID uuid) {
		return null;
	}
	
	List<Reservation> findReservationsByUUIDs(List<UUID> uuids){
		return null;
	}
	
	// 예약 처리 프로세스
	
	public void checkCustomerName(String customerName, int selectRoomNumber) {
		try {
	        // System.out.println("name: " + customerName);
			// test
	        if (!customerName.matches("^[a-zA-Z가-힣\\s]*$")) {
	            throw new IllegalArgumentException("예약자 이름은 특수 문자를 포함해서는 안 됩니다.");
	        }
	        
	        UUID uuid = UUID.randomUUID();
	        reservation.setUUID(uuid);
	        customer.addReservationId(uuid);
	        // 예약 번호 설정
	        customer.setName(customerName);
	        // 예약자 이름 설정
	        reservation.setRoom(getRooms().get(selectRoomNumber - 1));
	        // 예약 리스트 room 설정
	        reservation.setCustomerName(customerName);
	        // 예약자 이름 설정
	    } catch (IllegalArgumentException e) {
	        System.out.println("예외 발생: " + e.getMessage());
	        System.out.println("예약 페이지로 다시 돌아갑니다.");
            System.out.println("============================");
            viewManagement.test();
            return;
	    }
	}
	
	public boolean checkBlackListPhoneNumber(String customerPhoneNumber) {
	    boolean isBlackList = false;

	    try {
	    	String regex = "^010-[0-9]{4}-[0-9]{4}$";
	    	// 숫자와 하이픈만을 허용하는 정규표현식
	        Matcher matcher = Pattern.compile(regex).matcher(customerPhoneNumber);

	        if (!matcher.matches()) {
	            throw new IllegalArgumentException("올바른 전화번호 형식이 아닙니다. 다시 시도해주세요!");
	        } else if (blacklistPattern.matcher(customerPhoneNumber).matches()) {
	            throw new IllegalArgumentException("해당 사용자는 블랙리스트인 사용자입니다.");
	        } else {
	            customer.setPhoneNumber(customerPhoneNumber);
	            reservation.setCustomerPhoneNumber(customerPhoneNumber);
	            isBlackList = false;
	        }
	    } catch (IllegalArgumentException e) {
	        System.out.println("예외 발생: " + e.getMessage());
	        // 예외 처리 로직 추가
	        isBlackList = true;
	    }
	    return isBlackList;
	}

	public boolean checkMoney(double customerMoney, double selectRoomPrice, String selectDate) {
		customer.setMoney(customerMoney);
		boolean myAnswer = reservation.hasMoney(customer, selectRoomPrice);
		
		if(myAnswer) {
			// 고객의 돈이 호텔 룸 예약 가격보다 더 많을때
    		reservation.finalReservation(selectDate, reservations);
		}
		return true;
	}
}

 

-예약 화면 예시

호텔을 예약하시겠습니까? 
1. 예약 2. 취소 3. 조회
1
날짜를 입력해주세요 : 
2023-11-23
============================
해당 날짜 : 2023-11-23 방 예약
============================
1. size: 1 price: $90.0
2. size: 1 price: $110.0
3. size: 1 price: $130.0
4. size: 1 price: $190.0
5. size: 2 price: $140.0
6. size: 2 price: $160.0
7. size: 2 price: $200.0
8. size: 2 price: $220.0
============================
선택하고 싶은 방을 골라주세요 : 
5
======해당 방이 맞으십니까?======
=========2023-11-23=========
5. size : 2 price : $140.0
=====1. 예약하기 2. 취소하기=====
1
예약자 성함을 알려주세요 : 
papa
예약자 전화번호를 입력해주세요 : 
010-2222-3333
papa님 예약 완료되셨습니다.
papa님 예약 번호는 1입니다.
================================
name : papa
phoneNumber : 010-2222-3333
reservationId : 1
reservationDate : 2023-11-23
reservationDate2 : 2023-11-23
reservationUUID : f3d268a8-d64b-45cd-b8ad-46704659b489
reservationPrice : 140.0
roomSize : 2.0
================================

 

예약 선택 화면

 

예약 조회 메뉴 화면

객실 예약 조회
1. 모든 예약 조회(관리자 기능)
2.  예약 목록 조회
3. 예약 번호로 조회
4. 돌아가기

모든 예약을 조회합니다.
   [예약 정보]
예약 ID: 1234 방:  예약자 이름: 김진훈 휴대폰 번호: 010-1234-5678 예약 일자: 2023-11-11 

 예약 목록을 조회합니다.
   [예약 정보]
~~~ 위와 동일

예약 번호로 조회합니다.
   [예약 정보]
   위와 동일
    or 예약 번호로 조회할  없습니다.

- 예약 취소 예시

예약 취소 선택 메뉴 화면

객실 예약 취소  

취소할 객실의 예약 번호를 입력해주세요.
입력>   
0. 돌아가기
   

예약 취소 완료 화면

객실 에약이 취소 되었습니다.

객실 예약 취소  
객실 정보:
     객실명 :
     금액   :

3초 뒤 메인 화면으로 돌아갑니다....

예약 취소 실패 화면

 

객실 에약 취소가 실패하였습니다.
(이유?)

 

내일 할 일

   

   1. 팀원들과 코드 머지
   2. 해당사항 객체지향적 디자인으로 바꾸기

   3. 해당 코드 메서드 test(), receipt()와 같은 메서드 적절하게 변경

 

'Java > project' 카테고리의 다른 글