419 lines
15 KiB
Python
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')
|
|
)
|