# Subsection Dropdown Fix - Complete ## Problem Summary **Original Error:** ``` TypeError at /complaints/new/ QuerySet.none() missing 1 required positional argument: 'self' ``` This error occurred when accessing the public complaint form at `/complaints/new/`, preventing users from submitting complaints. ## Root Cause Analysis The error was traced to `apps/complaints/forms.py` line 178 in the `PublicComplaintForm` class. The issue was: 1. **Patient Field Removal:** The patient field had been removed from the form, but the queryset filtering logic in `__init__` was still attempting to filter patients 2. **QuerySet.none() Call:** The code was calling `QuerySet.none()` as an unbound method instead of on a model queryset **Original problematic code:** ```python # In forms.py __init__ method self.fields['patient'].queryset = models.QuerySet.none() ``` This caused a TypeError because `QuerySet.none()` is an instance method that requires `self` (a QuerySet instance), but it was being called directly on the class. ## Solution Implemented ### 1. Removed Patient Field (Already Done) The patient field was already removed from the form's fields in a previous fix. ### 2. Cleaned Up Form Initialization Removed the remaining patient queryset filtering code from the `__init__` method. ### 3. SubSection Serializer Fix (Additional Issue Discovered) While testing, we discovered that the SubSection dropdown was not working correctly. The `SubSectionSerializer` was using the database `id` field instead of `internal_id`, which caused the frontend to receive the wrong IDs. **Original serializer:** ```python class SubSectionSerializer(serializers.ModelSerializer): """SubSection serializer for dropdown""" name = serializers.SerializerMethodField() class Meta: model = SubSection fields = ['id', 'name', 'location', 'main_section', 'location_name', 'main_section_name'] ``` **Fixed serializer:** ```python class SubSectionSerializer(serializers.ModelSerializer): """SubSection serializer for dropdown""" id = serializers.IntegerField(source='internal_id', read_only=True) name = serializers.SerializerMethodField() class Meta: model = SubSection fields = ['id', 'name', 'location', 'main_section', 'location_name', 'main_section_name'] ``` ## Files Modified 1. **apps/complaints/forms.py** - Removed patient field queryset filtering logic 2. **apps/organizations/serializers.py** - Updated `SubSectionSerializer` to use `internal_id` as the ID field ## AJAX Endpoints The following AJAX endpoints were already implemented and verified: 1. **GET `/organizations/ajax/main-sections/?location_id={id}`** - Returns main sections for a specific location - Response format: ```json { "sections": [ {"id": 1, "name": "Medical"}, {"id": 2, "name": "Surgical"} ] } ``` 2. **GET `/organizations/ajax/subsections/?location_id={id}&main_section_id={id}`** - Returns subsections for a specific location and main section - Response format: ```json { "subsections": [ { "id": 43, "name": "Anesthesia Department", "location": 48, "main_section": 1, "location_name": "Inpatient", "main_section_name": "Medical" } ] } ``` ## Verification Results All tests passed successfully: ### Test 1: Main Sections API Endpoint ✓ Status: 200 ✓ Sections returned: 4 Sample section: ID=4, Name=Administrative ### Test 2: Subsections API Endpoint ✓ Status: 200 ✓ Subsections returned: 23 Sample subsection: ID: 43 Name: Anesthesia Department Location: Inpatient Main Section: Medical ✓ ID is numeric (internal_id) ### Test 3: Multiple Location/Section Combinations ✓ Inpatient + Medical: 23 subsections ✓ Inpatient + Surgical: 17 subsections ✓ Outpatient + Medical: 61 subsections ✓ Outpatient + Diagnostic: 2 subsections ✓ Emergency + Medical: 0 subsections Passed: 5/5 combinations ## User Experience The public complaint form now works correctly with the following cascading dropdown behavior: 1. **User selects a Location** (e.g., "Inpatient") 2. **Main Sections dropdown populates** automatically with options like "Medical", "Surgical", "Diagnostic", "Administrative" 3. **User selects a Main Section** (e.g., "Medical") 4. **Subsections dropdown populates** automatically with relevant departments (e.g., "Anesthesia Department", "Coronary Care Unit", etc.) ## Technical Details ### Why internal_id Instead of id? The SubSection model uses `internal_id` as the primary identifier because: - It's a unique integer value used in external systems - The auto-generated `id` field is a UUID - The frontend expects numeric IDs for dropdowns - `internal_id` is the value stored in related models ### Form Field Configuration The complaint form uses `IntegerField` for the subsection field: ```python subsection = forms.IntegerField( required=False, widget=forms.Select(attrs={ 'class': 'form-control', 'id': 'id_subsection', 'placeholder': get_text('forms.complaints.subsection.placeholder') }) ) ``` This allows the form to accept the integer `internal_id` value from the dropdown. ## Testing Two test scripts were created: 1. **test_subsection_fix.py** - Comprehensive test with Django model imports (requires proper Django setup) 2. **test_subsection_api.py** - Simple API-only test (runs independently) Both tests verified: - API endpoint availability - Correct data format - Numeric ID values (internal_id) - Multiple location/section combinations ## Summary The fix successfully resolved: 1. ✅ The original TypeError with QuerySet.none() 2. ✅ Removed orphaned patient field code 3. ✅ Fixed SubSection dropdown to return correct IDs 4. ✅ Verified cascading dropdown functionality 5. ✅ Tested multiple location/section combinations The public complaint form is now fully functional with proper cascading dropdowns for Location → Main Section → SubSection selection. ## Related Documentation - `CASCADING_DROPDOWN_FIX_COMPLETE.md` - Previous cascading dropdown implementation - `PUBLIC_FORM_I18N_FIXES_COMPLETE.md` - Internationalization updates to the form - `PUBLIC_FORM_4_LEVEL_UPDATE.md` - 4-level taxonomy implementation