Files
orion/app/modules/orders/exceptions.py
Samir Boulahtit 4e28d91a78 refactor: migrate templates and static files to self-contained modules
Templates Migration:
- Migrate admin templates to modules (tenancy, billing, monitoring, marketplace, etc.)
- Migrate vendor templates to modules (tenancy, billing, orders, messaging, etc.)
- Migrate storefront templates to modules (catalog, customers, orders, cart, checkout, cms)
- Migrate public templates to modules (billing, marketplace, cms)
- Keep shared templates in app/templates/ (base.html, errors/, partials/, macros/)
- Migrate letzshop partials to marketplace module

Static Files Migration:
- Migrate admin JS to modules: tenancy (23 files), core (5 files), monitoring (1 file)
- Migrate vendor JS to modules: tenancy (4 files), core (2 files)
- Migrate shared JS: vendor-selector.js to core, media-picker.js to cms
- Migrate storefront JS: storefront-layout.js to core
- Keep framework JS in static/ (api-client, utils, money, icons, log-config, lib/)
- Update all template references to use module_static paths

Naming Consistency:
- Rename static/platform/ to static/public/
- Rename app/templates/platform/ to app/templates/public/
- Update all extends and static references

Documentation:
- Update module-system.md with shared templates documentation
- Update frontend-structure.md with new module JS organization

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 14:34:16 +01:00

264 lines
8.6 KiB
Python

