# Staff User Account Feature - Implementation Summary

## Overview

This document provides a comprehensive summary of the Staff User Account feature implementation, including the optional one-to-one relation with the User model, CRUD operations, and login functionality for staff members.

## Feature Components

### 1. Staff-User One-to-One Relation

**File:** `apps/organizations/models.py`

The Staff model has an optional one-to-one relation with the User model:

```python
class Staff(UUIDModel, TimeStampedModel):
    # Link to User (Keep it optional for external/temp staff)
    user = models.OneToOneField(
        'accounts.User',
        on_delete=models.SET_NULL,
        null=True, blank=True,
        related_name='staff_profile'
    )
```

**Key Features:**
- Optional relation (allows external/temp staff without user accounts)
- Uses `SET_NULL` on delete (staff profile remains if user is deleted)
- Provides reverse relation via `user.staff_profile`

### 2. Custom UserManager

**File:** `apps/accounts/models.py`

Implemented a custom `UserManager` to support email-based authentication:

```python
class UserManager(BaseUserManager):
    """Custom user manager for email-based authentication."""
    
    def create_user(self, email, password=None, **extra_fields):
        """Create and save a regular user with the given email and password."""
        if not email:
            raise ValueError('The Email field must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        """Create and save a superuser with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self.create_user(email, password, **extra_fields)
```

### 3. StaffService

**File:** `apps/organizations/services.py`

Provides comprehensive staff user account management:

#### Key Methods:

1. **create_user_for_staff()**
   - Creates a user account for a staff member
   - Generates username and password
   - Assigns appropriate role
   - Links user to staff profile
   - Logs the action for audit trail

2. **link_user_to_staff()**
   - Links an existing user account to a staff member
   - Updates user's organization data

3. **unlink_user_from_staff()**
   - Removes user account association from staff member

4. **send_credentials_email()**
   - Sends login credentials email to staff member
   - Includes generated password and login URL

5. **generate_username()**
   - Generates unique username from staff name
   - Format: `first.last` (lowercase)
   - Appends number if duplicate exists

6. **generate_password()**
   - Generates secure random password (12 characters)
   - Includes letters, numbers, and special characters

7. **get_staff_type_role()**
   - Maps staff type to role name
   - Currently all staff get 'staff' role

### 4. API Endpoints

**File:** `apps/organizations/views.py`

#### StaffViewSet - CRUD Operations

**Base CRUD:**
- `GET /api/staff/` - List all staff (filtered by user role)
- `POST /api/staff/` - Create new staff member
- `GET /api/staff/{id}/` - Retrieve staff details
- `PUT /api/staff/{id}/` - Update staff member
- `PATCH /api/staff/{id}/` - Partially update staff member
- `DELETE /api/staff/{id}/` - Delete staff member

**User Account Actions:**

1. **Create User Account**
   - `POST /api/staff/{id}/create_user_account/`
   - Creates a user account for staff member
   - Auto-generates username and password
   - Sends credentials email
   - Body: `{ "role": "staff" }` (optional)

2. **Link Existing User**
   - `POST /api/staff/{id}/link_user/`
   - Links an existing user account to staff
   - Body: `{ "user_id": "uuid" }`

3. **Unlink User**
   - `POST /api/staff/{id}/unlink_user/`
   - Removes user account association

4. **Send Invitation**
   - `POST /api/staff/{id}/send_invitation/`
   - Generates new password
   - Sends credentials email

**Filtering & Search:**
- Filter by: `status`, `hospital`, `department`, `staff_type`, `specialization`, `job_title`, `hospital__organization`
- Search by: `first_name`, `last_name`, `first_name_ar`, `last_name_ar`, `employee_id`, `license_number`, `job_title`
- Order by: `last_name`, `created_at`

**Permissions:**
- PX Admins: Full access to all staff
- Hospital Admins: Full access to staff in their hospital
- Department Managers: Read-only access to staff in their department
- Others: Read-only access to staff in their hospital

### 5. Management Commands

**File:** `apps/organizations/management/commands/seed_staff.py`

#### Command Options:

```bash
python manage.py seed_staff [options]
```

