# app/exceptions/marketplace_import_job.py """ Marketplace import specific exceptions. """ from typing import Any from .base import ( AuthorizationException, BusinessLogicException, ExternalServiceException, ResourceNotFoundException, ValidationException, ) class MarketplaceImportException(BusinessLogicException): """Base exception for marketplace import operations.""" def __init__( self, message: str, error_code: str = "MARKETPLACE_IMPORT_ERROR", marketplace: str | None = None, details: dict[str, Any] | None = None, ): if not details: details = {} if marketplace: details["marketplace"] = marketplace super().__init__( message=message, error_code=error_code, details=details, ) class ImportJobNotFoundException(ResourceNotFoundException): """Raised when import job is not found.""" def __init__(self, job_id: int): super().__init__( resource_type="ImportJob", identifier=str(job_id), message=f"Import job with ID '{job_id}' not found", error_code="IMPORT_JOB_NOT_FOUND", ) class ImportJobNotOwnedException(AuthorizationException): """Raised when user tries to access import job they don't own.""" def __init__(self, job_id: int, user_id: int | None = None): details = {"job_id": job_id} if user_id: details["user_id"] = user_id super().__init__( message=f"Unauthorized access to import job '{job_id}'", error_code="IMPORT_JOB_NOT_OWNED", details=details, ) class InvalidImportDataException(ValidationException): """Raised when import data is invalid.""" def __init__( self, message: str = "Invalid import data", field: str | None = None, row_number: int | None = None, details: dict[str, Any] | None = None, ): if not details: details = {} if row_number: details["row_number"] = row_number super().__init__( message=message, field=field, details=details, ) self.error_code = "INVALID_IMPORT_DATA" class ImportJobCannotBeCancelledException(BusinessLogicException): """Raised when trying to cancel job that cannot be cancelled.""" def __init__(self, job_id: int, current_status: str): super().__init__( message=f"Import job '{job_id}' cannot be cancelled (current status: {current_status})", error_code="IMPORT_JOB_CANNOT_BE_CANCELLED", details={ "job_id": job_id, "current_status": current_status, }, ) class ImportJobCannotBeDeletedException(BusinessLogicException): """Raised when trying to delete job that cannot be deleted.""" def __init__(self, job_id: int, current_status: str): super().__init__( message=f"Import job '{job_id}' cannot be deleted (current status: {current_status})", error_code="IMPORT_JOB_CANNOT_BE_DELETED", details={ "job_id": job_id, "current_status": current_status, }, ) class MarketplaceConnectionException(ExternalServiceException): """Raised when marketplace connection fails.""" def __init__( self, marketplace: str, message: str = "Failed to connect to marketplace" ): super().__init__( service=marketplace, message=f"{message}: {marketplace}", error_code="MARKETPLACE_CONNECTION_FAILED", ) class MarketplaceDataParsingException(ValidationException): """Raised when marketplace data cannot be parsed.""" def __init__( self, marketplace: str, message: str = "Failed to parse marketplace data", details: dict[str, Any] | None = None, ): if not details: details = {} details["marketplace"] = marketplace super().__init__( message=f"{message} from {marketplace}", details=details, ) self.error_code = "MARKETPLACE_DATA_PARSING_FAILED" class ImportRateLimitException(BusinessLogicException): """Raised when import rate limit is exceeded.""" def __init__( self, max_imports: int, time_window: str, retry_after: int | None = None, ): details = { "max_imports": max_imports, "time_window": time_window, } if retry_after: details["retry_after"] = retry_after super().__init__( message=f"Import rate limit exceeded: {max_imports} imports per {time_window}", error_code="IMPORT_RATE_LIMIT_EXCEEDED", details=details, ) class InvalidMarketplaceException(ValidationException): """Raised when marketplace is not supported.""" def __init__(self, marketplace: str, supported_marketplaces: list | None = None): details = {"marketplace": marketplace} if supported_marketplaces: details["supported_marketplaces"] = supported_marketplaces super().__init__( message=f"Unsupported marketplace: {marketplace}", field="marketplace", details=details, ) self.error_code = "INVALID_MARKETPLACE" class ImportJobAlreadyProcessingException(BusinessLogicException): """Raised when trying to start import while another is already processing.""" def __init__(self, vendor_code: str, existing_job_id: int): super().__init__( message=f"Import already in progress for vendor '{vendor_code}'", error_code="IMPORT_JOB_ALREADY_PROCESSING", details={ "vendor_code": vendor_code, "existing_job_id": existing_job_id, }, )