from .CONSTANTS import UPPERCASE, LOWERCASE, DIGITS from .serializers import BookingSerializer, CateringSerializer from .models import Room, AvailableMeal, Catering from django.core.mail import EmailMessage import os from email.message import EmailMessage import ssl import smtplib from datetime import datetime GMAIL_ADMIN_USER = os.getenv("GMAIL_ADMIN_USER") ADMIN_PASSWORD = os.getenv("GMAIL_ADMIN_PASSWORD") # Utility function def get_booking_details(data): return { "user": None, "is_approved": False, "is_recurring": False, "is_cancelled": False, "event_duration": data["eventDuration"], "number_of_attendees": data["numberOfDelegates"], "room": data["room"], "event_type": data["eventType"], "event_date": data["eventDate"], "event_start": data["eventStartTime"], "event_end": data["eventEndTime"], "company_name": data["companyName"] } # To be removed def get_catering_details(data): # TODO: return { "user": None, "chosen_meal": data["chosenMeal"], "catering_package": data["cateringPackage"], "meal_time": data["teaMealBreakTime"], "special_dietary_requirements": data["specialDietaryRequirements"], "bar_requirements": data["barRequirements"], "served": data["served"], } def send_confirmation_email(user): """Sends a confirmation email to the user""" subject = "[Sabre] Booking succesfully submitted" body= f"""Hi, {user.first_name} Thank you for submitting your booking with Sabre. This email serves to inform you that we have received the request and we will be sending a confirmation soon! Please remember to pay as soon as possible for us to confirm your booking. Best, Sabre Admin Team. """ em = EmailMessage() em['From'] = GMAIL_ADMIN_USER em['To'] = user.email em['Subject'] = subject em.set_content(body) context = ssl.create_default_context() with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp: try: smtp.login(GMAIL_ADMIN_USER, ADMIN_PASSWORD) smtp.sendmail(GMAIL_ADMIN_USER, user.email, em.as_string()) except Exception as e: return {"error": str(e)} return {"success": True} def send_approval_email(user): """Sends a booking approval email to the user""" subject = "[Sabre] Booking Approved by admin." body = f"""Hi, {user.first_name} This email is to let you know that your booking has been approved by the admin. Hooray! Please check out your calendar to accept the invitation and you should be all set. Best, Sabre Admin Team. """ em = EmailMessage() em['From'] = GMAIL_ADMIN_USER em['To'] = user.email em['Subject'] = subject em.set_content(body) context = ssl.create_default_context() with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp: try: smtp.login(GMAIL_ADMIN_USER, ADMIN_PASSWORD) smtp.sendmail(GMAIL_ADMIN_USER, user.email, em.as_string()) except Exception as e: return {"error": str(e)} return {"success": True} def get_feedback_details(data): """ Extracts feedback details from the input json. Parameters: - data (dict): Dictionary with user's rating, recommendation score, and additional feedback details. Returns: - dict: Feedback details. """ return { "rating": data["rating"], "recommendation": data["recommendation"], "comments": data["comments"] # "user": user } def save_booking_details(data, user_id): """ Validates and saves booking details associated with a user to the database. Args: data (dict): Raw booking data. user_id (int): ID of the user associated with the booking. Returns: dict: A dictionary indicating operation success and either the booking object or errors. """ # Handle booking data booking_data = get_booking_details(data) # catering_data = get_catering_details(data) # catering_serializer = CateringSerializer(data=catering_data) # if catering_serializer.is_valid(): # catering_instance = catering_serializer.save() # else: # return {"success": False, "errors": catering_serializer.errors} room = Room.objects.get(name=booking_data["room"]) # associate a booking with the user booking_data["user"] = user_id booking_data["room"] = room.id # booking_data["catering"] = catering_instance.id PAY ATTENTION TO LINE 90. print(GMAIL_ADMIN_USER) print(ADMIN_PASSWORD) booking_serializer = BookingSerializer(data=booking_data) # save the booking is the serialized request is valid if booking_serializer.is_valid(): saved_booking = booking_serializer.save() booking_id = saved_booking.id return {"success": True, "booking": saved_booking, "booking_id": booking_id} # return an error if serialized request is not valid return {"success": False, "errors": booking_serializer.errors} def save_catering_details(data, user_id): """ Validates and saves catering details associated with a user to the database. Args: data (dict): Raw catering data. user_id (int): ID of the user associated with the catering. Returns: dict: A dictionary indicating operation success and either the catering object or errors. """ # catering_data = get_catering_details(data) # get a list of meal ids meal_IDs = [] for meal in data: meal_IDs.append(meal[id]) meals = AvailableMeal.objects.filter(id__in=meal_IDs) # create a catering object catering = Catering.objects.create(user=user_id) # save meals to catering meals field catering.meals.set(meals) #Get the id's of foreign fields. # chosen_meal = AvailableMeal.objects.filter(id=catering_data["chosen_meal"]) catering["user"] = user_id catering["special_dietary_requirements"] = data["special_dietary_requirements"] catering["bar_requirements"] = data["bar_requirements"] catering_serializer = CateringSerializer(catering) if catering_serializer.is_valid(): return {"success": True, "catering": catering_serializer.save()} else: return {"success": False, "errors": catering_serializer.errors} def get_available_rooms(date, event_start, event_end, number_of_attendees): """ Returns a list of available rooms based on given date, start and end times, and the number of attendees. Parameters: - date (str): The date for the event in the format 'YYYY-MM-DD'. - event_start (str): The start time for the event in the format 'HH:MM'. - event_end (str): The end time for the event in the format 'HH:MM'. - number_of_attendees (int/str): The number of attendees for the event. Returns: - list: A list of room names that are available for the given criteria. Note: This function assumes the existence of a Room model where each room has a capacity and associated bookings. """ # Convert the date string to a datetime.date object date = datetime.strptime(date, '%Y-%m-%d').date() # Convert the start and end time strings to datetime.time objects start = datetime.strptime(event_start, '%H:%M').time() end = datetime.strptime(event_end, '%H:%M').time() # Fetch all rooms ordered by their capacity rooms = set(Room.objects.all().order_by('capacity')) for room in list(rooms): # Loop through the list of rooms. # number of attendees exceed capacity, skip room. if room.capacity < int(number_of_attendees): rooms.discard(room) continue # confirm no bookings conflict with the proposed time. found_conflict = False for booking in room.bookings.all(): found_conflict = False if booking.event_date != date: continue if not (start >= booking.event_end or end <= booking.event_start): found_conflict = True break # check if any of the bookings caused a conflict. if found_conflict: rooms.discard(room) continue return [[room.id, room.name, room.capacity] for room in rooms] # for booking in room.bookings.all(): # Go over all the bookings associated with this room. # if booking.event_date != date: # If the booking date is not the same as our target date, ignore that booking. # continue # # Remove the room from the set if there is a conflict. # if not (start >= booking.event_end or end <= booking.event_start): # rooms.discard(room)