How to Create a Hotel with Hot Tub in Room in Python

Outlines a quick help guide for developing a basic hotel room booking system in Python, with a focus on incorporating a specific room amenity a hot tub. The tutorial leverages Python’s object oriented programming (OOP) capabilities to define Room objects with attributes like type, price, and available amenities (e.g., has_hot_tub).

  • Data Structure: Using a dictionary or list to store and manage room inventory and booking status.
  • Key Functions: Implementing functions to list available roomscheck amenitieshandle customer details, and calculate total stay costs.
  • Feature Integration: Demonstrates how to add a boolean or string attribute (hot_tub) to room objects and create logic for filtering rooms based on this specific feature for a tailored guest experience.

What is “hotel with hot tub in room”

Choosing what you want to simulate:

Let’s define what we mean by “hotel with hot tub in room”. In our simulation:

  • The hotel has multiple rooms. Some rooms are standard; some are “hot tub rooms”.
  • A “hot tub room” means the room has an in-room hot tub facility (so possibly higher price, maybe maintenance flag).
  • Customers can book a room for a number of nights.
  • The system should check availability (i.e., that the room is free for those nights).
  • The system should optionally add extra features for the hot tub room (e.g., extra nightly charge, or extra cleaning fee).
  • The system should allow checkout, compute total charge, maybe mark the room as needing maintenance for the hot tub.

Deciding a simple architecture:

To keep it understandable (easy English, human tone) I’ll go with a small object-oriented design:

  • A Room base class.
  • A HotTubRoom subclass that extends Room and adds hot tub specific attributes.
  • A Booking class to represent a booking (room, customer name, start date, nights, total price).
  • A Hotel class to hold list of rooms, manage bookings, etc.

The competitor guides mostly used flat functions with dictionaries and JSON; this will make our code cleaner and more extendable. And we’ll show how to add the hot tub feature.

Setting Up Classes

Defining the Room class:

class Room:
    def __init__(self, room_number, nightly_rate):
        self.room_number = room_number
        self.nightly_rate = nightly_rate
        self.is_booked = False
        self.current_booking = None

    def book(self, booking):
        if self.is_booked:
            raise Exception(f"Room {self.room_number} is already booked.")
        self.is_booked = True
        self.current_booking = booking

    def checkout(self):
        self.is_booked = False
        self.current_booking = None

Here we have a basic room: number, nightly rate, booked status, current booking. Very simple.

Defining the HotTubRoom subclass:

class HotTubRoom(Room):
    def __init__(self, room_number, nightly_rate, hot_tub_fee):
        super().__init__(room_number, nightly_rate)
        self.hot_tub_fee = hot_tub_fee
        self.hot_tub_needs_maintenance = False

    def book(self, booking):
        if self.hot_tub_needs_maintenance:
            raise Exception(f"Hot tub in room {self.room_number} is under maintenance.")
        super().book(booking)

    def checkout(self):
        # After checkout we might flag maintenance
        self.hot_tub_needs_maintenance = True
        super().checkout()

    def calculate_rate(self, nights):
        return self.nightly_rate * nights + self.hot_tub_fee * nights

Notice that the hot tub room adds: a hot tub fee, a maintenance flag, custom calculate_rate. This is new compared to competitor guides.

Defining the Booking class:

class Booking:
    def __init__(self, customer_name, room, start_date, nights):
        self.customer_name = customer_name
        self.room = room
        self.start_date = start_date  # e.g., a datetime.date
        self.nights = nights
        self.total_price = self.room.nightly_rate * nights
        if isinstance(self.room, HotTubRoom):
            self.total_price = self.room.calculate_rate(nights)

We compute the total price differently if it’s a hot tub room.

Defining the Hotel class:

class Hotel:
    def __init__(self, name):
        self.name = name
        self.rooms = []
        self.bookings = []

    def add_room(self, room):
        self.rooms.append(room)

    def find_available_room(self, nights, want_hot_tub=False):
        for room in self.rooms:
            if not room.is_booked:
                if want_hot_tub and isinstance(room, HotTubRoom):
                    return room
                if not want_hot_tub and not isinstance(room, HotTubRoom):
                    return room
        return None

    def make_booking(self, customer_name, nights, want_hot_tub=False):
        room = self.find_available_room(nights, want_hot_tub)
        if room is None:
            raise Exception("No available room meets your request.")
        booking = Booking(customer_name, room, date.today(), nights)
        room.book(booking)
        self.bookings.append(booking)
        print(f"Booked room {room.room_number} for {customer_name}. Total price: {booking.total_price}")
        return booking

    def checkout(self, booking):
        booking.room.checkout()
        print(f"{booking.customer_name} checked out from room {booking.room.room_number}.")

This gives us a complete mini-system: we can add rooms (standard or hot tub), make bookings, checkout, etc.

Using the System and Adding Features

Example usage:

from datetime import date

hotel = Hotel("Seaside Resort")

# add rooms
hotel.add_room(Room(101, 100))
hotel.add_room(Room(102, 110))
hotel.add_room(HotTubRoom(201, 150, hot_tub_fee=30))
hotel.add_room(HotTubRoom(202, 160, hot_tub_fee=35))

