# Complaint Form Fix Summary ## Issue The complaint form at `/complaints/new/` was failing with a TypeError due to incorrect usage of `QuerySet.none()`. ## Root Causes 1. **TypeError**: `QuerySet.none()` was being called as a class method instead of an instance method 2. **FieldError**: The form was trying to order by `name` field, but Location/MainSection/SubSection models use `name_en` for the display name 3. **Missing Fields**: The ComplaintForm was missing new fields added to the Complaint model ## Changes Made ### 1. Fixed `apps/complaints/forms.py` #### PublicComplaintForm (Line 178) **Before:** ```python queryset=models.QuerySet.none(), ``` **After:** ```python queryset=Department.objects.none(), ``` #### Initialize Cascading Dropdown Querysets **Problem:** The `main_section` and `subsection` fields had `queryset=None` initially, causing: ``` 'NoneType' object has no attribute '_prefetch_related_lookups' ``` **Solution:** Added initialization in `__init__` method for both ComplaintForm and PublicComplaintForm: ```python def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) from apps.organizations.models import Location, MainSection, SubSection # Initialize cascading dropdowns with empty querysets self.fields['main_section'].queryset = MainSection.objects.none() self.fields['subsection'].queryset = SubSection.objects.none() # Load all locations (no filtering needed) self.fields['location'].queryset = Location.objects.all().order_by('name_en') ``` #### Added ComplaintType Import ```python from apps.complaints.models import ( Complaint, ComplaintCategory, ComplaintSource, ComplaintStatus, ComplaintType, # Added Inquiry, ComplaintSLAConfig, EscalationRule, ComplaintThreshold, ) ``` #### Updated ComplaintForm with New Fields Added the following fields to ComplaintForm class: - `complaint_type` - Feedback type selection (Complaint/Appreciation) - `relation_to_patient` - Patient or Relative - `patient_name` - Name of patient involved - `national_id` - Saudi National ID or Iqama number - `incident_date` - Date when incident occurred - `staff_name` - Staff member involved (if known) - `expected_result` - Expected resolution from complainant #### Fixed Field Ordering Changed all `.order_by('name')` to `.order_by('name_en')` for Location, MainSection, and SubSection querysets to match the actual field names in the models. ### 2. Updated `templates/complaints/complaint_form.html` #### New Sections Added: 1. **Feedback Type Selection** - Visual cards for Complaint vs Appreciation selection - Interactive JavaScript handlers for selection 2. **Patient Information Section** - Relation to Patient dropdown - Patient Name field - National ID/Iqama field - Incident Date field - Encounter ID field (optional) 3. **Organization & Location Section** - Hospital dropdown - Department dropdown - Location hierarchy (Location → Main Section → Subsection) - Staff dropdown (optional) - Staff Name field (optional) 4. **Complaint Details Section** - Description field - Expected Result field 5. **Enhanced JavaScript** - Complaint type card selection handlers - Hospital change handler (reloads form) - Location change handler (loads sections via AJAX) - Main Section change handler (loads subsections via AJAX) - Department change handler (loads staff via AJAX) - Form validation 6. **Updated Sidebar** - AI Classification information - SLA Information display - Action buttons ## Model Fields Reference ### Location Hierarchy Models ```python # Location model name_en = models.CharField(max_length=200) # Display name name_ar = models.CharField(max_length=200, blank=True) # MainSection model name_en = models.CharField(max_length=200) # Display name name_ar = models.CharField(max_length=200, blank=True) # SubSection model name_en = models.CharField(max_length=200) # Display name name_ar = models.CharField(max_length=200, blank=True) ``` ### Complaint Model New Fields ```python complaint_type = models.CharField(max_length=20, choices=ComplaintType.choices) relation_to_patient = models.CharField(max_length=20) patient_name = models.CharField(max_length=200) national_id = models.CharField(max_length=20) incident_date = models.DateField() staff_name = models.CharField(max_length=200, blank=True) expected_result = models.TextField(blank=True) location = models.ForeignKey('organizations.Location') main_section = models.ForeignKey('organizations.MainSection') subsection = models.ForeignKey('organizations.SubSection') ``` ## Verification ✅ Form imports successfully without errors ✅ All new fields are properly defined ✅ Field ordering uses correct field names (`name_en`) ✅ Template includes all new form sections ✅ JavaScript handlers implemented for cascading dropdowns ✅ Internationalization support maintained (i18n) ## Testing Checklist - [ ] Form loads without errors at `/complaints/new/` - [ ] Location dropdown loads all locations - [ ] Selecting location loads sections via AJAX - [ ] Selecting section loads subsections via AJAX - [ ] Complaint type selection works visually - [ ] Form validation works for all required fields - [ ] Form submission creates complaint with all new fields - [ ] Patient information fields display correctly - [ ] Staff dropdown loads when department is selected ## Notes 1. **AJAX Endpoints**: The form relies on these AJAX endpoints: - `/organizations/ajax/main-sections/?location_id={id}` - `/organizations/ajax/subsections/?location_id={id}&main_section_id={id}` - `/complaints/ajax/physicians/?department_id={id}` 2. **Location Hierarchy**: The form implements a 3-level cascading dropdown system: - Level 1: Location (e.g., Riyadh, Jeddah) - Level 2: Main Section (e.g., Clinical, Administrative) - Level 3: Subsection (e.g., Outpatient, Inpatient) 3. **Complaint Type**: The form supports both Complaint and Appreciation types with a visual card-based selection interface. 4. **i18n Support**: All labels and placeholders use Django's translation system (`_("text")`) for multilingual support. ## Date Completed February 4, 2026