sabrebooking / sabrebackend / sabre / sabreapi / views.py
views.py
Raw
import os
import json
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.template.loader import render_to_string
from io import BytesIO
from .models import Room, Booking, CustomUser
from .serializers import BookingSerializer, RoomSerializer, CustomUserSerializer, AvailableMealSerializer, FeedbackSerializer
from rest_framework import status
from rest_framework.decorators import api_view
from .utils import *
from google.oauth2 import id_token
from google.auth.transport import requests
from .calendar import init_creds, list_upcoming_events, add_booking_to_calendar
import logging
from xhtml2pdf import pisa


logger = logging.getLogger(__name__)



CLIENT_ID = os.getenv("CLIENT_ID")

# Create your views here.
@api_view(["POST"])
def index(request):
    """
    Handle the POST request to register a user and save their booking details.

    This view first attempts to save user details. If successful, it then 
    attempts to save the associated booking details. If the user is not verified,
    it sends a verification link to the user. 

    Parameters:
    - request (HttpRequest): The Django request object containing the data.

    Returns:
    - JsonResponse: A JSON response indicating success or returning errors.
    """

    # Ensure the request is a POST request.
    if request.method == "POST":
        token_id = request.data["token"]
        print("CLIENT ID", CLIENT_ID)
        print("REQUEST REC: ", request.data)
        try:
            print("started saving user details.")
            idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
            user_id = idinfo['sub']
            user = CustomUser.objects.get(google_id=user_id)
            user.phone_number = request.data["phone"]
            user.VAT = request.data["VAT"]
            user.address = request.data["physicalAddress"]
            user.save()
            print("saving user details was successful")
        except Exception as e:
            print("saving user details not successful")
            return JsonResponse({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
        result = save_booking_details(request.data, user.id)
        booking_id = result["booking_id"]
        if not result["success"]:
            print("result not successful")
            return JsonResponse(result, status=status.HTTP_400_BAD_REQUEST)
        # print(send_confirmation_link(user))
        try:
            print("went to printing")
            send_confirmation_email(user) 
            print("printing successful")  
        except Exception as e:
            print(str(e))
            return JsonResponse({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
        print(booking_id, "Booking id")
        return JsonResponse({"success": True, "booking_id": booking_id}, status=status.HTTP_200_OK)



@api_view(["POST"])
def filter_rooms(request):
    """
    Handle the POST request to filter available rooms based on the event's details.

    This view expects details about the event, including the event date, start time, 
    end time, and number of attendees, in the request data. It then filters the rooms 
    that are available based on these details and returns the list of available rooms 
    in the JSON response.

    Parameters:
    - request (HttpRequest): The Django request object containing the event details.

    Returns:
    - JsonResponse: A JSON response containing a list of available rooms.
    """

    # Ensure the request is a POST request.
    if request.method == "POST":

        # Extract the event details from the request data.

        event_date = request.data["event_date"]

        start_time = request.data["start_time"]

        end_time = request.data["end_time"]

        number_of_attendees = request.data["number_of_attendees"]

        # Get the list of available rooms based on the provided event details.
        available_rooms = get_available_rooms(event_date, start_time,
                                              end_time, number_of_attendees)

        # Return the list of available rooms in the JSON response.
        return JsonResponse({"rooms": available_rooms})


@api_view(["GET"])
def get_rooms(request):
    if request.method == "GET":
        serializer = RoomSerializer(Room.objects.all(), many=True)
        return JsonResponse(serializer.data, safe=False, status=status.HTTP_200_OK)
    
@api_view(["POST"])
def authenticate_login(request):
    if request.method == "POST":
        token_id = request.data["token_id"]
        try:
            idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
            user_id = idinfo['sub']
            if not CustomUser.objects.filter(google_id=user_id).exists():
                user = CustomUser(is_logged_in=True,google_id=user_id, email=idinfo["email"],
                                  first_name=idinfo['given_name'], current_login_token=token_id,last_name=idinfo['family_name'], username=idinfo['sub'])
                user.set_unusable_password()
                user.save()
            user = CustomUser.objects.get(google_id=user_id)
            user.is_logged_in = True
            user.save()
            print(user.is_logged_in)
            return JsonResponse({"success": "User Successfully logged in"}, status=status.HTTP_200_OK)
        except Exception as e:
            return JsonResponse({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
        
@api_view(["POST"])
def logout(request):
    if request.method == "POST":
        token_id = request.data["token_id"]
    try:
        idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
    except:
        return JsonResponse({"error": "Invalid User Token"})
    if not CustomUser.objects.filter(google_id=idinfo['sub']).exists():
        return JsonResponse({"error": "User Not Found."}, status=status.HTTP_404_NOT_FOUND)
    user = CustomUser.objects.get(google_id = idinfo['sub'])
    user.is_logged_in = False
    user.current_login_token = None
    user.save()
    print(user.is_logged_in)
    return JsonResponse({"success": "User successfully logged out."})

@api_view(["GET"])
def get_room(request, pk):
    if request.method == "GET":
        try:
            room = Room.objects.get(pk=pk)
            # serializer = RoomSerializer(room)

            # print(serializer.data)
            room_details = {
                "id": room.id,
                "amenity": list(room.amenity.values_list("name", flat=True)),
                "name": room.name,
                "functions": list(room.functions.values_list("function", flat=True)),
                "is_booked": room.is_booked,
                "capacity": room.capacity,
                "equipment": list(room.equipment.values_list("name", flat=True))
            }

            # serializer = RoomSerializer(room_details)
            # return JsonResponse(serializer.data, status=status.HTTP_200_OK)
            return JsonResponse(room_details, status=status.HTTP_200_OK)

        except Room.DoesNotExist as e:
            return JsonResponse({"error": str(e)}, status=status.HTTP_404_NOT_FOUND)
    else:
        return JsonResponse({"error": "invalid request"}, status=status.HTTP_400_BAD_REQUEST)


@api_view(['POST'])
def catering(request):
    try:
        user = request.user
        data = json.loads(request.body)

        # get User details
        token_id = request.data["user_token"]
        idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
        user_id = idinfo['sub']
        user = CustomUser.objects.get(google_id=user_id)

        logger.info(f"Request Body: {data}")
        if request.method == "POST":

            meal_ids = [meal["id"] for meal in data["meal"]]

            catering_data = {
                "user": user,  
                "meals": meal_ids,  
                "special_dietary_requirements": data.get("special_dietary_requirements"),
                "bar_requirements": data.get("bar_requirements"),
            }

            catering_serializer = CateringSerializer(data=catering_data)

            if catering_serializer.is_valid():
                catering = catering_serializer.save()
                booking = Booking.objects.get(id=data["booking_id"])
                booking.catering = catering
                booking.save()
                logger.info("Catering details saved successfully")
                return JsonResponse({"success": True}, status=200)
            else:
                logger.error(f"Invalid Catering data: {catering_serializer.errors}")
                return JsonResponse({"error": "Invalid Catering data"}, status=400)

    except Exception as e:
        logger.error(f"Error during Catering save: {str(e)}")
        return JsonResponse({"error": str(e)}, status=400)

    return JsonResponse({"error": "Invalid request method"}, status=405)


@api_view(["GET"])
def get_available_meals(request):
    if request.method == "GET":
        serializer = AvailableMealSerializer(AvailableMeal.objects.all(), many=True)
        return JsonResponse(serializer.data, safe=False, status=status.HTTP_200_OK)

@api_view(["POST"])
def save_feedback(request):
    # Ensure the request is a POST request.
    if request.method == "POST":
        feedback_info = get_feedback_details(request.data)
        feedback_serializer = FeedbackSerializer(data=feedback_info)
        if feedback_serializer.is_valid():
            # Save the user id for use in creating a booking.
            feedback_serializer.save()
            return JsonResponse({"success": True}, status=status.HTTP_200_OK)
        else:
            return JsonResponse({"error": "Failed to save feedback details"}, status=status.HTTP_400_BAD_REQUEST)
    else:
        return JsonResponse({"error": "Post request not found"}, status=status.HTTP_404_NOT_FOUND)

@api_view(["GET"])
def run_creds(request):
    if request.method == "GET":
        creds = init_creds()

        print(add_booking_to_calendar(None, creds))
        return JsonResponse({"success": "event was created"}, status=status.HTTP_200_OK)

def view_events_control(request, object_id):
    booking = Booking.objects.get(id=object_id)
    return render(request, "sabreapi/control_sheet.html", {"booking": booking})
    



def approve_booking(request,id):
    """Approves a user's booking and adds it to the calendar"""

    booking = Booking.objects.get(id=id)
    if booking.is_approved:
        return JsonResponse({"message": "Booking is already approved."}, safe=False)
    booking.is_approved = True
    booking.save()
    creds = init_creds()
    add_booking_to_calendar(booking, creds)
    send_approval_email(booking.user)
    return HttpResponseRedirect(reverse('admin:sabreapi_booking_change', args=(booking.id,)))

def print_events_control(request, id):
    """Makes a pdf of the event control sheet."""
    booking = Booking.objects.get(id=id)
    context = {"booking": booking}
    html = render_to_string('sabreapi/control_sheet.html', context)
    result = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return None