사이먼's 코딩노트

[Java] 호텔 예약 관리 프로그램 제작(17) 본문

프로젝트/[Java] 호텔 예약 관리 프로그램 제작

[Java] 호텔 예약 관리 프로그램 제작(17)

simonpark817 2024. 4. 18. 17:34

[호텔 예약 관리 프로그램 제작]

 

GitHub - psm817/hotel_booking_proj

Contribute to psm817/hotel_booking_proj development by creating an account on GitHub.

github.com

 

[리뷰 작성 구현]

  • 이번에는 리뷰와 관련된 새로운 기능을 추가하려한다.
  • 리뷰는 호텔 숙박을 마친 회원에 한해서만 작성 가능하고, 프로그램에 방문한 사람들은 작성된 모든 리뷰를 볼 수 있다.
  • 먼저 리뷰와 관련된 데이터들을 정의하기 위해 Review.java 클래스를 새로 생성한다.
package org.example.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.util.Map;

@Getter
@Setter
@AllArgsConstructor
public class Review extends Dto {
    public String regDate;
    public int bookingId;
    public int guestId;
    public String body;
    public double score;

    public Review(Map<String, Object> row) {
        super(row);
        this.regDate = (String) row.get("regDate");
        this.bookingId = (int) row.get("bookingId");
        this.guestId = (int) row.get("guestId");
        this.body = (String) row.get("body");
        this.score = (double) row.get("score");
    }
}
  • 프로그램 내에서 선언된 Review 관련 데이터 변수들은 반드시 DB에서도 테이블을 생성하여 컬럼을 추가해야한다.
  • Review의 정보는 등록날짜, 예약번호, 회원번호, 내용, 평점이 포함된다.
  • 여기서 주의할 점은 평점은 최대 소수 첫번째 자리 숫자까지 작성할 수 있기 때문에 int가 아닌 double 타입으로 선언해야한다.

 

  • 다음으로는 Review와 관련된 모든 기능을 수행하는 ReviewController, ReviewService, ReviewDao를 순서대로 구현해야한다.
  • 먼저 review와 관련된 서비스 명령어가 추가되었기 때문에 App에서 해당 서비스를 구분하고 ReviewController와 연결되는 코드를 추가해야한다.
if(controllerName.equals("hotel")) {
    controller = hotelController;
}
else if(controllerName.equals("room")) {
    controller = roomController;
}
else if(controllerName.equals("booking")) {
    controller = bookingController;
}
else if(controllerName.equals("guest")) {
    controller = guestController;
}
else if(controllerName.equals("review")) {
    controller = reviewController;
}
  • 서비스 이름으로 구분 짓는 부분에서 controllerName.equals("review")를 조건문에 추가하여 사용자가 review로 시작되는 서비스를 입력했을 때 해당 컨트롤러로 연결되도록 한다.

 

  • 다음은 리뷰 작성(review write)과 관련된 기능을 구현하기 위해 ReviewController에 코드를 작성한다.
package org.example.controller;

import org.example.container.Container;
import org.example.dto.Booking;
import org.example.dto.Guest;
import org.example.dto.Review;
import org.example.service.BookingService;
import org.example.service.GuestService;
import org.example.service.ReviewService;
import org.example.util.Util;

import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;

public class ReviewController extends Controller{
    private Scanner sc;
    private ReviewService reviewService;
    private GuestService guestService;
    private BookingService bookingService;
    private Session session;

    public ReviewController() {
        sc = new Scanner(System.in);
        reviewService = Container.reviewService;
        guestService = Container.guestService;
        bookingService = Container.bookingService;
        session = Container.getSession();
    }

    public void doAction(String cmd, String actionMethodName) {
        switch(actionMethodName) {
            case "write" :
                doWriteReview();
                break;
            default :
                System.out.println("존재하지 않는 서비스입니다.");
                break;
        }
    }

