Spaces:
Sleeping
Sleeping
| """ | |
| Internal API endpoints for system user creation. | |
| These endpoints are used by other microservices (SCM, POS) to create system users. | |
| """ | |
| import secrets | |
| from fastapi import APIRouter, Depends, HTTPException, status | |
| from app.system_users.services.service import SystemUserService | |
| from app.system_users.schemas.schema import CreateUserRequest, UserInfoResponse | |
| from app.dependencies.auth import get_system_user_service | |
| from app.internal.schemas import CreateUserFromEmployeeRequest, CreateUserFromMerchantRequest | |
| from app.core.logging import get_logger | |
| logger = get_logger(__name__) | |
| router = APIRouter(prefix="/internal/system-users", tags=["internal"]) | |
| async def create_user_from_employee( | |
| request: CreateUserFromEmployeeRequest, | |
| user_service: SystemUserService = Depends(get_system_user_service) | |
| ): | |
| """ | |
| Create a system user from employee data. | |
| This endpoint is used by SCM service when creating employees with system access. | |
| Raises: | |
| HTTPException: 400 - Invalid data or missing required fields | |
| HTTPException: 500 - Database or server error | |
| """ | |
| try: | |
| # Validate required fields | |
| if not request.employee_id or not request.employee_id.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Employee ID is required" | |
| ) | |
| if not request.email or not request.email.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Email is required" | |
| ) | |
| if not request.first_name or not request.first_name.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="First name is required" | |
| ) | |
| if not request.merchant_id or not request.merchant_id.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Merchant ID is required" | |
| ) | |
| if not request.role_id or not request.role_id.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Role ID is required" | |
| ) | |
| # Generate username if not provided | |
| username = request.username | |
| if not username: | |
| # Generate from first name and last name | |
| base_username = f"{request.first_name.lower()}" | |
| if request.last_name: | |
| base_username += f"_{request.last_name.lower()}" | |
| username = base_username.replace(" ", "_").replace("-", "_") | |
| # Generate password if not provided | |
| password = request.password | |
| if not password: | |
| password = f"Temp@{secrets.token_urlsafe(8)}" | |
| # Prepare metadata | |
| metadata = request.metadata or {} | |
| metadata.update({ | |
| "employee_id": request.employee_id, | |
| "created_from": "employee", | |
| "created_via": "internal_api" | |
| }) | |
| # Create user request | |
| create_request = CreateUserRequest( | |
| username=username, | |
| email=request.email, | |
| merchant_id=request.merchant_id, | |
| merchant_type=request.merchant_type, | |
| password=password, | |
| first_name=request.first_name, | |
| last_name=request.last_name, | |
| phone=request.phone, | |
| role=request.role_id, | |
| metadata=metadata | |
| ) | |
| # Create user | |
| try: | |
| created_user = await user_service.create_user(create_request, "system_internal") | |
| except HTTPException as http_exc: | |
| # Re-raise HTTPException with more context | |
| logger.error(f"Failed to create user from employee {request.employee_id}: {http_exc.detail}") | |
| raise | |
| except Exception as create_error: | |
| logger.error(f"Unexpected error creating user from employee {request.employee_id}: {create_error}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to create user from employee" | |
| ) | |
| logger.info( | |
| f"Created system user from employee", | |
| extra={ | |
| "employee_id": request.employee_id, | |
| "user_id": created_user.user_id, | |
| "username": username, | |
| "merchant_id": request.merchant_id, | |
| "merchant_type": request.merchant_type | |
| } | |
| ) | |
| return user_service.convert_to_user_info_response(created_user) | |
| except HTTPException: | |
| raise | |
| except ValueError as e: | |
| logger.error(f"Validation error creating user from employee {request.employee_id}: {e}") | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail=str(e) | |
| ) | |
| except Exception as e: | |
| logger.error(f"Unexpected error creating user from employee: {str(e)}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="An unexpected error occurred while creating user from employee" | |
| ) | |
| async def create_user_from_merchant( | |
| request: CreateUserFromMerchantRequest, | |
| user_service: SystemUserService = Depends(get_system_user_service) | |
| ): | |
| """ | |
| Create a system user from merchant data. | |
| This endpoint is used by SCM service when creating merchants with system access. | |
| Raises: | |
| HTTPException: 400 - Invalid data or missing required fields | |
| HTTPException: 500 - Database or server error | |
| """ | |
| try: | |
| # Validate required fields | |
| if not request.merchant_id or not request.merchant_id.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Merchant ID is required" | |
| ) | |
| if not request.email or not request.email.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Email is required" | |
| ) | |
| if not request.merchant_name or not request.merchant_name.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Merchant name is required" | |
| ) | |
| if not request.merchant_type or not request.merchant_type.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Merchant type is required" | |
| ) | |
| if not request.role_id or not request.role_id.strip(): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Role ID is required" | |
| ) | |
| # Validate email format | |
| if "@" not in request.email: | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Invalid email format" | |
| ) | |
| # Generate username if not provided | |
| username = request.username | |
| if not username: | |
| # Generate from email (part before @) | |
| username = request.email.split('@')[0].lower().replace(".", "_").replace("-", "_") | |
| # Generate password if not provided | |
| password = request.password | |
| if not password: | |
| password = "Welcome@1234" # Default merchant password | |
| # Prepare metadata | |
| metadata = request.metadata or {} | |
| metadata.update({ | |
| "merchant_id": request.merchant_id, | |
| "merchant_type": request.merchant_type, | |
| "created_from": "merchant", | |
| "created_via": "internal_api" | |
| }) | |
| # Parse merchant name for first and last names | |
| name_parts = request.merchant_name.split() | |
| first_name = name_parts[0] if name_parts else "Merchant" | |
| last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else "User" | |
| # Create user request | |
| create_request = CreateUserRequest( | |
| username=username, | |
| email=request.email, | |
| merchant_id=request.merchant_id, | |
| merchant_type=request.merchant_type, | |
| password=password, | |
| first_name=first_name, | |
| last_name=last_name, | |
| phone=request.phone, | |
| role=request.role_id, | |
| metadata=metadata | |
| ) | |
| # Create user | |
| try: | |
| created_user = await user_service.create_user(create_request, "system_internal") | |
| except HTTPException as http_exc: | |
| # Re-raise HTTPException with more context | |
| logger.error(f"Failed to create user from merchant {request.merchant_id}: {http_exc.detail}") | |
| raise | |
| except Exception as create_error: | |
| logger.error(f"Unexpected error creating user from merchant {request.merchant_id}: {create_error}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to create user from merchant" | |
| ) | |
| logger.info( | |
| f"Created system user from merchant", | |
| extra={ | |
| "merchant_id": request.merchant_id, | |
| "merchant_type": request.merchant_type, | |
| "user_id": created_user.user_id, | |
| "username": username | |
| } | |
| ) | |
| return user_service.convert_to_user_info_response(created_user) | |
| except HTTPException: | |
| raise | |
| except ValueError as e: | |
| logger.error(f"Validation error creating user from merchant {request.merchant_id}: {e}") | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail=str(e) | |
| ) | |
| except Exception as e: | |
| logger.error(f"Unexpected error creating user from merchant: {str(e)}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="An unexpected error occurred while creating user from merchant" | |
| ) |