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"