HH/COMPLAINT_FORM_FIX_SUMMARY.md

6.1 KiB

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:

queryset=models.QuerySet.none(),

After:

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:

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

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

# 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

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