The new updates of partners and user
Made-with: Cursor
This commit is contained in:
246
events/api.py
Normal file
246
events/api.py
Normal file
@@ -0,0 +1,246 @@
|
||||
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 datetime import datetime
|
||||
|
||||
from events.models import Event
|
||||
from master_data.models import EventType
|
||||
from mobile_api.utils import validate_token_and_get_user
|
||||
from eventify_logger.services import log
|
||||
|
||||
|
||||
def _event_to_dict(event, request=None):
|
||||
"""Serialize Event for JSON."""
|
||||
data = model_to_dict(
|
||||
event,
|
||||
fields=[
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"start_time",
|
||||
"end_time",
|
||||
"all_year_event",
|
||||
"latitude",
|
||||
"longitude",
|
||||
"pincode",
|
||||
"district",
|
||||
"state",
|
||||
"place",
|
||||
"venue_name",
|
||||
"event_status",
|
||||
"cancelled_reason",
|
||||
"important_information",
|
||||
"source",
|
||||
"created_date",
|
||||
],
|
||||
)
|
||||
# Add event_type info
|
||||
data["event_type"] = {
|
||||
"id": event.event_type.id,
|
||||
"event_type": event.event_type.event_type,
|
||||
}
|
||||
if event.event_type.event_type_icon:
|
||||
if request:
|
||||
data["event_type"]["event_type_icon"] = request.build_absolute_uri(event.event_type.event_type_icon.url)
|
||||
else:
|
||||
data["event_type"]["event_type_icon"] = event.event_type.event_type_icon.url
|
||||
else:
|
||||
data["event_type"]["event_type_icon"] = None
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@method_decorator(csrf_exempt, name="dispatch")
|
||||
class EventCreateAPI(APIView):
|
||||
"""
|
||||
Create Event API.
|
||||
Body: token, username (required);
|
||||
name, description, latitude, longitude, pincode, place, event_type_id (required);
|
||||
start_date, end_date, start_time, end_time, all_year_event, venue_name,
|
||||
event_status, cancelled_reason, important_information, source, district, state (optional).
|
||||
Returns: created event data.
|
||||
"""
|
||||
|
||||
def post(self, request):
|
||||
try:
|
||||
user, token, data, error_response = validate_token_and_get_user(request, error_status_code=True)
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
# Extract required fields
|
||||
name = data.get("name")
|
||||
description = data.get("description")
|
||||
latitude = data.get("latitude")
|
||||
longitude = data.get("longitude")
|
||||
pincode = data.get("pincode")
|
||||
place = data.get("place")
|
||||
event_type_id = data.get("event_type_id") or data.get("event_type")
|
||||
|
||||
# Validate required fields
|
||||
if not all([name, description, latitude, longitude, pincode, place, event_type_id]):
|
||||
return JsonResponse(
|
||||
{
|
||||
"status": "error",
|
||||
"message": "name, description, latitude, longitude, pincode, place, and event_type_id are required.",
|
||||
},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Validate event_type exists
|
||||
try:
|
||||
event_type = EventType.objects.get(id=event_type_id)
|
||||
except EventType.DoesNotExist:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "EventType not found."},
|
||||
status=404,
|
||||
)
|
||||
|
||||
# Validate latitude and longitude
|
||||
try:
|
||||
latitude = float(latitude)
|
||||
if latitude < -90 or latitude > 90:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "latitude must be between -90 and 90."},
|
||||
status=400,
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "latitude must be numeric."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
try:
|
||||
longitude = float(longitude)
|
||||
if longitude < -180 or longitude > 180:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "longitude must be between -180 and 180."},
|
||||
status=400,
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "longitude must be numeric."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Handle all_year_event
|
||||
all_year_event = data.get("all_year_event", False)
|
||||
if isinstance(all_year_event, str):
|
||||
all_year_event = all_year_event.lower() in ['true', '1', 'yes', 'on']
|
||||
|
||||
# Handle dates and times - clear if all_year_event is True
|
||||
start_date = None
|
||||
end_date = None
|
||||
start_time = None
|
||||
end_time = None
|
||||
|
||||
if not all_year_event:
|
||||
# Parse start_date
|
||||
if data.get("start_date"):
|
||||
try:
|
||||
start_date = datetime.strptime(data["start_date"], "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "Invalid start_date format. Expected YYYY-MM-DD."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Parse end_date
|
||||
if data.get("end_date"):
|
||||
try:
|
||||
end_date = datetime.strptime(data["end_date"], "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "Invalid end_date format. Expected YYYY-MM-DD."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Parse start_time
|
||||
if data.get("start_time"):
|
||||
try:
|
||||
start_time = datetime.strptime(data["start_time"], "%H:%M:%S").time()
|
||||
except ValueError:
|
||||
try:
|
||||
start_time = datetime.strptime(data["start_time"], "%H:%M").time()
|
||||
except ValueError:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "Invalid start_time format. Expected HH:MM or HH:MM:SS."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Parse end_time
|
||||
if data.get("end_time"):
|
||||
try:
|
||||
end_time = datetime.strptime(data["end_time"], "%H:%M:%S").time()
|
||||
except ValueError:
|
||||
try:
|
||||
end_time = datetime.strptime(data["end_time"], "%H:%M").time()
|
||||
except ValueError:
|
||||
return JsonResponse(
|
||||
{"status": "error", "message": "Invalid end_time format. Expected HH:MM or HH:MM:SS."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Validate event_status if provided
|
||||
event_status = data.get("event_status", "pending")
|
||||
valid_statuses = ['created', 'cancelled', 'pending', 'completed', 'postponed']
|
||||
if event_status not in valid_statuses:
|
||||
return JsonResponse(
|
||||
{
|
||||
"status": "error",
|
||||
"message": f"Invalid event_status. Must be one of: {', '.join(valid_statuses)}",
|
||||
},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Validate source if provided
|
||||
source = data.get("source", "official")
|
||||
valid_sources = ['official', 'community']
|
||||
if source not in valid_sources:
|
||||
return JsonResponse(
|
||||
{
|
||||
"status": "error",
|
||||
"message": f"Invalid source. Must be one of: {', '.join(valid_sources)}",
|
||||
},
|
||||
status=400,
|
||||
)
|
||||
|
||||
# Create event
|
||||
event = Event.objects.create(
|
||||
name=name,
|
||||
description=description,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
all_year_event=all_year_event,
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
pincode=pincode,
|
||||
district=data.get("district", ""),
|
||||
state=data.get("state", ""),
|
||||
place=place,
|
||||
venue_name=data.get("venue_name", ""),
|
||||
event_type=event_type,
|
||||
event_status=event_status,
|
||||
cancelled_reason=data.get("cancelled_reason", "NA"),
|
||||
important_information=data.get("important_information", ""),
|
||||
source=source,
|
||||
)
|
||||
|
||||
log("info", "Event created", request=request, user=user, logger_data={"event_id": event.id, "event_name": name})
|
||||
return JsonResponse(
|
||||
{
|
||||
"status": "success",
|
||||
"message": "Event created successfully.",
|
||||
"event": _event_to_dict(event, request),
|
||||
},
|
||||
status=201,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
log("error", "Event create exception", request=request, logger_data={"error": str(e)})
|
||||
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.2.27 on 2026-03-13 16:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0006_alter_event_source'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='gst_percentage_1',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='gst_percentage_2',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='include_gst',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='event_status',
|
||||
field=models.CharField(choices=[('created', 'Created'), ('cancelled', 'Cancelled'), ('pending', 'Pending'), ('completed', 'Completed'), ('postponed', 'Postponed'), ('published', 'Published'), ('live', 'Live'), ('flagged', 'Flagged')], default='pending', max_length=250),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.2.27 on 2026-03-14 15:57
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('partner', '0001_initial'),
|
||||
('events', '0007_event_gst_percentage_1_event_gst_percentage_2_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='is_partner_event',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='partner',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='partner.partner'),
|
||||
),
|
||||
]
|
||||
@@ -1,6 +1,7 @@
|
||||
from random import choices
|
||||
from django.db import models
|
||||
from master_data.models import EventType
|
||||
from partner.models import Partner
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
@@ -21,10 +22,16 @@ class Event(models.Model):
|
||||
place = models.CharField(max_length=200)
|
||||
|
||||
is_bookable = models.BooleanField(default=False)
|
||||
include_gst = models.BooleanField(default=False)
|
||||
gst_percentage_1 = models.IntegerField(default=0)
|
||||
gst_percentage_2 = models.IntegerField(default=0)
|
||||
|
||||
is_eventify_event = models.BooleanField(default=True)
|
||||
outside_event_url = models.URLField(default='NA')
|
||||
|
||||
is_partner_event = models.BooleanField(default=False)
|
||||
partner = models.ForeignKey(Partner, on_delete=models.CASCADE, blank=True, null=True)
|
||||
|
||||
event_type = models.ForeignKey(EventType, on_delete=models.CASCADE)
|
||||
event_status = models.CharField(max_length=250, choices=[
|
||||
('created', 'Created'),
|
||||
@@ -32,6 +39,9 @@ class Event(models.Model):
|
||||
('pending', 'Pending'),
|
||||
('completed', 'Completed'),
|
||||
('postponed', 'Postponed'),
|
||||
('published', 'Published'),
|
||||
('live', 'Live'),
|
||||
('flagged', 'Flagged'),
|
||||
], default='pending')
|
||||
cancelled_reason = models.TextField(default='NA')
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
from . import api
|
||||
|
||||
app_name = 'events'
|
||||
|
||||
@@ -14,3 +15,8 @@ urlpatterns = [
|
||||
path('<int:pk>/images/<int:img_id>/delete/', views.delete_event_image, name='delete_event_image'),
|
||||
path('<int:pk>/images/<int:img_id>/primary/', views.set_primary_image, name='set_primary_image'),
|
||||
]
|
||||
|
||||
# Event API URLs
|
||||
urlpatterns += [
|
||||
path('api/create/', api.EventCreateAPI.as_view(), name='event_api_create'),
|
||||
]
|
||||
|
||||
@@ -10,8 +10,6 @@ from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
|
||||
from django.http import JsonResponse
|
||||
from .models import Event
|
||||
|
||||
|
||||
class EventListView(LoginRequiredMixin, generic.ListView):
|
||||
|
||||
Reference in New Issue
Block a user