396 lines
14 KiB
Python
396 lines
14 KiB
Python
"""
|
|
Core app forms for hospital management system.
|
|
Provides forms for tenant management, system configuration,
|
|
notifications, departments, and search functionality.
|
|
"""
|
|
|
|
from django import forms
|
|
from django.contrib.auth import get_user_model
|
|
from .models import Tenant, SystemConfiguration, SystemNotification
|
|
from accounts.models import User
|
|
from hr.models import Department
|
|
|
|
|
|
class TenantForm(forms.ModelForm):
|
|
"""Form for creating and editing tenant organizations."""
|
|
|
|
class Meta:
|
|
model = Tenant
|
|
fields = [
|
|
'name', 'display_name', 'description', 'organization_type',
|
|
'address_line1', 'address_line2', 'city', 'state', 'postal_code', 'country',
|
|
'phone_number', 'email', 'website', 'license_number',
|
|
'accreditation_body', 'accreditation_number',
|
|
'is_active'
|
|
]
|
|
widgets = {
|
|
'name': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter organization name'
|
|
}),
|
|
'display_name': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter display name'
|
|
}),
|
|
'description': forms.Textarea(attrs={
|
|
'class': 'form-control',
|
|
'rows': 3,
|
|
'placeholder': 'Enter organization description'
|
|
}),
|
|
'organization_type': forms.Select(attrs={
|
|
'class': 'form-select'
|
|
}),
|
|
'address_line1': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter address line 1'
|
|
}),
|
|
'address_line2': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter address line 2'
|
|
}),
|
|
'city': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter city'
|
|
}),
|
|
'state': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter state/province'
|
|
}),
|
|
'postal_code': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter postal code'
|
|
}),
|
|
'country': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter country'
|
|
}),
|
|
'phone_number': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter phone number'
|
|
}),
|
|
'email': forms.EmailInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter email address'
|
|
}),
|
|
'website': forms.URLInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter website URL'
|
|
}),
|
|
'license_number': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter license number'
|
|
}),
|
|
'accreditation_body': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter accreditation body'
|
|
}),
|
|
'accreditation_number': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter accreditation number'
|
|
}),
|
|
'is_active': forms.CheckboxInput(attrs={
|
|
'class': 'form-check-input'
|
|
})
|
|
}
|
|
|
|
def clean_email(self):
|
|
"""Validate email uniqueness."""
|
|
email = self.cleaned_data.get('email')
|
|
if email:
|
|
queryset = Tenant.objects.filter(email=email)
|
|
if self.instance.pk:
|
|
queryset = queryset.exclude(pk=self.instance.pk)
|
|
if queryset.exists():
|
|
raise forms.ValidationError('A tenant with this email already exists.')
|
|
return email
|
|
|
|
|
|
class SystemConfigurationForm(forms.ModelForm):
|
|
"""Form for managing system configuration settings."""
|
|
|
|
class Meta:
|
|
model = SystemConfiguration
|
|
fields = ['key', 'value', 'description', 'is_active']
|
|
widgets = {
|
|
'key': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter configuration key'
|
|
}),
|
|
'value': forms.Textarea(attrs={
|
|
'class': 'form-control',
|
|
'rows': 3,
|
|
'placeholder': 'Enter configuration value'
|
|
}),
|
|
'description': forms.Textarea(attrs={
|
|
'class': 'form-control',
|
|
'rows': 2,
|
|
'placeholder': 'Enter description'
|
|
}),
|
|
'is_active': forms.CheckboxInput(attrs={
|
|
'class': 'form-check-input'
|
|
})
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.tenant = kwargs.pop('tenant', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def clean_key(self):
|
|
"""Validate key uniqueness within tenant."""
|
|
key = self.cleaned_data.get('key')
|
|
if key and self.tenant:
|
|
queryset = SystemConfiguration.objects.filter(
|
|
tenant=self.tenant,
|
|
key=key
|
|
)
|
|
if self.instance.pk:
|
|
queryset = queryset.exclude(pk=self.instance.pk)
|
|
if queryset.exists():
|
|
raise forms.ValidationError('A configuration with this key already exists.')
|
|
return key
|
|
|
|
|
|
class SystemNotificationForm(forms.ModelForm):
|
|
"""Form for creating and managing system notifications."""
|
|
|
|
class Meta:
|
|
model = SystemNotification
|
|
fields = [
|
|
'title', 'message', 'notification_type', 'priority',
|
|
'target_audience', 'target_roles', 'target_users', 'is_active',
|
|
'start_date', 'end_date', 'is_dismissible', 'auto_dismiss_after',
|
|
'show_on_login', 'action_url', 'action_text'
|
|
]
|
|
widgets = {
|
|
'title': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter notification title'
|
|
}),
|
|
'message': forms.Textarea(attrs={
|
|
'class': 'form-control',
|
|
'rows': 4,
|
|
'placeholder': 'Enter notification message'
|
|
}),
|
|
'notification_type': forms.Select(attrs={
|
|
'class': 'form-select'
|
|
}),
|
|
'priority': forms.Select(attrs={
|
|
'class': 'form-select'
|
|
}),
|
|
'target_audience': forms.Select(attrs={
|
|
'class': 'form-select'
|
|
}),
|
|
'target_users': forms.SelectMultiple(attrs={
|
|
'class': 'form-select',
|
|
'size': '5'
|
|
}),
|
|
'is_active': forms.CheckboxInput(attrs={
|
|
'class': 'form-check-input'
|
|
}),
|
|
'start_date': forms.DateTimeInput(attrs={
|
|
'class': 'form-control',
|
|
'type': 'datetime-local'
|
|
}),
|
|
'end_date': forms.DateTimeInput(attrs={
|
|
'class': 'form-control',
|
|
'type': 'datetime-local'
|
|
}),
|
|
'is_dismissible': forms.CheckboxInput(attrs={
|
|
'class': 'form-check-input'
|
|
}),
|
|
'auto_dismiss_after': forms.NumberInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Seconds'
|
|
}),
|
|
'show_on_login': forms.CheckboxInput(attrs={
|
|
'class': 'form-check-input'
|
|
}),
|
|
'action_url': forms.URLInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter action URL'
|
|
}),
|
|
'action_text': forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Enter action button text'
|
|
})
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.tenant = kwargs.pop('tenant', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if self.tenant:
|
|
# Filter users by tenant
|
|
self.fields['target_users'].queryset = User.objects.filter(
|
|
tenant=self.tenant,
|
|
is_active=True
|
|
)
|
|
|
|
|
|
# class DepartmentForm(forms.ModelForm):
|
|
# """Form for creating and managing hospital departments."""
|
|
#
|
|
# class Meta:
|
|
# model = Department
|
|
# fields = [
|
|
# 'name', 'code', 'description', 'department_type',
|
|
# 'department_head', 'parent_department', 'building', 'floor',
|
|
# 'wing', 'room_numbers', 'phone', 'extension',
|
|
# 'email', 'is_active', 'is_24_hour'
|
|
# ]
|
|
# widgets = {
|
|
# 'name': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter department name'
|
|
# }),
|
|
# 'code': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter department code'
|
|
# }),
|
|
# 'description': forms.Textarea(attrs={
|
|
# 'class': 'form-control',
|
|
# 'rows': 3,
|
|
# 'placeholder': 'Enter department description'
|
|
# }),
|
|
# 'department_type': forms.Select(attrs={
|
|
# 'class': 'form-select'
|
|
# }),
|
|
# 'department_head': forms.Select(attrs={
|
|
# 'class': 'form-select'
|
|
# }),
|
|
# 'parent_department': forms.Select(attrs={
|
|
# 'class': 'form-select'
|
|
# }),
|
|
# 'building': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter building name/number'
|
|
# }),
|
|
# 'floor': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter floor'
|
|
# }),
|
|
# 'wing': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter wing/section'
|
|
# }),
|
|
# 'room_numbers': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter room numbers'
|
|
# }),
|
|
# 'phone': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter phone number'
|
|
# }),
|
|
# 'extension': forms.TextInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter extension'
|
|
# }),
|
|
# 'email': forms.EmailInput(attrs={
|
|
# 'class': 'form-control',
|
|
# 'placeholder': 'Enter email address'
|
|
# }),
|
|
# 'is_active': forms.CheckboxInput(attrs={
|
|
# 'class': 'form-check-input'
|
|
# }),
|
|
# 'is_24_hour': forms.CheckboxInput(attrs={
|
|
# 'class': 'form-check-input'
|
|
# })
|
|
# }
|
|
#
|
|
# def __init__(self, *args, **kwargs):
|
|
# self.tenant = kwargs.pop('tenant', None)
|
|
# super().__init__(*args, **kwargs)
|
|
#
|
|
# if self.tenant:
|
|
# # Filter department head by tenant and medical staff
|
|
# self.fields['department_head'].queryset = User.objects.filter(
|
|
# tenant=self.tenant,
|
|
# is_active=True,
|
|
# role__in=['DOCTOR', 'NURSE_MANAGER', 'ADMINISTRATOR']
|
|
# )
|
|
# # Filter parent department by tenant
|
|
# self.fields['parent_department'].queryset = Department.objects.filter(
|
|
# tenant=self.tenant,
|
|
# is_active=True
|
|
# )
|
|
#
|
|
# def clean_code(self):
|
|
# """Validate department code uniqueness within tenant."""
|
|
# code = self.cleaned_data.get('code')
|
|
# if code and self.tenant:
|
|
# queryset = Department.objects.filter(
|
|
# tenant=self.tenant,
|
|
# code=code
|
|
# )
|
|
# if self.instance.pk:
|
|
# queryset = queryset.exclude(pk=self.instance.pk)
|
|
# if queryset.exists():
|
|
# raise forms.ValidationError('A department with this code already exists.')
|
|
# return code
|
|
|
|
|
|
class CoreSearchForm(forms.Form):
|
|
"""Advanced search form for core entities."""
|
|
|
|
# General search
|
|
search = forms.CharField(
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Search...'
|
|
})
|
|
)
|
|
|
|
# Tenant filters
|
|
organization_type = forms.ChoiceField(
|
|
required=False,
|
|
choices=[('', 'All Types')] + Tenant._meta.get_field('organization_type').choices,
|
|
widget=forms.Select(attrs={'class': 'form-select'})
|
|
)
|
|
|
|
# Status filters
|
|
is_active = forms.ChoiceField(
|
|
required=False,
|
|
choices=[
|
|
('', 'All Status'),
|
|
('true', 'Active'),
|
|
('false', 'Inactive')
|
|
],
|
|
widget=forms.Select(attrs={'class': 'form-select'})
|
|
)
|
|
|
|
# Date filters
|
|
created_from = forms.DateField(
|
|
required=False,
|
|
widget=forms.DateInput(attrs={
|
|
'class': 'form-control',
|
|
'type': 'date'
|
|
})
|
|
)
|
|
created_to = forms.DateField(
|
|
required=False,
|
|
widget=forms.DateInput(attrs={
|
|
'class': 'form-control',
|
|
'type': 'date'
|
|
})
|
|
)
|
|
|
|
# Department filters
|
|
department_type = forms.ChoiceField(
|
|
required=False,
|
|
choices=[('', 'All Types')] + Department._meta.get_field('department_type').choices,
|
|
widget=forms.Select(attrs={'class': 'form-select'})
|
|
)
|
|
|
|
def clean(self):
|
|
"""Validate date ranges."""
|
|
cleaned_data = super().clean()
|
|
created_from = cleaned_data.get('created_from')
|
|
created_to = cleaned_data.get('created_to')
|
|
|
|
if created_from and created_to and created_from > created_to:
|
|
raise forms.ValidationError('Start date must be before end date.')
|
|
|
|
return cleaned_data
|
|
|