# 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 " \ -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": "", "department": "", "status": "active" }' # 2. Create user account for staff curl -X POST http://localhost:8000/api/staff//create_user_account/ \ -H "Authorization: Bearer " \ -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 " \ -H "Content-Type: application/json" \ -d '{"first_name": "Test", "last_name": "User", ...}' # List staff curl http://localhost:8000/api/staff/ \ -H "Authorization: Bearer " # Create user account curl -X POST http://localhost:8000/api/staff//create_user_account/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"role": "staff"}' # Send invitation curl -X POST http://localhost:8000/api/staff//send_invitation/ \ -H "Authorization: Bearer " ``` ## 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.