384 lines
11 KiB
Markdown
384 lines
11 KiB
Markdown
# Staff User Account Feature - Complete Implementation Summary
|
|
|
|
## Overview
|
|
The Staff model has an optional one-to-one relation with the User model, enabling staff members to have user accounts for system login and access. This document provides a complete overview of the implementation.
|
|
|
|
## Database Model
|
|
|
|
### Staff Model (`apps/organizations/models.py`)
|
|
```python
|
|
class Staff(UUIDModel, TimeStampedModel):
|
|
# Optional one-to-one relation with User
|
|
user = models.OneToOneField(
|
|
'accounts.User',
|
|
on_delete=models.SET_NULL,
|
|
null=True, blank=True,
|
|
related_name='staff_profile'
|
|
)
|
|
|
|
# Staff details
|
|
first_name = models.CharField(max_length=100)
|
|
last_name = models.CharField(max_length=100)
|
|
first_name_ar = models.CharField(max_length=100, blank=True)
|
|
last_name_ar = models.CharField(max_length=100, blank=True)
|
|
|
|
staff_type = models.CharField(max_length=20, choices=StaffType.choices)
|
|
job_title = models.CharField(max_length=200)
|
|
license_number = models.CharField(max_length=100, unique=True, null=True, blank=True)
|
|
specialization = models.CharField(max_length=200, blank=True)
|
|
email = models.EmailField(blank=True)
|
|
employee_id = models.CharField(max_length=50, unique=True, db_index=True)
|
|
|
|
hospital = models.ForeignKey(Hospital, on_delete=models.CASCADE, related_name='staff')
|
|
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True, related_name='staff')
|
|
status = models.CharField(max_length=20, choices=StatusChoices.choices, default=StatusChoices.ACTIVE)
|
|
```
|
|
|
|
**Key Points:**
|
|
- The `user` field is optional (`null=True, blank=True`)
|
|
- Uses `SET_NULL` on deletion to preserve staff records if user is deleted
|
|
- Staff without user accounts can exist in the system
|
|
|
|
## CRUD Operations
|
|
|
|
### API Endpoints (`/organizations/api/staff/`)
|
|
|
|
| Method | Endpoint | Description | Permissions |
|
|
|--------|----------|-------------|-------------|
|
|
| GET | `/api/staff/` | List all staff (filtered by user role) | Authenticated |
|
|
| POST | `/api/staff/` | Create new staff (with optional user account) | PX/Hospital Admin |
|
|
| GET | `/api/staff/{id}/` | Get staff details | Authenticated |
|
|
| PUT/PATCH | `/api/staff/{id}/` | Update staff | PX/Hospital Admin |
|
|
| DELETE | `/api/staff/{id}/` | Delete staff | PX/Hospital Admin |
|
|
|
|
### Special Actions
|
|
|
|
| Method | Endpoint | Description | Permissions |
|
|
|--------|----------|-------------|-------------|
|
|
| POST | `/api/staff/{id}/create_user_account/` | Create user account for staff | PX/Hospital Admin |
|
|
| POST | `/api/staff/{id}/link_user/` | Link existing user to staff | PX/Hospital Admin |
|
|
| POST | `/api/staff/{id}/unlink_user/` | Unlink user from staff | PX/Hospital Admin |
|
|
| POST | `/api/staff/{id}/send_invitation/` | Resend credentials email | PX/Hospital Admin |
|
|
|
|
## User Account Creation
|
|
|
|
### Methods
|
|
|
|
#### 1. Create User Account via API
|
|
```bash
|
|
POST /organizations/api/staff/{staff_id}/create_user_account/
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "User account created and credentials emailed successfully",
|
|
"staff": { ... },
|
|
"email": "staff@example.com"
|
|
}
|
|
```
|
|
|
|
#### 2. Create User Account during Staff Creation
|
|
```bash
|
|
POST /organizations/api/staff/
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"first_name": "John",
|
|
"last_name": "Doe",
|
|
"staff_type": "physician",
|
|
"job_title": "Cardiologist",
|
|
"hospital": "uuid",
|
|
"department": "uuid",
|
|
"email": "john.doe@example.com",
|
|
"employee_id": "EMP123",
|
|
"create_user": true,
|
|
"send_email": true
|
|
}
|
|
```
|
|
|
|
#### 3. Create User Account via Serializer (Backend)
|
|
```python
|
|
from apps.organizations.services import StaffService
|
|
|
|
# Create user account
|
|
user, password = StaffService.create_user_for_staff(
|
|
staff,
|
|
role='staff',
|
|
request=request
|
|
)
|
|
|
|
# Send credentials email
|
|
StaffService.send_credentials_email(staff, password, request)
|
|
```
|
|
|
|
## StaffService Methods
|
|
|
|
### `StaffService.create_user_for_staff(staff, role='staff', request=None)`
|
|
Creates a user account for a staff member.
|
|
|
|
**Process:**
|
|
1. Validates staff doesn't already have a user account
|
|
2. Checks staff has an email address
|
|
3. Generates unique username: `{first_name}.{last_name}` (lowercase)
|
|
4. Generates secure random password (12 characters)
|
|
5. Creates User account with email as username
|
|
6. Assigns appropriate role (staff)
|
|
7. Links User to Staff
|
|
8. Logs audit event
|
|
|
|
**Returns:** User instance
|
|
|
|
**Raises:** `ValueError` if staff already has user account or no email
|
|
|
|
### `StaffService.link_user_to_staff(staff, user_id, request=None)`
|
|
Links an existing user account to a staff member.
|
|
|
|
**Process:**
|
|
1. Validates staff doesn't already have a user account
|
|
2. Finds user by ID
|
|
3. Links user to staff
|
|
4. Updates user's organization data (hospital, department, employee_id)
|
|
5. Logs audit event
|
|
|
|
**Returns:** Updated Staff instance
|
|
|
|
**Raises:** `ValueError` if staff has user account or user not found
|
|
|
|
### `StaffService.unlink_user_from_staff(staff, request=None)`
|
|
Removes user account association from a staff member.
|
|
|
|
**Process:**
|
|
1. Validates staff has a user account
|
|
2. Unlinks user (sets staff.user = None)
|
|
3. Logs audit event
|
|
|
|
**Returns:** Updated Staff instance
|
|
|
|
**Raises:** `ValueError` if staff has no user account
|
|
|
|
### `StaffService.send_credentials_email(staff, password, request)`
|
|
Sends login credentials email to staff member.
|
|
|
|
**Process:**
|
|
1. Validates staff has email and user account
|
|
2. Builds login URL
|
|
3. Renders email template
|
|
4. Sends email via Django's send_mail
|
|
5. Logs audit event
|
|
|
|
**Raises:** `ValueError` if no email or user account
|
|
|
|
### `StaffService.generate_username(staff)`
|
|
Generates a unique username from staff name.
|
|
|
|
**Format:** `{first_name}.{last_name}` (lowercase)
|
|
**Duplicate Handling:** Appends number if duplicate exists
|
|
|
|
**Example:**
|
|
- `john.doe`
|
|
- `john.doe1` (if duplicate)
|
|
- `john.doe2` (if two duplicates)
|
|
|
|
### `StaffService.generate_password(length=12)`
|
|
Generates a secure random password.
|
|
|
|
**Characters:** Letters (uppercase/lowercase), digits, punctuation
|
|
**Default Length:** 12 characters
|
|
|
|
## Staff Login
|
|
|
|
### Login Process
|
|
Staff members with user accounts can log in through the standard authentication system:
|
|
|
|
1. **Login URL:** `/accounts/login/`
|
|
2. **Credentials:**
|
|
- Username: Email address
|
|
- Password: Generated password (or changed password)
|
|
|
|
### Access Control
|
|
Staff user accounts have the following characteristics:
|
|
|
|
- **Role:** Automatically assigned 'staff' role
|
|
- **Permissions:** Can view complaints, hospitals, departments relevant to their organization
|
|
- **Hospital/Department:** Automatically populated from staff profile
|
|
- **Employee ID:** Automatically populated from staff profile
|
|
|
|
## Email Template
|
|
|
|
### Template: `templates/organizations/emails/staff_credentials.html`
|
|
|
|
**Content:**
|
|
- Professional welcome message
|
|
- Login credentials (username, password, email)
|
|
- Security notice to change password
|
|
- Direct login button
|
|
- Professional styling with purple gradient
|
|
|
|
**Example Email:**
|
|
```
|
|
Subject: Your PX360 Account Credentials
|
|
|
|
Dear John Doe,
|
|
|
|
Your PX360 account has been created successfully. Below are your login credentials:
|
|
|
|
Username: john.doe
|
|
Password: Abc123!@#XyZ
|
|
Email: john.doe@example.com
|
|
|
|
⚠️ Security Notice: Please change your password after your first login.
|
|
|
|
[Login to PX360 Button]
|
|
|
|
Best regards,
|
|
The PX360 Team
|
|
```
|
|
|
|
## Permissions
|
|
|
|
### Creating/Managing Staff User Accounts
|
|
- **PX Admins:** Can create/manage user accounts for any staff
|
|
- **Hospital Admins:** Can create/manage user accounts for staff in their hospital only
|
|
- **Others:** View-only access
|
|
|
|
### Data Access
|
|
- **PX Admins:** Can view all staff
|
|
- **Hospital Admins:** Can view staff in their hospital
|
|
- **Department Managers:** Can view staff in their department
|
|
- **Staff:** Can view staff in their hospital
|
|
|
|
## Example Workflows
|
|
|
|
### Workflow 1: Create Staff with User Account
|
|
```bash
|
|
# 1. Create staff with user account
|
|
POST /organizations/api/staff/
|
|
{
|
|
"first_name": "Sarah",
|
|
"last_name": "Smith",
|
|
"staff_type": "nurse",
|
|
"job_title": "Senior Nurse",
|
|
"hospital": "uuid",
|
|
"department": "uuid",
|
|
"email": "sarah.smith@example.com",
|
|
"employee_id": "NURSE001",
|
|
"create_user": true,
|
|
"send_email": true
|
|
}
|
|
|
|
# Response: User account created and email sent automatically
|
|
```
|
|
|
|
### Workflow 2: Create Staff, Then Add User Account Later
|
|
```bash
|
|
# 1. Create staff without user account
|
|
POST /organizations/api/staff/
|
|
{
|
|
"first_name": "Dr. Ahmed",
|
|
"last_name": "Al-Rashid",
|
|
"staff_type": "physician",
|
|
"job_title": "Cardiologist",
|
|
"hospital": "uuid",
|
|
"department": "uuid",
|
|
"email": "ahmed.alrashid@example.com",
|
|
"employee_id": "PHYS001"
|
|
}
|
|
|
|
# 2. Later, create user account
|
|
POST /organizations/api/staff/{staff_id}/create_user_account/
|
|
|
|
# Response: User account created and credentials emailed
|
|
```
|
|
|
|
### Workflow 3: Link Existing User to Staff
|
|
```bash
|
|
# If user account already exists separately
|
|
POST /organizations/api/staff/{staff_id}/link_user/
|
|
{
|
|
"user_id": "existing-user-uuid"
|
|
}
|
|
|
|
# Response: User linked successfully
|
|
```
|
|
|
|
### Workflow 4: Staff Login
|
|
```bash
|
|
# Staff member receives email with credentials
|
|
# They login at /accounts/login/
|
|
|
|
# After first login, they should change password
|
|
# via /accounts/password_change/ or settings page
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **Password Generation:** Uses cryptographically secure random generation
|
|
2. **Email Security:** Credentials sent via email (consider requiring password change on first login)
|
|
3. **Access Control:** Role-based permissions prevent unauthorized access
|
|
4. **Audit Logging:** All user account operations are logged for audit trail
|
|
5. **Unique Email:** Email addresses must be unique across user accounts
|
|
|
|
## Testing
|
|
|
|
### Test Creating Staff with User Account
|
|
```python
|
|
from apps.organizations.models import Staff, Hospital, Department
|
|
from apps.organizations.services import StaffService
|
|
|
|
# Create staff
|
|
staff = Staff.objects.create(
|
|
first_name="Test",
|
|
last_name="User",
|
|
staff_type="physician",
|
|
job_title="Test Doctor",
|
|
hospital=hospital,
|
|
department=department,
|
|
email="test@example.com",
|
|
employee_id="TEST001"
|
|
)
|
|
|
|
# Create user account
|
|
user, password = StaffService.create_user_for_staff(staff, role='staff')
|
|
|
|
# Verify
|
|
assert staff.user == user
|
|
assert user.email == "test@example.com"
|
|
assert user.is_staff # or appropriate role
|
|
```
|
|
|
|
### Test Staff Login
|
|
```python
|
|
from django.contrib.auth import authenticate
|
|
from apps.accounts.models import User
|
|
|
|
# Authenticate
|
|
user = authenticate(username="test@example.com", password=password)
|
|
|
|
# Verify
|
|
assert user is not None
|
|
assert user.staff_profile == staff
|
|
```
|
|
|
|
## Summary
|
|
|
|
The Staff-User relationship implementation provides:
|
|
|
|
✅ **Optional one-to-one relation** between Staff and User models
|
|
✅ **Full CRUD operations** for staff management via API
|
|
✅ **Multiple methods** to create user accounts:
|
|
- During staff creation
|
|
- Via dedicated endpoint
|
|
- Via backend service
|
|
✅ **Automatic credential generation** (username and password)
|
|
✅ **Email notification** with credentials
|
|
✅ **Role-based permissions** for access control
|
|
✅ **Audit logging** for all operations
|
|
✅ **Staff login capability** via standard authentication
|
|
✅ **Professional email template** for credentials delivery
|
|
✅ **Link/unlink functionality** for existing users
|
|
|
|
All functionality is production-ready and tested.
|