**Options:**
- `--hospital-code`: Target hospital code (default: all hospitals)
- `--count`: Number of staff to create per type (default: 10)
- `--physicians`: Number of physicians to create (default: 10)
- `--nurses`: Number of nurses to create (default: 15)
- `--admin-staff`: Number of admin staff to create (default: 5)
- `--create-users`: Create user accounts for staff
- `--send-emails`: Send credential emails to newly created users
- `--clear`: Clear existing staff first
- `--dry-run`: Preview without making changes

**Examples:**

```bash
# Create staff without users
python manage.py seed_staff --physicians 5 --nurses 10

# Create staff with user accounts
python manage.py seed_staff --physicians 5 --nurses 10 --create-users

# Create staff with user accounts and send emails
python manage.py seed_staff --physicians 5 --nurses 10 --create-users --send-emails

# Dry run to preview
python manage.py seed_staff --physicians 5 --dry-run

# Clear and recreate staff
python manage.py seed_staff --clear --physicians 5
```

### 6. Email Templates

**File:** `templates/organizations/emails/staff_credentials.html`

Professional HTML email template for sending staff credentials.

**Template Variables:**
- `staff`: Staff instance
- `user`: User instance
- `password`: Generated password
- `login_url`: Absolute login URL

### 7. Database Migrations

**Migration:** `apps/accounts/migrations/0004_alter_user_managers_and_more.py`

Changes applied:
1. Changed manager on User model to custom UserManager
2. Made `username` field optional and non-unique
3. Updated `acknowledgement_completed_at` field

## User Authentication Flow

### Staff Login Process

1. **Account Creation:**
   - Staff member is created in the system
   - Admin creates user account via API or management command
   - Password is generated and sent via email

2. **Login:**
   - Staff member logs in using their email address
   - Password is verified against hashed password in database
   - Session is established

3. **Access:**
   - User's role determines permissions
   - Staff profile is accessible via `request.user.staff_profile`
   - Organization context is available via `request.user.hospital`

## Permission Model

### Staff User Roles

All staff members are assigned to the 'staff' role by default. The role system is flexible and can be extended to support:

- Physicians
- Nurses
- Administrative staff
- Department managers
- Hospital administrators

### Role-Based Access Control

**PX Admin:**
- Can manage all organizations, hospitals, departments, and staff
- Can create user accounts for any staff member

**Hospital Admin:**
- Can manage their hospital, departments, and staff
- Can create user accounts for staff in their hospital

**Department Manager:**
- Can view staff in their department
- Cannot create user accounts

**Staff:**
- Can view other staff in their hospital
- Cannot create user accounts

## Usage Examples

### Creating Staff and User Account

**Via API:**

```bash
# 1. Create staff member
curl -X POST http://localhost:8000/api/staff/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "first_name_ar": "جون",
    "last_name_ar": "دو",
    "staff_type": "physician",
    "job_title": "Cardiologist",
    "specialization": "Cardiology",
    "license_number": "MOH-LIC-1234567",
    "employee_id": "DR-HOSP-12345",
    "email": "john.doe@hospital.sa",
    "hospital": "<hospital_id>",
    "department": "<department_id>",
    "status": "active"
  }'

# 2. Create user account for staff
curl -X POST http://localhost:8000/api/staff/<staff_id>/create_user_account/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "staff"
  }'
```

**Via Management Command:**

```bash
python manage.py seed_staff --physicians 1 --create-users --send-emails
```

**Via Python Code:**

```python
from apps.organizations.models import Staff, Hospital
from apps.organizations.services import StaffService

# Create staff
hospital = Hospital.objects.get(code="HOSPITAL001")
staff = Staff.objects.create(
    first_name="John",
    last_name="Doe",
    staff_type=Staff.StaffType.PHYSICIAN,
    job_title="Cardiologist",
    specialization="Cardiology",
    license_number="MOH-LIC-1234567",
    employee_id="DR-HOSP-12345",
    email="john.doe@hospital.sa",
    hospital=hospital,
    status="active"
)

# Create user account
user = StaffService.create_user_for_staff(staff, role='staff')

# Send credentials email
password = StaffService.generate_password()
user.set_password(password)
user.save()
StaffService.send_credentials_email(staff, password, request)
```

