Marwan Alwali a710d1c4d8 update
2025-09-11 19:01:55 +03:00

291 lines
13 KiB
Python

"""
Forms for Patients app CRUD operations.
"""
from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
from .models import (
PatientProfile, EmergencyContact, InsuranceInfo,
ConsentTemplate, ConsentForm, PatientNote
)
class PatientProfileForm(forms.ModelForm):
"""
Form for patient profile management.
"""
class Meta:
model = PatientProfile
fields = [
'first_name', 'last_name', 'middle_name', 'preferred_name', 'suffix',
'id_number', 'date_of_birth', 'gender', 'phone_number', 'mobile_number',
'email', 'address_line_1', 'address_line_2', 'city', 'state', 'zip_code',
'country', 'marital_status', 'occupation', 'is_active'
]
widgets = {
'first_name': forms.TextInput(attrs={'class': 'form-control'}),
'last_name': forms.TextInput(attrs={'class': 'form-control'}),
'middle_name': forms.TextInput(attrs={'class': 'form-control'}),
'preferred_name': forms.TextInput(attrs={'class': 'form-control'}),
'suffix': forms.TextInput(attrs={'class': 'form-control'}),
'id_number': forms.TextInput(attrs={'class': 'form-control'}),
'date_of_birth': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'gender': forms.Select(attrs={'class': 'form-select'}),
'phone_number': forms.TextInput(attrs={'class': 'form-control'}),
'mobile_number': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'address_line_1': forms.TextInput(attrs={'class': 'form-control'}),
'address_line_2': forms.TextInput(attrs={'class': 'form-control'}),
'city': forms.TextInput(attrs={'class': 'form-control'}),
'state': forms.TextInput(attrs={'class': 'form-control'}),
'zip_code': forms.TextInput(attrs={'class': 'form-control'}),
'country': forms.TextInput(attrs={'class': 'form-control'}),
'marital_status': forms.Select(attrs={'class': 'form-select'}),
'occupation': forms.TextInput(attrs={'class': 'form-control'}),
'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
}
def clean_date_of_birth(self):
date_of_birth = self.cleaned_data.get('date_of_birth')
if date_of_birth and date_of_birth > timezone.now().date():
raise ValidationError('Date of birth cannot be in the future.')
return date_of_birth
def clean_email(self):
email = self.cleaned_data.get('email')
if email:
# Check for duplicate email within tenant
tenant = getattr(self.instance, 'tenant', None)
if tenant:
existing = PatientProfile.objects.filter(
tenant=tenant,
email=email
).exclude(pk=self.instance.pk if self.instance.pk else None)
if existing.exists():
raise ValidationError('A patient with this email already exists.')
return email
class EmergencyContactForm(forms.ModelForm):
"""
Form for emergency contact management.
"""
class Meta:
model = EmergencyContact
exclude = ["patient"]
fields = [
'first_name', 'last_name', 'relationship', 'phone_number',
'mobile_number', 'email', 'address_line_1', 'address_line_2', 'city',
'state', 'zip_code', 'priority', 'is_authorized_for_medical_decisions'
]
widgets = {
# 'patient': forms.Select(attrs={'class': 'form-select'}),
'first_name': forms.TextInput(attrs={'class': 'form-control'}),
'last_name': forms.TextInput(attrs={'class': 'form-control'}),
'relationship': forms.Select(attrs={'class': 'form-select'}),
'phone_number': forms.TextInput(attrs={'class': 'form-control'}),
'mobile_number': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'address_line_1': forms.TextInput(attrs={'class': 'form-control'}),
'address_line_2': forms.TextInput(attrs={'class': 'form-control'}),
'city': forms.TextInput(attrs={'class': 'form-control'}),
'state': forms.TextInput(attrs={'class': 'form-control'}),
'zip_code': forms.TextInput(attrs={'class': 'form-control'}),
'priority': forms.NumberInput(attrs={'class': 'form-control'}),
'is_authorized_for_medical_decisions': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
# if user and hasattr(user, 'tenant'):
# self.fields['patient'].queryset = PatientProfile.objects.filter(
# tenant=user.tenant,
# is_active=True
# ).order_by('last_name', 'first_name')
class InsuranceInfoForm(forms.ModelForm):
"""
Form for insurance information management.
"""
class Meta:
model = InsuranceInfo
exclude = ["patient"]
fields = [
'insurance_type', 'insurance_company', 'plan_name', 'plan_type',
'policy_number', 'group_number', 'subscriber_name', 'subscriber_relationship',
'subscriber_dob', 'subscriber_id_number', 'effective_date', 'termination_date',
'copay_amount', 'deductible_amount', 'out_of_pocket_max', 'is_verified',
'requires_authorization'
]
widgets = {
'insurance_type': forms.Select(attrs={'class': 'form-select'}),
'insurance_company': forms.TextInput(attrs={'class': 'form-control'}),
'plan_name': forms.TextInput(attrs={'class': 'form-control'}),
'plan_type': forms.Select(attrs={'class': 'form-select'}),
'policy_number': forms.TextInput(attrs={'class': 'form-control'}),
'group_number': forms.TextInput(attrs={'class': 'form-control'}),
'subscriber_name': forms.TextInput(attrs={'class': 'form-control'}),
'subscriber_relationship': forms.Select(attrs={'class': 'form-select'}),
'subscriber_dob': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'subscriber_id_number': forms.TextInput(attrs={'class': 'form-control'}),
'effective_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'termination_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'copay_amount': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'deductible_amount': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'out_of_pocket_max': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'is_verified': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'requires_authorization': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
# if user and hasattr(user, 'tenant'):
# self.fields['patient'].queryset = PatientProfile.objects.filter(
# tenant=user.tenant,
# is_active=True
# ).order_by('last_name', 'first_name')
class ConsentTemplateForm(forms.ModelForm):
"""
Form for consent template management.
"""
class Meta:
model = ConsentTemplate
fields = [
'name', 'description', 'category', 'content', 'version',
'is_active', 'requires_signature', 'requires_witness', 'requires_guardian',
'effective_date', 'expiry_date',
]
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'category': forms.Select(attrs={'class': 'form-select'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 10}),
'version': forms.TextInput(attrs={'class': 'form-control'}),
'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'requires_signature': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'requires_witness': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'requires_guardian': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'effective_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'expiry_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
}
class ConsentFormForm(forms.ModelForm):
"""
Form for consent form management.
"""
class Meta:
model = ConsentForm
fields = [
'patient', 'template', 'status', 'patient_signature', 'patient_signed_at',
'guardian_signature', 'guardian_signed_at', 'guardian_name', 'guardian_relationship',
'witness_signature', 'witness_signed_at', 'witness_name', 'notes'
]
widgets = {
'patient': forms.Select(attrs={'class': 'form-select'}),
'template': forms.Select(attrs={'class': 'form-select'}),
'status': forms.Select(attrs={'class': 'form-select'}),
'patient_signature': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'patient_signed_at': forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}),
'guardian_signature': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'guardian_signed_at': forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}),
'guardian_name': forms.TextInput(attrs={'class': 'form-control'}),
'guardian_relationship': forms.TextInput(attrs={'class': 'form-control'}),
'witness_signature': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'witness_signed_at': forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}),
'witness_name': forms.TextInput(attrs={'class': 'form-control'}),
'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
if user and hasattr(user, 'tenant'):
self.fields['patient'].queryset = PatientProfile.objects.filter(
tenant=user.tenant,
is_active=True
).order_by('last_name', 'first_name')
self.fields['template'].queryset = ConsentTemplate.objects.filter(
tenant=user.tenant,
is_active=True
).order_by('name')
class PatientNoteForm(forms.ModelForm):
"""
Form for patient note management.
"""
class Meta:
model = PatientNote
exclude = ["patient"]
fields = [
'title', 'content', 'category', 'priority',
'is_confidential', 'is_alert', 'is_active'
]
widgets = {
# 'patient': forms.Select(attrs={'class': 'form-select'}),
'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 6}),
'category': forms.Select(attrs={'class': 'form-select'}),
'priority': forms.Select(attrs={'class': 'form-select'}),
'is_confidential': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'is_alert': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
# if user and hasattr(user, 'tenant'):
# self.fields['patient'].queryset = PatientProfile.objects.filter(
# tenant=user.tenant,
# is_active=True
# ).order_by('last_name', 'first_name')
class PatientsSearchForm(forms.Form):
"""
Form for searching patient data.
"""
search = forms.CharField(
max_length=255,
required=False,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Search patients, contacts, insurance...'
})
)
gender = forms.ChoiceField(
choices=[('', 'All Genders')] + list(PatientProfile._meta.get_field('gender').choices),
required=False,
widget=forms.Select(attrs={'class': 'form-select'})
)
status = forms.ChoiceField(
choices=[
('', 'All Statuses'),
('active', 'Active'),
('inactive', 'Inactive'),
],
required=False,
widget=forms.Select(attrs={'class': 'form-select'})
)
date_from = forms.DateField(
required=False,
widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'})
)
date_to = forms.DateField(
required=False,
widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'})
)