Files
booking_backend/adventrues/views.py
2026-04-10 20:51:43 -05:00

118 lines
4.5 KiB
Python

from django.utils.dateparse import parse_datetime
from rest_framework import generics, permissions, viewsets
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response
from rest_framework.views import APIView
from booking.models import Booking
from marketing.mixins import AdventureListingClickTrackingMixin
from .models import AdventureOffering
from .serializers import AdventureOfferingSerializer
class PublicAdventureListView(generics.ListAPIView):
serializer_class = AdventureOfferingSerializer
permission_classes = (permissions.AllowAny,)
def get_queryset(self):
queryset = AdventureOffering.objects.filter(is_active=True).select_related("category", "vendor").prefetch_related("images")
params = self.request.query_params
category = params.get("category")
if category:
if category.isdigit():
queryset = queryset.filter(category_id=category)
else:
queryset = queryset.filter(category__slug=category)
location = params.get("location")
if location:
queryset = queryset.filter(meeting_point__icontains=location)
vendor_slug = params.get("vendor_slug")
if vendor_slug:
queryset = queryset.filter(vendor__slug=vendor_slug)
min_price = params.get("min_price")
if min_price:
queryset = queryset.filter(price_per_person__gte=min_price)
max_price = params.get("max_price")
if max_price:
queryset = queryset.filter(price_per_person__lte=max_price)
start = parse_datetime(params.get("available_from", "")) if params.get("available_from") else None
end = parse_datetime(params.get("available_to", "")) if params.get("available_to") else None
if start and end:
blocked_offering_ids = (
Booking.objects.filter(
adventure_offering__isnull=False,
status__in=[Booking.Status.REQUESTED, Booking.Status.APPROVED, Booking.Status.CONFIRMED],
)
.filter(starts_at__lt=end, ends_at__gt=start)
.values_list("adventure_offering_id", flat=True)
)
queryset = queryset.exclude(id__in=blocked_offering_ids)
return queryset
class PublicAdventureDetailView(AdventureListingClickTrackingMixin, generics.RetrieveAPIView):
serializer_class = AdventureOfferingSerializer
permission_classes = (permissions.AllowAny,)
lookup_field = "public_id"
def get_queryset(self):
return AdventureOffering.objects.filter(is_active=True).select_related("category", "vendor").prefetch_related("images")
class VendorAdventureViewSet(viewsets.ModelViewSet):
serializer_class = AdventureOfferingSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_queryset(self):
user = self.request.user
if not user.is_vendor or not hasattr(user, "vendor_profile"):
return AdventureOffering.objects.none()
return (
AdventureOffering.objects.filter(vendor=user.vendor_profile)
.select_related("category", "vendor")
.prefetch_related("images")
)
def perform_create(self, serializer):
user = self.request.user
if not user.is_vendor or not hasattr(user, "vendor_profile"):
raise PermissionDenied("Only vendors can create adventure offerings.")
serializer.save(vendor=user.vendor_profile)
class VendorAdventureStorefrontView(APIView):
permission_classes = (permissions.AllowAny,)
def get(self, request, slug):
offerings = (
AdventureOffering.objects.filter(vendor__slug=slug, is_active=True)
.select_related("category", "vendor")
.prefetch_related("images")
)
if not offerings.exists():
return Response({"detail": "Vendor adventure storefront not found."}, status=404)
vendor = offerings.first().vendor
return Response(
{
"vendor": {
"business_name": vendor.business_name,
"slug": vendor.slug,
"description": vendor.description,
"contact_email": vendor.contact_email,
"contact_phone": vendor.contact_phone,
"city": vendor.city,
"country": vendor.country,
},
"offerings": AdventureOfferingSerializer(offerings, many=True, context={"request": request}).data,
}
)