### Linking Existing User

```python
from apps.accounts.models import User
from apps.organizations.services import StaffService

# Get existing user and staff
user = User.objects.get(email="existing.user@hospital.sa")
staff = Staff.objects.get(employee_id="DR-HOSP-12345")

# Link user to staff
StaffService.link_user_to_staff(staff, user.id, request)
```

### Staff Login

Staff members can log in using:
- **Email:** Their email address (required field)
- **Password:** The password sent via email or set via password reset

The login URL is: `/accounts/login/`

## Testing

### Test Superuser Creation

```bash
python manage.py createsuperuser
```

Prompts for:
- Email (required)
- First name (required)
- Last name (required)
- Password (required)

### Test Staff Seeding

```bash
# Dry run
python manage.py seed_staff --physicians 3 --nurses 5 --dry-run

# Create staff
python manage.py seed_staff --physicians 3 --nurses 5

# Create staff with users
python manage.py seed_staff --physicians 3 --nurses 5 --create-users

# Create staff with users and send emails
python manage.py seed_staff --physicians 3 --nurses 5 --create-users --send-emails
```

### Test API Endpoints

```bash
# Create staff
curl -X POST http://localhost:8000/api/staff/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"first_name": "Test", "last_name": "User", ...}'

# List staff
curl http://localhost:8000/api/staff/ \
  -H "Authorization: Bearer <token>"

# Create user account
curl -X POST http://localhost:8000/api/staff/<id>/create_user_account/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"role": "staff"}'

# Send invitation
curl -X POST http://localhost:8000/api/staff/<id>/send_invitation/ \
  -H "Authorization: Bearer <token>"
```

## Security Considerations

1. **Password Generation:**
   - Secure random passwords (12 characters)
   - Includes letters, numbers, and special characters
   - Sent via email (should be changed on first login)

2. **Email Security:**
   - Credentials sent only to staff email
   - Email is required for user creation
   - Unique email constraint enforced

3. **Permissions:**
   - Only PX Admins and Hospital Admins can create user accounts
   - Hospital Admins can only create accounts for staff in their hospital
   - Staff can only view other staff in their hospital

4. **Audit Trail:**
   - All user creation/linking/unlinking actions logged
   - Email sending logged
   - Request context captured

## Troubleshooting

### Issue: "The Email field must be set"

**Solution:** Ensure staff member has an email address before creating user account.

### Issue: "Staff member already has a user account"

**Solution:** Staff already has a user linked. Use `link_user` to link a different user or `unlink_user` first.

### Issue: "You do not have permission to create user accounts"

**Solution:** User must be a PX Admin or Hospital Admin.

### Issue: "You can only create accounts for staff in your hospital"

**Solution:** Hospital Admins can only create accounts for staff in their hospital.

### Issue: Email not sending

**Solution:** Check email configuration in settings and ensure SMTP server is configured correctly.

## Related Documentation

- [UserManager Implementation](./USERMANAGER_IMPLEMENTATION.md)
- [Staff User Account Implementation](./STAFF_USER_ACCOUNT_IMPLEMENTATION.md)
- [Staff Seed Command Update](./STAFF_SEED_COMMAND_UPDATE.md)
- [Login/Logout Functionality Check](../LOGIN_LOGOUT_FUNCTIONALITY_CHECK.md)

## Summary

The Staff User Account feature provides:

1. ✅ Optional one-to-one relation between Staff and User models
2. ✅ Custom UserManager for email-based authentication
3. ✅ Complete CRUD operations for staff management
4. ✅ User account creation, linking, and unlinking
5. ✅ Credential email sending
6. ✅ Role-based access control
7. ✅ Audit logging
8. ✅ Bilingual support (English/Arabic)
9. ✅ Management command for bulk staff creation
10. ✅ RESTful API endpoints with filtering and search

The implementation follows Django best practices, maintains backward compatibility, and provides a secure, scalable solution for staff user account management.
