""" Admin configuration for patients app. """ from django.contrib import admin from django.utils.html import format_html from .models import * class EmergencyContactInline(admin.TabularInline): """ Inline admin for emergency contacts. """ model = EmergencyContact extra = 1 fields = [ 'first_name', 'last_name', 'relationship', 'phone_number', 'priority', 'is_authorized_for_medical_decisions', 'is_active' ] class InsuranceInfoInline(admin.TabularInline): """ Inline admin for insurance information. """ model = InsuranceInfo extra = 1 fields = [ 'insurance_type', 'insurance_company', 'policy_number', 'effective_date', 'is_verified', 'is_active' ] class ConsentFormInline(admin.TabularInline): """ Inline admin for consent forms. """ model = ConsentForm extra = 0 fields = ['template', 'status', 'effective_date', 'patient_signed_at'] readonly_fields = ['patient_signed_at'] class PatientNoteInline(admin.TabularInline): """ Inline admin for patient notes. """ model = PatientNote extra = 0 fields = ['title', 'category', 'priority', 'is_alert', 'created_at'] readonly_fields = ['created_at'] @admin.register(PatientProfile) class PatientProfileAdmin(admin.ModelAdmin): """ Admin configuration for PatientProfile model. """ list_display = [ 'mrn', 'get_full_name', 'date_of_birth', 'age', 'gender', 'mobile_number', 'is_active', ] list_filter = [ 'tenant', 'gender', 'marital_status', 'is_active', 'is_deceased', 'is_vip', 'confidential_patient', ] search_fields = [ 'mrn', 'id_number', 'first_name', 'last_name', 'email', 'mobile_number', ] ordering = ['last_name', 'first_name'] fieldsets = ( ('Basic Information', { 'fields': ( 'tenant', 'mrn', 'first_name', 'last_name', 'middle_name', 'preferred_name', 'suffix', 'photo' ) }), ('Demographics', { 'fields': ( 'date_of_birth', 'gender', 'marital_status' ) }), ('Contact Information', { 'fields': ( 'email', 'phone_number', 'mobile_number', 'address_line_1', 'address_line_2', 'city', 'state', 'zip_code', 'country' ) }), ('Language and Communication', { 'fields': ( 'primary_language', 'interpreter_needed', 'communication_preference' ) }), ('Employment', { 'fields': ('employer', 'occupation') }), ('Healthcare Information', { 'fields': ( 'primary_care_physician', 'referring_physician', 'allergies', 'medical_alerts' ) }), ('Advance Directives', { 'fields': ('has_advance_directive', 'advance_directive_type') }), ('Status and Flags', { 'fields': ( 'is_active', 'is_deceased', 'date_of_death', 'is_vip', 'confidential_patient' ) }), ('Registration', { 'fields': ( 'registered_by', 'last_visit_date'), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('patient_id', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['patient_id', 'created_at', 'updated_at', 'age'] inlines = [EmergencyContactInline, InsuranceInfoInline, ConsentFormInline, PatientNoteInline] def get_queryset(self, request): return super().get_queryset(request).select_related('tenant', 'registered_by') def age(self, obj): return obj.age age.short_description = 'Age' @admin.register(EmergencyContact) class EmergencyContactAdmin(admin.ModelAdmin): """ Admin configuration for EmergencyContact model. """ list_display = [ 'get_full_name', 'patient', 'relationship', 'phone_number', 'priority', 'is_authorized_for_medical_decisions', 'is_active' ] list_filter = [ 'relationship', 'priority', 'is_authorized_for_medical_decisions', 'is_authorized_for_financial_decisions', 'is_authorized_for_information', 'is_active' ] search_fields = [ 'first_name', 'last_name', 'phone_number', 'email', 'patient__first_name', 'patient__last_name', 'patient__mrn' ] ordering = ['patient__last_name', 'priority', 'last_name'] fieldsets = ( ('Contact Information', { 'fields': ( 'patient', 'first_name', 'last_name', 'relationship' ) }), ('Contact Details', { 'fields': ( 'phone_number', 'mobile_number', 'email' ) }), ('Address', { 'fields': ( 'address_line_1', 'address_line_2', 'city', 'state', 'zip_code' ) }), ('Authorization', { 'fields': ( 'priority', 'is_authorized_for_medical_decisions', 'is_authorized_for_financial_decisions', 'is_authorized_for_information' ) }), ('Status', { 'fields': ('is_active', 'notes') }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related('patient') @admin.register(InsuranceInfo) class InsuranceInfoAdmin(admin.ModelAdmin): """ Admin configuration for InsuranceInfo model. """ list_display = [ 'patient', 'insurance_company', 'insurance_type', 'policy_number', 'is_verified', 'is_coverage_active', 'effective_date' ] list_filter = [ 'insurance_type', 'plan_type', 'is_verified', 'is_active', 'subscriber_relationship', 'effective_date' ] search_fields = [ 'insurance_company', 'plan_name', 'policy_number', 'group_number', 'subscriber_name', 'patient__first_name', 'patient__last_name', 'patient__mrn' ] ordering = ['patient__last_name', 'insurance_type'] fieldsets = ( ('Patient Information', { 'fields': ('patient',) }), ('Insurance Details', { 'fields': ( 'insurance_type', 'insurance_company', 'plan_name', 'plan_type' ) }), ('Policy Information', { 'fields': ('policy_number', 'group_number') }), ('Subscriber Information', { 'fields': ( 'subscriber_name', 'subscriber_relationship', 'subscriber_dob', ) }), ('Coverage', { 'fields': ('effective_date', 'termination_date') }), ('Financial Information', { 'fields': ('copay_amount', 'deductible_amount', 'out_of_pocket_max') }), ('Verification', { 'fields': ('is_verified', 'verification_date', 'verified_by') }), ('Authorization', { 'fields': ( 'requires_authorization', 'authorization_number', 'authorization_expiry' ) }), ('Status', { 'fields': ('is_active', 'notes') }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related('patient', 'verified_by') def is_coverage_active(self, obj): return obj.is_coverage_active is_coverage_active.boolean = True is_coverage_active.short_description = 'Coverage Active' @admin.register(ConsentTemplate) class ConsentTemplateAdmin(admin.ModelAdmin): """ Admin configuration for ConsentTemplate model. """ list_display = [ 'name', 'category', 'version', 'is_active', 'effective_date', 'created_by' ] list_filter = [ 'tenant', 'category', 'is_active', 'requires_signature', 'requires_witness', 'requires_guardian', 'effective_date' ] search_fields = ['name', 'description', 'category'] ordering = ['category', 'name'] fieldsets = ( ('Template Information', { 'fields': ('tenant', 'name', 'description', 'category') }), ('Content', { 'fields': ('content',) }), ('Requirements', { 'fields': ( 'requires_signature', 'requires_witness', 'requires_guardian' ) }), ('Validity', { 'fields': ('is_active', 'version', 'effective_date', 'expiry_date') }), ('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(ConsentForm) class ConsentFormAdmin(admin.ModelAdmin): """ Admin configuration for ConsentForm model. """ list_display = [ 'patient', 'template', 'status', 'is_valid', 'patient_signed_at', 'effective_date' ] list_filter = [ 'status', 'template__category', 'patient_signed_at', 'effective_date', 'created_at' ] search_fields = [ 'patient__first_name', 'patient__last_name', 'patient__mrn', 'template__name', 'guardian_name', 'witness_name', 'provider_name' ] ordering = ['-created_at'] fieldsets = ( ('Consent Information', { 'fields': ('patient', 'template', 'status') }), ('Patient Signature', { 'fields': ( 'patient_signature', 'patient_signed_at', 'patient_ip_address' ) }), ('Guardian Signature', { 'fields': ( 'guardian_signature', 'guardian_signed_at', 'guardian_name', 'guardian_relationship' ) }), ('Witness Signature', { 'fields': ( 'witness_signature', 'witness_signed_at', 'witness_name', 'witness_title' ) }), ('Provider Information', { 'fields': ( 'provider_name', 'provider_signature', 'provider_signed_at' ) }), ('Validity', { 'fields': ('effective_date', 'expiry_date') }), ('Revocation', { 'fields': ('revoked_at', 'revoked_by', 'revocation_reason') }), ('Notes', { 'fields': ('notes',) }), ('Metadata', { 'fields': ('consent_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['consent_id', 'created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related( 'patient', 'template', 'created_by', 'revoked_by' ) def is_valid(self, obj): return obj.is_valid is_valid.boolean = True is_valid.short_description = 'Valid' @admin.register(PatientNote) class PatientNoteAdmin(admin.ModelAdmin): """ Admin configuration for PatientNote model. """ list_display = [ 'title', 'patient', 'category', 'priority', 'is_alert', 'is_confidential', 'created_by', 'created_at' ] list_filter = [ 'category', 'priority', 'is_alert', 'is_confidential', 'is_active', 'created_at' ] search_fields = [ 'title', 'content', 'patient__first_name', 'patient__last_name', 'patient__mrn' ] ordering = ['-created_at'] fieldsets = ( ('Note Information', { 'fields': ('patient', 'title', 'content') }), ('Classification', { 'fields': ('category', 'priority') }), ('Visibility', { 'fields': ('is_confidential', 'is_alert', 'is_active') }), ('Metadata', { 'fields': ('note_id', 'created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) readonly_fields = ['note_id', 'created_at', 'updated_at'] def get_queryset(self, request): return super().get_queryset(request).select_related('patient', 'created_by') class ClaimDocumentInline(admin.TabularInline): """Inline admin for claim documents.""" model = ClaimDocument extra = 0 readonly_fields = ['uploaded_at', 'file_size'] class ClaimStatusHistoryInline(admin.TabularInline): """Inline admin for claim status history.""" model = ClaimStatusHistory extra = 0 readonly_fields = ['changed_at'] ordering = ['-changed_at'] fields = [ 'changed_at'] @admin.register(InsuranceClaim) class InsuranceClaimAdmin(admin.ModelAdmin): """Admin interface for InsuranceClaim.""" list_display = [ 'claim_number', 'patient', 'claim_type', 'priority', 'billed_amount', 'approved_amount', 'service_date', 'submitted_date' ] list_filter = [ 'claim_type', 'priority', 'service_date', 'submitted_date', 'processed_date' ] search_fields = [ 'claim_number', 'patient__first_name', 'patient__last_name', 'service_provider', 'facility_name', 'primary_diagnosis_code' ] ordering = ['-created_at'] fieldsets = ( ('Claim Information', { 'fields': ('claim_number', 'patient', 'insurance_info', 'claim_type', 'status', 'priority') }), ('Service Information', { 'fields': ( 'service_date', 'service_provider', 'service_provider_license', 'facility_name', 'facility_license' ) }), ('Medical Codes', { 'fields': ( 'primary_diagnosis_code', 'primary_diagnosis_description', 'secondary_diagnosis_codes', 'procedure_codes' ) }), ('Financial Information', { 'fields': ( 'billed_amount', 'approved_amount', 'paid_amount', 'patient_responsibility', 'discount_amount' ) }), ('Processing Dates', { 'fields': ('submitted_date', 'processed_date', 'payment_date') }), ('Saudi-specific Information', { 'fields': ('saudi_id_number', 'insurance_card_number', 'authorization_number') }), ('Denial/Appeal Information', { 'fields': ('denial_reason', 'denial_code', 'appeal_date', 'appeal_reason'), 'classes': ('collapse',) }), ('Additional Information', { 'fields': ('notes', 'attachments'), 'classes': ('collapse',) }) ) readonly_fields = ['created_at', 'updated_at'] inlines = [ClaimDocumentInline, ClaimStatusHistoryInline] def get_queryset(self, request): """Optimize queryset with select_related.""" return super().get_queryset(request).select_related('patient', 'insurance_info') def formfield_for_foreignkey(self, db_field, request, **kwargs): """Optimize foreign key fields.""" if db_field.name == "patient": kwargs["queryset"] = PatientProfile.objects.select_related('tenant') elif db_field.name == "insurance_info": kwargs["queryset"] = InsuranceInfo.objects.select_related('patient') return super().formfield_for_foreignkey(db_field, request, **kwargs) @admin.register(ClaimDocument) class ClaimDocumentAdmin(admin.ModelAdmin): """Admin interface for ClaimDocument.""" list_display = [ 'title', 'claim', 'document_type', 'file_size_display', 'mime_type', 'uploaded_at', 'uploaded_by' ] list_filter = ['document_type', 'mime_type', 'uploaded_at'] search_fields = ['title', 'claim__claim_number', 'description'] ordering = ['-uploaded_at'] def file_size_display(self, obj): """Display file size in human readable format.""" size = obj.file_size for unit in ['B', 'KB', 'MB', 'GB']: if size < 1024.0: return f"{size:.1f} {unit}" size /= 1024.0 return f"{size:.1f} TB" file_size_display.short_description = 'File Size' @admin.register(ClaimStatusHistory) class ClaimStatusHistoryAdmin(admin.ModelAdmin): """Admin interface for ClaimStatusHistory.""" list_display = [ 'claim', 'from_status', 'to_status', 'changed_at', 'changed_by' ] list_filter = ['from_status', 'to_status', 'changed_at'] search_fields = ['claim__claim_number', 'reason', 'notes'] ordering = ['-changed_at'] def get_queryset(self, request): """Optimize queryset with select_related.""" return super().get_queryset(request).select_related('claim', 'changed_by') # Custom admin site configuration admin.site.site_header = "Hospital Management System - Patients" admin.site.site_title = "HMS Patients Admin" admin.site.index_title = "Patients Administration"