    public void doWriteReview() {
        // 로그인 된 게스트 가져오기
        Guest loginedGuest = session.getLoginedGuest();

        // 오늘 날짜로 체크아웃이 지난 booking 가져오기 (후기 작성한 예약목록 가져오기)
        List<Booking> forBookingAbleReview = bookingService.getBookingsAbleReview(loginedGuest.name, Util.getTodayDate());

        int foundBookingCount = forBookingAbleReview.size();
        System.out.printf("[%s]님, 총 [%d]건에 대해 리뷰 작성이 가능합니다.\n", loginedGuest.name, foundBookingCount);

        if(foundBookingCount == 0) {
            System.out.println("리뷰 작성할 객실이 없습니다.");
        }

        else {
            System.out.printf("================== [%s]님 숙박 이력 ==================\n", loginedGuest.name);
            System.out.printf("** 오늘 날짜 : %s **\n", Util.getTodayDate());
            System.out.println("예약번호 | 객실 | 체크인날짜 | 체크아웃날짜");

            // 예약한 목록 출력
            for(int i = 0; i < forBookingAbleReview.size(); i++) {
                Booking bookingByGuest = forBookingAbleReview.get(i);

                System.out.printf("    %4d |  %d | %4s |  %4s\n", bookingByGuest.id, bookingByGuest.roomId, bookingByGuest.checkInDate, bookingByGuest.checkOutDate);
            }

            System.out.println("==========================================================");

            while(true) {
                System.out.print("리뷰를 작성하시겠습니까?) ");
                String answer = sc.nextLine();

                if(answer.equals("yes")) {
                    while(true) {
                        System.out.print("작성하고 싶은 예약번호 입력(숫자만) : ");
                        int answerId = sc.nextInt();
                        sc.nextLine();

                        try {
                            // 예약번호에 따른 booking 가져오기
                            Booking forPrintBooking = bookingService.getForPrintBooking(answerId);

                            if(forPrintBooking.guestName.equals(loginedGuest.name)) {
                                while(true) {
                                    System.out.println("** 평점은 총 5점 만점 중 소수점 첫째자리까지 입력 가능 **");
                                    System.out.print("평점 입력) ");
                                    double score = sc.nextDouble();
                                    sc.nextLine();

                                    // 소수 첫째자리 체크
                                    if(score != Math.round(score * 10) / 10.0) {
                                        System.out.println("평점은 소수점 첫째짜리까지만 입력이 가능합니다.");
                                        continue;
                                    }
                                    else if(score > 5) {
                                        System.out.println("평점은 최대 5점 만점입니다.");
                                        continue;
                                    }
                                    else {
                                        System.out.print("리뷰 작성) ");
                                        String reviewBody = sc.nextLine();

                                        reviewService.doWrite(answerId, loginedGuest.id, reviewBody, score);
                                        System.out.println("리뷰가 등록되었습니다!!");
                                        break;
                                    }
                                }

                                break;
                            }
                            // 만약 게스트 이름이 같지 않다면
                            else {
                                System.out.printf("입력하신 예약번호는 [%s]님의 예약 건이 아닙니다.\n", loginedGuest.name);
                                continue;
                            }

                        } catch (NullPointerException | InputMismatchException e) {
                            System.out.println("예약번호를 잘못 입력하셨습니다.");
                            continue;
                        }
                    }

                    break;
                }

                else if(answer.equals("no")) {
                    System.out.println("리뷰 작성을 중단합니다.");
                    break;
                }

                else {
                    System.out.println("\'yes\' 또는 \'no\'를 입력해주세요");
                    continue;
                }
            }
        }
    }
}
  • App에서 reviewController와 연결되면 doAction을 통해 write 명령어를 받아 doWriteReview() 메서드를 호출하도록 한다.
  • 리뷰 작성은 로그인이 되어있는 상태에서만 가능하기 때문에 loginedGuest를 session을 통해 가져와야 하고, 해당 회원이 호텔에서 숙박한 기록이 있는지를 먼저 보여준다.
  • 이 때, 아직 숙박이 예정이거나 현재(오늘) 날짜를 기준으로 숙박을 진행 중인 케이스는 제외하고, 체크아웃 날짜가 지난 예약 건에 대해서만 리뷰가 작성이 가능하다.
  • [List<Booking> forBookingAbleReview = bookingService.getBookingAbleReview(loginedGuest.name, Util.getTodayDate());] 코드를 통해 리뷰 작성이 가능한 예약 목록을 가져온다.
  • 만약 리뷰 작성 가능한 예약 목록이 1건 이상이라면 예약 목록들을 보여주고 예약번호를 통해 리뷰 작성이 가능하다.
  • 예약번호를 통한 예약 건을 bookingService.getForPrintBooking(answerId)로 조회하고, 평점과 리뷰 내용을 작성한다.
  • 평점은 최대 5점 만점이며, 5점을 초과하거나 0점 미만이거나 소수점 첫째자리를 넘어서면 평점을 다시 입력하라고 안내한다.
  • 마지막으로 리뷰 내용까지 모두 작성했다면 [reviewService.doWrite(answerId, loginedGuest.id, reviewBody, score);] 코드를 통해 reviews List에 해당 리뷰 정보를 저장한다. 

 

  • 다음은 ReviewService.java 클래스를 추가하고 새로 작성한 코드이다.
package org.example.service;

import org.example.container.Container;
import org.example.dao.ReviewDao;
import org.example.dto.Review;

import java.util.List;

public class ReviewService {
    private ReviewDao reviewDao;

    public ReviewService() {
        reviewDao = Container.reviewDao;
    }

    public int doWrite(int answerId, int guestId, String reviewBody, double score) {
        return reviewDao.doWrite(answerId, guestId, reviewBody, score);
    }
}
  • ReviewService.java 에서는 reviewDao와 연결되는 생성자와 doWrite() 라는 메서드를 생성하고, 해당 메서드들은 다시 ReviewDao에게 실질적인 기능을 수행하도록 한다.

 

  • 다음은 ReviewDao.java 클래스를 추가하고 새로 작성한 코드이다.
package org.example.dao;

import org.example.container.Container;
import org.example.db.DBConnection;
import org.example.dto.Review;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ReviewDao extends Dao {
    public List<Review> reviews;
    private DBConnection dbConnection;

    public ReviewDao() {
        reviews = new ArrayList<>();
        dbConnection = Container.getDBConnection();
    }

    public int doWrite(int answerId, int guestId, String reviewBody, double score) {
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("INSERT INTO review "));
        sb.append(String.format("SET regDate = NOW(), "));
        sb.append(String.format("bookingId = %d, ", answerId));
        sb.append(String.format("guestId = %d, ", guestId));
        sb.append(String.format("`body` = '%s', ", reviewBody));
        sb.append(String.format("score = '%1$f' ", score));

        return dbConnection.insert(sb.toString());
    }
}
  • 최종적으로 ReviewDao.java 에 도달하게 되면 메서드의 기능을 확인할 수 있다.
  • doWrite() 메서드는 DB 쿼리문을 통해 새로 등록된 리뷰의 정보를 삽입하는 기능을 수행한다.
  • StringBuilder를 통해 쿼리문을 차례로 작성하고, 지금 같은 경우는 "INSERT INTO review SET ~~" 이라는 쿼리문을 통해 리뷰의 정보를 새로 추가한다.
  • INSERT 문을 통해 삽입이 완료된다면 dbConnection과 연결하여 insert() 메서드를 실행한다.
  • 실제로 DB를 통해 새로운 리뷰가 등록되었다면 review 테이블을 SELECT 문으로 조회했을 때 해당 리뷰가 포함되어 있다.

 

 

반응형