Compare commits

...

2 Commits

2 changed files with 97 additions and 100 deletions

View File

@ -649,106 +649,107 @@ class AppointmentRequest(models.Model):
if commit: if commit:
self.save() self.save()
def reject_appointment(self, reason='', commit=True):
self.status = 'rejected' def reject_appointment(self, reason='', commit=True):
self.rejection_reason = reason self.status = 'rejected'
self.scheduled_datetime = None self.rejection_reason = reason
self.jitsi_meet_url = None self.scheduled_datetime = None
self.jitsi_room_id = None self.jitsi_meet_url = None
self.jitsi_room_id = None
if commit:
self.save()
def cancel_appointment(self, reason='', commit=True):
self.status = 'cancelled'
self.rejection_reason = reason
if commit:
self.save()
def complete_appointment(self, commit=True):
self.status = 'completed'
if commit:
self.save()
def start_meeting(self, commit=True):
if self.status == 'scheduled':
self.meeting_started_at = timezone.now()
if commit: if commit:
self.save() self.save(update_fields=['meeting_started_at'])
def end_meeting(self, commit=True):
if self.meeting_started_at and not self.meeting_ended_at:
self.meeting_ended_at = timezone.now()
if self.meeting_started_at:
duration = self.meeting_ended_at - self.meeting_started_at
self.meeting_duration_actual = int(duration.total_seconds() / 60)
def cancel_appointment(self, reason='', commit=True):
self.status = 'cancelled'
self.rejection_reason = reason
if commit: if commit:
self.save() self.save(update_fields=[
'meeting_ended_at',
'meeting_duration_actual'
])
def complete_appointment(self, commit=True): def can_join_meeting(self, *args, **kwargs):
self.status = 'completed' if args:
if commit: user_type = args[0]
self.save() elif 'user_type' in kwargs:
user_type = kwargs['user_type']
else:
user_type = 'participant'
def start_meeting(self, commit=True): if not self.scheduled_datetime or not self.has_jitsi_meeting:
if self.status == 'scheduled': return False
self.meeting_started_at = timezone.now()
if commit:
self.save(update_fields=['meeting_started_at'])
def end_meeting(self, commit=True): if self.status not in ['scheduled', 'in_progress']:
if self.meeting_started_at and not self.meeting_ended_at: return False
self.meeting_ended_at = timezone.now()
if self.meeting_started_at: now = timezone.now()
duration = self.meeting_ended_at - self.meeting_started_at meeting_start = self.scheduled_datetime
self.meeting_duration_actual = int(duration.total_seconds() / 60) meeting_end = meeting_start + timedelta(minutes=self.scheduled_duration + 30)
if commit: if user_type == 'moderator':
self.save(update_fields=[ return meeting_start - timedelta(minutes=15) <= now <= meeting_end + timedelta(minutes=15)
'meeting_ended_at', else:
'meeting_duration_actual' return meeting_start - timedelta(minutes=5) <= now <= meeting_end
])
def can_join_meeting(self, *args, **kwargs): def get_meeting_join_info(self, user_type='participant'):
if args: if not self.has_jitsi_meeting:
user_type = args[0] return None
elif 'user_type' in kwargs:
user_type = kwargs['user_type']
else:
user_type = 'participant'
if not self.scheduled_datetime or not self.has_jitsi_meeting: join_url = self.get_moderator_join_url() if user_type == 'moderator' else self.get_participant_join_url()
return False
if self.status not in ['scheduled', 'in_progress']: return {
return False 'meeting_url': join_url,
'room_id': self.jitsi_room_id,
'scheduled_time': self.formatted_scheduled_datetime,
'duration': self.meeting_duration_display,
'password': self.jitsi_meeting_password if user_type == 'participant' else None,
'can_join_now': self.can_join_meeting(user_type),
'join_window_start': (self.scheduled_datetime - timedelta(minutes=15)).strftime("%I:%M %p") if user_type == 'moderator' else (self.scheduled_datetime - timedelta(minutes=5)).strftime("%I:%M %p"),
'join_window_end': (self.scheduled_datetime + timedelta(minutes=self.scheduled_duration + 30)).strftime("%I:%M %p"),
'status': self.get_status_display(),
}
now = timezone.now() def update_meeting_data(self, data):
meeting_start = self.scheduled_datetime if not isinstance(data, dict):
meeting_end = meeting_start + timedelta(minutes=self.scheduled_duration + 30) return
if user_type == 'moderator': current_data = self.jitsi_meeting_data or {}
return meeting_start - timedelta(minutes=15) <= now <= meeting_end + timedelta(minutes=15) current_data.update(data)
else: self.jitsi_meeting_data = current_data
return meeting_start - timedelta(minutes=5) <= now <= meeting_end self.save(update_fields=['jitsi_meeting_data'])
def get_meeting_join_info(self, user_type='participant'): def get_meeting_analytics(self):
if not self.has_jitsi_meeting: return {
return None 'scheduled_duration': self.scheduled_duration,
'actual_duration': self.meeting_duration_actual,
join_url = self.get_moderator_join_url() if user_type == 'moderator' else self.get_participant_join_url() 'started_at': self.meeting_started_at.isoformat() if self.meeting_started_at else None,
'ended_at': self.meeting_ended_at.isoformat() if self.meeting_ended_at else None,
return { 'status': self.status,
'meeting_url': join_url, 'punctuality': self._calculate_punctuality(),
'room_id': self.jitsi_room_id, 'efficiency': self._calculate_efficiency(),
'scheduled_time': self.formatted_scheduled_datetime, }
'duration': self.meeting_duration_display,
'password': self.jitsi_meeting_password if user_type == 'participant' else None,
'can_join_now': self.can_join_meeting(user_type),
'join_window_start': (self.scheduled_datetime - timedelta(minutes=15)).strftime("%I:%M %p") if user_type == 'moderator' else (self.scheduled_datetime - timedelta(minutes=5)).strftime("%I:%M %p"),
'join_window_end': (self.scheduled_datetime + timedelta(minutes=self.scheduled_duration + 30)).strftime("%I:%M %p"),
'status': self.get_status_display(),
}
def update_meeting_data(self, data):
if not isinstance(data, dict):
return
current_data = self.jitsi_meeting_data or {}
current_data.update(data)
self.jitsi_meeting_data = current_data
self.save(update_fields=['jitsi_meeting_data'])
def get_meeting_analytics(self):
return {
'scheduled_duration': self.scheduled_duration,
'actual_duration': self.meeting_duration_actual,
'started_at': self.meeting_started_at.isoformat() if self.meeting_started_at else None,
'ended_at': self.meeting_ended_at.isoformat() if self.meeting_ended_at else None,
'status': self.status,
'punctuality': self._calculate_punctuality(),
'efficiency': self._calculate_efficiency(),
}
def _calculate_punctuality(self): def _calculate_punctuality(self):
if not self.meeting_started_at or not self.scheduled_datetime: if not self.meeting_started_at or not self.scheduled_datetime:

