alternative-backend-service/meetings/views.py
saani ea99552d95 refactor(meetings): change UserAppointmentStatsView from GET to POST
Modified UserAppointmentStatsView to accept POST requests instead of GET
and retrieve email from request body rather than from authenticated user.
This allows querying appointment statistics for any email address instead
of being limited to the current user's email.

Changes:
- Changed HTTP method from GET to POST
- Added email parameter extraction from request.data
- Updated filter to use provided email instead of request.user.email
2025-11-26 16:03:09 +00:00

202 lines
7.4 KiB
Python

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,IsAdminUser
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
from django.db.models import Count, Q
class AdminAvailabilityView(generics.RetrieveUpdateAPIView):
permission_classes = [IsAuthenticated, IsAdminUser]
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'
class ScheduleAppointmentView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsAdminUser]
serializer_class = AppointmentScheduleSerializer
queryset = AppointmentRequest.objects.all()
lookup_field = 'pk'
def post(self, request, pk):
appointment = self.get_object()
if appointment.status != 'pending_review':
return Response(
{'error': 'Only pending review appointments can be scheduled.'},
status=status.HTTP_400_BAD_REQUEST
)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
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
})
class RejectAppointmentView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
serializer_class = AppointmentRejectSerializer
queryset = AppointmentRequest.objects.all()
lookup_field = 'pk'
def post(self, request, pk):
appointment = self.get_object()
if appointment.status != 'pending_review':
return Response(
{'error': 'Only pending appointments can be rejected'},
status=status.HTTP_400_BAD_REQUEST
)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
appointment.reject_appointment(
serializer.validated_data.get('rejection_reason', '')
)
EmailService.send_appointment_rejected(appointment)
response_serializer = AppointmentRequestSerializer(appointment)
return Response(response_serializer.data)
class AvailableDatesView(generics.GenericAPIView):
permission_classes = [AllowAny]
def get(self, 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)
class UserAppointmentsView(generics.ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = AppointmentRequestSerializer
def get_queryset(self):
return AppointmentRequest.objects.filter(
email=self.request.user.email
).order_by('-created_at')
class AppointmentStatsView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsAdminUser]
def get(self, request):
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
})
class UserAppointmentStatsView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
def post(self, request):
email = request.data.get('email')
stats = AppointmentRequest.objects.filter(
email=email
).aggregate(
total=Count('id'),
pending=Count('id', filter=Q(status='pending_review')),
scheduled=Count('id', filter=Q(status='scheduled')),
rejected=Count('id', filter=Q(status='rejected')),
completed=Count('id', filter=Q(status='completed'))
)
total = stats['total']
scheduled = stats['scheduled']
completion_rate = round((scheduled / total * 100), 2) if total > 0 else 0
return Response({
'total_requests': total,
'pending_review': stats['pending'],
'scheduled': scheduled,
'rejected': stats['rejected'],
'completed': stats['completed'],
'completion_rate': completion_rate
})