# app/exceptions/admin.py """ Admin operations specific exceptions. """ from typing import Any from .base import ( AuthorizationException, BusinessLogicException, ResourceNotFoundException, ValidationException, ) class UserNotFoundException(ResourceNotFoundException): """Raised when user is not found in admin operations.""" def __init__(self, user_identifier: str, identifier_type: str = "ID"): if identifier_type.lower() == "username": message = f"User with username '{user_identifier}' not found" elif identifier_type.lower() == "email": message = f"User with email '{user_identifier}' not found" else: message = f"User with ID '{user_identifier}' not found" super().__init__( resource_type="User", identifier=user_identifier, message=message, error_code="USER_NOT_FOUND", ) class UserStatusChangeException(BusinessLogicException): """Raised when user status cannot be changed.""" def __init__( self, user_id: int, current_status: str, attempted_action: str, reason: str | None = None, ): message = f"Cannot {attempted_action} user {user_id} (current status: {current_status})" if reason: message += f": {reason}" super().__init__( message=message, error_code="USER_STATUS_CHANGE_FAILED", details={ "user_id": user_id, "current_status": current_status, "attempted_action": attempted_action, "reason": reason, }, ) class AdminOperationException(BusinessLogicException): """Raised when admin operation fails.""" def __init__( self, operation: str, reason: str, target_type: str | None = None, target_id: str | None = None, ): message = f"Admin operation '{operation}' failed: {reason}" details = { "operation": operation, "reason": reason, } if target_type: details["target_type"] = target_type if target_id: details["target_id"] = target_id super().__init__( message=message, error_code="ADMIN_OPERATION_FAILED", details=details, ) class CannotModifyAdminException(AuthorizationException): """Raised when trying to modify another admin user.""" def __init__(self, target_user_id: int, admin_user_id: int): super().__init__( message=f"Cannot modify admin user {target_user_id}", error_code="CANNOT_MODIFY_ADMIN", details={ "target_user_id": target_user_id, "admin_user_id": admin_user_id, }, ) class CannotModifySelfException(BusinessLogicException): """Raised when admin tries to modify their own status.""" def __init__(self, user_id: int, operation: str): super().__init__( message=f"Cannot perform '{operation}' on your own account", error_code="CANNOT_MODIFY_SELF", details={ "user_id": user_id, "operation": operation, }, ) class InvalidAdminActionException(ValidationException): """Raised when admin action is invalid.""" def __init__( self, action: str, reason: str, valid_actions: list | None = None, ): details = { "action": action, "reason": reason, } if valid_actions: details["valid_actions"] = valid_actions super().__init__( message=f"Invalid admin action '{action}': {reason}", details=details, ) self.error_code = "INVALID_ADMIN_ACTION" class BulkOperationException(BusinessLogicException): """Raised when bulk admin operation fails.""" def __init__( self, operation: str, total_items: int, failed_items: int, errors: dict[str, Any] | None = None, ): message = f"Bulk {operation} completed with errors: {failed_items}/{total_items} failed" details = { "operation": operation, "total_items": total_items, "failed_items": failed_items, "success_items": total_items - failed_items, } if errors: details["errors"] = errors super().__init__( message=message, error_code="BULK_OPERATION_PARTIAL_FAILURE", details=details, ) class ConfirmationRequiredException(BusinessLogicException): """Raised when a destructive operation requires explicit confirmation.""" def __init__( self, operation: str, message: str | None = None, confirmation_param: str = "confirm", ): if not message: message = f"Operation '{operation}' requires confirmation parameter: {confirmation_param}=true" super().__init__( message=message, error_code="CONFIRMATION_REQUIRED", details={ "operation": operation, "confirmation_param": confirmation_param, }, ) class VendorVerificationException(BusinessLogicException): """Raised when vendor verification fails.""" def __init__( self, vendor_id: int, reason: str, current_verification_status: bool | None = None, ): details = { "vendor_id": vendor_id, "reason": reason, } if current_verification_status is not None: details["current_verification_status"] = current_verification_status super().__init__( message=f"Vendor verification failed for vendor {vendor_id}: {reason}", error_code="VENDOR_VERIFICATION_FAILED", details=details, ) class UserCannotBeDeletedException(BusinessLogicException): """Raised when a user cannot be deleted due to ownership constraints.""" def __init__(self, user_id: int, reason: str, owned_count: int = 0): details = { "user_id": user_id, "reason": reason, } if owned_count > 0: details["owned_companies_count"] = owned_count super().__init__( message=f"Cannot delete user {user_id}: {reason}", error_code="USER_CANNOT_BE_DELETED", details=details, ) class UserRoleChangeException(BusinessLogicException): """Raised when user role cannot be changed.""" def __init__(self, user_id: int, current_role: str, target_role: str, reason: str): super().__init__( message=f"Cannot change user {user_id} role from {current_role} to {target_role}: {reason}", error_code="USER_ROLE_CHANGE_FAILED", details={ "user_id": user_id, "current_role": current_role, "target_role": target_role, "reason": reason, }, )