# booking a regular room
b1 = hotel.make_booking("Alice", nights=2, want_hot_tub=False)

# booking a hot tub room
b2 = hotel.make_booking("Bob", nights=3, want_hot_tub=True)

# checkout
hotel.checkout(b1)
hotel.checkout(b2)

You’ll see Alice pays 2 nights * 100 = 200, Bob pays 3 nights * (150 + 30) = 540.

New feature: Mark the hot tub room ready after maintenance

A new bit of logic not found in many beginner tutorials: after checkout, you might want to reset the hot tub maintenance flag only after a cleaning cycle. For example:

def clean_hot_tub_room(hot_tub_room):
    if hot_tub_room.hot_tub_needs_maintenance:
        print(f"Cleaning hot tub in room {hot_tub_room.room_number}")
        hot_tub_room.hot_tub_needs_maintenance = False
    else:
        print("No maintenance needed.")

This extra step ensures a hot tub room isn’t instantly re-bookable until cleaned adds realism.

Handling Availability Over Dates and Nights

One of the weak spots of many guides is date span checking. They just mark rooms as free/free without considering overlapping bookings. Let’s fix that.

Improved Room Class to Handle Bookings List:

Instead of just is_booked, we track booked periods.

class Room:
    def __init__(self, room_number, nightly_rate):
        self.room_number = room_number
        self.nightly_rate = nightly_rate
        self.booked_periods = []  # list of tuples: (start_date, end_date)

    def is_available(self, start_date, nights):
        end_date = start_date + timedelta(days=nights)
        for (s, e) in self.booked_periods:
            # if periods overlap:
            if s < end_date and start_date < e:
                return False
        return True

    def book_period(self, booking):
        end_date = booking.start_date + timedelta(days=booking.nights)
        self.booked_periods.append((booking.start_date, end_date))

Then in Hotel:

def find_available_room(self, start_date, nights, want_hot_tub=False):
    for room in self.rooms:
        if want_hot_tub and isinstance(room, HotTubRoom) and room.is_available(start_date, nights):
            return room
        if not want_hot_tub and not isinstance(room, HotTubRoom) and room.is_available(start_date, nights):
            return room
    return None

And our make_booking method updates accordingly.

Why this is better

Most competitor guides don’t handle date overlaps—for example, if someone books room 101 for nights 3–5, you need to block nights 3–4 and not let someone else book them. The above logic handles that.

Extra Services and Pricing Beyond Hot Tub

To push beyond what typical guides offer, let’s add more new features:

Optional mini-bar service

We can allow rooms to have optional add-ons. For example:

class Service:
    def __init__(self, name, fee):
        self.name = name
        self.fee = fee

class Booking:
    def __init__(self, customer_name, room, start_date, nights, services=None):
        if services is None:
            services = []
        self.customer_name = customer_name
        self.room = room
        self.start_date = start_date
        self.nights = nights
        self.services = services
        self.total_price = self.compute_price()

    def compute_price(self):
        base = self.room.nightly_rate * self.nights
        if isinstance(self.room, HotTubRoom):
            base += self.room.hot_tub_fee * self.nights
        svc_fee = sum(s.fee for s in self.services)
        return base + svc_fee

Now you can pass services like Service("Mini-bar", 20) or Service("Room Service Breakfast", 30).

Discount logic

Maybe if someone books a hot tub room for more than 5 nights, you give a discount:

if isinstance(self.room, HotTubRoom) and self.nights >= 5:
    self.total_price *= 0.9  # 10% discount

This is new compared to many guides.

Waiting list / upgrade logic

If someone requests a hot tub room but none are available, maybe you can put them on a waiting list or offer a standard room with upgrade possibility. This is more advanced and not typically covered in simple tutorials.

User Interface: Simple Console Loop

To make this usable, you might buil a loop like:

while True:
    print("1. Book room")
    print("2. Checkout booking")
    print("3. Clean hot tub room")
    print("4. Exit")
    choice = input("Choose an option: ")
    if choice == '1':
        name = input("Customer name: ")
        nights = int(input("Nights: "))
        want_hot = input("Want hot tub room? (y/n): ") == 'y'
        try:
            booking = hotel.make_booking(name, nights, want_hot)
        except Exception as e:
            print("Error:", e)
    elif choice == '2':
        name = input("Customer name for checkout: ")
        # find booking by name
        bk = next((b for b in hotel.bookings if b.customer_name == name), None)
        if bk:
            hotel.checkout(bk)
        else:
            print("Booking not found.")
    elif choice == '3':
        room_no = int(input("Room number to clean hot tub: "))
        room = next((r for r in hotel.rooms if r.room_number == room_no and isinstance(r, HotTubRoom)), None)
        if room:
            clean_hot_tub_room(room)
        else:
            print("No hot tub room found with that number.")
    elif choice == '4':
        print("Goodbye!")
        break
    else:
        print("Invalid choice.")

Conclusion

If you’ve followed along, you now know how to create a hotel with hot tub in room in Python you’ve seen code to build room classes, hot tub room subclass, booking logic, availability by dates, extra services, maintenance flags, interactive console loop. You’ve also seen how this post gives you more depth than many simpler tutorials out there.

Related blog posts