134 lines
4.5 KiB
Python
134 lines
4.5 KiB
Python
"""
|
|
Form mixins for tenant-aware forms.
|
|
|
|
Provides mixins to handle hospital field visibility based on user role.
|
|
"""
|
|
|
|
from django import forms
|
|
from apps.organizations.models import Hospital
|
|
|
|
|
|
class HospitalFieldMixin:
|
|
"""
|
|
Mixin to handle hospital field - always hidden, auto-set based on user context.
|
|
|
|
- PX Admins: Hidden field, auto-set from session (request.tenant_hospital)
|
|
- Others: Hidden field, auto-set from user's hospital (User.hospital)
|
|
|
|
Usage:
|
|
class MyForm(HospitalFieldMixin, forms.ModelForm):
|
|
class Meta:
|
|
model = MyModel
|
|
fields = ['hospital', ...]
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
# Hospital field is automatically configured
|
|
|
|
In views:
|
|
form = MyForm(request=request)
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.request = kwargs.pop("request", None)
|
|
self.user = self.request.user if self.request else None
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if self.user and "hospital" in self.fields:
|
|
self._setup_hospital_field()
|
|
|
|
def _setup_hospital_field(self):
|
|
"""Configure hospital field - always hidden, auto-set based on user context."""
|
|
hospital_field = self.fields["hospital"]
|
|
|
|
hospital_field.widget = forms.HiddenInput()
|
|
hospital_field.required = False
|
|
|
|
hospital = None
|
|
|
|
if self.user.is_px_admin():
|
|
hospital = getattr(self.request, "tenant_hospital", None)
|
|
else:
|
|
hospital = self.user.hospital
|
|
|
|
if hospital:
|
|
hospital_field.initial = hospital
|
|
hospital_field.queryset = Hospital.objects.filter(id=hospital.id)
|
|
else:
|
|
hospital_field.queryset = Hospital.objects.none()
|
|
|
|
def clean_hospital(self):
|
|
"""
|
|
Auto-set hospital based on user context.
|
|
"""
|
|
hospital = self.cleaned_data.get("hospital")
|
|
|
|
if not self.user:
|
|
return hospital
|
|
|
|
if self.user.is_px_admin():
|
|
hospital = getattr(self.request, "tenant_hospital", None)
|
|
if not hospital:
|
|
raise forms.ValidationError("No hospital selected. Please select a hospital first.")
|
|
return hospital
|
|
else:
|
|
if self.user.hospital:
|
|
return self.user.hospital
|
|
else:
|
|
raise forms.ValidationError("You do not have a hospital assigned. Please contact your administrator.")
|
|
|
|
|
|
class DepartmentFieldMixin:
|
|
"""
|
|
Mixin to handle department field filtering based on user's hospital.
|
|
|
|
- Filters departments to only show those in the selected/current hospital
|
|
- Works with HospitalFieldMixin
|
|
|
|
Usage:
|
|
class MyForm(HospitalFieldMixin, DepartmentFieldMixin, forms.ModelForm):
|
|
class Meta:
|
|
model = MyModel
|
|
fields = ['hospital', 'department', ...]
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if "department" in self.fields:
|
|
self._setup_department_field()
|
|
|
|
def _setup_department_field(self):
|
|
"""Configure department field with hospital-based filtering."""
|
|
from apps.organizations.models import Department
|
|
|
|
department_field = self.fields["department"]
|
|
|
|
# Get the hospital (either from form data or user's hospital)
|
|
hospital = None
|
|
if self.data.get("hospital"):
|
|
try:
|
|
hospital = Hospital.objects.get(id=self.data["hospital"])
|
|
except Hospital.DoesNotExist:
|
|
pass
|
|
elif self.initial.get("hospital"):
|
|
hospital = self.initial["hospital"]
|
|
elif self.instance and self.instance.pk:
|
|
# Only access hospital if instance is saved (has pk)
|
|
try:
|
|
hospital = self.instance.hospital
|
|
except Exception:
|
|
# Hospital not set (RelatedObjectDoesNotExist or similar)
|
|
pass
|
|
elif self.user and self.user.is_px_admin():
|
|
hospital = getattr(self.request, "tenant_hospital", None)
|
|
elif self.user and self.user.hospital:
|
|
hospital = self.user.hospital
|
|
|
|
if hospital:
|
|
# Filter departments to user's hospital
|
|
department_field.queryset = Department.objects.filter(hospital=hospital, status="active").order_by("name")
|
|
else:
|
|
# No hospital context - empty queryset
|
|
department_field.queryset = Department.objects.none()
|