""" Admin configuration for appointments app. """ from django.contrib import admin from django.utils.html import format_html from django.utils import timezone from .models import * class QueueEntryInline(admin.TabularInline): """ Inline admin for queue entries. """ model = QueueEntry extra = 0 fields = [ 'patient', 'queue_position', 'priority_score', 'status', 'assigned_provider', 'joined_at' ] readonly_fields = ['joined_at'] class TelemedicineSessionInline(admin.StackedInline): """ Inline admin for telemedicine sessions. """ model = TelemedicineSession extra = 0 fields = [ 'platform', 'meeting_url', 'meeting_id', 'meeting_password', 'status', 'scheduled_start', 'scheduled_end' ] @admin.register(AppointmentRequest) class AppointmentRequestAdmin(admin.ModelAdmin): """ Admin configuration for AppointmentRequest model. """ list_display = [ 'patient', 'provider', 'appointment_type', 'specialty', 'scheduled_datetime', 'status', 'priority', 'is_telemedicine' ] list_filter = [ 'tenant', 'appointment_type', 'specialty', 'status', 'priority', 'is_telemedicine', 'insurance_verified', 'authorization_required', 'scheduled_datetime', 'created_at' ] search_fields = [ 'patient__first_name', 'patient__last_name', 'patient__mrn', 'provider__first_name', 'provider__last_name', 'chief_complaint', 'referring_provider' ] ordering = ['-scheduled_datetime', '-created_at'] fieldsets = ( ('Basic Information', { 'fields': ( 'tenant', 'patient', 'provider', 'appointment_type', 'specialty' ) }), ('Scheduling', { 'fields': ( 'preferred_date', 'preferred_time', 'duration_minutes', 'scheduled_datetime', 'scheduled_end_datetime', 'flexible_scheduling', 'earliest_acceptable_date', 'latest_acceptable_date' ) }), ('Priority and Urgency', { 'fields': ('priority', 'urgency_score') }), ('Clinical Information', { 'fields': ( 'chief_complaint', 'clinical_notes', 'referring_provider' ) }), ('Insurance and Authorization', { 'fields': ( 'insurance_verified', 'authorization_required', 'authorization_number' ) }), ('Location', { 'fields': ('location', 'room_number') }), ('Telemedicine', { 'fields': ( 'is_telemedicine', 'telemedicine_platform', 'meeting_url', 'meeting_id', 'meeting_password' ) }), ('Status and Workflow', { 'fields': ('status',) }), ('Check-in Information', { 'fields': ('checked_in_at', 'checked_in_by'), 'classes': ('collapse',) }), ('Completion Information', { 'fields': ('completed_at', 'actual_duration_minutes'), 'classes': ('collapse',) }), ('Cancellation Information', { 'fields': ('cancelled_at', 'cancelled_by', 'cancellation_reason'), 'classes': ('collapse',) }), ('Special Requirements', { 'fields': ( 'special_requirements', 'interpreter_needed', 'interpreter_language' ), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('request_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['request_id', 'created_at', 'updated_at'] inlines = [TelemedicineSessionInline, QueueEntryInline] def get_queryset(self, request): return super().get_queryset(request).select_related( 'tenant', 'patient', 'provider', 'created_by', 'checked_in_by', 'cancelled_by' ) def is_telemedicine(self, obj): return obj.is_telemedicine is_telemedicine.boolean = True is_telemedicine.short_description = 'Telemedicine' @admin.register(SlotAvailability) class SlotAvailabilityAdmin(admin.ModelAdmin): """ Admin configuration for SlotAvailability model. """ list_display = [ 'provider', 'date', 'start_time', 'end_time', 'specialty', 'max_appointments', 'booked_appointments', 'available_capacity', 'is_active', 'is_blocked' ] list_filter = [ 'tenant', 'provider', 'specialty', 'availability_type', 'is_active', 'is_blocked', 'supports_telemedicine', 'telemedicine_only', 'date' ] search_fields = [ 'provider__first_name', 'provider__last_name', 'specialty', 'location', 'room_number' ] ordering = ['date', 'start_time'] fieldsets = ( ('Basic Information', { 'fields': ('tenant', 'provider', 'specialty') }), ('Date and Time', { 'fields': ( 'date', 'start_time', 'end_time', 'duration_minutes' ) }), ('Capacity', { 'fields': ('max_appointments', 'booked_appointments') }), ('Location', { 'fields': ('location', 'room_number') }), ('Availability Type', { 'fields': ('availability_type',) }), ('Telemedicine', { 'fields': ('supports_telemedicine', 'telemedicine_only') }), ('Status', { 'fields': ('is_active', 'is_blocked', 'block_reason') }), ('Recurring Pattern', { 'fields': ( 'is_recurring', 'recurrence_pattern', 'recurrence_end_date' ), 'classes': ('collapse',) }), ('Restrictions', { 'fields': ('patient_restrictions', 'insurance_restrictions'), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('slot_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['slot_id', 'created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'tenant', 'provider', 'created_by' ) def available_capacity(self, obj): return obj.available_capacity available_capacity.short_description = 'Available' @admin.register(WaitingQueue) class WaitingQueueAdmin(admin.ModelAdmin): """ Admin configuration for WaitingQueue model. """ list_display = [ 'name', 'queue_type', 'specialty', 'current_queue_size', 'max_queue_size', 'estimated_wait_time_minutes', 'is_active', 'is_accepting_patients' ] list_filter = [ 'tenant', 'queue_type', 'specialty', 'is_active', 'is_accepting_patients' ] search_fields = ['name', 'description', 'specialty', 'location'] ordering = ['name'] fieldsets = ( ('Basic Information', { 'fields': ('tenant', 'name', 'description', 'queue_type') }), ('Associated Resources', { 'fields': ('providers', 'specialty', 'location') }), ('Queue Management', { 'fields': ( 'max_queue_size', 'average_service_time_minutes', 'priority_weights' ) }), ('Status', { 'fields': ('is_active', 'is_accepting_patients') }), ('Operating Hours', { 'fields': ('operating_hours',), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('queue_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['queue_id', 'created_at', 'updated_at'] inlines = [QueueEntryInline] filter_horizontal = ['providers'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'tenant', 'created_by' ).prefetch_related('providers') def current_queue_size(self, obj): return obj.current_queue_size current_queue_size.short_description = 'Current Size' def estimated_wait_time_minutes(self, obj): return f"{obj.estimated_wait_time_minutes} min" estimated_wait_time_minutes.short_description = 'Est. Wait Time' @admin.register(QueueEntry) class QueueEntryAdmin(admin.ModelAdmin): """ Admin configuration for QueueEntry model. """ list_display = [ 'patient', 'queue', 'queue_position', 'priority_score', 'status', 'wait_time_display', 'assigned_provider', 'joined_at' ] list_filter = [ 'queue', 'status', 'assigned_provider', 'notification_sent', 'notification_method', 'joined_at' ] search_fields = [ 'patient__first_name', 'patient__last_name', 'patient__mrn', 'queue__name', 'assigned_provider__first_name', 'assigned_provider__last_name' ] ordering = ['queue', 'priority_score', 'joined_at'] fieldsets = ( ('Queue Information', { 'fields': ('queue', 'patient', 'appointment') }), ('Position and Priority', { 'fields': ('queue_position', 'priority_score') }), ('Timing', { 'fields': ( 'joined_at', 'estimated_service_time', 'called_at', 'served_at' ) }), ('Status and Assignment', { 'fields': ('status', 'assigned_provider') }), ('Communication', { 'fields': ('notification_sent', 'notification_method') }), ('Notes', { 'fields': ('notes',) }), ('Metadata', { 'fields': ('entry_id', 'updated_at', 'updated_by'), 'classes': ('collapse',) }), ) readonly_fields = ['entry_id', 'joined_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'queue', 'patient', 'appointment', 'assigned_provider', 'updated_by' ) def wait_time_display(self, obj): wait_time = obj.wait_time_minutes if wait_time is not None: return f"{wait_time} min" return "-" wait_time_display.short_description = 'Wait Time' @admin.register(TelemedicineSession) class TelemedicineSessionAdmin(admin.ModelAdmin): """ Admin configuration for TelemedicineSession model. """ list_display = [ 'appointment', 'platform', 'status', 'scheduled_start', 'duration_display', 'connection_quality', 'recording_enabled' ] list_filter = [ 'platform', 'status', 'connection_quality', 'recording_enabled', 'recording_consent', 'encryption_enabled', 'scheduled_start' ] search_fields = [ 'appointment__patient__first_name', 'appointment__patient__last_name', 'appointment__provider__first_name', 'appointment__provider__last_name', 'meeting_id' ] ordering = ['-scheduled_start'] fieldsets = ( ('Session Information', { 'fields': ('appointment', 'platform') }), ('Meeting Details', { 'fields': ( 'meeting_url', 'meeting_id', 'meeting_password' ) }), ('Configuration', { 'fields': ( 'waiting_room_enabled', 'recording_enabled', 'recording_consent' ) }), ('Security', { 'fields': ('encryption_enabled', 'password_required') }), ('Timing', { 'fields': ( 'scheduled_start', 'scheduled_end', 'actual_start', 'actual_end' ) }), ('Participants', { 'fields': ('provider_joined_at', 'patient_joined_at') }), ('Technical Information', { 'fields': ('connection_quality', 'technical_issues') }), ('Recording', { 'fields': ( 'recording_url', 'recording_duration_minutes' ), 'classes': ('collapse',) }), ('Notes', { 'fields': ('session_notes',) }), ('Metadata', { 'fields': ('session_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['session_id', 'created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'appointment__patient', 'appointment__provider', 'created_by' ) def duration_display(self, obj): duration = obj.duration_minutes if duration is not None: return f"{duration} min" return "-" duration_display.short_description = 'Duration' @admin.register(AppointmentTemplate) class AppointmentTemplateAdmin(admin.ModelAdmin): """ Admin configuration for AppointmentTemplate model. """ list_display = [ 'name', 'specialty', 'appointment_type', 'duration_minutes', 'advance_booking_days', 'minimum_notice_hours', 'is_active' ] list_filter = [ 'tenant', 'specialty', 'appointment_type', 'is_active', 'insurance_verification_required', 'authorization_required' ] search_fields = ['name', 'description', 'specialty', 'appointment_type'] ordering = ['specialty', 'name'] fieldsets = ( ('Template Information', { 'fields': ('tenant', 'name', 'description') }), ('Appointment Configuration', { 'fields': ('appointment_type', 'specialty', 'duration_minutes') }), ('Scheduling Rules', { 'fields': ('advance_booking_days', 'minimum_notice_hours') }), ('Requirements', { 'fields': ('insurance_verification_required', 'authorization_required') }), ('Instructions', { 'fields': ( 'pre_appointment_instructions', 'post_appointment_instructions' ) }), ('Forms and Documents', { 'fields': ('required_forms',) }), ('Status', { 'fields': ('is_active',) }), ('Metadata', { 'fields': ('created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'tenant', 'created_by' ) @admin.register(WaitingList) class WaitingListAdmin(admin.ModelAdmin): """ Admin configuration for WaitingList model. """ list_display = [ 'patient', 'specialty', 'priority', 'urgency_score', 'status', 'position', 'days_waiting', 'last_contacted' ] list_filter = [ 'tenant', 'department', 'specialty', 'priority', 'status', 'appointment_type', 'authorization_required', 'requires_interpreter' ] search_fields = [ 'patient__first_name', 'patient__last_name', 'patient__mrn', 'clinical_indication', 'referring_provider' ] ordering = ['priority', 'urgency_score', 'created_at'] fieldsets = ( ('Patient Information', { 'fields': ('tenant', 'patient', 'department', 'provider') }), ('Service Request', { 'fields': ('appointment_type', 'specialty', 'clinical_indication') }), ('Priority and Urgency', { 'fields': ('priority', 'urgency_score', 'diagnosis_codes') }), ('Patient Preferences', { 'fields': ( 'preferred_date', 'preferred_time', 'flexible_scheduling', 'earliest_acceptable_date', 'latest_acceptable_date' ) }), ('Contact Information', { 'fields': ('contact_method', 'contact_phone', 'contact_email') }), ('Status and Position', { 'fields': ('status', 'position', 'estimated_wait_time') }), ('Contact History', { 'fields': ( 'last_contacted', 'contact_attempts', 'max_contact_attempts', 'appointments_offered', 'appointments_declined' ) }), ('Requirements', { 'fields': ( 'requires_interpreter', 'interpreter_language', 'accessibility_requirements', 'transportation_needed' ), 'classes': ('collapse',) }), ('Insurance and Authorization', { 'fields': ( 'insurance_verified', 'authorization_required', 'authorization_status', 'authorization_number' ), 'classes': ('collapse',) }), ('Referral Information', { 'fields': ( 'referring_provider', 'referral_date', 'referral_urgency' ), 'classes': ('collapse',) }), ('Outcome', { 'fields': ( 'scheduled_appointment', 'removal_reason', 'removal_notes', 'removed_at', 'removed_by' ), 'classes': ('collapse',) }), ('Notes', { 'fields': ('notes',) }), ('Metadata', { 'fields': ('waiting_list_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['waiting_list_id', 'created_at', 'updated_at', 'days_waiting'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'tenant', 'patient', 'department', 'provider', 'created_by', 'removed_by', 'scheduled_appointment' ) def days_waiting(self, obj): return obj.days_waiting days_waiting.short_description = 'Days Waiting' @admin.register(WaitingListContactLog) class WaitingListContactLogAdmin(admin.ModelAdmin): """ Admin configuration for WaitingListContactLog model. """ list_display = [ 'waiting_list_entry', 'contact_date', 'contact_method', 'contact_outcome', 'appointment_offered', 'patient_response' ] list_filter = [ 'contact_method', 'contact_outcome', 'appointment_offered', 'patient_response', 'contact_date' ] search_fields = [ 'waiting_list_entry__patient__first_name', 'waiting_list_entry__patient__last_name', 'notes' ] ordering = ['-contact_date'] fieldsets = ( ('Contact Information', { 'fields': ('waiting_list_entry', 'contact_method', 'contact_outcome') }), ('Appointment Offer', { 'fields': ( 'appointment_offered', 'offered_date', 'offered_time', 'patient_response' ) }), ('Follow-up', { 'fields': ('next_contact_date',) }), ('Notes', { 'fields': ('notes',) }), ('Metadata', { 'fields': ('contact_date', 'contacted_by'), 'classes': ('collapse',) }), ) readonly_fields = ['contact_date'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'waiting_list_entry__patient', 'contacted_by' )