""" SLP (Speech-Language Pathology) forms for the Tenhal Multidisciplinary Healthcare Platform. This module contains forms for SLP consultations, assessments, interventions, and progress reports. Based on SLP-F-1, F-2, F-3, and F-4 forms. """ from django import forms from django.forms import inlineformset_factory from django.utils.translation import gettext_lazy as _ from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Fieldset, Row, Column, Submit, HTML from .models import SLPConsult, SLPAssessment, SLPIntervention, SLPTarget, SLPProgressReport class SLPConsultForm(forms.ModelForm): """ Form for SLP consultation (SLP-F-1). Supports variant-specific questionnaires (ASD/LanguageDelay/Fluency). """ class Meta: model = SLPConsult fields = [ 'patient', 'appointment', 'consultation_date', 'provider', 'consult_variant', 'primary_concern', 'suspected_areas', 'type_of_service', 'communication_modes', 'screen_time_hours', 'variant_questionnaire', 'skills_to_observe', 'oral_motor_screening', 'recommendations', ] widgets = { 'consultation_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'consult_variant': forms.Select(attrs={'class': 'form-control'}), 'primary_concern': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'suspected_areas': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Articulation, Language comprehension, Social communication')}), 'type_of_service': forms.Select(attrs={'class': 'form-control'}), 'communication_modes': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Verbal, Gestures, AAC device, Sign language')}), 'screen_time_hours': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), 'variant_questionnaire': forms.Textarea(attrs={'rows': 4, 'class': 'form-control', 'placeholder': _('Describe variant-specific observations and responses')}), 'skills_to_observe': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Receptive: follows commands, understands questions. Expressive: vocabulary, sentence structure')}), 'oral_motor_screening': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Lips: adequate, Tongue: adequate, Jaw: adequate, Palate: intact')}), 'recommendations': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'patient': forms.HiddenInput(), 'appointment': forms.HiddenInput(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'patient', 'appointment', Fieldset( _('Consultation Information'), Row( Column('consultation_date', css_class='form-group col-md-6 mb-0'), Column('provider', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), ), Fieldset( _('Consultation Type'), Row( Column('consult_variant', css_class='form-group col-md-6 mb-0'), Column('type_of_service', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), HTML('{}'.format(_('Variant selection will show specific questionnaire'))), ), Fieldset( _('Primary Concerns'), 'primary_concern', 'suspected_areas', ), Fieldset( _('Communication & Environment'), 'communication_modes', 'screen_time_hours', ), Fieldset( _('Variant-Specific Questionnaire'), HTML('
{}
'.format(_('ASD: Social interaction, repetitive behaviors | Language Delay: Milestones, comprehension | Fluency: Stuttering patterns'))), 'variant_questionnaire', ), Fieldset( _('Skills to Observe'), 'skills_to_observe', ), Fieldset( _('Oral Motor Screening'), 'oral_motor_screening', ), Fieldset( _('Recommendations'), 'recommendations', ), Submit('submit', _('Save SLP Consultation'), css_class='btn btn-primary') ) class SLPAssessmentForm(forms.ModelForm): """ Form for SLP assessment/reassessment (SLP-F-2). Comprehensive evaluation with standardized tests. """ class Meta: model = SLPAssessment fields = [ 'patient', 'appointment', 'assessment_date', 'provider', 'diagnosis_statement', 'case_history', 'prenatal_history', 'perinatal_history', 'postnatal_history', 'developmental_history', 'medical_status', 'speech_language_detail', 'gfta3_score', 'jat_score', 'ssi_score', 'oral_mechanism', 'rossetti_domains', 'joint_attention_skills', 'clinical_summary', 'recommendations', 'frequency_per_week', 'session_duration_minutes', 'referral_rules', ] widgets = { 'patient': forms.HiddenInput(), 'appointment': forms.HiddenInput(), 'assessment_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'diagnosis_statement': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'case_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'prenatal_history': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'perinatal_history': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'postnatal_history': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'developmental_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'medical_status': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'speech_language_detail': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Articulation: details, Phonology: details, Fluency: details')}), 'gfta3_score': forms.TextInput(attrs={'class': 'form-control'}), 'jat_score': forms.TextInput(attrs={'class': 'form-control'}), 'ssi_score': forms.TextInput(attrs={'class': 'form-control'}), 'oral_mechanism': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Structure: adequate, Function: adequate, Diadochokinesis: adequate')}), 'rossetti_domains': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Interaction: 12-15 months, Pragmatics: 9-12 months, Gesture: 12-15 months')}), 'joint_attention_skills': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Eye contact: present, Pointing: absent, Showing: present')}), 'clinical_summary': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'recommendations': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'frequency_per_week': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), 'session_duration_minutes': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), 'referral_rules': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Refer to: Audiology, OT. Reason: Sensory concerns')}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'patient', 'appointment', Fieldset( _('Assessment Information'), Row( Column('assessment_date', css_class='form-group col-md-6 mb-0'), Column('provider', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), ), Fieldset( _('Diagnosis & Case History'), 'diagnosis_statement', 'case_history', ), Fieldset( _('History Sections'), 'prenatal_history', 'perinatal_history', 'postnatal_history', 'developmental_history', 'medical_status', ), Fieldset( _('Speech/Language Detail & Test Scores'), 'speech_language_detail', Row( Column('gfta3_score', css_class='form-group col-md-4 mb-0'), Column('jat_score', css_class='form-group col-md-4 mb-0'), Column('ssi_score', css_class='form-group col-md-4 mb-0'), css_class='form-row' ), HTML('{}'.format(_('GFTA-3: Goldman-Fristoe | JAT: Joliet Articulation | SSI: Stuttering Severity'))), ), Fieldset( _('Oral Mechanism'), 'oral_mechanism', ), Fieldset( _('Rossetti Infant-Toddler Language Scale'), 'rossetti_domains', ), Fieldset( _('Joint Attention Skills'), 'joint_attention_skills', ), Fieldset( _('Summary & Plan'), 'clinical_summary', 'recommendations', Row( Column('frequency_per_week', css_class='form-group col-md-6 mb-0'), Column('session_duration_minutes', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), ), Fieldset( _('Referral Rules'), 'referral_rules', ), Submit('submit', _('Save SLP Assessment'), css_class='btn btn-primary') ) class SLPInterventionForm(forms.ModelForm): """ Form for SLP intervention session (SLP-F-3). Session notes with SOAP format for targets stored as JSON. """ class Meta: model = SLPIntervention fields = [ 'patient', 'appointment', 'session_number', 'session_date', 'session_time', 'provider', 'previous_session', 'intervention_targets_json', ] widgets = { 'patient': forms.HiddenInput(), 'appointment': forms.HiddenInput(), 'session_number': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), 'session_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'session_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'previous_session': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select previous session'}), 'intervention_targets_json': forms.HiddenInput(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Filter previous_session queryset to only show sessions for the same patient if self.instance and self.instance.patient_id: # For existing intervention, filter by the patient self.fields['previous_session'].queryset = SLPIntervention.objects.filter( patient=self.instance.patient ).exclude(pk=self.instance.pk).order_by('-session_date', '-session_number') elif self.initial.get('patient'): # For new intervention with initial patient data from core.models import Patient try: patient = Patient.objects.get(pk=self.initial['patient']) self.fields['previous_session'].queryset = SLPIntervention.objects.filter( patient=patient ).order_by('-session_date', '-session_number') except Patient.DoesNotExist: self.fields['previous_session'].queryset = SLPIntervention.objects.none() else: # No patient selected yet, show no options self.fields['previous_session'].queryset = SLPIntervention.objects.none() self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'patient', 'appointment', Fieldset( _('Session Information'), Row( Column('session_number', css_class='form-group col-md-4 mb-0'), Column('session_date', css_class='form-group col-md-4 mb-0'), Column('session_time', css_class='form-group col-md-4 mb-0'), css_class='form-row' ), 'provider', 'previous_session', HTML('{}
{}
'.format(_('Add 1-2 targets below with SOAP notes and prompt strategies'))), Submit('submit', _('Save SLP Intervention'), css_class='btn btn-primary') ) class SLPTargetForm(forms.ModelForm): """ Form for SLP intervention targets with SOAP format. """ class Meta: model = SLPTarget fields = [ 'target_number', 'subjective', 'objective', 'assessment', 'plan', 'prompt_strategies', ] widgets = { 'target_number': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), 'subjective': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('Subjective observations')}), 'objective': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('Objective measurements and data')}), 'assessment': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('Assessment of progress')}), 'plan': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('Plan for next session')}), 'prompt_strategies': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('["Visual cues", "Verbal prompts", "Physical guidance"]')}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Add help text for prompt strategies self.fields['prompt_strategies'].help_text = _('JSON array: ["Visual cues", "Verbal prompts", "Physical guidance"]') # Inline formset for SLP targets SLPTargetFormSet = inlineformset_factory( SLPIntervention, SLPTarget, form=SLPTargetForm, extra=2, max_num=2, can_delete=True, min_num=1, validate_min=True, ) class SLPProgressReportForm(forms.ModelForm): """ Form for SLP progress report (SLP-F-4). Comprehensive progress summary with outcomes. """ class Meta: model = SLPProgressReport fields = [ 'patient', 'report_date', 'provider', 'sessions_scheduled', 'sessions_attended', 'final_diagnosis', 'objectives_progress', 'plan_details', 'overall_progress', 'participation_level', 'attendance_rate', 'carryover_level', 'prognosis', 'recommendations', 'package_sessions_count', 'reassessment_needed', ] widgets = { 'patient': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select patient'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'report_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'final_diagnosis': forms.Textarea(attrs={'rows': 2}), 'overall_progress': forms.Textarea(attrs={'rows': 4}), 'participation_level': forms.Textarea(attrs={'rows': 2}), 'carryover_level': forms.Textarea(attrs={'rows': 2}), 'prognosis': forms.Textarea(attrs={'rows': 2}), 'recommendations': forms.Textarea(attrs={'rows': 4}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'patient', Row( Column('report_date', css_class='form-group col-md-6 mb-0'), Column('provider', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), Fieldset( _('Session Summary'), Row( Column('sessions_scheduled', css_class='form-group col-md-4 mb-0'), Column('sessions_attended', css_class='form-group col-md-4 mb-0'), Column('attendance_rate', css_class='form-group col-md-4 mb-0'), css_class='form-row' ), HTML('{}'.format(_('Attendance rate will be auto-calculated if not provided'))), ), Fieldset( _('Diagnosis'), 'final_diagnosis', ), Fieldset( _('Objectives & Progress'), HTML('{}
'.format(_('Objective → % accuracy mapping (JSON format)'))), HTML('