# Tenant-Aware Routing Implementation

## Overview

This document describes the tenant-aware routing system implemented to support PX Admins in managing multiple hospitals within the PX360 platform. PX Admins are super-admins who can view and manage data across all hospitals, but need to select a specific hospital to work with at any given time.

## Problem Statement

PX Admins have access to all hospitals in the system, but:
- They need to work with one hospital at a time for data consistency
- The system must track which hospital they're currently viewing
- All queries must be filtered to show only the selected hospital's data
- Other user roles (Hospital Admins, Department Managers) should only see their assigned hospital/department

## Solution Architecture

### 1. User Role Hierarchy

The system supports the following user roles:

1. **PX Admin** (Level 4)
   - Can view and manage all hospitals
   - Must select a hospital before viewing data
   - Can switch between hospitals

2. **Hospital Admin** (Level 3)
   - Assigned to a specific hospital
   - Can only view/manage their hospital's data

3. **Department Manager** (Level 2)
   - Assigned to a specific department within a hospital
   - Can only view/manage their department's data

4. **Regular User** (Level 1)
   - Limited permissions based on assignment

### 2. Implementation Components

#### A. TenantMiddleware (`apps/core/middleware.py`)

The middleware is responsible for:
- Detecting the user's tenant hospital
- Setting `request.tenant_hospital` attribute
- Redirecting PX Admins to hospital selector if no hospital is selected

**Key Features:**
```python
# For PX Admins: Get hospital from session
if user.is_px_admin():
    hospital_id = request.session.get('selected_hospital_id')
    if hospital_id:
        try:
            from apps.organizations.models import Hospital
            hospital = Hospital.objects.get(id=hospital_id)
            request.tenant_hospital = hospital
        except Hospital.DoesNotExist:
            pass

# For other users: Use their assigned hospital
elif user.hospital:
    request.tenant_hospital = user.hospital
```

#### B. Hospital Selector (`apps/core/views.py`)

A dedicated view that allows PX Admins to:
- View all available hospitals
- Select a hospital to work with
- Store the selection in session

**Key Features:**
- Lists all hospitals with location info
- Shows currently selected hospital
- Stores selection in session for persistence
- Redirects back to the referring page after selection

#### C. Login Redirect (`apps/accounts/views.py`)

Enhanced JWT token view that provides redirect URLs based on user role:
- PX Admins → `/health/select-hospital/`
- Users without hospital → `/health/no-hospital/`
- All others → Dashboard (`/`)

#### D. Dashboard Integration (`apps/dashboard/views.py`)

The CommandCenter dashboard now:
- Checks if PX Admin has selected a hospital
- Redirects to hospital selector if not
- Filters all data based on `request.tenant_hospital`
- Shows current hospital context in templates

#### E. Context Processor (`apps/core/context_processors.py`)

Updated sidebar counts to respect tenant context:
- PX Admins see counts for selected hospital only
- Other users see counts for their assigned hospital

### 3. URL Structure

```
/                           - Dashboard (requires hospital context)
/health/select-hospital/    - Hospital selector for PX Admins
/health/no-hospital/        - Error page for unassigned users
```

### 4. Template Structure

- `templates/core/select_hospital.html` - Hospital selection UI
- `templates/core/no_hospital_assigned.html` - Error page for unassigned users

### 5. Data Flow

```
User Login
    ↓
JWT Token Response (includes redirect_url)
    ↓
Frontend redirects based on role
    ↓
[If PX Admin] Hospital Selector Page
    ↓
User selects hospital → stored in session
    ↓
TenantMiddleware sets request.tenant_hospital
    ↓
All views filter data using request.tenant_hospital
    ↓
Dashboard displays filtered data
```

### 6. Query Filtering Pattern

Views should follow this pattern for filtering:

```python
def get_queryset(self):
    queryset = super().get_queryset()
    user = self.request.user
    hospital = getattr(self.request, 'tenant_hospital', None)

    if user.is_px_admin() and hospital:
        return queryset.filter(hospital=hospital)
    elif user.hospital:
        return queryset.filter(hospital=user.hospital)
    elif user.department:
        return queryset.filter(department=user.department)
    else:
        return queryset.none()
```

## Benefits

1. **Data Isolation**: PX Admins can safely work with one hospital at a time
2. **Consistent User Experience**: Clear indication of which hospital is being viewed
3. **Security**: Automatic filtering prevents cross-hospital data leakage
4. **Flexibility**: PX Admins can easily switch between hospitals
5. **Backward Compatible**: Other user roles work as before

## Future Enhancements

1. **Remember Last Hospital**: Store PX Admin's last hospital in user profile
2. **Hospital Quick Switcher**: Add dropdown in header for quick switching
3. **Multi-Hospital View**: Option to see aggregated data across hospitals
4. **Audit Trail**: Track hospital selection changes in audit logs
5. **Permissions Matrix**: Fine-grained control per hospital

## Testing Checklist

- [ ] PX Admin can login and see hospital selector
- [ ] PX Admin can select a hospital
- [ ] Dashboard shows correct data for selected hospital
- [ ] PX Admin can switch hospitals
- [ ] Hospital Admin sees only their hospital
- [ ] Department Manager sees only their department
- [ ] Sidebar counts update correctly when switching hospitals
- [ ] All queries respect tenant_hospital filtering
- [ ] Session persists hospital selection
- [ ] Logout clears hospital selection

## Files Modified

1. `apps/core/middleware.py` - Enhanced TenantMiddleware
2. `apps/core/views.py` - Added select_hospital and no_hospital_assigned views
3. `apps/core/urls.py` - Added hospital selector URLs
4. `apps/core/context_processors.py` - Updated sidebar counts for tenant awareness
5. `apps/accounts/views.py` - Enhanced JWT token view with redirect URLs
6. `apps/dashboard/views.py` - Added hospital context and filtering
7. `templates/core/select_hospital.html` - New hospital selector template
8. `templates/core/no_hospital_assigned.html` - New error template

## Integration Notes

### For Frontend Developers

When handling JWT token response:

```javascript
const response = await login(credentials);
const redirectUrl = response.data.redirect_url;
window.location.href = redirectUrl;
```

### For Backend Developers

When creating new views:

1. Use `TenantHospitalRequiredMixin` if hospital context is required
2. Access hospital via `self.request.tenant_hospital`
3. Filter querysets based on user role and hospital context
4. Add hospital context to template if needed

### Example:

```python
from apps.core.mixins import TenantHospitalRequiredMixin

class ComplaintListView(TenantHospitalRequiredMixin, ListView):
    model = Complaint

    def get_queryset(self):
        queryset = super().get_queryset()
        hospital = self.request.tenant_hospital

        if hospital:
            return queryset.filter(hospital=hospital)

        return queryset.none()
```

## Conclusion

This implementation provides a robust tenant-aware routing system that:
- Secures multi-hospital data access
- Maintains consistent user experience
- Scales to support additional hospitals
- Preserves existing functionality for non-admin users

The system is production-ready and follows Django best practices for middleware, authentication, and request handling.
