sabrebooking / sabrebackend / sabre / sabreapi / models.py
models.py
Raw
from django.db import models
from django.db.models import F
from django.contrib.auth.models import User
from datetime import timedelta
import arrow



# Booking Entity Class


class CustomUser(User):
    """
    Extends the default User model to include additional fields specific to the system's requirements.

    Attributes:
    - is_verified (BooleanField): Indicates if the user has been verified, default is False.
    - phone_number (BigIntegerField): The user's phone number. Defaults to 0 if not provided.

    Inheritance:
    - Inherits from the built-in User model, thus retaining fields and methods associated with it.
    """
    is_logged_in = models.BooleanField(default=False)
    current_login_token = models.TextField(default=None, null=True, blank=True)
    phone_number = models.BigIntegerField(blank=True, default=0, null=True)
    address = models.CharField(max_length=300, default=None, null=True)
    VAT = models.IntegerField(default=None, null=True)
    google_id = models.TextField(blank=True, default=None, null=True)

    def __str__(self) -> str:
        return super().first_name + " " + super().last_name


class Booking(models.Model):
    """
    Represents a booking entity in the system.

    Attributes:
    - user (ForeignKey): A reference to the user who made the booking.
    - is_approved (BooleanField): Indicates if the booking has been approved.
    - is_recurring (BooleanField): Indicates if the booking is recurring.
    - is_cancelled (BooleanField): Indicates if the booking has been cancelled.
    - event_duration (DurationField): The duration of the event.
    - number_of_attendees (IntegerField): The number of attendees for the event.
    - room (ForeignKey): A reference to the room associated with the booking.
    - date_created (DateTimeField): The date and time when the booking was created.
    - event_start (TimeField): The start time of the event.
    - event_end (TimeField): The end time of the event.
    - event_date (DateField): The date of the event.
    """
    DURATION_CHOICES = [
        ("half-day", "Half-Day"), ("full-day", "Full-day"), ("over-a-day", "Many days")]
    user = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE, blank=True, related_name="bookings")
    is_approved = models.BooleanField(default=False)
    is_recurring = models.BooleanField(default=True)
    is_cancelled = models.BooleanField(default=False)
    event_duration = models.CharField(
        max_length=40, choices=DURATION_CHOICES, default="half-day")
    number_of_attendees = models.IntegerField()
    event_leader_name = models.CharField(
        max_length=200, default=None, null=True, blank=True)
    room = models.ForeignKey(
        "Room", on_delete=models.CASCADE, blank=True, null=True, related_name="bookings")
    date_created = models.DateTimeField(auto_now_add=True)
    catering = models.OneToOneField(
        "Catering", on_delete=models.CASCADE, default=None, null=True)
    event_start = models.TimeField(default=None)
    event_end = models.TimeField(default=None)
    event_date = models.DateField(default=None)
    event_type = models.CharField(max_length=200, default=None)
    event_name = models.CharField(max_length=200, default="UNKNOWN")
    company_name = models.CharField(max_length=300, default="NO NAME PROVIDED")

    def __str__(self):
        """The string representation of the booking model.

        Returns:
            str: The name of the user associated with the booking
        """
        # return f"{self.company_name, Booking.humanize_date(self.event_date)}"
        return f"{self.company_name}, {Booking.humanize_date(self.event_date)}"
    
    
    @classmethod
    def humanize_date(cls, date):
        """Returns a human readable form of the date."""
        return arrow.get(date).format("dddd D MMMM YYYY") + ", " +  arrow.get(date).humanize() 
    

class Room(models.Model):
    """
    Represents a room entity in the system, detailing its amenities, name, booking status, type, and capacity.

    Attributes:
    - amenity (ManyToManyField): References to the amenities associated with the room.
    - name (CharField): The name of the room.
    - is_booked (BooleanField): Indicates if the room is currently booked.
    - room_type (CharField): The type or category of the room.
    - capacity (IntegerField): The maximum number of people the room can accommodate.

    Methods:
    - __str__(): Returns the name of the room as its string representation.
    """
    amenity = models.ManyToManyField(
        "Amenity", blank=True, related_name="rooms")
    equipment = models.ManyToManyField(
        "Equipment", blank=True, related_name="rooms"
    )
    functions = models.ManyToManyField(
        "RoomFunction", default=None, related_name="rooms")
    name = models.CharField(max_length=100)
    is_booked = models.BooleanField(default=False)
    room_type = models.CharField(max_length=100)
    capacity = models.IntegerField()
    equipment = models.ManyToManyField("Equipment", default=None, related_name="equipment")

    def __str__(self):
        """The string representation of the room model.

        Returns:s
            str: The name of the room
        """
        return self.name

# Amenity Entity Class


class Amenity(models.Model):
    """
    Represents an amenity entity in the system, detailing its name, availability upon request, and associated image.

    Attributes:
    - name (CharField): The name of the amenity.
    - upon_request (BooleanField): Indicates if the amenity is available upon request.
    - svg_code (ImageField): An image representing the amenity, typically an SVG.

    Methods:
    - __str__(): Returns the name of the amenity as its string representation.
    """
    name = models.CharField(max_length=100)
    upon_request = models.BooleanField(default=False)
    # svg_code = models.ImageField(upload_to="svg_images/")

    def __str__(self):
        """The string representation of the amenities model.

        Returns:
            str: the name of the model.
        """
        return self.name
    
    class Meta:
        verbose_name_plural = "All Amenities"

# Image Entity Class


