302 lines
9.4 KiB
Python
302 lines
9.4 KiB
Python
from django.http import JsonResponse
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.forms.models import model_to_dict
|
|
|
|
from rest_framework.views import APIView
|
|
|
|
from bookings.models import Ticket
|
|
from events.models import Event
|
|
from mobile_api.utils import validate_token_and_get_user
|
|
|
|
|
|
def _ticket_to_dict(ticket):
|
|
"""
|
|
Helper to serialise a Ticket instance into a simple dict suitable for JSON.
|
|
"""
|
|
data = model_to_dict(
|
|
ticket,
|
|
fields=[
|
|
"id",
|
|
"ticket_name",
|
|
"price_per_ticket",
|
|
"maximum_quantity",
|
|
"available_quantity",
|
|
"is_active",
|
|
"created_date",
|
|
"updated_date",
|
|
],
|
|
)
|
|
data["event_id"] = ticket.event_id
|
|
return data
|
|
|
|
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
|
class TicketCreateAPI(APIView):
|
|
"""
|
|
Create a new Ticket.
|
|
|
|
Expected JSON body (along with token & username used across mobile_api):
|
|
{
|
|
"token": "...",
|
|
"username": "...",
|
|
"event_id": 1,
|
|
"ticket_name": "VIP",
|
|
"price_per_ticket": 1000.0,
|
|
"maximum_quantity": 50,
|
|
"available_quantity": 50, # optional, defaults to maximum_quantity
|
|
"is_active": true # optional, defaults to true
|
|
}
|
|
"""
|
|
|
|
def post(self, request):
|
|
try:
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
|
if error_response:
|
|
return error_response
|
|
|
|
event_id = data.get("event_id")
|
|
ticket_name = data.get("ticket_name")
|
|
price_per_ticket = data.get("price_per_ticket")
|
|
maximum_quantity = data.get("maximum_quantity")
|
|
available_quantity = data.get("available_quantity")
|
|
is_active = data.get("is_active", True)
|
|
|
|
if not event_id or not ticket_name or price_per_ticket is None or maximum_quantity is None:
|
|
return JsonResponse(
|
|
{
|
|
"status": "error",
|
|
"message": "event_id, ticket_name, price_per_ticket and maximum_quantity are required.",
|
|
},
|
|
status=400,
|
|
)
|
|
|
|
try:
|
|
event = Event.objects.get(id=event_id)
|
|
except Event.DoesNotExist:
|
|
return JsonResponse(
|
|
{"status": "error", "message": "Event not found."},
|
|
status=404,
|
|
)
|
|
|
|
try:
|
|
price_per_ticket = float(price_per_ticket)
|
|
maximum_quantity = int(maximum_quantity)
|
|
if available_quantity is not None:
|
|
available_quantity = int(available_quantity)
|
|
else:
|
|
available_quantity = maximum_quantity
|
|
except (TypeError, ValueError):
|
|
return JsonResponse(
|
|
{
|
|
"status": "error",
|
|
"message": "price_per_ticket, maximum_quantity and available_quantity must be numeric.",
|
|
},
|
|
status=400,
|
|
)
|
|
|
|
if maximum_quantity <= 0:
|
|
return JsonResponse(
|
|
{
|
|
"status": "error",
|
|
"message": "maximum_quantity must be greater than zero.",
|
|
},
|
|
status=400,
|
|
)
|
|
|
|
ticket = Ticket.objects.create(
|
|
event=event,
|
|
ticket_name=ticket_name,
|
|
price_per_ticket=price_per_ticket,
|
|
maximum_quantity=maximum_quantity,
|
|
available_quantity=available_quantity,
|
|
is_active=bool(is_active),
|
|
)
|
|
|
|
return JsonResponse(
|
|
{"status": "success", "ticket": _ticket_to_dict(ticket)},
|
|
status=201,
|
|
)
|
|
|
|
except Exception as e:
|
|
return JsonResponse(
|
|
{"status": "error", "message": str(e)},
|
|
status=500,
|
|
)
|
|
|
|
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
|
class TicketListAPI(APIView):
|
|
"""
|
|
List tickets, optionally filtered by event_id.
|
|
|
|
Expected JSON body:
|
|
{
|
|
"token": "...",
|
|
"username": "...",
|
|
"event_id": 1 # optional
|
|
}
|
|
"""
|
|
|
|
def post(self, request):
|
|
try:
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
|
if error_response:
|
|
return error_response
|
|
|
|
event_id = data.get("event_id")
|
|
|
|
tickets_qs = Ticket.objects.all().order_by("-created_date")
|
|
if event_id:
|
|
tickets_qs = tickets_qs.filter(event_id=event_id)
|
|
|
|
tickets = [_ticket_to_dict(t) for t in tickets_qs]
|
|
|
|
return JsonResponse(
|
|
{"status": "success", "tickets": tickets},
|
|
status=200,
|
|
)
|
|
except Exception as e:
|
|
return JsonResponse(
|
|
{"status": "error", "message": str(e)},
|
|
status=500,
|
|
)
|
|
|
|
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
|
class TicketUpdateAPI(APIView):
|
|
"""
|
|
Update an existing Ticket.
|
|
|
|
Expected JSON body:
|
|
{
|
|
"token": "...",
|
|
"username": "...",
|
|
"ticket_id": 1,
|
|
"ticket_name": "...", # optional
|
|
"price_per_ticket": 1000.0, # optional
|
|
"maximum_quantity": 50, # optional
|
|
"available_quantity": 50, # optional
|
|
"is_active": true # optional
|
|
}
|
|
"""
|
|
|
|
def post(self, request):
|
|
try:
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
|
if error_response:
|
|
return error_response
|
|
|
|
ticket_id = data.get("ticket_id")
|
|
if not ticket_id:
|
|
return JsonResponse(
|
|
{"status": "error", "message": "ticket_id is required."},
|
|
status=400,
|
|
)
|
|
|
|
try:
|
|
ticket = Ticket.objects.get(id=ticket_id)
|
|
except Ticket.DoesNotExist:
|
|
return JsonResponse(
|
|
{"status": "error", "message": "Ticket not found."},
|
|
status=404,
|
|
)
|
|
|
|
# Optional updates
|
|
ticket_name = data.get("ticket_name")
|
|
price_per_ticket = data.get("price_per_ticket")
|
|
maximum_quantity = data.get("maximum_quantity")
|
|
available_quantity = data.get("available_quantity")
|
|
is_active = data.get("is_active")
|
|
|
|
if ticket_name is not None:
|
|
ticket.ticket_name = ticket_name
|
|
|
|
try:
|
|
if price_per_ticket is not None:
|
|
ticket.price_per_ticket = float(price_per_ticket)
|
|
if maximum_quantity is not None:
|
|
maximum_quantity = int(maximum_quantity)
|
|
if maximum_quantity <= 0:
|
|
return JsonResponse(
|
|
{
|
|
"status": "error",
|
|
"message": "maximum_quantity must be greater than zero.",
|
|
},
|
|
status=400,
|
|
)
|
|
ticket.maximum_quantity = maximum_quantity
|
|
if available_quantity is not None:
|
|
ticket.available_quantity = int(available_quantity)
|
|
except (TypeError, ValueError):
|
|
return JsonResponse(
|
|
{
|
|
"status": "error",
|
|
"message": "price_per_ticket, maximum_quantity and available_quantity must be numeric.",
|
|
},
|
|
status=400,
|
|
)
|
|
|
|
if is_active is not None:
|
|
ticket.is_active = bool(is_active)
|
|
|
|
ticket.save()
|
|
|
|
return JsonResponse(
|
|
{"status": "success", "ticket": _ticket_to_dict(ticket)},
|
|
status=200,
|
|
)
|
|
except Exception as e:
|
|
return JsonResponse(
|
|
{"status": "error", "message": str(e)},
|
|
status=500,
|
|
)
|
|
|
|
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
|
class TicketDeleteAPI(APIView):
|
|
"""
|
|
Delete an existing Ticket.
|
|
|
|
Expected JSON body:
|
|
{
|
|
"token": "...",
|
|
"username": "...",
|
|
"ticket_id": 1
|
|
}
|
|
"""
|
|
|
|
def post(self, request):
|
|
try:
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
|
if error_response:
|
|
return error_response
|
|
|
|
ticket_id = data.get("ticket_id")
|
|
if not ticket_id:
|
|
return JsonResponse(
|
|
{"status": "error", "message": "ticket_id is required."},
|
|
status=400,
|
|
)
|
|
|
|
try:
|
|
ticket = Ticket.objects.get(id=ticket_id)
|
|
except Ticket.DoesNotExist:
|
|
return JsonResponse(
|
|
{"status": "error", "message": "Ticket not found."},
|
|
status=404,
|
|
)
|
|
|
|
ticket.delete()
|
|
|
|
return JsonResponse(
|
|
{"status": "success", "message": "Ticket deleted successfully."},
|
|
status=200,
|
|
)
|
|
except Exception as e:
|
|
return JsonResponse(
|
|
{"status": "error", "message": str(e)},
|
|
status=500,
|
|
)
|
|
|