1127 lines
40 KiB
Python
1127 lines
40 KiB
Python
import datetime
|
|
from django.shortcuts import get_object_or_404
|
|
from django.utils import timezone
|
|
from django_filters.rest_framework import DjangoFilterBackend
|
|
import googlemaps
|
|
from rest_framework import status, generics, mixins
|
|
from rest_framework.views import APIView
|
|
from django.conf import settings
|
|
from accounts import resource_action
|
|
from accounts.models import IAmPrincipalLocation
|
|
from goodtimes import constants
|
|
from django.db.models import Q, Count
|
|
from taggit.models import Tag
|
|
from django.utils.dateparse import parse_date
|
|
from goodtimes import services
|
|
from goodtimes.services import GoogleMapsservice
|
|
from goodtimes.utils import ApiResponse, CapacityError
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework_simplejwt.authentication import JWTAuthentication
|
|
from manage_cms.api.serializers import TagSerializer
|
|
from manage_events.api.serializers import (
|
|
AgeGroupsSerializer,
|
|
EventDateRangeSerializer,
|
|
EventMasterSearchSerializer,
|
|
EventMasterSerializer,
|
|
CreateEventSerializer,
|
|
CreateVenueSerializer,
|
|
EventCategorySerializer,
|
|
EventDetailSerializer,
|
|
EventReviewSerializer,
|
|
FreeUsageFeatureLimitSerializer,
|
|
IAmPrincipalLocationSerializer,
|
|
PrincipalPreferenceSerializer,
|
|
VenueSerializer,
|
|
EventListSerializer,
|
|
)
|
|
from manage_events.models import (
|
|
AgeGroups,
|
|
EventInteractionType,
|
|
EventMaster,
|
|
Event,
|
|
EventCategory,
|
|
EventPrincipalInteraction,
|
|
EventReview,
|
|
EventShare,
|
|
EventView,
|
|
Favorites,
|
|
FreeUsageFeatureLimit,
|
|
PrincipalPreference,
|
|
Venue,
|
|
)
|
|
import requests
|
|
|
|
from manage_events.utils import haversine_one, update_principal_location
|
|
from manage_subscriptions.models import PrincipalSubscription
|
|
from .filters import EventFilter
|
|
|
|
class FreeUsageFeatureLimitView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
model = FreeUsageFeatureLimit
|
|
serializer_class = FreeUsageFeatureLimitSerializer
|
|
|
|
def get(self, request):
|
|
obj = self.model.objects.first()
|
|
serializer = self.serializer_class(obj)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
class CreateEventApi(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
print("Data: ", request.data)
|
|
serializer = CreateEventSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
serializer.save(created_by=self.request.user, principal=self.request.user)
|
|
|
|
# Add additional logic for handling other relationships (e.g., Venue)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_201_CREATED,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
|
|
class EventEditAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
"""
|
|
Retrieve, update or delete a event instance.
|
|
"""
|
|
|
|
def get_object(self, pk):
|
|
try:
|
|
return Event.objects.get(pk=pk)
|
|
except Event.DoesNotExist:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors="Event not found",
|
|
)
|
|
|
|
def get(self, request, pk, format=None):
|
|
event = self.get_object(pk)
|
|
serializer = EventDetailSerializer(event)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
def patch(self, request, pk, format=None):
|
|
event = self.get_object(pk)
|
|
serializer = CreateEventSerializer(event, data=request.data, partial=True)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors=serializer.errors,
|
|
)
|
|
|
|
|
|
class CreateVenueApi(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
|
|
data = request.data.copy()
|
|
|
|
# Convert latitude and longitude to float and round to 8 decimal places
|
|
data["latitude"] = round(float(data["latitude"]), 8)
|
|
data["longitude"] = round(float(data["longitude"]), 8)
|
|
|
|
serializer = VenueSerializer(data=data, context={"request": request})
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
serializer.save(
|
|
created_by=self.request.user, principal=self.request.user, active=True
|
|
)
|
|
|
|
# Add additional logic for handling other relationships (e.g., Venue)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_201_CREATED,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
|
|
# # Prepare the email
|
|
# subject = f"Your Event Report for {start_date.month} {start_date.year}."
|
|
# body = f"Please find attached the event report for {start_date.month} {start_date.month}."
|
|
# email_service = EmailService(
|
|
# subject="Good Times - Report",
|
|
# to=[user.email],
|
|
# from_email=settings.EMAIL_HOST_USER,
|
|
# )
|
|
# email_service.attach(filename, buffer.getvalue(), "application/pdf")
|
|
|
|
# # Send the email
|
|
# email_service.send()
|
|
|
|
|
|
class VenueDeleteAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
"""
|
|
API view to set a venue's 'deleted' to True and 'active' to False.
|
|
"""
|
|
|
|
def patch(self, request, pk):
|
|
try:
|
|
venue = Venue.objects.get(pk=pk)
|
|
venue.deleted = True
|
|
venue.active = False
|
|
venue.save()
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data="Venue deleted successfully",
|
|
)
|
|
except Venue.DoesNotExist:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors="Venue not found",
|
|
)
|
|
|
|
|
|
class EventsAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
filter = request.query_params.get("filter", None)
|
|
query = request.query_params.get("query", None)
|
|
category_id = request.query_params.get("category_id", None)
|
|
params = [
|
|
"expensive",
|
|
"cheap",
|
|
"preference",
|
|
"today",
|
|
"tomorrow",
|
|
"category",
|
|
"key_guest",
|
|
"tags",
|
|
]
|
|
if filter not in params:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors="No filter found",
|
|
)
|
|
|
|
try:
|
|
if filter == "today":
|
|
events = services.EventFilterService.filter_events_for_today()
|
|
elif filter == "tomorrow":
|
|
events = services.EventFilterService.filter_events_for_tomorrow()
|
|
elif filter == "key_guest":
|
|
events = services.EventFilterService.filter_events_by_search(
|
|
search_query=query
|
|
)
|
|
elif filter == "category" and category_id is not None:
|
|
events = services.EventFilterService.filter_events_by_category(
|
|
int(category_id)
|
|
)
|
|
else:
|
|
events = services.EventFilterService.filter_events(
|
|
filter_type=filter, principal=request.user
|
|
)
|
|
# serializer = EventDetailSerializer(
|
|
# events, context={"request": request}, many=True
|
|
# )
|
|
serializer = EventListSerializer(
|
|
events, context={"request": request}, many=True
|
|
)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
except Exception as e:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors=str(e),
|
|
)
|
|
|
|
|
|
class MyEventsAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
filter_type = request.query_params.get("filter", None)
|
|
user = request.user
|
|
params = [
|
|
"draft",
|
|
"active",
|
|
"active_past",
|
|
"draft_past",
|
|
]
|
|
if filter_type not in params:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors="No filter found",
|
|
)
|
|
|
|
if filter_type == "draft":
|
|
events = services.MyEventFilterService.filter_my_events_draft(user)
|
|
elif filter_type == "active":
|
|
events = services.MyEventFilterService.filter_my_events_active(user)
|
|
elif filter_type == "active_past":
|
|
events = services.MyEventFilterService.filter_my_events_active_past(user)
|
|
elif filter_type == "draft_past":
|
|
events = services.MyEventFilterService.filter_my_events_draft_past(user)
|
|
else:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=constants.FAILURE,
|
|
errors="Invalid filter parameter",
|
|
)
|
|
|
|
serializer = EventDetailSerializer(
|
|
events, context={"request": request}, many=True
|
|
)
|
|
# serializer = EventListSerializer(
|
|
# events, context={"request": request}, many=True
|
|
# )
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
|
|
class PrinciaplPreferenceEventsAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
today = timezone.now().date()
|
|
try:
|
|
preferences = PrincipalPreference.objects.get(principal=request.user)
|
|
preferred_categories_ids = preferences.preferred_categories.values_list(
|
|
"id", flat=True
|
|
)
|
|
# Filter events based on user preferences and that are upcoming or ongoing
|
|
events = Event.objects.filter(
|
|
category__in=preferred_categories_ids, end_date__gte=today
|
|
).distinct()
|
|
|
|
if not events.exists():
|
|
# If no events found based on preferences, get future events
|
|
events = Event.objects.filter(start_date__gt=today)
|
|
serializer = EventDetailSerializer(events, many=True)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
except PrincipalPreference.DoesNotExist:
|
|
# If the user has no preferences, default to future events
|
|
events = Event.objects.filter(start_date__gt=today)
|
|
|
|
|
|
class EventDetailAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
try:
|
|
event = Event.objects.get(pk=pk)
|
|
interaction = services.InteractionCalculator(event)
|
|
interactions = interaction.calculate()
|
|
|
|
# Serialize your event data here
|
|
event_data = EventDetailSerializer(event, context={"request": request}).data
|
|
event_data["interactions"] = interactions
|
|
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=event_data,
|
|
)
|
|
except Event.DoesNotExist:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
message=constants.FAILURE,
|
|
errors=constants.RECORD_NOT_FOUND,
|
|
)
|
|
except CapacityError as e:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_405_METHOD_NOT_ALLOWED,
|
|
message=constants.FAILURE,
|
|
errors=str(e),
|
|
)
|
|
|
|
|
|
class VenueListView(generics.ListAPIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
serializer_class = VenueSerializer
|
|
|
|
def get_queryset(self):
|
|
# Ensures that a user sees only their venues
|
|
return Venue.objects.filter(
|
|
created_by=self.request.user, deleted=False, active=True
|
|
)
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
queryset = self.get_queryset()
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
# Customizing the response format
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
|
|
class VenueDetailView(generics.RetrieveUpdateDestroyAPIView):
|
|
queryset = Venue.objects.all()
|
|
serializer_class = VenueSerializer
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get_queryset(self):
|
|
# This ensures a user can only access their own venues
|
|
return self.queryset.filter(
|
|
created_by=self.request.user, deleted=False, active=True
|
|
)
|
|
|
|
|
|
class GeocodeAPIView(APIView):
|
|
authentication_classes = []
|
|
permission_classes = []
|
|
"""
|
|
API View to fetch latitude and longitude for a given address using the Google Maps Geocoding API.
|
|
"""
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
# Extract 'address' from query parameters
|
|
address = request.query_params.get("address")
|
|
print("address: ", address)
|
|
if not address:
|
|
return ApiResponse.error(
|
|
{"error": "Address parameter is missing."},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
# Call the get_lat_long method
|
|
lat_long = self.get_lat_long(address)
|
|
if lat_long:
|
|
return ApiResponse.success(
|
|
{"latitude": lat_long[0], "longitude": lat_long[1]}
|
|
)
|
|
else:
|
|
return ApiResponse.error(
|
|
{"error": "Failed to fetch latitude and longitude."},
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
)
|
|
|
|
def get_lat_long(self, address):
|
|
"""
|
|
Fetches latitude and longitude for a given address using the Google Maps Geocoding API.
|
|
"""
|
|
url = "https://maps.googleapis.com/maps/api/geocode/json?"
|
|
params = {
|
|
"address": address,
|
|
# "key": settings.GOOGLE_MAPS_API_KEY, # Replace with your actual API key
|
|
"key": "AIzaSyCQv-Cfzkh3cXerrui55oId7CDHhuIImhc", # Replace with your actual API key
|
|
}
|
|
|
|
response = requests.get(url, params=params)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
if data["status"] == "OK":
|
|
location = data["results"][0]["geometry"]["location"]
|
|
latitude = location["lat"]
|
|
longitude = location["lng"]
|
|
return latitude, longitude
|
|
else:
|
|
print(f"Geocoding failed: {data['status']}")
|
|
return None
|
|
else:
|
|
print(f"API request failed with status code: {response.status_code}")
|
|
return None
|
|
|
|
|
|
class EventCategoryListAPIView(generics.ListAPIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
queryset = EventCategory.objects.all()
|
|
serializer_class = EventCategorySerializer
|
|
|
|
|
|
class IAmPrincipalLocationAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
# Assuming there's a UserLocation model that stores user locations,
|
|
# and it has a ForeignKey to the user model.
|
|
try:
|
|
user_location = IAmPrincipalLocation.objects.filter(
|
|
principal=request.user
|
|
).last()
|
|
print("user_location: ", user_location)
|
|
serializer = IAmPrincipalLocationSerializer(user_location)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
except IAmPrincipalLocation.DoesNotExist:
|
|
return ApiResponse.error(
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
message="Location not found for the user.",
|
|
errors="No location data available for the current user.",
|
|
)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
data = request.data.copy()
|
|
|
|
# Convert latitude and longitude to float and round to 8 decimal places
|
|
latitude = round(float(data["latitude"]), 15)
|
|
longitude = round(float(data["longitude"]), 15)
|
|
|
|
try:
|
|
principal = request.user
|
|
location = IAmPrincipalLocation.objects.get(principal=principal)
|
|
|
|
# Update existing location
|
|
location.latitude = latitude
|
|
location.longitude = longitude
|
|
location.save()
|
|
|
|
# Update principal fields using the utility function
|
|
update_principal_location(principal, latitude, longitude)
|
|
|
|
serializer = IAmPrincipalLocationSerializer(
|
|
location, context={"request": request}
|
|
)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_200_OK,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
except IAmPrincipalLocation.DoesNotExist:
|
|
# Create a new location object
|
|
location = IAmPrincipalLocation.objects.create(
|
|
principal=principal, latitude=latitude, longitude=longitude
|
|
)
|
|
|
|
# Update principal fields using the utility function
|
|
update_principal_location(principal, latitude, longitude)
|
|
|
|
serializer = IAmPrincipalLocationSerializer(
|
|
location, context={"request": request}
|
|
)
|
|
return ApiResponse.success(
|
|
status=status.HTTP_201_CREATED,
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
)
|
|
|
|
except Exception as e:
|
|
print(f"Error occurred while saving location: {e}")
|
|
return ApiResponse.error(
|
|
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
message=constants.FAILURE,
|
|
errors=str(e),
|
|
)
|
|
|
|
|
|
class PrincipalPreferenceView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
principal = request.user
|
|
# Check if the principal has a subscription
|
|
if not PrincipalSubscription.has_principal_subscription(principal):
|
|
# Get the preferred categories from the request data
|
|
preferred_categories = request.data.get("preferred_categories", [])
|
|
|
|
# Get the category limit for free usage
|
|
category_limit = FreeUsageFeatureLimit.get_category_limit()
|
|
|
|
# Check if the principal is an event user and has exceeded the category limit
|
|
if principal.principal_type.name == resource_action.PRINCIPAL_TYPE_EVENT_USER and len(preferred_categories) > category_limit:
|
|
# Create an error message indicating that a paid subscription is required
|
|
error_message = f"Upgrade to paid subscription to select more than {category_limit} categories."
|
|
|
|
return ApiResponse.error(
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
message=error_message,
|
|
errors=error_message,
|
|
)
|
|
|
|
serializer = PrincipalPreferenceSerializer(
|
|
data=request.data, context={"request": request}
|
|
)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return ApiResponse.success(
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
status=status.HTTP_201_CREATED,
|
|
)
|
|
return ApiResponse.error(
|
|
message=constants.FAILURE,
|
|
errors=serializer.errors,
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
|
|
class PrincipalPreferenceDetailView(generics.RetrieveAPIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
serializer_class = PrincipalPreferenceSerializer
|
|
|
|
def get_object(self):
|
|
# Attempt to retrieve the authenticated user's preferences
|
|
user = self.request.user
|
|
obj, created = PrincipalPreference.objects.get_or_create(principal=user)
|
|
return obj
|
|
|
|
def retrieve(self, request, *args, **kwargs):
|
|
instance = self.get_object()
|
|
serializer = self.get_serializer(instance)
|
|
return ApiResponse.success(
|
|
data=serializer.data,
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
class EventPreferencesView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
model = EventCategory
|
|
serializer_class = EventCategorySerializer
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
"""Get all event categories for the authenticated user."""
|
|
obj = self.model.objects.filter(active=True, deleted=False)
|
|
serializer = self.serializer_class(obj, many=True, context={"request": request})
|
|
return ApiResponse.success(
|
|
data=serializer.data, message=constants.SUCCESS, status=status.HTTP_200_OK
|
|
)
|
|
|
|
|
|
class EventMasterSearchAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
serializer = EventMasterSearchSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
title = serializer.validated_data.get("title")
|
|
# Search for existing brands
|
|
existing_event_master = EventMaster.objects.filter(title__icontains=title)
|
|
if existing_event_master.exists():
|
|
# Return existing brands
|
|
return ApiResponse.success(
|
|
data=EventMasterSerializer(existing_event_master, many=True).data,
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
else:
|
|
# No brand found, return an empty list
|
|
return ApiResponse.success(
|
|
data=[],
|
|
message="No related EventMaster Found",
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
return ApiResponse.error(
|
|
message=constants.FAILURE,
|
|
errors=serializer.errors,
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
|
|
class ToggleFavoriteView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request, event_id, format=None):
|
|
principal = request.user
|
|
event = get_object_or_404(Event, pk=event_id)
|
|
|
|
favorite, created = Favorites.objects.get_or_create(
|
|
principal=principal, event=event
|
|
)
|
|
if not created:
|
|
favorite.delete()
|
|
return ApiResponse.success(
|
|
data="removed",
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
return ApiResponse.success(
|
|
data="added",
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_201_CREATED,
|
|
)
|
|
|
|
|
|
class EventStatusUpdateAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request, event_id):
|
|
principal = (
|
|
request.user
|
|
) # Assuming you're using some form of user authentication
|
|
event = get_object_or_404(Event, pk=event_id)
|
|
|
|
status_requested = request.data.get("status") # 'going' or 'interested'
|
|
if status_requested not in EventInteractionType.values:
|
|
return ApiResponse.error(
|
|
message=constants.FAILURE,
|
|
errors="Invalid status provided.",
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
interaction, created = EventPrincipalInteraction.objects.update_or_create(
|
|
principal=principal,
|
|
event=event,
|
|
defaults={"status": status_requested},
|
|
)
|
|
|
|
if created:
|
|
return ApiResponse.success(
|
|
data=status_requested,
|
|
message=f"Marked as {status_requested}.",
|
|
status=status.HTTP_201_CREATED,
|
|
)
|
|
else:
|
|
return ApiResponse.success(
|
|
data=status_requested,
|
|
message=f"Updated status to {status_requested}.",
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
# Filter Events within 10 KMs
|
|
class EventFilterByLocationAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
principal = request.user
|
|
today = timezone.now().date()
|
|
# Fetching user location from IAmPrincipalLocation
|
|
try:
|
|
user_location = IAmPrincipalLocation.objects.filter(
|
|
principal=principal
|
|
).last()
|
|
print("user_location: ", user_location)
|
|
print("principal_user_location: ", user_location.principal)
|
|
user_lat = user_location.latitude
|
|
user_lon = user_location.longitude
|
|
except IAmPrincipalLocation.DoesNotExist:
|
|
return ApiResponse.error(
|
|
errors=constants.FAILURE,
|
|
message="User location not set.",
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
max_distance_km = 10 # Set your desired maximum distance
|
|
current_and_future_events_query = Q(
|
|
active=True,
|
|
deleted=False,
|
|
draft=False,
|
|
created_by__is_active=True,
|
|
) & (Q(end_date__gte=today))
|
|
|
|
# Get the queryset based on the filter conditions
|
|
events_queryset = Event.objects.filter(current_and_future_events_query)
|
|
|
|
venue_ids = events_queryset.values_list("venue", flat=True).distinct()
|
|
venues = Venue.objects.filter(id__in=venue_ids)
|
|
print("venues: ", venues)
|
|
|
|
venues_within_range = []
|
|
for venue in venues:
|
|
if venue.longitude is None or venue.latitude is None:
|
|
continue # Skip this venue if longitude or latitude is missing
|
|
distance = haversine_one(
|
|
user_lon, user_lat, venue.longitude, venue.latitude
|
|
)
|
|
print("distance: ", distance)
|
|
if distance <= max_distance_km:
|
|
print(
|
|
venue
|
|
) # This will print the venue object, or whatever __str__ returns for the venue model
|
|
venues_within_range.append(venue.id)
|
|
print("venues_within_range: ", venues_within_range)
|
|
# venues_data = [venue_to_dict(venue) for venue in venues_within_range]
|
|
events = events_queryset.filter(venue__id__in=venues_within_range)
|
|
|
|
# Serialize and return the filtered events
|
|
serializer = EventDetailSerializer(
|
|
events, context={"request": request}, many=True
|
|
)
|
|
return ApiResponse.success(
|
|
data=serializer.data,
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
# Filter Principal's Favorites Events
|
|
class FavoriteEventsList(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
principal = request.user
|
|
events = Event.objects.filter(
|
|
id__in=Favorites.objects.filter(principal=principal)
|
|
.select_related("event")
|
|
.values_list("event_id", flat=True),
|
|
deleted=False,
|
|
active=True,
|
|
draft=False,
|
|
)
|
|
serializer = EventDetailSerializer(
|
|
events, context={"request": request}, many=True
|
|
)
|
|
return ApiResponse.success(
|
|
data=serializer.data,
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
class EventDateRangeAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
start_date_str = request.query_params.get("start_date")
|
|
end_date_str = request.query_params.get("end_date")
|
|
|
|
# Attempt to parse the dates from the query parameters
|
|
start_date = parse_date(start_date_str)
|
|
end_date = parse_date(end_date_str)
|
|
|
|
# Validate the parsed dates
|
|
if not start_date or not end_date:
|
|
return ApiResponse.error(
|
|
errors={
|
|
"start_date": "Invalid or missing",
|
|
"end_date": "Invalid or missing",
|
|
},
|
|
message=constants.FAILURE,
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
events = Event.objects.filter(
|
|
Q(end_date__gte=start_date)
|
|
& Q(start_date__lte=end_date)
|
|
& Q(deleted=False)
|
|
& Q(active=True)
|
|
& Q(draft=False)
|
|
)
|
|
|
|
serializer = EventDetailSerializer(
|
|
events, context={"request": request}, many=True
|
|
)
|
|
return ApiResponse.success(
|
|
data=serializer.data,
|
|
message=constants.SUCCESS,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
class EventReviewCreateAPIView(mixins.CreateModelMixin, generics.GenericAPIView):
|
|
queryset = EventReview.objects.filter(active=True, deleted=False)
|
|
serializer_class = EventReviewSerializer
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
serializer = self.get_serializer(data=request.data)
|
|
if serializer.is_valid():
|
|
self.perform_create(serializer)
|
|
headers = self.get_success_headers(serializer.data)
|
|
return ApiResponse.success(
|
|
"Review created successfully.",
|
|
data=serializer.data,
|
|
status=status.HTTP_201_CREATED,
|
|
)
|
|
else:
|
|
return ApiResponse.error(
|
|
"Validation error.",
|
|
errors=serializer.errors,
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
|
|
class CheckPrincipalPreference(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
try:
|
|
principal = request.user
|
|
exists = PrincipalPreference.objects.filter(principal=principal).exists()
|
|
return ApiResponse.success(
|
|
message=constants.SUCCESS,
|
|
data=exists,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
except Exception as e:
|
|
return ApiResponse.error(
|
|
message=constants.FAILURE,
|
|
errors=str(e),
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
|
|
# class PrincipalEventsInteractionView(APIView):
|
|
# authentication_classes = [JWTAuthentication]
|
|
# permission_classes = [IsAuthenticated]
|
|
|
|
# def get(self, request, *args, **kwargs):
|
|
# principal = self.request.user
|
|
# interactions = EventPrincipalInteraction.objects.filter(
|
|
# principal=principal
|
|
# ).prefetch_related("event")
|
|
|
|
# # Prefetch related events, sorting them by start_date
|
|
# events = Event.objects.filter(
|
|
# id__in=[interaction.event_id for interaction in interactions]
|
|
# ).order_by("-start_date")
|
|
# serializer = EventDetailSerializer(
|
|
# events, context={"request": request}, many=True
|
|
# )
|
|
# return ApiResponse.success(
|
|
# message=constants.SUCCESS,
|
|
# data=serializer.data,
|
|
# status=status.HTTP_200_OK,
|
|
# )
|
|
|
|
|
|
class PrincipalEventsInteractionView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
principal = self.request.user
|
|
interactions = EventPrincipalInteraction.objects.filter(
|
|
principal=principal
|
|
).prefetch_related("event")
|
|
favorite_events = Favorites.objects.filter(
|
|
principal=principal
|
|
).prefetch_related("event")
|
|
|
|
event_ids = set(interaction.event.id for interaction in interactions) | set(
|
|
favorite.event.id for favorite in favorite_events
|
|
)
|
|
|
|
events = Event.objects.filter(id__in=event_ids).order_by("-start_date")
|
|
events = list(
|
|
events
|
|
) # To ensure that the queryset is evaluated and we don't send a QuerySet object in the serializer context
|
|
|
|
serializer = EventDetailSerializer(
|
|
events, context={"request": request}, many=True
|
|
)
|
|
return ApiResponse.success(
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
class TagListView(generics.ListAPIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
serializer_class = TagSerializer
|
|
|
|
def get_queryset(self):
|
|
return Tag.objects.all().distinct()
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
queryset = self.get_queryset()
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return ApiResponse.success(
|
|
message=constants.SUCCESS,
|
|
data=serializer.data,
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
class CaptureEventViewAPIView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request, pk):
|
|
try:
|
|
event = Event.objects.get(pk=pk)
|
|
user = request.user
|
|
location_parts = [user.city, user.state, user.country]
|
|
location = " ".join(part for part in location_parts if part)
|
|
|
|
EventView.objects.create(event=event, principal=user, location=location)
|
|
|
|
return ApiResponse.success(
|
|
message=constants.SUCCESS,
|
|
data="Event view recorded successfully.",
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
except Event.DoesNotExist:
|
|
return ApiResponse.error(
|
|
message=constants.FAILURE,
|
|
errors="Event not found.",
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
|
|
class EventShareView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request, pk):
|
|
try:
|
|
event = Event.objects.get(id=pk)
|
|
except Event.DoesNotExist:
|
|
return ApiResponse.error(
|
|
message=constants.FAILURE,
|
|
errors="Event not found.",
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
# Incrementing the social media shares count
|
|
event.increment_shares()
|
|
|
|
user = request.user # Assuming the user is authenticated
|
|
EventShare.objects.create(principal=user, event=event)
|
|
|
|
return ApiResponse.success(
|
|
message=constants.SUCCESS,
|
|
data="Event shared successfully.",
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
class AgeGroupListView(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
serializer_class = AgeGroupsSerializer
|
|
model = AgeGroups
|
|
|
|
def get(self, request):
|
|
queryset = self.model.objects.filter(active=True)
|
|
serializer = self.serializer_class(queryset, many=True)
|
|
return ApiResponse.success(message=constants.SUCCESS, data=serializer.data)
|
|
|
|
|
|
class EventListView(generics.ListAPIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
serializer_class = EventListSerializer
|
|
filter_backends = [DjangoFilterBackend]
|
|
filterset_class = EventFilter
|
|
|
|
def get_queryset(self):
|
|
"""
|
|
Returns a queryset of events filtered by the user's preferences and subscription status.
|
|
"""
|
|
principal = self.request.user
|
|
|
|
# Filter the base queryset to only include active, non-draft, non-deleted events with an end date in the future
|
|
queryset = Event.objects.filter(
|
|
active=True,
|
|
draft=False,
|
|
deleted=False,
|
|
end_date__gte=timezone.now().date()
|
|
)
|
|
|
|
# If no filter is applied and the user does not have a subscription,
|
|
# only show events that match the user's preferred categories
|
|
if not self.request.query_params or not PrincipalSubscription.has_principal_subscription(principal):
|
|
# Get the user's preferred categories
|
|
preferences = PrincipalPreference.objects.get(principal=principal)
|
|
preferred_categories_ids = preferences.preferred_categories.values_list("id", flat=True)
|
|
|
|
# Filter the queryset to only include events in the user's preferred categories
|
|
queryset = queryset.filter(category__in=preferred_categories_ids).order_by("start_date")
|
|
|
|
return queryset
|
|
|
|
def filter_queryset(self, queryset):
|
|
queryset = super().filter_queryset(queryset)
|
|
|
|
# Get query parameters
|
|
latitude = self.request.query_params.get("latitude", "")
|
|
longitude = self.request.query_params.get("longitude", "")
|
|
ordering = self.request.query_params.get("sort", "")
|
|
|
|
# Handle nearest location sorting
|
|
if latitude and longitude and "nearest" in ordering:
|
|
queryset = self.apply_nearest_filter(queryset, latitude, longitude)
|
|
|
|
# Handle popularity and latest sorting
|
|
queryset = self.apply_sorting(queryset, ordering)
|
|
|
|
return queryset
|
|
|
|
def apply_nearest_filter(self, queryset, latitude, longitude):
|
|
gmaps_service = GoogleMapsservice()
|
|
return gmaps_service.get_nearest_events(queryset, float(latitude), float(longitude))
|
|
|
|
def apply_sorting(self, queryset, ordering):
|
|
# Split ordering fields and process each field
|
|
ordering_fields = [field.lstrip("-") for field in ordering.split(",")]
|
|
|
|
# Remove 'nearest' from ordering as it's handled separately
|
|
if "nearest" in ordering_fields:
|
|
ordering_fields.remove("nearest")
|
|
ordering = ordering.replace("nearest", "")
|
|
|
|
# Annotate with popularity and order it if requested
|
|
if "popularity" in ordering_fields:
|
|
queryset = queryset.annotate(popularity=Count("interaction_event")).order_by("-popularity")
|
|
|
|
# order latest record and by default sorting
|
|
if "latest" in ordering_fields:
|
|
queryset = queryset.order_by("start_date")
|
|
|
|
if "price" in ordering_fields:
|
|
queryset = queryset.order_by('entry_fee')
|
|
|
|
return queryset
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
queryset = self.filter_queryset(self.get_queryset())
|
|
page = self.paginate_queryset(queryset)
|
|
if page is not None:
|
|
serializer = self.get_serializer(page, many=True)
|
|
return self.get_paginated_response(serializer.data)
|
|
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) |