""" 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()