class Image(models.Model):
    """
    Represents an image entity in the system, specifically associated with a room.

    Attributes:
    - image_url (URLField): The URL where the image can be accessed.
    - room (ForeignKey): A reference to the room with which this image is associated.

    Relations:
    - Foreign Key to the Room model, indicating which room the image belongs to.
    """
    image_url = models.URLField()
    room = models.ForeignKey(
        "Room", on_delete=models.CASCADE, blank=True, related_name="images")


class Waitlist(models.Model):
    """
    Represents a waitlist entry in the system. Each entry indicates a user's intent 
    to book a certain booking that might be already occupied.

    Attributes:
    - room (ForeignKey): A reference to the room that the user is waitlisted for.
    - user (ForeignKey): The user who is on the waitlist for a specific booking.
    - timestamp (DateTimeField): The date and time when the user was added to the waitlist.
    - event_start (TimeField): The start time of the event.
    - event_end (TimeField): The end time of the event.
    - event_date (DateField): The date of the event.

    Relations:
    - Foreign Key to the Room model, showing which room the waitlist entry pertains to.
    - Foreign Key to the CustomUser model, indicating the user associated with the waitlist entry.
    """
    room = models.ForeignKey(
        "Room", blank=True, default=None, on_delete=models.CASCADE, related_name="waitlist")
    user = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE, blank=True, related_name="waitlist")
    timestamp = models.DateTimeField(auto_now_add=True)
    event_start = models.TimeField(default=None)
    event_date = models.TimeField(default=None)
    event_date = models.DateField(default=None)


class RoomFunction(models.Model):
    function = models.CharField(max_length=256)

    def __str__(self):
        return self.function
    
class AvailableMeal(models.Model):
    """
    Stores all meals that can be offered

    Attributes:
    - price: Stores the price for one person of that meal.
    - meal_time: Determines the meal type interms of time.
    - meal_description: Description of the meal.
    - picture_id:

    """
   

    CATERING_PACKAGES = [("Gold","gold"), ( "Silver","silver"), ("Bronze","bronze")]
    MEAL_TIME = [("arrival teas", "Arrival Teas"), ("mid-morning-teas", "Mid-Morning-Teas"),
                 ("lunch", "Lunch"), ("dinner", "Dinner")]
    CATERING_TYPES = [("morning arrival teas and snacks", "Morning Arrival Teas and Snacks"), ("breakfast", "Breakfast"), ("mid-morning teas and snacks", "Mid-morning Teas and Snacks"),
                 ("lunch", "Lunch"), ("afternoon arrival teas and snacks", "Afternoon Arrival Teas and Snacks"), ("evening drinks and snacks", "Evening Drinks and Snacks"), ("dinner", "Dinner")]
    
    title = models.CharField(max_length = 100, default = None)
    meal_description = models.CharField(max_length = 256, blank = True)
    catering_package = models.CharField(
        max_length=10, choices=CATERING_PACKAGES, default="gold")
    meal_time = models.CharField(
        max_length=25, choices=MEAL_TIME, default="lunch")
    catering_type = models.CharField(
        max_length=100, choices=CATERING_TYPES, default="morning arrival teas and snacks")
    picture_id = models.CharField(max_length = 250, blank = True)
    price = models.DecimalField(max_digits=10, decimal_places=2)


    def __str__(self):
        
        if self.meal_description:
            return self.title + ", " + self.meal_description
        return self.title


class Catering(models.Model):
    """
    Represents a catering entity in the system.

    Attributes:
    - user (ForeignKey): A reference to the user who made the booking.
    - catering_package: The catering package of the event.
    - meal_time: The time of the meals.
    - special_dietary_requirements: Dietry requirements if any.
    - bar_requirements: Bar requirements if any.
    - chosen_meal: Relation to the AvailableMeal model for the chosen meal.

    """
    # CATERING_CHOICES = [
    #     ("gold", "Gold"), ("silver", "Silver"), ("bronze", "Bronze")]
    # MEAL_TIME = [("arrival ", "Arrival"), ("mid-morning", "Mid-morning"),
    #              ("lunch", "Lunch"), ("afternoon", "Afternoon"), ("evening", "Evening")]
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default=None) 
    # chosen_meal = models.ForeignKey(AvailableMeal, on_delete = models.CASCADE, blank = True, default=None)
    meals = models.ManyToManyField(
        "AvailableMeal", default=None, related_name="meals")
    # catering_package = models.CharField(
    #     max_length=10, choices=CATERING_CHOICES, default="gold")
    # meal_type = models.CharField(
    #     max_length=25, choices=MEAL_TIME, default="lunch")
    special_dietary_requirements = models.TextField(default = "no special dietary requirements", blank=True)
    bar_requirements = models.TextField(default = "No bar requirements", blank=True)
    # served = models.BooleanField(default = False)

    def __str__(self):
        return (self.user.first_name + " " + self.user.last_name)
    
    class Meta:
        verbose_name_plural = "Requested Catering"

    

class Equipment(models.Model):
    name = models.CharField(max_length=80)
    upon_request = models.BooleanField(default=False)

    def __str__(self):
        return self.name
    
    class Meta:
        verbose_name_plural = "All Equipment"

class Feedback(models.Model):
    rating = models.FloatField()
    recommendation = models.IntegerField()
    comments = models.TextField(default=None)
   
    def __str__(self):
        """The string representation of the feedback model.

        Returns:
            str: The details of the feedback recieved, the rating, recomendation score and comments.
        """
        return f"RATING: {self.rating}, RECOMMENDATION SCORE: {self.recommendation}, COMMENT: {self.comments}"

    class Meta:
        verbose_name_plural = "User Feedback"