""" Call Center Console UI views """ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from django.db.models import Q, Avg from django.http import JsonResponse from django.shortcuts import get_object_or_404, redirect, render from django.utils import timezone from django.views.decorators.http import require_http_methods from apps.complaints.models import Complaint, ComplaintSource, Inquiry from apps.core.services import AuditService from apps.organizations.models import Department, Hospital, Patient, Staff from .models import CallCenterInteraction @login_required def interaction_list(request): """Call center interactions list view""" queryset = CallCenterInteraction.objects.select_related( 'patient', 'hospital', 'department', 'agent' ) # Apply RBAC filters user = request.user if user.is_px_admin(): pass elif user.hospital: queryset = queryset.filter(hospital=user.hospital) else: queryset = queryset.none() # Apply filters call_type_filter = request.GET.get('call_type') if call_type_filter: queryset = queryset.filter(call_type=call_type_filter) hospital_filter = request.GET.get('hospital') if hospital_filter: queryset = queryset.filter(hospital_id=hospital_filter) is_low_rating = request.GET.get('is_low_rating') if is_low_rating == 'true': queryset = queryset.filter(is_low_rating=True) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(subject__icontains=search_query) | Q(caller_name__icontains=search_query) | Q(patient__mrn__icontains=search_query) ) # Date range date_from = request.GET.get('date_from') if date_from: queryset = queryset.filter(call_started_at__gte=date_from) date_to = request.GET.get('date_to') if date_to: queryset = queryset.filter(call_started_at__lte=date_to) # Ordering queryset = queryset.order_by('-call_started_at') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get filter options hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) # Statistics stats = { 'total': queryset.count(), 'low_rating': queryset.filter(is_low_rating=True).count(), 'avg_satisfaction': queryset.filter(satisfaction_rating__isnull=False).aggregate( avg=Avg('satisfaction_rating') )['avg'] or 0, } context = { 'page_obj': page_obj, 'interactions': page_obj.object_list, 'stats': stats, 'hospitals': hospitals, 'filters': request.GET, } return render(request, 'callcenter/interaction_list.html', context) @login_required def interaction_detail(request, pk): """Call center interaction detail view""" interaction = get_object_or_404( CallCenterInteraction.objects.select_related( 'patient', 'hospital', 'department', 'agent' ), pk=pk ) context = { 'interaction': interaction, } return render(request, 'callcenter/interaction_detail.html', context) # ============================================================================ # COMPLAINT CREATION FOR CALL CENTER # ============================================================================ @login_required @require_http_methods(["GET", "POST"]) def create_complaint(request): """ Create complaint from call center interaction. Call center staff can create complaints on behalf of patients/callers. """ if request.method == 'POST': try: # Get form data patient_id = request.POST.get('patient_id', None) hospital_id = request.POST.get('hospital_id') department_id = request.POST.get('department_id', None) staff_id = request.POST.get('staff_id', None) title = request.POST.get('title') description = request.POST.get('description') category = request.POST.get('category') subcategory = request.POST.get('subcategory', '') priority = request.POST.get('priority') severity = request.POST.get('severity') encounter_id = request.POST.get('encounter_id', '') # Call center specific fields caller_name = request.POST.get('caller_name', '') caller_phone = request.POST.get('caller_phone', '') caller_relationship = request.POST.get('caller_relationship', 'patient') # Validate required fields if not all([hospital_id, title, description, category, priority, severity]): messages.error(request, "Please fill in all required fields.") return redirect('callcenter:create_complaint') # If no patient selected, we need caller info if not patient_id and not caller_name: messages.error(request, "Please provide either patient or caller information.") return redirect('callcenter:create_complaint') # Create complaint complaint = Complaint.objects.create( patient_id=patient_id if patient_id else None, hospital_id=hospital_id, department_id=department_id if department_id else None, staff_id=staff_id if staff_id else None, title=title, description=description, category=category, subcategory=subcategory, priority=priority, severity=severity, source=ComplaintSource.CALL_CENTER, encounter_id=encounter_id, ) # Create call center interaction record CallCenterInteraction.objects.create( patient_id=patient_id if patient_id else None, caller_name=caller_name, caller_phone=caller_phone, caller_relationship=caller_relationship, hospital_id=hospital_id, department_id=department_id if department_id else None, agent=request.user, call_type='complaint', subject=title, notes=description, metadata={ 'complaint_id': str(complaint.id), 'category': category, 'severity': severity, } ) # Log audit AuditService.log_event( event_type='complaint_created', description=f"Complaint created via call center: {complaint.title}", user=request.user, content_object=complaint, metadata={ 'category': complaint.category, 'severity': complaint.severity, 'source': 'call_center', 'caller_name': caller_name, } ) messages.success(request, f"Complaint #{complaint.id} created successfully.") return redirect('callcenter:complaint_success', pk=complaint.id) except Exception as e: messages.error(request, f"Error creating complaint: {str(e)}") return redirect('callcenter:create_complaint') # GET request - show form hospitals = Hospital.objects.filter(status='active') if not request.user.is_px_admin() and request.user.hospital: hospitals = hospitals.filter(id=request.user.hospital.id) context = { 'hospitals': hospitals, } return render(request, 'callcenter/complaint_form.html', context) @login_required def complaint_success(request, pk): """Success page after creating complaint""" complaint = get_object_or_404(Complaint, pk=pk) context = { 'complaint': complaint, } return render(request, 'callcenter/complaint_success.html', context) @login_required def complaint_list(request): """List complaints created by call center""" queryset = Complaint.objects.filter( source=ComplaintSource.CALL_CENTER ).select_related( 'patient', 'hospital', 'department', 'staff', 'assigned_to' ) # Apply RBAC filters user = request.user if user.is_px_admin(): pass elif user.hospital: queryset = queryset.filter(hospital=user.hospital) else: queryset = queryset.none() # Apply filters status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) severity_filter = request.GET.get('severity') if severity_filter: queryset = queryset.filter(severity=severity_filter) hospital_filter = request.GET.get('hospital') if hospital_filter: queryset = queryset.filter(hospital_id=hospital_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(title__icontains=search_query) | Q(description__icontains=search_query) | Q(patient__mrn__icontains=search_query) ) # Ordering queryset = queryset.order_by('-created_at') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get filter options hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) # Statistics stats = { 'total': queryset.count(), 'open': queryset.filter(status='open').count(), 'in_progress': queryset.filter(status='in_progress').count(), 'resolved': queryset.filter(status='resolved').count(), } context = { 'page_obj': page_obj, 'complaints': page_obj.object_list, 'stats': stats, 'hospitals': hospitals, 'filters': request.GET, } return render(request, 'callcenter/complaint_list.html', context) # ============================================================================ # INQUIRY CREATION FOR CALL CENTER # ============================================================================ @login_required @require_http_methods(["GET", "POST"]) def create_inquiry(request): """ Create inquiry from call center interaction. Call center staff can create inquiries for general questions/requests. """ if request.method == 'POST': try: # Get form data patient_id = request.POST.get('patient_id', None) hospital_id = request.POST.get('hospital_id') department_id = request.POST.get('department_id', None) subject = request.POST.get('subject') message = request.POST.get('message') category = request.POST.get('category') # Contact info (if no patient) contact_name = request.POST.get('contact_name', '') contact_phone = request.POST.get('contact_phone', '') contact_email = request.POST.get('contact_email', '') # Call center specific caller_relationship = request.POST.get('caller_relationship', 'patient') # Validate required fields if not all([hospital_id, subject, message, category]): messages.error(request, "Please fill in all required fields.") return redirect('callcenter:create_inquiry') # If no patient, need contact info if not patient_id and not contact_name: messages.error(request, "Please provide either patient or contact information.") return redirect('callcenter:create_inquiry') # Create inquiry inquiry = Inquiry.objects.create( patient_id=patient_id if patient_id else None, hospital_id=hospital_id, department_id=department_id if department_id else None, subject=subject, message=message, category=category, contact_name=contact_name, contact_phone=contact_phone, contact_email=contact_email, ) # Create call center interaction record CallCenterInteraction.objects.create( patient_id=patient_id if patient_id else None, caller_name=contact_name, caller_phone=contact_phone, caller_relationship=caller_relationship, hospital_id=hospital_id, department_id=department_id if department_id else None, agent=request.user, call_type='inquiry', subject=subject, notes=message, metadata={ 'inquiry_id': str(inquiry.id), 'category': category, } ) # Log audit AuditService.log_event( event_type='inquiry_created', description=f"Inquiry created via call center: {inquiry.subject}", user=request.user, content_object=inquiry, metadata={ 'category': inquiry.category, 'source': 'call_center', 'contact_name': contact_name, } ) messages.success(request, f"Inquiry #{inquiry.id} created successfully.") return redirect('callcenter:inquiry_success', pk=inquiry.id) except Exception as e: messages.error(request, f"Error creating inquiry: {str(e)}") return redirect('callcenter:create_inquiry') # GET request - show form hospitals = Hospital.objects.filter(status='active') if not request.user.is_px_admin() and request.user.hospital: hospitals = hospitals.filter(id=request.user.hospital.id) context = { 'hospitals': hospitals, } return render(request, 'callcenter/inquiry_form.html', context) @login_required def inquiry_success(request, pk): """Success page after creating inquiry""" inquiry = get_object_or_404(Inquiry, pk=pk) context = { 'inquiry': inquiry, } return render(request, 'callcenter/inquiry_success.html', context) @login_required def inquiry_list(request): """List inquiries created by call center""" queryset = Inquiry.objects.select_related( 'patient', 'hospital', 'department', 'assigned_to', 'responded_by' ) # Apply RBAC filters user = request.user if user.is_px_admin(): pass elif user.hospital: queryset = queryset.filter(hospital=user.hospital) else: queryset = queryset.none() # Apply filters status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) category_filter = request.GET.get('category') if category_filter: queryset = queryset.filter(category=category_filter) hospital_filter = request.GET.get('hospital') if hospital_filter: queryset = queryset.filter(hospital_id=hospital_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(subject__icontains=search_query) | Q(message__icontains=search_query) | Q(contact_name__icontains=search_query) ) # Ordering queryset = queryset.order_by('-created_at') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get filter options hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) # Statistics stats = { 'total': queryset.count(), 'open': queryset.filter(status='open').count(), 'in_progress': queryset.filter(status='in_progress').count(), 'resolved': queryset.filter(status='resolved').count(), } context = { 'page_obj': page_obj, 'inquiries': page_obj.object_list, 'stats': stats, 'hospitals': hospitals, 'filters': request.GET, } return render(request, 'callcenter/inquiry_list.html', context) # ============================================================================ # AJAX/API HELPERS # ============================================================================ @login_required def get_departments_by_hospital(request): """Get departments for a hospital (AJAX)""" hospital_id = request.GET.get('hospital_id') if not hospital_id: return JsonResponse({'departments': []}) departments = Department.objects.filter( hospital_id=hospital_id, status='active' ).values('id', 'name', 'name_ar') return JsonResponse({'departments': list(departments)}) @login_required def get_staff_by_hospital(request): """Get staff for a hospital (AJAX)""" hospital_id = request.GET.get('hospital_id') if not hospital_id: return JsonResponse({'staff': []}) staff_members = Staff.objects.filter( hospital_id=hospital_id, status='active' ).values('id', 'first_name', 'last_name', 'staff_type', 'specialization') # Format staff names staff_list = [ { 'id': str(s['id']), 'name': f"Dr. {s['first_name']} {s['last_name']}" if s['staff_type'] == 'physician' else f"{s['first_name']} {s['last_name']}", 'staff_type': s['staff_type'], 'specialization': s['specialization'] } for s in staff_members ] return JsonResponse({'staff': staff_list}) @login_required def search_patients(request): """Search patients by MRN or name (AJAX)""" query = request.GET.get('q', '') hospital_id = request.GET.get('hospital_id', None) if len(query) < 2: return JsonResponse({'patients': []}) patients = Patient.objects.filter( Q(mrn__icontains=query) | Q(first_name__icontains=query) | Q(last_name__icontains=query) | Q(national_id__icontains=query) | Q(phone__icontains=query) ) if hospital_id: patients = patients.filter(hospital_id=hospital_id) patients = patients[:20] results = [ { 'id': str(p.id), 'mrn': p.mrn, 'name': p.get_full_name(), 'phone': p.phone, 'email': p.email, 'national_id': p.national_id, } for p in patients ] return JsonResponse({'patients': results})