11import json
22import uuid
3- import logging
4- import traceback
53from datetime import timedelta
64import pytz
75
2624from utils .embedding_utils import find_similar_events
2725from utils .filters import EventFilter
2826from utils .validation import validate_event_data
27+ from utils .date_utils import parse_utc_datetime
2928
3029from .models import Events , EventSubmission , EventInterest , EventDates
3130
32- logger = logging .getLogger (__name__ )
33-
3431
3532@api_view (["GET" ])
3633@permission_classes ([AllowAny ])
@@ -109,12 +106,7 @@ def get_events(request):
109106 cursor_dtstart_utc_str = cursor_parts [0 ]
110107 cursor_id = int (cursor_parts [1 ])
111108
112- from dateutil import parser as dateutil_parser
113- cursor_dtstart_utc = dateutil_parser .parse (cursor_dtstart_utc_str )
114- if cursor_dtstart_utc .tzinfo is None :
115- cursor_dtstart_utc = pytz .UTC .localize (cursor_dtstart_utc )
116- else :
117- cursor_dtstart_utc = cursor_dtstart_utc .astimezone (pytz .UTC )
109+ cursor_dtstart_utc = parse_utc_datetime (cursor_dtstart_utc_str )
118110
119111 # Filter events after cursor position
120112 filtered_queryset = filtered_queryset .filter (
@@ -218,7 +210,7 @@ def get_event(request, event_id):
218210 event_data ["is_submitter" ] = submission and request .user_id and str (submission .submitted_by ) == str (request .user_id )
219211
220212 # Get all event dates
221- event_data ["dates " ] = list (
213+ event_data ["occurrences " ] = list (
222214 EventDates .objects .filter (event_id = event_id )
223215 .order_by ('dtstart_utc' ).values ("dtstart_utc" , "dtend_utc" )
224216 )
@@ -600,7 +592,6 @@ def submit_event(request):
600592 # Event data is passed flat at top level
601593 cleaned = validate_event_data (data )
602594
603- from dateutil import parser as dateutil_parser
604595 with transaction .atomic ():
605596 event = Events .objects .create (
606597 title = cleaned ["title" ],
@@ -618,19 +609,8 @@ def submit_event(request):
618609
619610 # Create EventDates for each occurrence
620611 for occ in cleaned ["occurrences" ]:
621- dtstart_utc = dateutil_parser .parse (occ ["start_utc" ])
622- if dtstart_utc .tzinfo is None :
623- dtstart_utc = pytz .UTC .localize (dtstart_utc )
624- else :
625- dtstart_utc = dtstart_utc .astimezone (pytz .UTC )
626-
627- dtend_utc = None
628- if occ .get ("end_utc" ):
629- dtend_utc = dateutil_parser .parse (occ ["end_utc" ])
630- if dtend_utc .tzinfo is None :
631- dtend_utc = pytz .UTC .localize (dtend_utc )
632- else :
633- dtend_utc = dtend_utc .astimezone (pytz .UTC )
612+ dtstart_utc = parse_utc_datetime (occ ["dtstart_utc" ])
613+ dtend_utc = parse_utc_datetime (occ .get ("dtend_utc" )) if occ .get ("dtend_utc" ) else None
634614
635615 EventDates .objects .create (
636616 event = event ,
@@ -654,7 +634,7 @@ def submit_event(request):
654634
655635@api_view (["GET" ])
656636@ratelimit (key = "ip" , rate = "100/hr" , block = True )
657- @jwt_required
637+ @admin_required
658638def get_submissions (request ):
659639 try :
660640 submissions = EventSubmission .objects .select_related ("created_event" ).all ().order_by ("-submitted_at" )
@@ -675,121 +655,38 @@ def get_submissions(request):
675655
676656
677657@api_view (["POST" ])
678- @jwt_required
658+ @admin_required
679659@ratelimit (key = "ip" , rate = "100/hr" , block = True )
680660def review_submission (request , event_id ):
681661 """Approve or reject submission"""
682662 try :
683- logger .info (f"[review_submission] Starting review for event_id={ event_id } , user_id={ request .user_id } " )
684-
685- # Parse request body
686- try :
687- data = json .loads (request .body )
688- logger .debug (f"[review_submission] Parsed request data: { data } " )
689- except json .JSONDecodeError as e :
690- logger .error (f"[review_submission] JSON decode error: { e } , body: { request .body } " )
691- return Response (
692- {"message" : "Invalid JSON in request body" , "error" : str (e )},
693- status = status .HTTP_400_BAD_REQUEST
694- )
695-
696- # Get event
697- try :
698- event = get_object_or_404 (Events , id = event_id )
699- logger .debug (f"[review_submission] Found event: id={ event .id } , title={ event .title } , status={ event .status } " )
700- except Exception as e :
701- logger .error (f"[review_submission] Error getting event { event_id } : { e } " )
702- logger .error (f"[review_submission] Traceback: { traceback .format_exc ()} " )
703- return Response (
704- {"message" : f"Event not found: { event_id } " , "error" : str (e )},
705- status = status .HTTP_404_NOT_FOUND
706- )
707-
708- # Get submission (safer query method)
709- try :
710- submission = EventSubmission .objects .filter (created_event = event ).first ()
711- if not submission :
712- logger .warning (f"[review_submission] No submission found for event_id={ event_id } " )
713- return Response (
714- {"message" : "No submission found for this event" },
715- status = status .HTTP_404_NOT_FOUND
716- )
717- logger .debug (f"[review_submission] Found submission: id={ submission .id } , submitted_by={ submission .submitted_by } " )
718- except Exception as e :
719- logger .error (f"[review_submission] Error getting submission for event { event_id } : { e } " )
720- logger .error (f"[review_submission] Traceback: { traceback .format_exc ()} " )
721- return Response (
722- {"message" : "Error retrieving submission" , "error" : str (e )},
723- status = status .HTTP_500_INTERNAL_SERVER_ERROR
724- )
725-
726- # Get action
663+ data = json .loads (request .body )
664+ event = get_object_or_404 (Events , id = event_id )
665+ submission = EventSubmission .objects .filter (created_event = event ).first ()
666+ if not submission :
667+ return Response ({"message" : "No submission found for this event" }, status = status .HTTP_404_NOT_FOUND )
727668 action = data .get ("action" )
728- if not action :
729- logger .warning (f"[review_submission] No action provided in request data" )
730- return Response (
731- {"message" : "Action is required. Use 'approve' or 'reject'" },
732- status = status .HTTP_400_BAD_REQUEST
733- )
734-
735- logger .info (f"[review_submission] Processing action={ action } for event_id={ event_id } " )
736669
737670 if action == "approve" :
738- try :
739- event .status = "CONFIRMED"
740- event .save ()
741- logger .debug (f"[review_submission] Updated event status to CONFIRMED" )
742-
743- submission .reviewed_at = timezone .now ()
744- submission .reviewed_by = request .user_id
745- submission .save ()
746- logger .info (f"[review_submission] Successfully approved event_id={ event_id } " )
747-
748- return Response ({"message" : "Event approved" , "event_id" : event .id })
749- except Exception as e :
750- logger .error (f"[review_submission] Error approving event { event_id } : { e } " )
751- logger .error (f"[review_submission] Traceback: { traceback .format_exc ()} " )
752- return Response (
753- {"message" : "Error approving event" , "error" : str (e )},
754- status = status .HTTP_500_INTERNAL_SERVER_ERROR
755- )
671+ event .status = "CONFIRMED"
672+ event .save ()
673+ submission .reviewed_at = timezone .now ()
674+ submission .reviewed_by = request .user_id
675+ submission .save ()
676+ return Response ({"message" : "Event approved" , "event_id" : event .id })
756677
757678 elif action == "reject" :
758- try :
759- submission .reviewed_at = timezone .now ()
760- submission .reviewed_by = request .user_id
761- submission .save ()
762- logger .debug (f"[review_submission] Updated submission review info" )
763-
764- if event :
765- event .status = "CANCELLED"
766- event .save ()
767- logger .debug (f"[review_submission] Updated event status to CANCELLED" )
768-
769- logger .info (f"[review_submission] Successfully rejected event_id={ event_id } " )
770- return Response ({"message" : "Event rejected" })
771- except Exception as e :
772- logger .error (f"[review_submission] Error rejecting event { event_id } : { e } " )
773- logger .error (f"[review_submission] Traceback: { traceback .format_exc ()} " )
774- return Response (
775- {"message" : "Error rejecting event" , "error" : str (e )},
776- status = status .HTTP_500_INTERNAL_SERVER_ERROR
777- )
679+ submission .reviewed_at = timezone .now ()
680+ submission .reviewed_by = request .user_id
681+ submission .save ()
682+ if event :
683+ event .status = "CANCELLED"
684+ event .save ()
685+ return Response ({"message" : "Event rejected" })
778686
779- logger .warning (f"[review_submission] Invalid action: { action } " )
780- return Response (
781- {"message" : "Invalid action. Use 'approve' or 'reject'" },
782- status = status .HTTP_400_BAD_REQUEST
783- )
784-
687+ return Response ({"message" : "Invalid action. Use 'approve' or 'reject'" }, status = status .HTTP_400_BAD_REQUEST )
785688 except Exception as e :
786- logger .error (f"[review_submission] Unexpected error in review_submission: { e } " )
787- logger .error (f"[review_submission] Traceback: { traceback .format_exc ()} " )
788- logger .error (f"[review_submission] Request data: event_id={ event_id } , user_id={ getattr (request , 'user_id' , 'unknown' )} " )
789- return Response (
790- {"message" : "Internal server error" , "error" : str (e )},
791- status = status .HTTP_500_INTERNAL_SERVER_ERROR
792- )
689+ return Response ({"message" : str (e )}, status = status .HTTP_500_INTERNAL_SERVER_ERROR )
793690
794691
795692@api_view (["GET" ])
@@ -976,21 +873,9 @@ def update_event(request, event_id):
976873 # Update occurrences if provided
977874 if cleaned .get ("occurrences" ):
978875 EventDates .objects .filter (event = event ).delete ()
979- from dateutil import parser as dateutil_parser
980876 for occ in cleaned ["occurrences" ]:
981- dtstart_utc = dateutil_parser .parse (occ ["start_utc" ])
982- if dtstart_utc .tzinfo is None :
983- dtstart_utc = pytz .UTC .localize (dtstart_utc )
984- else :
985- dtstart_utc = dtstart_utc .astimezone (pytz .UTC )
986-
987- dtend_utc = None
988- if occ .get ("end_utc" ):
989- dtend_utc = dateutil_parser .parse (occ ["end_utc" ])
990- if dtend_utc .tzinfo is None :
991- dtend_utc = pytz .UTC .localize (dtend_utc )
992- else :
993- dtend_utc = dtend_utc .astimezone (pytz .UTC )
877+ dtstart_utc = parse_utc_datetime (occ ["dtstart_utc" ])
878+ dtend_utc = parse_utc_datetime (occ .get ("dtend_utc" )) if occ .get ("dtend_utc" ) else None
994879
995880 EventDates .objects .create (
996881 event = event ,
0 commit comments