HH/docs/STAFF_USER_ACCOUNT_FEATURE_SUMMARY.md
2026-01-12 12:19:19 +03:00

478 lines
14 KiB
Markdown

# 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.