478 lines
14 KiB
Markdown
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.
|