""" Medical forms for the Tenhal Multidisciplinary Healthcare Platform. This module contains forms for medical consultations and follow-ups. Based on MD-F-1 and MD-F-2 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 MedicalConsultation, MedicationPlan, MedicalFollowUp, ConsultationResponse, ConsultationFeedback class MedicalConsultationForm(forms.ModelForm): """ Form for medical consultation (MD-F-1). Comprehensive initial consultation form. """ class Meta: model = MedicalConsultation fields = [ 'patient', 'appointment', 'consultation_date', 'provider', 'chief_complaint', 'present_illness_history', 'past_medical_history', 'vaccination_status', 'family_history', 'social_history', 'pregnancy_history', 'neonatal_history', 'developmental_motor_milestones', 'developmental_language_milestones', 'developmental_social_milestones', 'developmental_cognitive_milestones', 'behavioral_symptoms', 'physical_exam', 'clinical_summary', 'recommendations', ] widgets = { 'consultation_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'chief_complaint': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'present_illness_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'past_medical_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'vaccination_status': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'family_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'social_history': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'pregnancy_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'neonatal_history': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'developmental_motor_milestones': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'developmental_language_milestones': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'developmental_social_milestones': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'developmental_cognitive_milestones': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'behavioral_symptoms': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'physical_exam': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'clinical_summary': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), '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( _('Chief Complaint & Present History'), 'chief_complaint', 'present_illness_history', ), Fieldset( _('Past History'), 'past_medical_history', 'vaccination_status', ), Fieldset( _('Family & Social History'), 'family_history', 'social_history', ), Fieldset( _('Pregnancy & Neonatal History'), 'pregnancy_history', 'neonatal_history', ), Fieldset( _('Developmental History'), HTML('

{}

'.format(_('Motor, Language, Social, and Cognitive Milestones'))), 'developmental_motor_milestones', 'developmental_language_milestones', 'developmental_social_milestones', 'developmental_cognitive_milestones', ), Fieldset( _('Behavioral Symptoms'), HTML('

{}

'.format(_('Checklist of behavioral observations'))), 'behavioral_symptoms', ), Fieldset( _('Physical Examination'), 'physical_exam', ), Fieldset( _('Summary & Recommendations'), 'clinical_summary', 'recommendations', ), HTML('
{}
'.format(_('Medications'))), HTML('

{}

'.format(_('Add current medications below'))), Submit('submit', _('Save Consultation'), css_class='btn btn-primary') ) class MedicationPlanForm(forms.ModelForm): """ Form for medication plans. """ class Meta: model = MedicationPlan fields = [ 'drug_name', 'dose', 'frequency', 'compliance', 'gains', 'side_effects', 'target_behavior', 'improved', ] widgets = { 'drug_name': forms.TextInput(attrs={'class': 'form-control'}), 'dose': forms.TextInput(attrs={'class': 'form-control'}), 'frequency': forms.TextInput(attrs={'class': 'form-control'}), 'compliance': forms.Select(attrs={'class': 'form-control'}), 'gains': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'side_effects': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'target_behavior': forms.TextInput(attrs={'class': 'form-control'}), 'improved': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } # Inline formset for medications MedicationPlanFormSet = inlineformset_factory( MedicalConsultation, MedicationPlan, form=MedicationPlanForm, extra=3, can_delete=True, min_num=0, ) class MedicalFollowUpForm(forms.ModelForm): """ Form for medical follow-up (MD-F-2). Links to previous consultation. """ class Meta: model = MedicalFollowUp fields = [ 'patient', 'appointment', 'followup_date', 'provider', 'previous_consultation', 'previous_complaints_status', 'new_complaints', 'nursing_vitals', 'assessment', 'recommendations', 'family_satisfaction', ] widgets = { 'patient': forms.HiddenInput(), 'appointment': forms.HiddenInput(), 'followup_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}), 'previous_consultation': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select previous consultation'}), 'previous_complaints_status': forms.HiddenInput(), 'new_complaints': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'nursing_vitals': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select nursing vitals'}), 'assessment': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'recommendations': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'family_satisfaction': forms.RadioSelect(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Filter previous_consultation queryset to only show consultations for the same patient if self.instance and self.instance.patient_id: self.fields['previous_consultation'].queryset = MedicalConsultation.objects.filter( patient=self.instance.patient ).order_by('-consultation_date') elif self.initial.get('patient'): from core.models import Patient try: patient = Patient.objects.get(pk=self.initial['patient']) self.fields['previous_consultation'].queryset = MedicalConsultation.objects.filter( patient=patient ).order_by('-consultation_date') except Patient.DoesNotExist: self.fields['previous_consultation'].queryset = MedicalConsultation.objects.none() else: self.fields['previous_consultation'].queryset = MedicalConsultation.objects.none() # Filter nursing_vitals to same patient if available if self.instance and self.instance.patient_id: from nursing.models import NursingEncounter self.fields['nursing_vitals'].queryset = NursingEncounter.objects.filter( patient=self.instance.patient ).order_by('-encounter_date') elif self.initial.get('patient'): from core.models import Patient from nursing.models import NursingEncounter try: patient = Patient.objects.get(pk=self.initial['patient']) self.fields['nursing_vitals'].queryset = NursingEncounter.objects.filter( patient=patient ).order_by('-encounter_date') except Patient.DoesNotExist: self.fields['nursing_vitals'].queryset = NursingEncounter.objects.none() else: from nursing.models import NursingEncounter self.fields['nursing_vitals'].queryset = NursingEncounter.objects.none() self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'patient', 'appointment', Fieldset( _('Follow-up Information'), Row( Column('followup_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' ), 'previous_consultation', 'nursing_vitals', ), Fieldset( _('Previous Complaints Status'), HTML('

{}

'.format(_('Status of complaints from previous consultation'))), 'previous_complaints_status', ), Fieldset( _('New Complaints'), 'new_complaints', ), Fieldset( _('Assessment & Plan'), 'assessment', 'recommendations', ), Fieldset( _('Family Satisfaction'), HTML('

{}

'.format(_('Rate family satisfaction: 0 (Not Satisfied), 50 (Neutral), 100 (Very Satisfied)'))), 'family_satisfaction', ), HTML('
{}
'.format(_('Current Medications'))), HTML('

{}

'.format(_('Medication snapshot from previous consultation will be displayed here'))), Submit('submit', _('Save Follow-up'), css_class='btn btn-primary') ) def clean(self): cleaned_data = super().clean() previous_consultation = cleaned_data.get('previous_consultation') patient = cleaned_data.get('patient') # Validate that previous consultation belongs to same patient if previous_consultation and patient: if previous_consultation.patient != patient: raise forms.ValidationError( _('Previous consultation must belong to the same patient.') ) return cleaned_data class ConsultationResponseForm(forms.ModelForm): """ Form for responding to medical consultation from other disciplines. """ class Meta: model = ConsultationResponse fields = [ 'consultation', 'response_type', 'responder', 'response_date', 'assessment', 'recommendations', 'follow_up_needed', 'notes', ] widgets = { 'consultation': forms.HiddenInput(), 'response_type': forms.Select(attrs={'class': 'form-control'}), 'responder': forms.HiddenInput(), 'response_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'assessment': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}), 'recommendations': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'follow_up_needed': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 'notes': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'consultation', 'responder', Fieldset( _('Response Information'), Row( Column('response_type', css_class='form-group col-md-6 mb-0'), Column('response_date', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), ), Fieldset( _('Assessment & Recommendations'), 'assessment', 'recommendations', ), Fieldset( _('Follow-up'), Row( Column('follow_up_needed', css_class='form-group col-md-12 mb-0'), css_class='form-row' ), 'notes', ), Submit('submit', _('Submit Response'), css_class='btn btn-primary') ) class ConsultationFeedbackForm(forms.ModelForm): """ Form for providing feedback on medical consultation. """ class Meta: model = ConsultationFeedback fields = [ 'consultation', 'feedback_type', 'submitted_by', 'submitted_by_name', 'feedback_date', 'satisfaction_rating', 'communication_rating', 'care_quality_rating', 'comments', 'concerns', 'suggestions', ] widgets = { 'consultation': forms.HiddenInput(), 'submitted_by': forms.HiddenInput(), 'feedback_type': forms.Select(attrs={'class': 'form-control'}), 'submitted_by_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Name (for family/caregiver)')}), 'feedback_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'satisfaction_rating': forms.RadioSelect(), 'communication_rating': forms.RadioSelect(), 'care_quality_rating': forms.RadioSelect(), 'comments': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}), 'concerns': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), 'suggestions': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( 'consultation', 'submitted_by', Fieldset( _('Feedback Information'), Row( Column('feedback_type', css_class='form-group col-md-6 mb-0'), Column('feedback_date', css_class='form-group col-md-6 mb-0'), css_class='form-row' ), 'submitted_by_name', ), Fieldset( _('Ratings'), HTML('

{}

'.format(_('Rate your experience (1=Very Dissatisfied, 5=Very Satisfied)'))), 'satisfaction_rating', 'communication_rating', 'care_quality_rating', ), Fieldset( _('Comments & Suggestions'), 'comments', 'concerns', 'suggestions', ), Submit('submit', _('Submit Feedback'), css_class='btn btn-primary') ) class MedicalConsultationSearchForm(forms.Form): """ Form for searching medical consultations. """ search_query = forms.CharField( required=False, label=_('Search'), widget=forms.TextInput(attrs={ 'placeholder': _('Patient name, MRN, Chief complaint...'), '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.DOCTOR ) self.helper = FormHelper() self.helper.form_method = 'get' self.helper.layout = Layout( Row( Column('search_query', css_class='form-group col-md-4 mb-0'), Column('provider', css_class='form-group col-md-3 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') )