1.
App Setup and Imports
• Flask & Extensions
python
from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_apscheduler import APScheduler
o Flask is the core web framework.
o render_template renders HTML templates.
o request gives you form data.
o redirect & url_for help you send the user to another page.
o flash shows one-time messages (success, error, warning).
o session lets you keep data (like username) across requests.
o Note: you imported APScheduler but haven’t yet scheduled any background
jobs.
• Database & Security
python
CopyEdit
import pyodbc, datetime
from werkzeug.security import generate_password_hash, check_password_hash
from pyodbc import IntegrityError
o pyodbc connects to SQL Server.
o datetime is used to calculate dates (e.g. checkout date).
o generate_password_hash & check_password_hash securely store and verify
passwords.
o IntegrityError is raised if you try to insert a duplicate key (e.g. same email).
• Flask App Instance & Secret
python
CopyEdit
app = Flask(__name__)
app.secret_key = "23453"
o Creates the Flask application.
o secret_key signs cookies and enables flash and session features.
2. Database Connection Helper
python
CopyEdit
def get_db_connection():
return pyodbc.connect(
f"DRIVER={DRIVER};SERVER={SERVER};DATABASE={DATABASE};"
"Trusted_Connection=yes;TrustServerCertificate=yes;Encrypt=yes;"
• Centralizes your connection details (driver, server, database).
• Returns an open database connection you can .cursor() on.
• Always call .close() when you’re done to free up resources.
3. User Registration (/register)
python
CopyEdit
@app.route('/register', methods=['POST'])
def register():
# 1. Read form inputs
name = request.form['username']
email = request.form['email']
password = request.form['password']
# 2. Hash the password
hash_pw = generate_password_hash(password)
# 3. Insert into database, handling duplicates
try:
cur.execute(
"INSERT INTO Coustomerlogin (Username, Email, Password) VALUES (?, ?, ?)",
(name, email, hash_pw)
conn.commit()
flash("Registration successful! Please log in.", "success")
except IntegrityError:
flash("Registration failed: That email address is already in use.", "warning")
except:
flash("Registration failed due to a server error. Please try again later.", "danger")
finally:
conn.close()
# 4. Redirect back to the reservation page
return redirect(url_for('reservation'))
• Flow:
1. Grab the submitted username, email, and password.
2. Hash the password before saving.
3. Try to INSERT into your Coustomerlogin table.
▪ If the email is already there, catch IntegrityError and flash a warning.
▪ If any other error happens, flash a generic error.
4. Close the DB connection.
5. Redirect so the user sees the reservation page (your modal or UI logic should
reopen the register form if needed).
4. User Login (/login) and Logout (/logout)
python
CopyEdit
@app.route('/login', methods=['POST'])
def login():
# 1. Read credentials
email = request.form['email']
password = request.form['password']
# 2. Fetch stored hash
cur.execute("SELECT Username, Password FROM Coustomerlogin WHERE Email=?",
(email,))
row = cur.fetchone()
conn.close()
# 3. Verify
if row and check_password_hash(row[1], password):
session['username'] = row[0]
flash(f"Welcome, {row[0]}!", "success")
else:
flash("Login failed. Check your credentials.", "danger")
return redirect(url_for('reservation'))
@app.route('/logout')
def logout():
session.clear()
flash("Logged out successfully.", "success")
return redirect(url_for('reservation'))
• Login:
1. Look up the user by email.
2. If found, compare the submitted password against the hashed password.
3. On success, store username in session so you know who’s logged in.
4. Flash a success or error message.
• Logout:
o Clears the session and flashes a confirmation.
5. Room Reservation (/)
python
CopyEdit
@app.route('/', methods=['GET', 'POST'])
def reservation():
if request.method == 'POST':
# 1. Read form fields (guest details, dates, payment info)
# 2. Determine if payment is “pay later” or immediate
# 3. Calculate `paid` flag and `total`
# 4. INSERT into dbo.Bookings
flash("Reservation received!", "success")
return redirect(url_for('reservation'))
# GET logic: Fetch available suites for the “Suite Section”
cur.execute("SELECT SuiteID, SuiteNumber, Type, WeeklyRate, MonthlyRate FROM Suites
WHERE Status='Available'")
suites = cur.fetchall()
conn.close()
logged_in = 'username' in session
return render_template('home.html', suites=suites, logged_in=logged_in)
• POST:
o Takes guest info, credit-card data (if any), computes total price, and inserts a
booking.
• GET:
o Queries the Suites table for all available suites and passes them to
home.html.
o Also tells your template whether a user is logged in.
6. Suite Reservation (/reserve-suite)
python
CopyEdit
@app.route('/reserve-suite', methods=['POST'])
def reserve_suite():
# 1. Read suite booking form data (guest info, suite ID, duration)
# 2. Look up the suite’s weekly & monthly rates
# 3. Compute check-in/out dates and total price
# 4. INSERT into SuiteBookings
# 5. Flash success or error message
return redirect(url_for('reservation'))
• Handles a special “suite” booking flow.
• Calculates whether it’s a weekly or monthly stay, figures total cost, and records it.
7. Running the App
python
CopyEdit
if __name__ == '__main__':
app.run(debug=True)
• Starts Flask’s built-in development server.
• debug=True gives you automatic reloads on code changes and shows detailed error
pages.
How It All Fits Together
1. Users can register, log in, and log out, with passwords stored hashed.
2. On the home page, anyone can make a standard room reservation (stored in
Bookings).
3. Logged-in or not, they can also reserve a suite (stored in SuiteBookings).
4. Flash messages surface success or errors in your UI modal or alert area.
5. Sessions keep track of the logged-in user for personalized experiences (e.g. hiding
or showing certain UI elements.
Sql code
1. Database & Core Tables
1. Creating the database
sql
CopyEdit
CREATE DATABASE hotel;
o Sets up a new “hotel” database to hold all subsequent tables.
2. Rooms
sql
CopyEdit
CREATE TABLE dbo.Rooms (
RoomID INT IDENTITY(1,1) PRIMARY KEY,
RoomNumber VARCHAR(50) NOT NULL UNIQUE,
Type VARCHAR(50) NOT NULL,
IsOccupied BIT NOT NULL,
RoomStatus VARCHAR(20) NOT NULL DEFAULT 'Available'
);
o RoomID: auto-increment PK.
o RoomNumber: human-friendly identifier, must be unique.
o Type: e.g. “Single”, “Double”, “Suite.”
o IsOccupied & RoomStatus track availability; the default for RoomStatus is
“Available.”
2. Guest Reservations
1. Bookings
sql
CopyEdit
CREATE TABLE dbo.Bookings (
BookingID INT IDENTITY(1,1) PRIMARY KEY,
GuestName VARCHAR(100) NOT NULL,
GuestEmail VARCHAR(150) NULL,
GuestPhone VARCHAR(50) NULL,
RoomType VARCHAR(50) NOT NULL,
Occupants INT NOT NULL,
CheckIn DATE NOT NULL,
CheckOut DATE NOT NULL,
CreditCardNumber VARCHAR(30) NULL,
CreditCardMonth INT NULL,
CreditCardYear INT NULL,
CSV VARCHAR(10) NULL,
TotalPrice DECIMAL(10,2) NOT NULL DEFAULT 0,
Paid BIT NOT NULL DEFAULT 0,
Status VARCHAR(20) NOT NULL DEFAULT 'Booked'
);
o Records each reservation’s core data.
o Defaults ensure numeric fields aren’t left null and that new bookings start
with Status = 'Booked'.
2. CustomerRooms
sql
CopyEdit
CREATE TABLE dbo.CustomerRooms (
CustomerRoomID INT IDENTITY(1,1) PRIMARY KEY,
BookingID INT NOT NULL,
CustomerName VARCHAR(100) NOT NULL,
RoomID INT NOT NULL,
CheckIn DATETIME NOT NULL DEFAULT GETDATE(),
FOREIGN KEY (BookingID) REFERENCES dbo.Bookings(BookingID),
FOREIGN KEY (RoomID) REFERENCES dbo.Rooms(RoomID)
);
o Links a booking to the actual room assigned.
o Timestamps when the customer checks in.
3. Users & Security
1. Users
sql
CopyEdit
CREATE TABLE Users (
UserID INT IDENTITY(1,1) PRIMARY KEY,
Username VARCHAR(100) NOT NULL UNIQUE,
Password VARCHAR(100) NOT NULL
);
o Simple demo table for application users (e.g. admins or staff).
o Plain-text password here for demonstration only—always hash in production!
2. Clerks
sql
CopyEdit
CREATE TABLE dbo.Clerks (
Username NVARCHAR(60) NOT NULL UNIQUE,
PasswordHash NVARCHAR(255) NOT NULL,
ClerkID INT IDENTITY(1,1) PRIMARY KEY
);
o More secure staff logins: stores a hash instead of plain text.
4. Financial Tracking
1. Billing
sql
CopyEdit
CREATE TABLE dbo.Billing (
BillingID INT IDENTITY(1,1) PRIMARY KEY,
BookingID INT NOT NULL,
GuestName VARCHAR(100) NOT NULL,
Amount DECIMAL(10,2) NOT NULL,
BillingDate DATETIME NOT NULL DEFAULT GETDATE(),
PaymentMethod VARCHAR(50) NULL,
ExtraCharges DECIMAL(10,2) NOT NULL DEFAULT 0,
FOREIGN KEY (BookingID) REFERENCES dbo.Bookings(BookingID)
);
o Captures individual bills tied back to a booking.
2. Charges
sql
CopyEdit
CREATE TABLE Charges (
ChargeID INT IDENTITY(1,1) PRIMARY KEY,
BookingID INT NOT NULL,
Description NVARCHAR(100) NOT NULL,
Amount DECIMAL(10,2) NOT NULL,
ChargeDate DATETIME NOT NULL DEFAULT GETDATE(),
FOREIGN KEY (BookingID) REFERENCES dbo.Bookings(BookingID)
);
CREATE INDEX IDX_Charges_BookingID ON Charges(BookingID);
o Tracks add-ons (mini-bar, laundry, etc.).
o Index on BookingID speeds up lookups per reservation.
5. Extended Entities
1. Employees
sql
CopyEdit
CREATE TABLE Employees (
EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(100) NOT NULL,
Position NVARCHAR(100) NOT NULL,
HireDate DATETIME NOT NULL DEFAULT GETDATE()
);
o Staff directory.
2. Customers
sql
CopyEdit
CREATE TABLE Customers (
CustomerID INT IDENTITY(1,1) PRIMARY KEY,
BookingID INT NOT NULL,
RoomID INT NOT NULL,
CheckInTime DATETIME NOT NULL,
CheckOutTime DATETIME NULL,
FOREIGN KEY (BookingID) REFERENCES Bookings(BookingID),
FOREIGN KEY (RoomID) REFERENCES Rooms(RoomID)
);
o Redundant to CustomerRooms, but could serve distinct reporting needs.
3. Companies & TravelCompanyBookings
sql
CopyEdit
CREATE TABLE Companies (...);
CREATE TABLE TravelCompanyBookings (...);
o Allows corporate accounts to book multiple rooms/nights at negotiated
rates.
o You can later add a foreign key from TravelCompanyBookings.CompanyID
back to Companies.
6. Suites & Suite Bookings
1. Suites
sql
CopyEdit
CREATE TABLE Suites (
SuiteID INT IDENTITY(1,1) PRIMARY KEY,
SuiteNumber NVARCHAR(10) NOT NULL,
Type NVARCHAR(50) NOT NULL,
WeeklyRate DECIMAL(10,2) NOT NULL,
MonthlyRate DECIMAL(10,2) NOT NULL,
Status NVARCHAR(20) NOT NULL DEFAULT 'Available'
);
2. SuiteBookings
sql
CopyEdit
CREATE TABLE SuiteBookings (
BookingID INT IDENTITY(1,1) PRIMARY KEY,
GuestName VARCHAR(100) NOT NULL,
GuestEmail VARCHAR(150) NULL,
SuiteID INT NOT NULL,
CheckIn DATE NOT NULL,
CheckOut DATE NOT NULL,
DurationType VARCHAR(10) NOT NULL,
DurationCount INT NOT NULL,
TotalPrice DECIMAL(10,2) NOT NULL,
CreatedAt DATETIME DEFAULT GETDATE(),
FOREIGN KEY (SuiteID) REFERENCES Suites(SuiteID)
);
o Mirrors your Flask “reserve-suite” logic: weekly vs. monthly rates.
Key Takeaways
• Normalization & Relationships
o Most tables reference Bookings or Rooms via foreign keys—this keeps your
data consistent.
• Defaults & Constraints
o Defaults on status/date fields reduce boilerplate in your INSERTs.
• Indexes
o You’ve added indexes on Charges and Billing to optimize joins and lookups.
• Security Reminder
o Never store passwords in plain text; always use a hashing function (as you do
in your Flask code).