195 lines
6.2 KiB
Markdown
195 lines
6.2 KiB
Markdown
# 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 |