""" OT (Occupational Therapy) forms for the Tenhal Multidisciplinary Healthcare Platform. This module contains forms for OT consultations, sessions, and progress tracking. Based on OT-F-1 and OT-F-3 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 OTConsult, OTSession, OTTargetSkill, OTProgressReport class OTConsultForm(forms.ModelForm): """ Form for OT consultation (OT-F-1). Initial occupational therapy assessment. """ class Meta: model = OTConsult fields = [ 'patient', 'appointment', 'consultation_date', 'provider', 'reasons', 'top_difficulty_areas', 'developmental_motor_milestones', 'self_help_skills', 'feeding_participation', 'infant_behavior_descriptors', 'current_behavior_descriptors', 'recommendation', 'recommendation_notes', ] widgets = { 'consultation_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'reasons': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Motor delays, Self-care difficulties, Sensory processing issues')}), 'top_difficulty_areas': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'developmental_motor_milestones': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Sitting at 6 months, Walking at 12 months, Running at 18 months')}), 'self_help_skills': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Feeding: independent, Dressing: needs help, Toileting: training')}), 'feeding_participation': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'infant_behavior_descriptors': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Alertness: good, Responsiveness: appropriate')}), 'current_behavior_descriptors': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Cooperation: good, Focus: adequate')}), 'recommendation': forms.Select(attrs={'class': 'form-control'}), 'recommendation_notes': 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( _('Referral Information'), 'reasons', 'top_difficulty_areas', ), Fieldset( _('Developmental Motor Milestones'), 'developmental_motor_milestones', ), Fieldset( _('Self-Help Skills'), 'self_help_skills', ), Fieldset( _('Feeding & Behavior'), 'feeding_participation', 'infant_behavior_descriptors', 'current_behavior_descriptors', ), Fieldset( _('Recommendations'), 'recommendation', 'recommendation_notes', ), Submit('submit', _('Save OT Consultation'), css_class='btn btn-primary') ) class OTSessionForm(forms.ModelForm): """ Form for OT session notes (OT-F-3). Session documentation with target skills. """ class Meta: model = OTSession fields = [ 'patient', 'appointment', 'session_date', 'provider', 'session_type', 'cooperative_level', 'distraction_tolerance', 'activities_checklist', 'observations', 'activities_performed', 'recommendations', ] widgets = { 'session_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'session_type': forms.Select(attrs={'class': 'form-control'}), 'cooperative_level': forms.NumberInput(attrs={'class': 'form-control', 'min': '1', 'max': '4'}), 'distraction_tolerance': forms.NumberInput(attrs={'class': 'form-control', 'min': '1', 'max': '4'}), 'activities_checklist': forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': _('e.g., Fine motor skills, Gross motor skills, Sensory integration')}), 'observations': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'activities_performed': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'recommendations': forms.Textarea(attrs={'rows': 3, '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( _('Session Information'), Row( Column('session_date', css_class='form-group col-md-6 mb-0'), Column('session_type', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), 'provider', ), Fieldset( _('Session Metrics'), Row( Column('cooperative_level', css_class='form-group col-md-6 mb-0'), Column('distraction_tolerance', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), HTML('{}'.format(_('Rate from 1 (Poor) to 4 (Excellent)'))), ), Fieldset( _('Today We Work On...'), 'activities_checklist', ), Fieldset( _('Session Notes'), 'observations', 'activities_performed', 'recommendations', ), HTML('
{}
'.format(_('Add target skills below with baseline and current scores'))), Submit('submit', _('Save OT Session'), css_class='btn btn-primary') ) def clean(self): cleaned_data = super().clean() cooperative_level = cleaned_data.get('cooperative_level') distraction_tolerance = cleaned_data.get('distraction_tolerance') # Validate levels are within range if cooperative_level and (cooperative_level < 1 or cooperative_level > 4): self.add_error('cooperative_level', _('Level must be between 1 and 4')) if distraction_tolerance and (distraction_tolerance < 1 or distraction_tolerance > 4): self.add_error('distraction_tolerance', _('Level must be between 1 and 4')) return cleaned_data class OTTargetSkillForm(forms.ModelForm): """ Form for OT target skills with 0-10 scoring. """ class Meta: model = OTTargetSkill fields = [ 'skill_name', 'score', 'notes', 'order', ] widgets = { 'skill_name': forms.TextInput(attrs={'placeholder': _('e.g., Pencil grip'), 'class': 'form-control'}), 'score': forms.NumberInput(attrs={'class': 'form-control', 'min': '0', 'max': '10'}), 'notes': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'order': forms.HiddenInput(), } def clean(self): cleaned_data = super().clean() score = cleaned_data.get('score') # Validate score is within 0-10 range if score is not None and (score < 0 or score > 10): self.add_error('score', _('Score must be between 0 and 10')) return cleaned_data # Inline formset for target skills OTTargetSkillFormSet = inlineformset_factory( OTSession, OTTargetSkill, form=OTTargetSkillForm, extra=3, can_delete=True, min_num=1, validate_min=True, ) class OTProgressReportForm(forms.ModelForm): """ Form for OT progress reports. """ class Meta: model = OTProgressReport fields = [ 'patient', 'report_date', 'provider', 'sessions_scheduled', 'sessions_attended', 'goals_progress', 'overall_progress', 'recommendations', 'continue_treatment', ] widgets = { 'patient': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select patient'}), 'report_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'sessions_scheduled': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), 'sessions_attended': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), 'goals_progress': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('e.g., Goal 1: Achieved, Goal 2: In Progress, Goal 3: Not Started')}), 'overall_progress': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'recommendations': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'continue_treatment': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } 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-6 mb-0'), Column('sessions_attended', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), ), Fieldset( _('Progress Summary'), 'goals_progress', 'overall_progress', ), Fieldset( _('Recommendations'), 'recommendations', 'continue_treatment', ), Submit('submit', _('Save Progress Report'), css_class='btn btn-primary') ) class OTSessionSearchForm(forms.Form): """ Form for searching OT sessions. """ search_query = forms.CharField( required=False, label=_('Search'), widget=forms.TextInput(attrs={ 'placeholder': _('Patient name, MRN...'), 'class': 'form-control' }) ) session_type = forms.ChoiceField( required=False, label=_('Session Type'), choices=[('', _('All'))] + list(OTSession.SessionType.choices), widget=forms.Select(attrs={'class': 'form-control'}) ) provider = forms.ModelChoiceField( required=False, label=_('Provider'), queryset=None, # Will be set in __init__ widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}) ) date_from = forms.DateField( required=False, label=_('From Date'), widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}) ) date_to = forms.DateField( required=False, label=_('To Date'), widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}) ) def __init__(self, *args, **kwargs): tenant = kwargs.pop('tenant', None) super().__init__(*args, **kwargs) if tenant: from core.models import User self.fields['provider'].queryset = User.objects.filter( tenant=tenant, role=User.Role.OT ) self.helper = FormHelper() self.helper.form_method = 'get' self.helper.layout = Layout( Row( Column('search_query', css_class='form-group col-md-3 mb-0'), Column('session_type', css_class='form-group col-md-2 mb-0'), Column('provider', css_class='form-group col-md-2 mb-0'), Column('date_from', css_class='form-group col-md-2 mb-0'), Column('date_to', css_class='form-group col-md-2 mb-0'), css_class='form-row' ), Submit('search', _('Search'), css_class='btn btn-primary') )