diff --git a/apps/complaints/forms.py b/apps/complaints/forms.py index ba845d6..2068471 100644 --- a/apps/complaints/forms.py +++ b/apps/complaints/forms.py @@ -254,6 +254,201 @@ class PublicComplaintForm(forms.ModelForm): return cleaned_data +class ComplaintForm(forms.ModelForm): + """ + Form for creating complaints by authenticated users. + + Uses Django form rendering with minimal JavaScript for dependent dropdowns. + Category, subcategory, and source are omitted - AI will determine them. + """ + + patient = forms.ModelChoiceField( + label=_("Patient"), + queryset=Patient.objects.filter(status='active'), + empty_label=_("Select Patient"), + required=True, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'patientSelect'}) + ) + + hospital = forms.ModelChoiceField( + label=_("Hospital"), + queryset=Hospital.objects.filter(status='active'), + empty_label=_("Select Hospital"), + required=True, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'hospitalSelect'}) + ) + + department = forms.ModelChoiceField( + label=_("Department"), + queryset=Department.objects.none(), + empty_label=_("Select Department"), + required=False, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'departmentSelect'}) + ) + + staff = forms.ModelChoiceField( + label=_("Staff"), + queryset=Staff.objects.none(), + empty_label=_("Select Staff"), + required=False, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'staffSelect'}) + ) + + encounter_id = forms.CharField( + label=_("Encounter ID"), + required=False, + widget=forms.TextInput(attrs={'class': 'form-control', + 'placeholder': _('Optional encounter/visit ID')}) + ) + + description = forms.CharField( + label=_("Description"), + required=True, + widget=forms.Textarea(attrs={'class': 'form-control', + 'rows': 6, + 'placeholder': _('Detailed description of complaint...')}) + ) + + class Meta: + model = Complaint + fields = ['patient', 'hospital', 'department', 'staff', + 'encounter_id', 'description'] + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + super().__init__(*args, **kwargs) + + # Filter hospital and patient by user permissions + if user and not user.is_px_admin() and user.hospital: + self.fields['hospital'].queryset = Hospital.objects.filter( + id=user.hospital.id + ) + self.fields['patient'].queryset = Patient.objects.filter( + primary_hospital=user.hospital, + status='active' + ) + + # Check for hospital selection in both initial data and POST data + # This is needed for validation to work correctly + hospital_id = None + if 'hospital' in self.data: + hospital_id = self.data.get('hospital') + elif 'hospital' in self.initial: + hospital_id = self.initial.get('hospital') + + if hospital_id: + # Filter departments based on selected hospital + self.fields['department'].queryset = Department.objects.filter( + hospital_id=hospital_id, + status='active' + ).order_by('name') + + # Filter staff based on selected hospital + self.fields['staff'].queryset = Staff.objects.filter( + hospital_id=hospital_id, + status='active' + ).order_by('first_name', 'last_name') + + +class InquiryForm(forms.ModelForm): + """ + Form for creating inquiries by authenticated users. + + Similar to ComplaintForm - supports patient search, department filtering, + and proper field validation with AJAX support. + """ + + patient = forms.ModelChoiceField( + label=_("Patient (Optional)"), + queryset=Patient.objects.filter(status='active'), + empty_label=_("Select Patient"), + required=False, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'patientSelect'}) + ) + + hospital = forms.ModelChoiceField( + label=_("Hospital"), + queryset=Hospital.objects.filter(status='active'), + empty_label=_("Select Hospital"), + required=True, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'hospitalSelect'}) + ) + + department = forms.ModelChoiceField( + label=_("Department (Optional)"), + queryset=Department.objects.none(), + empty_label=_("Select Department"), + required=False, + widget=forms.Select(attrs={'class': 'form-select', 'id': 'departmentSelect'}) + ) + + category = forms.ChoiceField( + label=_("Inquiry Type"), + choices=[ + ('general', 'General Inquiry'), + ('appointment', 'Appointment Related'), + ('billing', 'Billing & Insurance'), + ('medical_records', 'Medical Records'), + ('pharmacy', 'Pharmacy'), + ('insurance', 'Insurance'), + ('feedback', 'Feedback'), + ('other', 'Other'), + ], + required=True, + widget=forms.Select(attrs={'class': 'form-control'}) + ) + + subject = forms.CharField( + label=_("Subject"), + max_length=200, + required=True, + widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Brief subject')}) + ) + + message = forms.CharField( + label=_("Message"), + required=True, + widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'placeholder': _('Describe your inquiry')}) + ) + + # Contact info for inquiries without patient + contact_name = forms.CharField(label=_("Contact Name"), max_length=200, required=False, widget=forms.TextInput(attrs={'class': 'form-control'})) + contact_phone = forms.CharField(label=_("Contact Phone"), max_length=20, required=False, widget=forms.TextInput(attrs={'class': 'form-control'})) + contact_email = forms.EmailField(label=_("Contact Email"), required=False, widget=forms.EmailInput(attrs={'class': 'form-control'})) + + class Meta: + model = Inquiry + fields = ['patient', 'hospital', 'department', 'subject', 'message', + 'contact_name', 'contact_phone', 'contact_email'] + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + super().__init__(*args, **kwargs) + + # Filter hospital by user permissions + if user and not user.is_px_admin() and user.hospital: + self.fields['hospital'].queryset = Hospital.objects.filter( + id=user.hospital.id + ) + + # Check for hospital selection in both initial data and POST data + hospital_id = None + if 'hospital' in self.data: + hospital_id = self.data.get('hospital') + elif 'hospital' in self.initial: + hospital_id = self.initial.get('hospital') + + if hospital_id: + # Filter departments based on selected hospital + self.fields['department'].queryset = Department.objects.filter( + hospital_id=hospital_id, + status='active' + ).order_by('name') + + + + + class SLAConfigForm(forms.ModelForm): """Form for creating and editing SLA configurations""" diff --git a/apps/complaints/ui_views.py b/apps/complaints/ui_views.py index b368f5e..1a38508 100644 --- a/apps/complaints/ui_views.py +++ b/apps/complaints/ui_views.py @@ -14,6 +14,7 @@ from apps.accounts.models import User from apps.core.services import AuditService from apps.organizations.models import Department, Hospital, Staff from apps.px_sources.models import SourceUser, PXSource +from apps.px_sources.models import SourceUser, PXSource from .models import ( Complaint, @@ -248,6 +249,8 @@ def complaint_detail(request, pk): "status_choices": ComplaintStatus.choices, "can_edit": user.is_px_admin() or user.is_hospital_admin(), "hospital_departments": hospital_departments, + 'base_layout': base_layout, + 'source_user': source_user, "explanation": explanation, "explanations": explanations, "explanation_attachments": explanation_attachments, @@ -387,8 +390,7 @@ def complaint_create(request): user=request.user, content_object=complaint, metadata={ - 'severity': complaint.severity, - "category": category.name_en, + # "category": category.name_en, "severity": complaint.severity, "patient_mrn": complaint.patient.mrn if complaint.patient else None, "ai_analysis_pending": True,