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>
This commit is contained in:
@@ -2,23 +2,20 @@
|
||||
"""
|
||||
Customers module exceptions.
|
||||
|
||||
Re-exports customer-related exceptions from their source locations.
|
||||
This module provides exception classes for customer operations including:
|
||||
- Customer management (create, update, authentication)
|
||||
- Address management
|
||||
- Password reset
|
||||
"""
|
||||
|
||||
from app.exceptions.customer import (
|
||||
CustomerNotFoundException,
|
||||
CustomerAlreadyExistsException,
|
||||
DuplicateCustomerEmailException,
|
||||
CustomerNotActiveException,
|
||||
InvalidCustomerCredentialsException,
|
||||
CustomerValidationException,
|
||||
CustomerAuthorizationException,
|
||||
)
|
||||
from typing import Any
|
||||
|
||||
from app.exceptions.address import (
|
||||
AddressNotFoundException,
|
||||
AddressLimitExceededException,
|
||||
InvalidAddressTypeException,
|
||||
from app.exceptions.base import (
|
||||
AuthenticationException,
|
||||
BusinessLogicException,
|
||||
ConflictException,
|
||||
ResourceNotFoundException,
|
||||
ValidationException,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
@@ -30,8 +27,155 @@ __all__ = [
|
||||
"InvalidCustomerCredentialsException",
|
||||
"CustomerValidationException",
|
||||
"CustomerAuthorizationException",
|
||||
"InvalidPasswordResetTokenException",
|
||||
"PasswordTooShortException",
|
||||
# Address exceptions
|
||||
"AddressNotFoundException",
|
||||
"AddressLimitExceededException",
|
||||
"InvalidAddressTypeException",
|
||||
]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Customer Exceptions
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class CustomerNotFoundException(ResourceNotFoundException):
|
||||
"""Raised when a customer is not found."""
|
||||
|
||||
def __init__(self, customer_identifier: str):
|
||||
super().__init__(
|
||||
resource_type="Customer",
|
||||
identifier=customer_identifier,
|
||||
message=f"Customer '{customer_identifier}' not found",
|
||||
error_code="CUSTOMER_NOT_FOUND",
|
||||
)
|
||||
|
||||
|
||||
class CustomerAlreadyExistsException(ConflictException):
|
||||
"""Raised when trying to create a customer that already exists."""
|
||||
|
||||
def __init__(self, email: str):
|
||||
super().__init__(
|
||||
message=f"Customer with email '{email}' already exists",
|
||||
error_code="CUSTOMER_ALREADY_EXISTS",
|
||||
details={"email": email},
|
||||
)
|
||||
|
||||
|
||||
class DuplicateCustomerEmailException(ConflictException):
|
||||
"""Raised when email already exists for vendor."""
|
||||
|
||||
def __init__(self, email: str, vendor_code: str):
|
||||
super().__init__(
|
||||
message=f"Email '{email}' is already registered for this vendor",
|
||||
error_code="DUPLICATE_CUSTOMER_EMAIL",
|
||||
details={"email": email, "vendor_code": vendor_code},
|
||||
)
|
||||
|
||||
|
||||
class CustomerNotActiveException(BusinessLogicException):
|
||||
"""Raised when trying to perform operations on inactive customer."""
|
||||
|
||||
def __init__(self, email: str):
|
||||
super().__init__(
|
||||
message=f"Customer account '{email}' is not active",
|
||||
error_code="CUSTOMER_NOT_ACTIVE",
|
||||
details={"email": email},
|
||||
)
|
||||
|
||||
|
||||
class InvalidCustomerCredentialsException(AuthenticationException):
|
||||
"""Raised when customer credentials are invalid."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
message="Invalid email or password",
|
||||
error_code="INVALID_CUSTOMER_CREDENTIALS",
|
||||
)
|
||||
|
||||
|
||||
class CustomerValidationException(ValidationException):
|
||||
"""Raised when customer data validation fails."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message: str = "Customer validation failed",
|
||||
field: str | None = None,
|
||||
details: dict[str, Any] | None = None,
|
||||
):
|
||||
super().__init__(message=message, field=field, details=details)
|
||||
self.error_code = "CUSTOMER_VALIDATION_FAILED"
|
||||
|
||||
|
||||
class CustomerAuthorizationException(BusinessLogicException):
|
||||
"""Raised when customer is not authorized for operation."""
|
||||
|
||||
def __init__(self, customer_email: str, operation: str):
|
||||
super().__init__(
|
||||
message=f"Customer '{customer_email}' not authorized for: {operation}",
|
||||
error_code="CUSTOMER_NOT_AUTHORIZED",
|
||||
details={"customer_email": customer_email, "operation": operation},
|
||||
)
|
||||
|
||||
|
||||
class InvalidPasswordResetTokenException(ValidationException):
|
||||
"""Raised when password reset token is invalid or expired."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
message="Invalid or expired password reset link. Please request a new one.",
|
||||
field="reset_token",
|
||||
)
|
||||
self.error_code = "INVALID_RESET_TOKEN"
|
||||
|
||||
|
||||
class PasswordTooShortException(ValidationException):
|
||||
"""Raised when password doesn't meet minimum length requirement."""
|
||||
|
||||
def __init__(self, min_length: int = 8):
|
||||
super().__init__(
|
||||
message=f"Password must be at least {min_length} characters long",
|
||||
field="password",
|
||||
details={"min_length": min_length},
|
||||
)
|
||||
self.error_code = "PASSWORD_TOO_SHORT"
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Address Exceptions
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class AddressNotFoundException(ResourceNotFoundException):
|
||||
"""Raised when a customer address is not found."""
|
||||
|
||||
def __init__(self, address_id: str | int):
|
||||
super().__init__(
|
||||
resource_type="Address",
|
||||
identifier=str(address_id),
|
||||
error_code="ADDRESS_NOT_FOUND",
|
||||
)
|
||||
|
||||
|
||||
class AddressLimitExceededException(BusinessLogicException):
|
||||
"""Raised when customer exceeds maximum number of addresses."""
|
||||
|
||||
def __init__(self, max_addresses: int = 10):
|
||||
super().__init__(
|
||||
message=f"Maximum number of addresses ({max_addresses}) reached",
|
||||
error_code="ADDRESS_LIMIT_EXCEEDED",
|
||||
details={"max_addresses": max_addresses},
|
||||
)
|
||||
|
||||
|
||||
class InvalidAddressTypeException(BusinessLogicException):
|
||||
"""Raised when an invalid address type is provided."""
|
||||
|
||||
def __init__(self, address_type: str):
|
||||
super().__init__(
|
||||
message=f"Invalid address type '{address_type}'. Must be 'shipping' or 'billing'",
|
||||
error_code="INVALID_ADDRESS_TYPE",
|
||||
details={"address_type": address_type},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user