# app/exceptions/stock.py """ Stock management specific exceptions. """ from typing import Any, Dict, Optional from .base import ResourceNotFoundException, ValidationException, BusinessLogicException class StockNotFoundException(ResourceNotFoundException): """Raised when stock record is not found.""" def __init__(self, identifier: str, identifier_type: str = "ID"): if identifier_type.lower() == "gtin": message = f"No stock found for GTIN '{identifier}'" else: message = f"Stock record with {identifier_type} '{identifier}' not found" super().__init__( resource_type="Stock", identifier=identifier, message=message, error_code="STOCK_NOT_FOUND", ) class InsufficientStockException(BusinessLogicException): """Raised when trying to remove more stock than available.""" def __init__( self, gtin: str, location: str, requested: int, available: int, ): message = f"Insufficient stock for GTIN '{gtin}' at '{location}'. Requested: {requested}, Available: {available}" super().__init__( message=message, error_code="INSUFFICIENT_STOCK", details={ "gtin": gtin, "location": location, "requested_quantity": requested, "available_quantity": available, }, ) class InvalidStockOperationException(ValidationException): """Raised when stock operation is invalid.""" def __init__( self, message: str, operation: Optional[str] = None, details: Optional[Dict[str, Any]] = None, ): if not details: details = {} if operation: details["operation"] = operation super().__init__( message=message, details=details, ) self.error_code = "INVALID_STOCK_OPERATION" class StockValidationException(ValidationException): """Raised when stock data validation fails.""" def __init__( self, message: str = "Stock validation failed", field: Optional[str] = None, validation_errors: Optional[Dict[str, str]] = None, ): details = {} if validation_errors: details["validation_errors"] = validation_errors super().__init__( message=message, field=field, details=details, ) self.error_code = "STOCK_VALIDATION_FAILED" class NegativeStockException(BusinessLogicException): """Raised when stock quantity would become negative.""" def __init__(self, gtin: str, location: str, resulting_quantity: int): message = f"Stock operation would result in negative quantity ({resulting_quantity}) for GTIN '{gtin}' at '{location}'" super().__init__( message=message, error_code="NEGATIVE_STOCK_NOT_ALLOWED", details={ "gtin": gtin, "location": location, "resulting_quantity": resulting_quantity, }, ) class InvalidQuantityException(ValidationException): """Raised when quantity value is invalid.""" def __init__(self, quantity: Any, message: str = "Invalid quantity"): super().__init__( message=f"{message}: {quantity}", field="quantity", details={"quantity": quantity}, ) self.error_code = "INVALID_QUANTITY" class LocationNotFoundException(ResourceNotFoundException): """Raised when stock location is not found.""" def __init__(self, location: str): super().__init__( resource_type="Location", identifier=location, message=f"Stock location '{location}' not found", error_code="LOCATION_NOT_FOUND", )