feat: remove debug print statements and add timezone handling in appointment serializers and views #71

Merged
Saani merged 1 commits from feature/meetings into main 2025-12-05 16:56:29 +00:00
3 changed files with 33 additions and 32 deletions

View File

@ -516,11 +516,6 @@ class AppointmentRequest(models.Model):
self.jitsi_meeting_config = meeting_config self.jitsi_meeting_config = meeting_config
self.jitsi_meeting_created = True self.jitsi_meeting_created = True
print(f"DEBUG - Field lengths before save:")
print(f"jitsi_room_id: {len(self.jitsi_room_id) if self.jitsi_room_id else 0} chars")
print(f"jitsi_meet_url: {len(self.jitsi_meet_url) if self.jitsi_meet_url else 0} chars")
print(f"jitsi_meeting_password: {len(self.jitsi_meeting_password) if self.jitsi_meeting_password else 0} chars")
self.save() self.save()
return self.jitsi_meet_url return self.jitsi_meet_url

View File

@ -137,20 +137,17 @@ class AppointmentRequestSerializer(serializers.ModelSerializer):
if not obj.has_jitsi_meeting or not obj.email: if not obj.has_jitsi_meeting or not obj.email:
return None return None
# Try to get the participant user from the appointment's email
participant_user = None participant_user = None
try: try:
from users.models import CustomUser from users.models import CustomUser
participant_user = CustomUser.objects.get(email=obj.email) participant_user = CustomUser.objects.get(email=obj.email)
except CustomUser.DoesNotExist: except CustomUser.DoesNotExist:
# Participant user doesn't exist (not registered)
return None return None
# Check if current user is authorized to view this URL
current_user = request.user current_user = request.user
is_authorized = ( is_authorized = (
current_user.is_staff or # Staff can see participant URLs for all appointments current_user.is_staff or
current_user.email == obj.email or # Participant can see their own URL current_user.email == obj.email or
(hasattr(obj, 'invited_participants') and current_user.email in obj.invited_participants) (hasattr(obj, 'invited_participants') and current_user.email in obj.invited_participants)
) )
@ -225,21 +222,35 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
required=True, required=True,
help_text="List of selected day-time combinations: [{'day': 0, 'time_slot': 'morning'}]" help_text="List of selected day-time combinations: [{'day': 0, 'time_slot': 'morning'}]"
) )
timezone = serializers.CharField(
required=False,
default='UTC',
help_text="User's timezone (e.g., 'America/New_York', 'Africa/Accra')"
)
class Meta: class Meta:
model = AppointmentRequest model = AppointmentRequest
fields = [ fields = [
'first_name', 'last_name', 'email', 'phone', 'reason', 'first_name', 'last_name', 'email', 'phone', 'reason',
'selected_slots' 'selected_slots', 'timezone'
] ]
def validate_timezone(self, value):
"""Validate that the timezone string is valid"""
try:
from zoneinfo import ZoneInfo
ZoneInfo(value)
return value
except Exception:
# If invalid, default to UTC but don't raise error
return 'UTC'
def validate(self, data): def validate(self, data):
selected_slots = data.get('selected_slots') selected_slots = data.get('selected_slots')
if not selected_slots: if not selected_slots:
raise serializers.ValidationError("At least one time slot must be selected.") raise serializers.ValidationError("At least one time slot must be selected.")
# Your existing validation logic
availability = get_admin_availability() availability = get_admin_availability()
if not availability: if not availability:
raise serializers.ValidationError("No admin availability set.") raise serializers.ValidationError("No admin availability set.")
@ -257,34 +268,27 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
f"Slot {i+1}: '{time_slot}' on {day_name} is not available." f"Slot {i+1}: '{time_slot}' on {day_name} is not available."
) )
# Add dates to the slots and store enhanced version
enhanced_slots = self._add_dates_to_slots(selected_slots) enhanced_slots = self._add_dates_to_slots(selected_slots)
data['selected_slots'] = enhanced_slots data['selected_slots'] = enhanced_slots
# Calculate preferred_dates and preferred_time_slots for backward compatibility
data['preferred_dates'] = self._extract_unique_dates(enhanced_slots) data['preferred_dates'] = self._extract_unique_dates(enhanced_slots)
data['preferred_time_slots'] = self._extract_unique_time_slots(enhanced_slots) data['preferred_time_slots'] = self._extract_unique_time_slots(enhanced_slots)
return data return data
def _add_dates_to_slots(self, selected_slots): def _add_dates_to_slots(self, selected_slots):
"""Add actual dates to the slots based on day numbers"""
from datetime import datetime from datetime import datetime
today = datetime.now().date() today = datetime.now().date()
enhanced_slots = [] enhanced_slots = []
# We need to find the next occurrence of each day
# Keep track of which dates we've assigned to which day
day_date_map = {} day_date_map = {}
for slot in selected_slots: for slot in selected_slots:
day = slot.get('day') day = slot.get('day')
time_slot = slot.get('time_slot') time_slot = slot.get('time_slot')
# If we haven't assigned a date to this day yet, find the next occurrence
if day not in day_date_map: if day not in day_date_map:
found_date = None found_date = None
for days_ahead in range(1, 15): # Look ahead 2 weeks for days_ahead in range(1, 15):
check_date = today + timedelta(days=days_ahead) check_date = today + timedelta(days=days_ahead)
if check_date.weekday() == day: if check_date.weekday() == day:
found_date = check_date found_date = check_date
@ -293,7 +297,6 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
if found_date: if found_date:
day_date_map[day] = found_date.strftime('%Y-%m-%d') day_date_map[day] = found_date.strftime('%Y-%m-%d')
# Add the slot with date
if day in day_date_map: if day in day_date_map:
enhanced_slots.append({ enhanced_slots.append({
'day': day, 'day': day,
@ -304,7 +307,6 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
return enhanced_slots return enhanced_slots
def _extract_unique_dates(self, enhanced_slots): def _extract_unique_dates(self, enhanced_slots):
"""Extract unique dates from enhanced slots"""
dates = [] dates = []
for slot in enhanced_slots: for slot in enhanced_slots:
date_str = slot.get('date') date_str = slot.get('date')
@ -313,7 +315,6 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
return dates return dates
def _extract_unique_time_slots(self, enhanced_slots): def _extract_unique_time_slots(self, enhanced_slots):
"""Extract unique time slots from enhanced slots"""
time_slots = [] time_slots = []
for slot in enhanced_slots: for slot in enhanced_slots:
time_slot = slot.get('time_slot') time_slot = slot.get('time_slot')
@ -322,9 +323,17 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
return time_slots return time_slots
def create(self, validated_data): def create(self, validated_data):
# Create the appointment with all data # Extract timezone before creating
# The selected_slots will be saved to the database automatically timezone = validated_data.pop('timezone', 'UTC')
return super().create(validated_data)
# Create appointment
appointment = super().create(validated_data)
# Set timezone on the created appointment
appointment.user_timezone = timezone
appointment.save(update_fields=['user_timezone'])
return appointment
class AppointmentScheduleSerializer(serializers.Serializer): class AppointmentScheduleSerializer(serializers.Serializer):
scheduled_datetime = serializers.DateTimeField() scheduled_datetime = serializers.DateTimeField()
@ -333,7 +342,6 @@ class AppointmentScheduleSerializer(serializers.Serializer):
time_slot = serializers.CharField(required=False, write_only=True) time_slot = serializers.CharField(required=False, write_only=True)
create_jitsi_meeting = serializers.BooleanField(default=True) create_jitsi_meeting = serializers.BooleanField(default=True)
jitsi_custom_config = serializers.JSONField(required=False, default=dict) jitsi_custom_config = serializers.JSONField(required=False, default=dict)
timezone = serializers.CharField(required=False, default='UTC')
def validate(self, data): def validate(self, data):
scheduled_datetime = data.get('scheduled_datetime') scheduled_datetime = data.get('scheduled_datetime')
@ -420,6 +428,7 @@ class AppointmentScheduleSerializer(serializers.Serializer):
'scheduled_datetime': instance.scheduled_datetime, 'scheduled_datetime': instance.scheduled_datetime,
'scheduled_duration': instance.scheduled_duration, 'scheduled_duration': instance.scheduled_duration,
'jitsi_meeting_created': instance.jitsi_meeting_created, 'jitsi_meeting_created': instance.jitsi_meeting_created,
'user_timezone': instance.user_timezone,
} }
if instance.has_jitsi_meeting: if instance.has_jitsi_meeting:
@ -429,7 +438,6 @@ class AppointmentScheduleSerializer(serializers.Serializer):
return representation return representation
class AppointmentDetailSerializer(serializers.ModelSerializer): class AppointmentDetailSerializer(serializers.ModelSerializer):
meeting_info = serializers.SerializerMethodField() meeting_info = serializers.SerializerMethodField()
meeting_analytics = serializers.SerializerMethodField() meeting_analytics = serializers.SerializerMethodField()

View File

@ -76,6 +76,7 @@ class AppointmentRequestCreateView(generics.CreateAPIView):
EmailService.send_admin_notification(appointment, availability_mismatch=True) EmailService.send_admin_notification(appointment, availability_mismatch=True)
class AppointmentRequestDetailView(generics.RetrieveAPIView): class AppointmentRequestDetailView(generics.RetrieveAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
queryset = AppointmentRequest.objects.all() queryset = AppointmentRequest.objects.all()
@ -103,9 +104,6 @@ class ScheduleAppointmentView(generics.GenericAPIView):
create_jitsi_meeting = serializer.validated_data.get('create_jitsi_meeting', True) create_jitsi_meeting = serializer.validated_data.get('create_jitsi_meeting', True)
jitsi_custom_config = serializer.validated_data.get('jitsi_custom_config', {}) jitsi_custom_config = serializer.validated_data.get('jitsi_custom_config', {})
user_timezone = serializer.validated_data.get('timezone', 'UTC')
appointment.user_timezone = user_timezone
admin_user = request.user admin_user = request.user