View File

@ -79,8 +79,6 @@ class AppointmentRequestSerializer(serializers.ModelSerializer):
moderator_join_url = serializers.SerializerMethodField() moderator_join_url = serializers.SerializerMethodField()
participant_join_url = serializers.SerializerMethodField() participant_join_url = serializers.SerializerMethodField()
meeting_analytics = serializers.SerializerMethodField() meeting_analytics = serializers.SerializerMethodField()
# Add selected_slots field
selected_slots = serializers.JSONField() selected_slots = serializers.JSONField()
class Meta: class Meta:
@ -101,7 +99,7 @@ class AppointmentRequestSerializer(serializers.ModelSerializer):
'id', 'status', 'scheduled_datetime', 'scheduled_duration', 'id', 'status', 'scheduled_datetime', 'scheduled_duration',
'rejection_reason', 'jitsi_meet_url', 'jitsi_room_id', 'rejection_reason', 'jitsi_meet_url', 'jitsi_room_id',
'created_at', 'updated_at', 'preferred_dates', 'preferred_time_slots', 'created_at', 'updated_at', 'preferred_dates', 'preferred_time_slots',
'selected_slots' # Make selected_slots read-only in this serializer 'selected_slots'
] ]
def get_can_join_meeting(self, obj): def get_can_join_meeting(self, obj):
@ -234,8 +232,6 @@ class AppointmentRequestCreateSerializer(serializers.ModelSerializer):
'first_name', 'last_name', 'email', 'phone', 'reason', 'first_name', 'last_name', 'email', 'phone', 'reason',
'selected_slots' 'selected_slots'
] ]
# Remove preferred_dates and preferred_time_slots from fields list
# They will be calculated automatically
def validate(self, data): def validate(self, data):
selected_slots = data.get('selected_slots') selected_slots = data.get('selected_slots')