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