# app/modules/checkout/exceptions.py """ Checkout module exceptions. Module-specific exceptions for the checkout process. """ from app.exceptions.base import ( BusinessLogicException, ResourceNotFoundException, ValidationException, ) class CheckoutValidationException(ValidationException): """Raised when checkout data validation fails.""" def __init__( self, message: str = "Checkout validation failed", field: str | None = None, details: dict | None = None, ): super().__init__( message=message, field=field, details=details, ) self.error_code = "CHECKOUT_VALIDATION_FAILED" class CheckoutSessionNotFoundException(ResourceNotFoundException): """Raised when checkout session is not found.""" def __init__(self, session_id: str): super().__init__( resource_type="CheckoutSession", identifier=session_id, message=f"Checkout session '{session_id}' not found", error_code="CHECKOUT_SESSION_NOT_FOUND", ) class CheckoutSessionExpiredException(BusinessLogicException): """Raised when checkout session has expired.""" def __init__(self, session_id: str): super().__init__( message="Checkout session has expired", error_code="CHECKOUT_SESSION_EXPIRED", details={"session_id": session_id}, ) class EmptyCheckoutException(ValidationException): """Raised when trying to checkout with empty cart.""" def __init__(self): super().__init__( message="Cannot checkout with an empty cart", details={}, ) self.error_code = "EMPTY_CHECKOUT" class PaymentRequiredException(BusinessLogicException): """Raised when payment is required but not provided.""" def __init__(self, order_total: float): super().__init__( message="Payment is required to complete this order", error_code="PAYMENT_REQUIRED", details={"order_total": order_total}, ) class PaymentFailedException(BusinessLogicException): """Raised when payment processing fails.""" def __init__(self, reason: str, details: dict | None = None): super().__init__( message=f"Payment failed: {reason}", error_code="PAYMENT_FAILED", details={"reason": reason, **(details or {})}, ) class InvalidShippingAddressException(ValidationException): """Raised when shipping address is invalid or missing.""" def __init__(self, message: str = "Invalid shipping address", details: dict | None = None): super().__init__( message=message, field="shipping_address", details=details, ) self.error_code = "INVALID_SHIPPING_ADDRESS" class ShippingMethodNotAvailableException(BusinessLogicException): """Raised when selected shipping method is not available.""" def __init__(self, shipping_method: str, reason: str | None = None): message = f"Shipping method '{shipping_method}' is not available" if reason: message += f": {reason}" super().__init__( message=message, error_code="SHIPPING_METHOD_NOT_AVAILABLE", details={"shipping_method": shipping_method, "reason": reason}, ) class CheckoutInventoryException(BusinessLogicException): """Raised when inventory check fails during checkout.""" def __init__(self, product_id: int, available: int, requested: int): super().__init__( message=f"Insufficient inventory for product {product_id}", error_code="CHECKOUT_INVENTORY_ERROR", details={ "product_id": product_id, "available_quantity": available, "requested_quantity": requested, }, ) __all__ = [ "CheckoutInventoryException", "CheckoutSessionExpiredException", "CheckoutSessionNotFoundException", "CheckoutValidationException", "EmptyCheckoutException", "InvalidShippingAddressException", "PaymentFailedException", "PaymentRequiredException", "ShippingMethodNotAvailableException", ]