Compare commits
2 Commits
518e13f84c
...
034a1ccccc
| Author | SHA1 | Date | |
|---|---|---|---|
| 034a1ccccc | |||
| 875a284893 |
@ -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 cancel_appointment(self, reason='', commit=True):
|
def end_meeting(self, commit=True):
|
||||||
self.status = 'cancelled'
|
if self.meeting_started_at and not self.meeting_ended_at:
|
||||||
self.rejection_reason = reason
|
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)
|
||||||
|
|
||||||
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'
|
||||||
|
|
||||||
|
if not self.scheduled_datetime or not self.has_jitsi_meeting:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.status not in ['scheduled', 'in_progress']:
|
||||||
|
return False
|
||||||
|
|
||||||
|
now = timezone.now()
|
||||||
|
meeting_start = self.scheduled_datetime
|
||||||
|
meeting_end = meeting_start + timedelta(minutes=self.scheduled_duration + 30)
|
||||||
|
|
||||||
|
if user_type == 'moderator':
|
||||||
|
return meeting_start - timedelta(minutes=15) <= now <= meeting_end + timedelta(minutes=15)
|
||||||
|
else:
|
||||||
|
return meeting_start - timedelta(minutes=5) <= now <= meeting_end
|
||||||
|
|
||||||
|
def get_meeting_join_info(self, user_type='participant'):
|
||||||
|
if not self.has_jitsi_meeting:
|
||||||
|
return None
|
||||||
|
|
||||||
|
join_url = self.get_moderator_join_url() if user_type == 'moderator' else self.get_participant_join_url()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'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(),
|
||||||
|
}
|
||||||
|
|
||||||
def start_meeting(self, commit=True):
|
def update_meeting_data(self, data):
|
||||||
if self.status == 'scheduled':
|
if not isinstance(data, dict):
|
||||||
self.meeting_started_at = timezone.now()
|
return
|
||||||
if commit:
|
|
||||||
self.save(update_fields=['meeting_started_at'])
|
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 end_meeting(self, commit=True):
|
def get_meeting_analytics(self):
|
||||||
if self.meeting_started_at and not self.meeting_ended_at:
|
return {
|
||||||
self.meeting_ended_at = timezone.now()
|
'scheduled_duration': self.scheduled_duration,
|
||||||
|
'actual_duration': self.meeting_duration_actual,
|
||||||
if self.meeting_started_at:
|
'started_at': self.meeting_started_at.isoformat() if self.meeting_started_at else None,
|
||||||
duration = self.meeting_ended_at - self.meeting_started_at
|
'ended_at': self.meeting_ended_at.isoformat() if self.meeting_ended_at else None,
|
||||||
self.meeting_duration_actual = int(duration.total_seconds() / 60)
|
'status': self.status,
|
||||||
|
'punctuality': self._calculate_punctuality(),
|
||||||
if commit:
|
'efficiency': self._calculate_efficiency(),
|
||||||
self.save(update_fields=[
|
}
|
||||||
'meeting_ended_at',
|
|
||||||
'meeting_duration_actual'
|
|
||||||
])
|
|
||||||
|
|
||||||
def can_join_meeting(self, *args, **kwargs):
|
|
||||||
if args:
|
|
||||||
user_type = args[0]
|
|
||||||
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:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if self.status not in ['scheduled', 'in_progress']:
|
|
||||||
return False
|
|
||||||
|
|
||||||
now = timezone.now()
|
|
||||||
meeting_start = self.scheduled_datetime
|
|
||||||
meeting_end = meeting_start + timedelta(minutes=self.scheduled_duration + 30)
|
|
||||||
|
|
||||||
if user_type == 'moderator':
|
|
||||||
return meeting_start - timedelta(minutes=15) <= now <= meeting_end + timedelta(minutes=15)
|
|
||||||
else:
|
|
||||||
return meeting_start - timedelta(minutes=5) <= now <= meeting_end
|
|
||||||
|
|
||||||
def get_meeting_join_info(self, user_type='participant'):
|
|
||||||
if not self.has_jitsi_meeting:
|
|
||||||
return None
|
|
||||||
|
|
||||||
join_url = self.get_moderator_join_url() if user_type == 'moderator' else self.get_participant_join_url()
|
|
||||||
|
|
||||||
return {
|
|
||||||
'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(),
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
||||||
|
|||||||
@ -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,9 +99,9 @@ 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):
|
||||||
return obj.can_join_meeting('participant')
|
return obj.can_join_meeting('participant')
|
||||||
|
|
||||||
@ -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')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user