agdar/referrals/forms.py
Marwan Alwali 2f1681b18c update
2025-11-11 13:44:48 +03:00

419 lines
15 KiB
Python

"""
Referrals forms for the Tenhal Multidisciplinary Healthcare Platform.
This module contains forms for inter-discipline and external referrals.
"""
from django import forms
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 Referral
class ReferralForm(forms.ModelForm):
"""
Form for creating referrals (internal and external).
"""
class Meta:
model = Referral
fields = [
'patient', 'from_clinic', 'to_clinic', 'referred_to',
'referral_type', 'priority', 'reason', 'clinical_notes'
]
widgets = {
'patient': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select patient'}),
'from_clinic': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'}),
'from_provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}),
'to_clinic': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'}),
'to_provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}),
'external_provider_name': forms.TextInput(attrs={'class': 'form-control'}),
'external_provider_contact': forms.TextInput(attrs={'class': 'form-control'}),
'urgency': forms.Select(attrs={'class': 'form-select'}),
'reason': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}),
'clinical_summary': forms.Textarea(attrs={'rows': 4, 'class': 'form-control'}),
'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(
'patient',
Fieldset(
_('From (Source)'),
Row(
Column('from_clinic', css_class='form-group col-md-6 mb-0'),
Column('from_provider', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
),
Fieldset(
_('To (Destination) - Internal'),
HTML('<p class="text-muted">{}</p>'.format(_('For internal referrals within the facility'))),
Row(
Column('to_clinic', css_class='form-group col-md-6 mb-0'),
Column('to_provider', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
),
Fieldset(
_('To (Destination) - External'),
HTML('<p class="text-muted">{}</p>'.format(_('For external referrals to outside providers (leave internal fields empty)'))),
Row(
Column('external_provider_name', css_class='form-group col-md-6 mb-0'),
Column('external_provider_contact', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
),
Fieldset(
_('Referral Details'),
'reason',
'urgency',
'clinical_summary',
'notes',
),
Submit('submit', _('Create Referral'), css_class='btn btn-primary')
)
def clean(self):
cleaned_data = super().clean()
to_clinic = cleaned_data.get('to_clinic')
external_provider_name = cleaned_data.get('external_provider_name')
# Validate that either internal or external destination is provided
if not to_clinic and not external_provider_name:
raise forms.ValidationError(
_('Please specify either an internal clinic or an external provider.')
)
# Validate that both are not provided
if to_clinic and external_provider_name:
raise forms.ValidationError(
_('Please specify either internal OR external destination, not both.')
)
# Validate external provider contact if external provider is specified
if external_provider_name and not cleaned_data.get('external_provider_contact'):
raise forms.ValidationError(
_('External provider contact information is required for external referrals.')
)
return cleaned_data
class ExternalReferralForm(forms.Form):
"""
Form for external centers to refer patients to our center.
Does not require authentication.
"""
# Referring Center Information
referring_center_name = forms.CharField(
label=_('Referring Center/Hospital Name'),
max_length=200,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter your center name')
})
)
referring_doctor_name = forms.CharField(
label=_('Referring Doctor Name'),
max_length=200,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter doctor name')
})
)
referring_contact_phone = forms.CharField(
label=_('Contact Phone'),
max_length=20,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter phone number')
})
)
referring_contact_email = forms.EmailField(
label=_('Contact Email'),
widget=forms.EmailInput(attrs={
'class': 'form-control',
'placeholder': _('Enter email address')
})
)
# Patient Information
patient_first_name = forms.CharField(
label=_('Patient First Name'),
max_length=100,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter first name')
})
)
patient_last_name = forms.CharField(
label=_('Patient Last Name'),
max_length=100,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter last name')
})
)
patient_date_of_birth = forms.DateField(
label=_('Date of Birth'),
widget=forms.DateInput(attrs={
'type': 'date',
'class': 'form-control'
})
)
patient_sex = forms.ChoiceField(
label=_('Sex'),
choices=[
('', _('Select...')),
('M', _('Male')),
('F', _('Female'))
],
widget=forms.Select(attrs={'class': 'form-select'})
)
patient_national_id = forms.CharField(
label=_('National ID (Optional)'),
max_length=20,
required=False,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter national ID if available')
})
)
# Guardian/Caregiver Information
caregiver_name = forms.CharField(
label=_('Parent/Guardian Name'),
max_length=200,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter parent/guardian name')
})
)
caregiver_phone = forms.CharField(
label=_('Parent/Guardian Phone'),
max_length=20,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter phone number')
})
)
caregiver_relationship = forms.CharField(
label=_('Relationship to Patient'),
max_length=100,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('e.g., Mother, Father, Guardian')
})
)
# Referral Details
urgency = forms.ChoiceField(
label=_('Urgency Level'),
choices=Referral.Priority.choices,
widget=forms.Select(attrs={'class': 'form-select'})
)
reason = forms.CharField(
label=_('Reason for Referral'),
widget=forms.Textarea(attrs={
'rows': 4,
'class': 'form-control',
'placeholder': _('Please describe the reason for referral')
})
)
clinical_summary = forms.CharField(
label=_('Clinical Summary'),
required=False,
widget=forms.Textarea(attrs={
'rows': 5,
'class': 'form-control',
'placeholder': _('Provide relevant clinical information, diagnosis, current treatment, etc.')
})
)
requested_specialty = forms.ChoiceField(
label=_('Requested Specialty'),
choices=[
('', _('Select specialty...')),
('MEDICAL', _('Medical')),
('OT', _('Occupational Therapy')),
('SLP', _('Speech-Language Pathology')),
('ABA', _('ABA Therapy')),
],
widget=forms.Select(attrs={'class': 'form-select'})
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.layout = Layout(
Fieldset(
_('Referring Center Information'),
'referring_center_name',
Row(
Column('referring_doctor_name', css_class='form-group col-md-6 mb-0'),
Column('referring_contact_phone', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'referring_contact_email',
),
Fieldset(
_('Patient Information'),
Row(
Column('patient_first_name', css_class='form-group col-md-6 mb-0'),
Column('patient_last_name', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
Row(
Column('patient_date_of_birth', css_class='form-group col-md-4 mb-0'),
Column('patient_sex', css_class='form-group col-md-4 mb-0'),
Column('patient_national_id', css_class='form-group col-md-4 mb-0'),
css_class='form-row'
),
),
Fieldset(
_('Parent/Guardian Information'),
'caregiver_name',
Row(
Column('caregiver_phone', css_class='form-group col-md-6 mb-0'),
Column('caregiver_relationship', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
),
Fieldset(
_('Referral Details'),
Row(
Column('urgency', css_class='form-group col-md-6 mb-0'),
Column('requested_specialty', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'reason',
'clinical_summary',
),
Submit('submit', _('Submit Referral'), css_class='btn btn-primary btn-lg')
)
class ReferralResponseForm(forms.Form):
"""
Form for responding to referrals.
"""
status = forms.ChoiceField(
label=_('Status'),
choices=Referral.Status.choices,
widget=forms.RadioSelect
)
response_notes = forms.CharField(
label=_('Response Notes'),
widget=forms.Textarea(attrs={'rows': 3}),
required=False
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.layout = Layout(
'status',
'response_notes',
Submit('submit', _('Submit Response'), css_class='btn btn-primary')
)
class ReferralSearchForm(forms.Form):
"""
Form for searching referrals.
"""
search_query = forms.CharField(
required=False,
label=_('Search'),
widget=forms.TextInput(attrs={
'placeholder': _('Patient name, MRN, Reason...'),
'class': 'form-control'
})
)
status = forms.ChoiceField(
required=False,
label=_('Status'),
choices=[('', _('All'))] + list(Referral.Status.choices),
widget=forms.Select(attrs={'class': 'form-control'})
)
urgency = forms.ChoiceField(
required=False,
label=_('Urgency'),
choices=[('', _('All'))] + list(Referral.Priority.choices),
widget=forms.Select(attrs={'class': 'form-control'})
)
from_clinic = forms.ModelChoiceField(
required=False,
label=_('From Clinic'),
queryset=None, # Will be set in __init__
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'})
)
to_clinic = forms.ModelChoiceField(
required=False,
label=_('To Clinic'),
queryset=None, # Will be set in __init__
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'})
)
referral_type = forms.ChoiceField(
required=False,
label=_('Type'),
choices=[
('', _('All')),
('internal', _('Internal')),
('external', _('External')),
],
widget=forms.Select(attrs={'class': 'form-control'})
)
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 Clinic
self.fields['from_clinic'].queryset = Clinic.objects.filter(
tenant=tenant,
is_active=True
)
self.fields['to_clinic'].queryset = Clinic.objects.filter(
tenant=tenant,
is_active=True
)
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('status', css_class='form-group col-md-2 mb-0'),
Column('urgency', css_class='form-group col-md-1 mb-0'),
Column('referral_type', css_class='form-group col-md-1 mb-0'),
Column('from_clinic', css_class='form-group col-md-1.5 mb-0'),
Column('to_clinic', css_class='form-group col-md-1.5 mb-0'),
Column('date_from', css_class='form-group col-md-1 mb-0'),
Column('date_to', css_class='form-group col-md-1 mb-0'),
css_class='form-row'
),
Submit('search', _('Search'), css_class='btn btn-primary')
)