""" 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 visibility based on user role. - PX Admins: See dropdown with all active hospitals - Others: Hidden field, auto-set to user's 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(user=request.user) """ def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', 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 based on user role.""" hospital_field = self.fields['hospital'] if self.user.is_px_admin(): # PX Admin: Show dropdown with all active hospitals hospital_field.queryset = Hospital.objects.filter(status='active').order_by('name') hospital_field.required = True # Update widget attrs instead of replacing widget to preserve choices hospital_field.widget.attrs.update({ 'class': 'w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:border-navy focus:ring-2 focus:ring-navy/20 transition text-sm bg-white' }) else: # Regular user: Hide field and set default hospital_field.widget = forms.HiddenInput() hospital_field.required = False # Set initial value to user's hospital if self.user.hospital: hospital_field.initial = self.user.hospital # Limit queryset to just user's hospital (for validation) hospital_field.queryset = Hospital.objects.filter(id=self.user.hospital.id) else: # User has no hospital - empty queryset hospital_field.queryset = Hospital.objects.none() def clean_hospital(self): """ Ensure non-PX admins can only use their own hospital. PX Admins can select any hospital. """ hospital = self.cleaned_data.get('hospital') if not self.user: return hospital if self.user.is_px_admin(): # PX Admin must select a hospital if not hospital: raise forms.ValidationError("Please select a hospital.") return hospital else: # Non-PX admins: Force user's hospital 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 and self.instance.hospital: hospital = self.instance.hospital 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()