# app/modules/orders/exceptions.py
"""
Orders module exceptions.
This module provides exception classes for order operations including:
- Order management (not found, validation, status)
- Order item exceptions (unresolved, resolution)
- Invoice operations (PDF generation, status transitions)
"""
from typing import Any
from app.exceptions.base import (
BusinessLogicException,
ResourceNotFoundException,
ValidationException,
WizamartException,
)
__all__ = [
# Order exceptions
"OrderNotFoundException",
"OrderAlreadyExistsException",
"OrderValidationException",
"InvalidOrderStatusException",
"OrderCannotBeCancelledException",
# Order item exception exceptions
"OrderItemExceptionNotFoundException",
"OrderHasUnresolvedExceptionsException",
"ExceptionAlreadyResolvedException",
"InvalidProductForExceptionException",
# Invoice exceptions
"InvoiceNotFoundException",
"InvoiceSettingsNotFoundException",
"InvoiceSettingsAlreadyExistException",
"InvoiceValidationException",
"InvoicePDFGenerationException",
"InvoicePDFNotFoundException",
"InvalidInvoiceStatusTransitionException",
"OrderNotFoundForInvoiceException",
]
# =============================================================================
# Order Exceptions
# =============================================================================
class OrderNotFoundException(ResourceNotFoundException):
"""Raised when an order is not found."""
def __init__(self, order_identifier: str):
super().__init__(
resource_type="Order",
identifier=order_identifier,
message=f"Order '{order_identifier}' not found",
error_code="ORDER_NOT_FOUND",
)
class OrderAlreadyExistsException(ValidationException):
"""Raised when trying to create a duplicate order."""
def __init__(self, order_number: str):
super().__init__(
message=f"Order with number '{order_number}' already exists",
details={"order_number": order_number},
)
self.error_code = "ORDER_ALREADY_EXISTS"
class OrderValidationException(ValidationException):
"""Raised when order data validation fails."""
def __init__(self, message: str, details: dict | None = None):
super().__init__(message=message, details=details)
self.error_code = "ORDER_VALIDATION_FAILED"
class InvalidOrderStatusException(BusinessLogicException):
"""Raised when trying to set an invalid order status."""
def __init__(self, current_status: str, new_status: str):
super().__init__(
message=f"Cannot change order status from '{current_status}' to '{new_status}'",
error_code="INVALID_ORDER_STATUS_CHANGE",
details={"current_status": current_status, "new_status": new_status},
)
class OrderCannotBeCancelledException(BusinessLogicException):
"""Raised when order cannot be cancelled."""
def __init__(self, order_number: str, reason: str):
super().__init__(
message=f"Order '{order_number}' cannot be cancelled: {reason}",
error_code="ORDER_CANNOT_BE_CANCELLED",
details={"order_number": order_number, "reason": reason},
)
# =============================================================================
# Order Item Exception Exceptions
# =============================================================================
class OrderItemExceptionNotFoundException(ResourceNotFoundException):
"""Raised when an order item exception is not found."""
def __init__(self, exception_id: int | str):
super().__init__(
resource_type="OrderItemException",
identifier=str(exception_id),
error_code="ORDER_ITEM_EXCEPTION_NOT_FOUND",
)
class OrderHasUnresolvedExceptionsException(BusinessLogicException):
"""Raised when trying to confirm an order with unresolved exceptions."""
def __init__(self, order_id: int, unresolved_count: int):
super().__init__(
message=(
f"Order has {unresolved_count} unresolved product exception(s). "
f"Please resolve all exceptions before confirming the order."
),
error_code="ORDER_HAS_UNRESOLVED_EXCEPTIONS",
details={
"order_id": order_id,
"unresolved_count": unresolved_count,
},
)
class ExceptionAlreadyResolvedException(BusinessLogicException):
"""Raised when trying to resolve an already resolved exception."""
def __init__(self, exception_id: int):
super().__init__(
message=f"Exception {exception_id} has already been resolved",
error_code="EXCEPTION_ALREADY_RESOLVED",
details={"exception_id": exception_id},
)
class InvalidProductForExceptionException(BusinessLogicException):
"""Raised when the product provided for resolution is invalid."""
def __init__(self, product_id: int, reason: str):
super().__init__(
message=f"Cannot use product {product_id} for resolution: {reason}",
error_code="INVALID_PRODUCT_FOR_EXCEPTION",
details={"product_id": product_id, "reason": reason},
)
# =============================================================================
# Invoice Exceptions
# =============================================================================
class InvoiceNotFoundException(ResourceNotFoundException):
"""Raised when an invoice is not found."""
def __init__(self, invoice_id: int | str):
super().__init__(
resource_type="Invoice",
identifier=str(invoice_id),
error_code="INVOICE_NOT_FOUND",
)
class InvoiceSettingsNotFoundException(ResourceNotFoundException):
"""Raised when invoice settings are not found for a vendor."""
def __init__(self, vendor_id: int):
super().__init__(
resource_type="InvoiceSettings",
identifier=str(vendor_id),
message="Invoice settings not found. Create settings first.",
error_code="INVOICE_SETTINGS_NOT_FOUND",
)
class InvoiceSettingsAlreadyExistException(WizamartException):
"""Raised when trying to create invoice settings that already exist."""
def __init__(self, vendor_id: int):
super().__init__(
message=f"Invoice settings already exist for vendor {vendor_id}",
error_code="INVOICE_SETTINGS_ALREADY_EXIST",
status_code=409,
details={"vendor_id": vendor_id},
)
class InvoiceValidationException(BusinessLogicException):
"""Raised when invoice data validation fails."""
def __init__(self, message: str, details: dict[str, Any] | None = None):
super().__init__(
message=message,
error_code="INVOICE_VALIDATION_ERROR",
details=details,
)
class InvoicePDFGenerationException(WizamartException):
"""Raised when PDF generation fails."""
def __init__(self, invoice_id: int, reason: str):
super().__init__(
message=f"Failed to generate PDF for invoice {invoice_id}: {reason}",
error_code="INVOICE_PDF_GENERATION_FAILED",
status_code=500,
details={"invoice_id": invoice_id, "reason": reason},
)
class InvoicePDFNotFoundException(ResourceNotFoundException):
"""Raised when invoice PDF file is not found."""
def __init__(self, invoice_id: int):
super().__init__(
resource_type="InvoicePDF",
identifier=str(invoice_id),
message="PDF file not found. Generate the PDF first.",
error_code="INVOICE_PDF_NOT_FOUND",
)
class InvalidInvoiceStatusTransitionException(BusinessLogicException):
"""Raised when an invalid invoice status transition is attempted."""
def __init__(
self,
current_status: str,
new_status: str,
reason: str | None = None,
):
message = f"Cannot change invoice status from '{current_status}' to '{new_status}'"
if reason:
message += f": {reason}"
super().__init__(
message=message,
error_code="INVALID_INVOICE_STATUS_TRANSITION",
details={
"current_status": current_status,
"new_status": new_status,
},
)
class OrderNotFoundForInvoiceException(ResourceNotFoundException):
"""Raised when an order for invoice creation is not found."""
def __init__(self, order_id: int):
super().__init__(
resource_type="Order",
identifier=str(order_id),
error_code="ORDER_NOT_FOUND_FOR_INVOICE",
)