generated from bisco/codex-bootstrap
129 lines
4.4 KiB
Python
129 lines
4.4 KiB
Python
from django.shortcuts import get_object_or_404
|
|
from rest_framework import status
|
|
from rest_framework.decorators import api_view, authentication_classes, permission_classes, throttle_classes
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.response import Response
|
|
from rest_framework.throttling import AnonRateThrottle
|
|
|
|
from shows.models import Performance
|
|
|
|
from .serializers import (
|
|
ReservationConfirmResponseSerializer,
|
|
ReservationConfirmSerializer,
|
|
ReservationCreateResponseSerializer,
|
|
ReservationCreateSerializer,
|
|
ReservationQRResponseSerializer,
|
|
)
|
|
from .services import (
|
|
AlreadyConfirmedReservation,
|
|
ExpiredToken,
|
|
InvalidToken,
|
|
NotEnoughSeats,
|
|
PerformanceNotAvailable,
|
|
ReservationNotConfirmed,
|
|
confirm_reservation_from_token,
|
|
create_pending_reservation,
|
|
retrieve_reservation_qr_from_token,
|
|
)
|
|
|
|
|
|
class ReservationCreateThrottle(AnonRateThrottle):
|
|
scope = "reservation_create"
|
|
|
|
|
|
class ReservationConfirmThrottle(AnonRateThrottle):
|
|
scope = "reservation_confirm"
|
|
|
|
|
|
@api_view(["POST"])
|
|
@authentication_classes([])
|
|
@permission_classes([AllowAny])
|
|
@throttle_classes([ReservationCreateThrottle])
|
|
def create_reservation(request, performance_id):
|
|
get_object_or_404(Performance, pk=performance_id, show__is_published=True)
|
|
|
|
serializer = ReservationCreateSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
try:
|
|
result = create_pending_reservation(
|
|
performance_id=performance_id,
|
|
name=serializer.validated_data["name"],
|
|
email=serializer.validated_data["email"],
|
|
phone=serializer.validated_data.get("phone", ""),
|
|
party_size=serializer.validated_data["party_size"],
|
|
notes=serializer.validated_data.get("notes", ""),
|
|
)
|
|
except (NotEnoughSeats, PerformanceNotAvailable) as exc:
|
|
return Response(
|
|
{"status": "booking_unavailable", "detail": str(exc)},
|
|
status=status.HTTP_409_CONFLICT,
|
|
)
|
|
|
|
response_serializer = ReservationCreateResponseSerializer(
|
|
{
|
|
"id": result.reservation.id,
|
|
"status": result.reservation.status,
|
|
"performance_id": result.reservation.performance_id,
|
|
"party_size": result.reservation.party_size,
|
|
"message": "Reservation created. Please check your email to confirm it.",
|
|
}
|
|
)
|
|
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
|
|
|
|
|
|
@api_view(["GET", "POST"])
|
|
@throttle_classes([ReservationConfirmThrottle])
|
|
def confirm_reservation(request):
|
|
payload = request.query_params if request.method == "GET" else request.data
|
|
serializer = ReservationConfirmSerializer(data=payload)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
try:
|
|
result = confirm_reservation_from_token(serializer.validated_data["token"])
|
|
except InvalidToken as exc:
|
|
return Response(
|
|
{"status": "invalid_token", "detail": str(exc)},
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
)
|
|
except ExpiredToken as exc:
|
|
return Response(
|
|
{"status": "token_expired", "detail": str(exc)},
|
|
status=status.HTTP_410_GONE,
|
|
)
|
|
except NotEnoughSeats as exc:
|
|
return Response(
|
|
{"status": "not_enough_seats", "detail": str(exc)},
|
|
status=status.HTTP_409_CONFLICT,
|
|
)
|
|
except AlreadyConfirmedReservation as exc:
|
|
return Response(
|
|
{"status": "already_confirmed", "detail": str(exc)},
|
|
status=status.HTTP_409_CONFLICT,
|
|
)
|
|
|
|
response_serializer = ReservationConfirmResponseSerializer(result)
|
|
return Response(response_serializer.data)
|
|
|
|
|
|
@api_view(["GET"])
|
|
def retrieve_reservation_qr(request):
|
|
serializer = ReservationConfirmSerializer(data=request.query_params)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
try:
|
|
result = retrieve_reservation_qr_from_token(serializer.validated_data["token"])
|
|
except InvalidToken as exc:
|
|
return Response(
|
|
{"status": "invalid_token", "detail": str(exc)},
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
)
|
|
except ReservationNotConfirmed as exc:
|
|
return Response(
|
|
{"status": "reservation_not_confirmed", "detail": str(exc)},
|
|
status=status.HTTP_409_CONFLICT,
|
|
)
|
|
|
|
response_serializer = ReservationQRResponseSerializer(result)
|
|
return Response(response_serializer.data)
|