alternative-backend-service/meetings/views.py

171 lines
6.3 KiB
Python
Raw Normal View History

from rest_framework import generics, status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from django.utils import timezone
from datetime import datetime, timedelta
from .models import AdminWeeklyAvailability, AppointmentRequest
from .serializers import (
AdminWeeklyAvailabilitySerializer,
AppointmentRequestSerializer,
AppointmentRequestCreateSerializer,
AppointmentScheduleSerializer,
AppointmentRejectSerializer
)
from .email_service import EmailService
from users.models import CustomUser
class AdminAvailabilityView(generics.RetrieveUpdateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = AdminWeeklyAvailabilitySerializer
def get_object(self):
obj, created = AdminWeeklyAvailability.objects.get_or_create(
defaults={'available_days': []}
)
return obj
class AppointmentRequestListView(generics.ListAPIView):
serializer_class = AppointmentRequestSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
queryset = AppointmentRequest.objects.all()
if self.request.user.is_staff:
return queryset
return queryset.filter(email=self.request.user.email)
class AppointmentRequestCreateView(generics.CreateAPIView):
permission_classes = [IsAuthenticated]
queryset = AppointmentRequest.objects.all()
serializer_class = AppointmentRequestCreateSerializer
def perform_create(self, serializer):
availability = AdminWeeklyAvailability.objects.first()
if availability:
available_days = availability.available_days
preferred_dates = serializer.validated_data['preferred_dates']
for date_str in preferred_dates:
date_obj = datetime.strptime(date_str, '%Y-%m-%d').date()
if date_obj.weekday() not in available_days:
from rest_framework.exceptions import ValidationError
raise ValidationError(f'Date {date_str} is not available for appointments.')
appointment = serializer.save()
EmailService.send_admin_notification(appointment)
class AppointmentRequestDetailView(generics.RetrieveAPIView):
permission_classes = [IsAuthenticated]
queryset = AppointmentRequest.objects.all()
serializer_class = AppointmentRequestSerializer
lookup_field = 'pk'
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def schedule_appointment(request, pk):
try:
appointment = AppointmentRequest.objects.get(pk=pk)
except AppointmentRequest.DoesNotExist:
return Response({'error': 'Appointment not found'}, status=status.HTTP_404_NOT_FOUND)
if appointment.status != 'pending_review':
return Response(
{'error': 'Only pending review appointments can be scheduled.'},
status=status.HTTP_400_BAD_REQUEST
)
serializer = AppointmentScheduleSerializer(data=request.data)
if serializer.is_valid():
appointment.schedule_appointment(
datetime_obj=serializer.validated_data['scheduled_datetime'],
duration=serializer.validated_data['scheduled_duration']
)
EmailService.send_appointment_scheduled(appointment)
response_serializer = AppointmentRequestSerializer(appointment)
return Response({
**response_serializer.data,
'message': 'Appointment scheduled successfully. Jitsi meeting created.',
'jitsi_meeting_created': appointment.has_jitsi_meeting
})
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def reject_appointment(request, pk):
try:
appointment = AppointmentRequest.objects.get(pk=pk)
except AppointmentRequest.DoesNotExist:
return Response({'error': 'Appointment not found'}, status=status.HTTP_404_NOT_FOUND)
if appointment.status != 'pending_review':
return Response(
{'error': 'Only pending appointments can be rejected'},
status=status.HTTP_400_BAD_REQUEST
)
serializer = AppointmentRejectSerializer(data=request.data)
if serializer.is_valid():
appointment.reject_appointment(serializer.validated_data.get('rejection_reason', ''))
EmailService.send_appointment_rejected(appointment)
return Response(AppointmentRequestSerializer(appointment).data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@permission_classes([AllowAny])
def available_dates(request):
availability = AdminWeeklyAvailability.objects.first()
if not availability:
return Response([])
available_days = availability.available_days
today = timezone.now().date()
available_dates = []
for i in range(1, 31):
date = today + timedelta(days=i)
if date.weekday() in available_days:
available_dates.append(date.strftime('%Y-%m-%d'))
return Response(available_dates)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_appointments(request):
appointments = AppointmentRequest.objects.filter(
email=request.user.email
).order_by('-created_at')
serializer = AppointmentRequestSerializer(appointments, many=True)
return Response(serializer.data)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def appointment_stats(request):
if not request.user.is_staff:
return Response(
{'error': 'Unauthorized'},
status=status.HTTP_403_FORBIDDEN
)
total = AppointmentRequest.objects.count()
users = CustomUser.objects.filter(is_staff=False).count()
pending = AppointmentRequest.objects.filter(status='pending_review').count()
scheduled = AppointmentRequest.objects.filter(status='scheduled').count()
rejected = AppointmentRequest.objects.filter(status='rejected').count()
return Response({
'total_requests': total,
'pending_review': pending,
'scheduled': scheduled,
'rejected': rejected,
'users': users,
'completion_rate': round((scheduled / total * 100), 2) if total > 0 else 0
})