Files
orion/app/exceptions/inventory.py
Samir Boulahtit 238c1ec9b8 refactor: modernize code quality tooling with Ruff
- Replace black, isort, and flake8 with Ruff (all-in-one linter and formatter)
- Add comprehensive pyproject.toml configuration
- Simplify Makefile code quality targets
- Configure exclusions for venv/.venv in pyproject.toml
- Auto-fix 1,359 linting issues across codebase

Benefits:
- Much faster builds (Ruff is written in Rust)
- Single tool replaces multiple tools
- More comprehensive rule set (UP, B, C4, SIM, PIE, RET, Q)
- All configuration centralized in pyproject.toml
- Better import sorting and formatting consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:37:38 +01:00

136 lines
3.9 KiB
Python

# app/exceptions/inventory.py
"""
Inventory management specific exceptions.
"""
from typing import Any
from .base import BusinessLogicException, ResourceNotFoundException, ValidationException
class InventoryNotFoundException(ResourceNotFoundException):
"""Raised when inventory record is not found."""
def __init__(self, identifier: str, identifier_type: str = "ID"):
if identifier_type.lower() == "gtin":
message = f"No inventory found for GTIN '{identifier}'"
else:
message = (
f"Inventory record with {identifier_type} '{identifier}' not found"
)
super().__init__(
resource_type="Inventory",
identifier=identifier,
message=message,
error_code="INVENTORY_NOT_FOUND",
)
class InsufficientInventoryException(BusinessLogicException):
"""Raised when trying to remove more inventory than available."""
def __init__(
self,
gtin: str,
location: str,
requested: int,
available: int,
):
message = f"Insufficient inventory for GTIN '{gtin}' at '{location}'. Requested: {requested}, Available: {available}"
super().__init__(
message=message,
error_code="INSUFFICIENT_INVENTORY",
details={
"gtin": gtin,
"location": location,
"requested_quantity": requested,
"available_quantity": available,
},
)
class InvalidInventoryOperationException(ValidationException):
"""Raised when inventory operation is invalid."""
def __init__(
self,
message: str,
operation: str | None = None,
details: dict[str, Any] | None = None,
):
if not details:
details = {}
if operation:
details["operation"] = operation
super().__init__(
message=message,
details=details,
)
self.error_code = "INVALID_INVENTORY_OPERATION"
class InventoryValidationException(ValidationException):
"""Raised when inventory data validation fails."""
def __init__(
self,
message: str = "Inventory validation failed",
field: str | None = None,
validation_errors: dict[str, str] | None = None,
):
details = {}
if validation_errors:
details["validation_errors"] = validation_errors
super().__init__(
message=message,
field=field,
details=details,
)
self.error_code = "INVENTORY_VALIDATION_FAILED"
class NegativeInventoryException(BusinessLogicException):
"""Raised when inventory quantity would become negative."""
def __init__(self, gtin: str, location: str, resulting_quantity: int):
message = f"Inventory operation would result in negative quantity ({resulting_quantity}) for GTIN '{gtin}' at '{location}'"
super().__init__(
message=message,
error_code="NEGATIVE_INVENTORY_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 inventory location is not found."""
def __init__(self, location: str):
super().__init__(
resource_type="Location",
identifier=location,
message=f"Inventory location '{location}' not found",
error_code="LOCATION_NOT_FOUND",
)