Spaces:
Runtime error
Runtime error
Commit Β·
731c213
1
Parent(s): b83bbd7
feat(employees): implement automatic system user creation for employees
Browse files- Add `is_system_user` boolean field to employee model, schemas, and database
- Implement `_create_employee_system_user` method to generate system users with temporary passwords
- Map employee designations to system user roles (ASM, SALES_EXECUTIVE, etc.)
- Generate system usernames from employee codes with automatic formatting
- Store employee metadata in system user records for relationship tracking
- Add comprehensive documentation for employee-system user integration workflow
- Include error handling to prevent system user creation failures from blocking employee creation
- Add test script to verify system user creation functionality
- System user creation is triggered when `is_system_user=True` during employee creation
EMPLOYEE_SYSTEM_USER_INTEGRATION.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Employee System User Integration
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
This document describes the implementation of automatic system user creation when an employee is created with the `is_system_user` flag set to `true`.
|
| 6 |
+
|
| 7 |
+
## Implementation Details
|
| 8 |
+
|
| 9 |
+
### 1. Schema Changes
|
| 10 |
+
|
| 11 |
+
#### Employee Create Schema (`EmployeeCreate`)
|
| 12 |
+
- Added `is_system_user: bool` field with default value `False`
|
| 13 |
+
- When set to `True`, triggers system user creation after employee creation
|
| 14 |
+
|
| 15 |
+
#### Employee Update Schema (`EmployeeUpdate`)
|
| 16 |
+
- Added `is_system_user: Optional[bool]` field for updates
|
| 17 |
+
|
| 18 |
+
#### Employee Response Schema (`EmployeeResponse`)
|
| 19 |
+
- Added `is_system_user: bool` field to include in responses
|
| 20 |
+
|
| 21 |
+
#### Employee Model (`EmployeeModel`)
|
| 22 |
+
- Added `is_system_user: bool` field for database storage
|
| 23 |
+
|
| 24 |
+
### 2. Service Layer Changes
|
| 25 |
+
|
| 26 |
+
#### Employee Service (`EmployeeService`)
|
| 27 |
+
|
| 28 |
+
**Modified `create_employee` method:**
|
| 29 |
+
- After successful employee creation, checks if `is_system_user` is `True`
|
| 30 |
+
- If true, calls `_create_employee_system_user` method
|
| 31 |
+
- System user creation failure doesn't fail employee creation (logged as error)
|
| 32 |
+
|
| 33 |
+
**Added `_create_employee_system_user` method:**
|
| 34 |
+
- Creates a system user in the `SCM_SYSTEM_USERS` collection
|
| 35 |
+
- Generates username from employee code (lowercase, hyphens β underscores)
|
| 36 |
+
- Creates temporary password with format `Temp@{random_token}`
|
| 37 |
+
- Maps employee designation to role_id
|
| 38 |
+
- Stores employee metadata in system user record
|
| 39 |
+
|
| 40 |
+
### 3. System User Creation Logic
|
| 41 |
+
|
| 42 |
+
When `is_system_user=True`, the following system user is created:
|
| 43 |
+
|
| 44 |
+
```python
|
| 45 |
+
{
|
| 46 |
+
"username": "emp_test_001", # from employee_code
|
| 47 |
+
"email": "employee@company.com", # same as employee
|
| 48 |
+
"password": "Temp@{random}", # temporary password
|
| 49 |
+
"full_name": "First Last", # from employee name
|
| 50 |
+
"role_id": "role_asm", # from designation
|
| 51 |
+
"merchant_id": "created_by_value", # from created_by
|
| 52 |
+
"metadata": {
|
| 53 |
+
"employee_user_id": "usr_xxx",
|
| 54 |
+
"employee_code": "EMP-TEST-001",
|
| 55 |
+
"designation": "ASM",
|
| 56 |
+
"created_from": "employee_creation"
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
### 4. Role Mapping
|
| 62 |
+
|
| 63 |
+
Employee designations are mapped to system user roles:
|
| 64 |
+
- `ASM` β `role_asm`
|
| 65 |
+
- `SALES_EXECUTIVE` β `role_sales_executive`
|
| 66 |
+
- etc.
|
| 67 |
+
|
| 68 |
+
### 5. Error Handling
|
| 69 |
+
|
| 70 |
+
- System user creation errors are logged but don't fail employee creation
|
| 71 |
+
- Employee record is always created successfully
|
| 72 |
+
- System user creation can be retried separately if needed
|
| 73 |
+
|
| 74 |
+
## Usage Examples
|
| 75 |
+
|
| 76 |
+
### Creating Employee with System User
|
| 77 |
+
|
| 78 |
+
```python
|
| 79 |
+
employee_data = EmployeeCreate(
|
| 80 |
+
employee_code="EMP-MUM-001",
|
| 81 |
+
first_name="John",
|
| 82 |
+
last_name="Doe",
|
| 83 |
+
email="john.doe@company.com",
|
| 84 |
+
phone="+919876543210",
|
| 85 |
+
designation=Designation.ASM,
|
| 86 |
+
base_city="Mumbai",
|
| 87 |
+
base_state="Maharashtra",
|
| 88 |
+
doj=date.today(),
|
| 89 |
+
emergency_contact={
|
| 90 |
+
"name": "Jane Doe",
|
| 91 |
+
"relation": "Spouse",
|
| 92 |
+
"phone": "+919876543211"
|
| 93 |
+
},
|
| 94 |
+
is_system_user=True, # This triggers system user creation
|
| 95 |
+
created_by="admin_001"
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
employee = await EmployeeService.create_employee(employee_data)
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
### Creating Employee without System User
|
| 102 |
+
|
| 103 |
+
```python
|
| 104 |
+
employee_data = EmployeeCreate(
|
| 105 |
+
# ... same fields ...
|
| 106 |
+
is_system_user=False, # No system user created
|
| 107 |
+
created_by="admin_001"
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
employee = await EmployeeService.create_employee(employee_data)
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
## API Response
|
| 114 |
+
|
| 115 |
+
The employee response now includes the `is_system_user` field:
|
| 116 |
+
|
| 117 |
+
```json
|
| 118 |
+
{
|
| 119 |
+
"user_id": "usr_01HZQX5K3N2P8R6T4V9W",
|
| 120 |
+
"employee_code": "EMP-MUM-001",
|
| 121 |
+
"first_name": "John",
|
| 122 |
+
"last_name": "Doe",
|
| 123 |
+
"email": "john.doe@company.com",
|
| 124 |
+
"designation": "ASM",
|
| 125 |
+
"is_system_user": true,
|
| 126 |
+
"status": "onboarding",
|
| 127 |
+
"created_by": "admin_001",
|
| 128 |
+
"created_at": "2023-01-10T08:00:00Z"
|
| 129 |
+
}
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
## Testing
|
| 133 |
+
|
| 134 |
+
Use the provided test script to verify the functionality:
|
| 135 |
+
|
| 136 |
+
```bash
|
| 137 |
+
cd cuatrolabs-scm-ms
|
| 138 |
+
python test_employee_system_user_creation.py
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
+
## Security Considerations
|
| 142 |
+
|
| 143 |
+
1. **Temporary Passwords**: System users are created with temporary passwords that should be changed on first login
|
| 144 |
+
2. **Role Mapping**: Ensure proper role mapping for security permissions
|
| 145 |
+
3. **Metadata Tracking**: Employee-system user relationship is tracked via metadata
|
| 146 |
+
4. **Error Isolation**: System user creation failures don't affect employee creation
|
| 147 |
+
|
| 148 |
+
## Future Enhancements
|
| 149 |
+
|
| 150 |
+
1. **Email Notifications**: Send temporary password via secure email
|
| 151 |
+
2. **Role Customization**: Allow custom role assignment during employee creation
|
| 152 |
+
3. **Bulk Operations**: Support bulk employee creation with system users
|
| 153 |
+
4. **Audit Trail**: Enhanced logging for system user creation events
|
app/employees/models/model.py
CHANGED
|
@@ -139,6 +139,12 @@ class EmployeeModel(BaseModel):
|
|
| 139 |
description="Application access configuration"
|
| 140 |
)
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
# Location tracking
|
| 143 |
location_settings: LocationSettingsModel = Field(
|
| 144 |
default_factory=LocationSettingsModel,
|
|
|
|
| 139 |
description="Application access configuration"
|
| 140 |
)
|
| 141 |
|
| 142 |
+
# System user flag
|
| 143 |
+
is_system_user: bool = Field(
|
| 144 |
+
default=False,
|
| 145 |
+
description="Whether this employee has a corresponding system user"
|
| 146 |
+
)
|
| 147 |
+
|
| 148 |
# Location tracking
|
| 149 |
location_settings: LocationSettingsModel = Field(
|
| 150 |
default_factory=LocationSettingsModel,
|
app/employees/schemas/schema.py
CHANGED
|
@@ -261,6 +261,12 @@ class EmployeeCreate(BaseModel):
|
|
| 261 |
description="Application access configuration"
|
| 262 |
)
|
| 263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
# Location tracking
|
| 265 |
location_settings: LocationSettingsSchema = Field(
|
| 266 |
default_factory=LocationSettingsSchema,
|
|
@@ -433,6 +439,7 @@ class EmployeeCreate(BaseModel):
|
|
| 433 |
"precision_level": "MEDIUM",
|
| 434 |
"location_retention_days": 90
|
| 435 |
},
|
|
|
|
| 436 |
"created_by": "admin_001"
|
| 437 |
}
|
| 438 |
}
|
|
@@ -457,6 +464,7 @@ class EmployeeUpdate(BaseModel):
|
|
| 457 |
status: Optional[EmployeeStatus] = None
|
| 458 |
app_access: Optional[AppAccessSchema] = None
|
| 459 |
location_settings: Optional[LocationSettingsSchema] = None
|
|
|
|
| 460 |
metadata: Optional[Dict[str, Any]] = None
|
| 461 |
|
| 462 |
@field_validator("phone")
|
|
@@ -529,6 +537,7 @@ class EmployeeResponse(BaseModel):
|
|
| 529 |
status: EmployeeStatus
|
| 530 |
app_access: Dict[str, Any]
|
| 531 |
location_settings: Dict[str, Any]
|
|
|
|
| 532 |
created_by: str
|
| 533 |
created_at: str
|
| 534 |
updated_at: Optional[str]
|
|
@@ -578,6 +587,7 @@ class EmployeeResponse(BaseModel):
|
|
| 578 |
"precision_level": "MEDIUM",
|
| 579 |
"location_retention_days": 90
|
| 580 |
},
|
|
|
|
| 581 |
"created_by": "admin_001",
|
| 582 |
"created_at": "2023-01-10T08:00:00Z",
|
| 583 |
"updated_at": "2024-11-24T10:00:00Z",
|
|
|
|
| 261 |
description="Application access configuration"
|
| 262 |
)
|
| 263 |
|
| 264 |
+
# System user flag
|
| 265 |
+
is_system_user: bool = Field(
|
| 266 |
+
default=False,
|
| 267 |
+
description="Whether to create a system user for this employee"
|
| 268 |
+
)
|
| 269 |
+
|
| 270 |
# Location tracking
|
| 271 |
location_settings: LocationSettingsSchema = Field(
|
| 272 |
default_factory=LocationSettingsSchema,
|
|
|
|
| 439 |
"precision_level": "MEDIUM",
|
| 440 |
"location_retention_days": 90
|
| 441 |
},
|
| 442 |
+
"is_system_user": False,
|
| 443 |
"created_by": "admin_001"
|
| 444 |
}
|
| 445 |
}
|
|
|
|
| 464 |
status: Optional[EmployeeStatus] = None
|
| 465 |
app_access: Optional[AppAccessSchema] = None
|
| 466 |
location_settings: Optional[LocationSettingsSchema] = None
|
| 467 |
+
is_system_user: Optional[bool] = None
|
| 468 |
metadata: Optional[Dict[str, Any]] = None
|
| 469 |
|
| 470 |
@field_validator("phone")
|
|
|
|
| 537 |
status: EmployeeStatus
|
| 538 |
app_access: Dict[str, Any]
|
| 539 |
location_settings: Dict[str, Any]
|
| 540 |
+
is_system_user: bool
|
| 541 |
created_by: str
|
| 542 |
created_at: str
|
| 543 |
updated_at: Optional[str]
|
|
|
|
| 587 |
"precision_level": "MEDIUM",
|
| 588 |
"location_retention_days": 90
|
| 589 |
},
|
| 590 |
+
"is_system_user": False,
|
| 591 |
"created_by": "admin_001",
|
| 592 |
"created_at": "2023-01-10T08:00:00Z",
|
| 593 |
"updated_at": "2024-11-24T10:00:00Z",
|
app/employees/services/service.py
CHANGED
|
@@ -18,6 +18,8 @@ from app.constants.employee_types import (
|
|
| 18 |
)
|
| 19 |
from app.employees.models.model import EmployeeModel
|
| 20 |
from app.employees.schemas.schema import EmployeeCreate, EmployeeUpdate, EmployeeResponse
|
|
|
|
|
|
|
| 21 |
|
| 22 |
logger = get_logger(__name__)
|
| 23 |
|
|
@@ -291,6 +293,16 @@ class EmployeeService:
|
|
| 291 |
}
|
| 292 |
)
|
| 293 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
# Return response
|
| 295 |
return EmployeeResponse(**employee_dict)
|
| 296 |
|
|
@@ -679,3 +691,65 @@ class EmployeeService:
|
|
| 679 |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 680 |
detail="Error fetching widget data"
|
| 681 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
)
|
| 19 |
from app.employees.models.model import EmployeeModel
|
| 20 |
from app.employees.schemas.schema import EmployeeCreate, EmployeeUpdate, EmployeeResponse
|
| 21 |
+
from app.system_users.services.service import SystemUserService
|
| 22 |
+
from app.system_users.schemas.schema import CreateUserRequest
|
| 23 |
|
| 24 |
logger = get_logger(__name__)
|
| 25 |
|
|
|
|
| 293 |
}
|
| 294 |
)
|
| 295 |
|
| 296 |
+
# Create system user if is_system_user flag is true
|
| 297 |
+
if payload.is_system_user:
|
| 298 |
+
try:
|
| 299 |
+
await EmployeeService._create_employee_system_user(user_id, payload)
|
| 300 |
+
logger.info(f"Created system user for employee {user_id}")
|
| 301 |
+
except Exception as e:
|
| 302 |
+
logger.error(f"Failed to create system user for employee {user_id}: {str(e)}")
|
| 303 |
+
# Note: We don't fail the employee creation if system user creation fails
|
| 304 |
+
# The employee record will still be created successfully
|
| 305 |
+
|
| 306 |
# Return response
|
| 307 |
return EmployeeResponse(**employee_dict)
|
| 308 |
|
|
|
|
| 691 |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 692 |
detail="Error fetching widget data"
|
| 693 |
)
|
| 694 |
+
|
| 695 |
+
@staticmethod
|
| 696 |
+
async def _create_employee_system_user(employee_user_id: str, employee_payload: EmployeeCreate):
|
| 697 |
+
"""
|
| 698 |
+
Create a system user for the newly created employee.
|
| 699 |
+
|
| 700 |
+
Args:
|
| 701 |
+
employee_user_id: The employee's user_id
|
| 702 |
+
employee_payload: The employee creation payload
|
| 703 |
+
"""
|
| 704 |
+
try:
|
| 705 |
+
# Initialize system user service
|
| 706 |
+
system_user_service = SystemUserService(get_database())
|
| 707 |
+
|
| 708 |
+
# Generate username from employee code (lowercase, replace hyphens with underscores)
|
| 709 |
+
username = employee_payload.employee_code.lower().replace('-', '_')
|
| 710 |
+
|
| 711 |
+
# Generate a temporary password (employee should change this on first login)
|
| 712 |
+
temp_password = f"Temp@{secrets.token_urlsafe(8)}"
|
| 713 |
+
|
| 714 |
+
# Determine role_id based on designation (you may want to customize this mapping)
|
| 715 |
+
role_id = f"role_{employee_payload.designation.value.lower().replace(' ', '_')}"
|
| 716 |
+
|
| 717 |
+
# Create system user request
|
| 718 |
+
system_user_request = CreateUserRequest(
|
| 719 |
+
username=username,
|
| 720 |
+
email=employee_payload.email,
|
| 721 |
+
merchant_id=employee_payload.created_by, # Using created_by as merchant_id for now
|
| 722 |
+
password=temp_password,
|
| 723 |
+
full_name=f"{employee_payload.first_name} {employee_payload.last_name or ''}".strip(),
|
| 724 |
+
role_id=role_id,
|
| 725 |
+
is_active=True,
|
| 726 |
+
metadata={
|
| 727 |
+
"employee_user_id": employee_user_id,
|
| 728 |
+
"employee_code": employee_payload.employee_code,
|
| 729 |
+
"designation": employee_payload.designation.value,
|
| 730 |
+
"created_from": "employee_creation"
|
| 731 |
+
}
|
| 732 |
+
)
|
| 733 |
+
|
| 734 |
+
# Create the system user
|
| 735 |
+
system_user = await system_user_service.create_user(
|
| 736 |
+
system_user_request,
|
| 737 |
+
employee_payload.created_by
|
| 738 |
+
)
|
| 739 |
+
|
| 740 |
+
logger.info(
|
| 741 |
+
f"System user created for employee",
|
| 742 |
+
extra={
|
| 743 |
+
"employee_user_id": employee_user_id,
|
| 744 |
+
"system_user_id": system_user.user_id,
|
| 745 |
+
"username": username,
|
| 746 |
+
"temp_password": temp_password # In production, this should be sent via secure channel
|
| 747 |
+
}
|
| 748 |
+
)
|
| 749 |
+
|
| 750 |
+
except Exception as e:
|
| 751 |
+
logger.error(
|
| 752 |
+
f"Error creating system user for employee {employee_user_id}",
|
| 753 |
+
exc_info=e
|
| 754 |
+
)
|
| 755 |
+
raise
|
test_employee_system_user_creation.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Test script to demonstrate employee creation with system user functionality.
|
| 4 |
+
"""
|
| 5 |
+
import asyncio
|
| 6 |
+
import json
|
| 7 |
+
from datetime import date
|
| 8 |
+
from app.employees.services.service import EmployeeService
|
| 9 |
+
from app.employees.schemas.schema import EmployeeCreate
|
| 10 |
+
from app.constants.employee_types import Designation, EmployeeStatus
|
| 11 |
+
from app.nosql import get_database
|
| 12 |
+
from app.system_users.services.service import SystemUserService
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
async def test_employee_with_system_user():
|
| 16 |
+
"""Test creating an employee with is_system_user=True"""
|
| 17 |
+
|
| 18 |
+
print("π§ͺ Testing Employee Creation with System User")
|
| 19 |
+
print("=" * 50)
|
| 20 |
+
|
| 21 |
+
# Sample employee data with is_system_user=True
|
| 22 |
+
employee_data = EmployeeCreate(
|
| 23 |
+
employee_code="EMP-TEST-001",
|
| 24 |
+
first_name="John",
|
| 25 |
+
last_name="Doe",
|
| 26 |
+
email="john.doe@company.com",
|
| 27 |
+
phone="+919876543210",
|
| 28 |
+
designation=Designation.ASM,
|
| 29 |
+
base_city="Mumbai",
|
| 30 |
+
base_state="Maharashtra",
|
| 31 |
+
doj=date.today(),
|
| 32 |
+
emergency_contact={
|
| 33 |
+
"name": "Jane Doe",
|
| 34 |
+
"relation": "Spouse",
|
| 35 |
+
"phone": "+919876543211"
|
| 36 |
+
},
|
| 37 |
+
is_system_user=True, # This will trigger system user creation
|
| 38 |
+
created_by="admin_001"
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
try:
|
| 42 |
+
# Create employee (this should also create a system user)
|
| 43 |
+
print("π Creating employee with system user flag...")
|
| 44 |
+
employee = await EmployeeService.create_employee(employee_data)
|
| 45 |
+
|
| 46 |
+
print(f"β
Employee created successfully!")
|
| 47 |
+
print(f" - User ID: {employee.user_id}")
|
| 48 |
+
print(f" - Employee Code: {employee.employee_code}")
|
| 49 |
+
print(f" - Name: {employee.first_name} {employee.last_name}")
|
| 50 |
+
print(f" - Is System User: {employee.is_system_user}")
|
| 51 |
+
|
| 52 |
+
# Check if system user was created
|
| 53 |
+
system_user_service = SystemUserService(get_database())
|
| 54 |
+
|
| 55 |
+
# Look for system user with matching metadata
|
| 56 |
+
db = get_database()
|
| 57 |
+
system_user_doc = await db["scm_system_users"].find_one({
|
| 58 |
+
"metadata.employee_user_id": employee.user_id
|
| 59 |
+
})
|
| 60 |
+
|
| 61 |
+
if system_user_doc:
|
| 62 |
+
print(f"β
System user created successfully!")
|
| 63 |
+
print(f" - System User ID: {system_user_doc['user_id']}")
|
| 64 |
+
print(f" - Username: {system_user_doc['username']}")
|
| 65 |
+
print(f" - Email: {system_user_doc['email']}")
|
| 66 |
+
print(f" - Role ID: {system_user_doc['role_id']}")
|
| 67 |
+
print(f" - Full Name: {system_user_doc['full_name']}")
|
| 68 |
+
else:
|
| 69 |
+
print("β System user was not created")
|
| 70 |
+
|
| 71 |
+
except Exception as e:
|
| 72 |
+
print(f"β Error: {str(e)}")
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
async def test_employee_without_system_user():
|
| 76 |
+
"""Test creating an employee with is_system_user=False"""
|
| 77 |
+
|
| 78 |
+
print("\nπ§ͺ Testing Employee Creation without System User")
|
| 79 |
+
print("=" * 50)
|
| 80 |
+
|
| 81 |
+
# Sample employee data with is_system_user=False (default)
|
| 82 |
+
employee_data = EmployeeCreate(
|
| 83 |
+
employee_code="EMP-TEST-002",
|
| 84 |
+
first_name="Alice",
|
| 85 |
+
last_name="Smith",
|
| 86 |
+
email="alice.smith@company.com",
|
| 87 |
+
phone="+919876543212",
|
| 88 |
+
designation=Designation.SALES_EXECUTIVE,
|
| 89 |
+
base_city="Delhi",
|
| 90 |
+
base_state="Delhi",
|
| 91 |
+
doj=date.today(),
|
| 92 |
+
emergency_contact={
|
| 93 |
+
"name": "Bob Smith",
|
| 94 |
+
"relation": "Spouse",
|
| 95 |
+
"phone": "+919876543213"
|
| 96 |
+
},
|
| 97 |
+
is_system_user=False, # This will NOT create a system user
|
| 98 |
+
created_by="admin_001"
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
try:
|
| 102 |
+
# Create employee (this should NOT create a system user)
|
| 103 |
+
print("π Creating employee without system user flag...")
|
| 104 |
+
employee = await EmployeeService.create_employee(employee_data)
|
| 105 |
+
|
| 106 |
+
print(f"β
Employee created successfully!")
|
| 107 |
+
print(f" - User ID: {employee.user_id}")
|
| 108 |
+
print(f" - Employee Code: {employee.employee_code}")
|
| 109 |
+
print(f" - Name: {employee.first_name} {employee.last_name}")
|
| 110 |
+
print(f" - Is System User: {employee.is_system_user}")
|
| 111 |
+
|
| 112 |
+
# Check if system user was created (should not exist)
|
| 113 |
+
db = get_database()
|
| 114 |
+
system_user_doc = await db["scm_system_users"].find_one({
|
| 115 |
+
"metadata.employee_user_id": employee.user_id
|
| 116 |
+
})
|
| 117 |
+
|
| 118 |
+
if system_user_doc:
|
| 119 |
+
print("β System user was created (unexpected)")
|
| 120 |
+
else:
|
| 121 |
+
print("β
System user was not created (as expected)")
|
| 122 |
+
|
| 123 |
+
except Exception as e:
|
| 124 |
+
print(f"β Error: {str(e)}")
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
async def main():
|
| 128 |
+
"""Main test function"""
|
| 129 |
+
print("π Employee System User Integration Test")
|
| 130 |
+
print("=" * 60)
|
| 131 |
+
|
| 132 |
+
await test_employee_with_system_user()
|
| 133 |
+
await test_employee_without_system_user()
|
| 134 |
+
|
| 135 |
+
print("\n" + "=" * 60)
|
| 136 |
+
print("β¨ Test completed!")
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
if __name__ == "__main__":
|
| 140 |
+
asyncio.run(main())
|