HH/SUBSECTION_DROPDOWN_FIX_COMPLETE.md

6.2 KiB

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:

# 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:

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:

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:
      {
        "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:
      {
        "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:

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.

  • 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