Implemented a complete shopping cart system with database persistence, replacing the previous stub implementation. The cart now properly stores items across sessions and follows the project's architecture patterns. Database Changes: - Add cart_items table with vendor_id, session_id, product_id, quantity, price_at_add - Create unique constraint to prevent duplicate items per session - Add indexes for session lookups and old cart cleanup - Run migration a2064e1dfcd4 to create cart_items table New Models & Schemas: - models/database/cart.py: CartItem SQLAlchemy model with relationships - models/schema/cart.py: Pydantic schemas for requests/responses * AddToCartRequest, UpdateCartItemRequest * CartResponse, CartItemResponse, CartOperationResponse, ClearCartResponse Exception Handling: - app/exceptions/cart.py: Cart-specific exceptions following project patterns * CartItemNotFoundException - item not found in cart * InsufficientInventoryForCartException - not enough inventory for cart operation * InvalidCartQuantityException - invalid quantity validation * CartValidationException - general cart validation * EmptyCartException - operations on empty cart * ProductNotAvailableForCartException - product unavailable - Updated app/exceptions/__init__.py to export cart exceptions Service Layer: - Implement cart_service.get_cart() - fetch cart from database with totals - Implement cart_service.add_to_cart() - create or update cart items with inventory checks - Implement cart_service.update_cart_item() - update quantity with validation - Implement cart_service.remove_from_cart() - delete cart item - Implement cart_service.clear_cart() - remove all items for session - Replace generic exceptions with cart-specific ones - Fix InsufficientInventoryException usage (was using wrong parameters) API Layer: - Update app/api/v1/shop/cart.py to use Pydantic schemas - Add response_model declarations to all endpoints - Add return type hints for type safety - Convert service dict responses to Pydantic models Features: - Cart items persist in database across server restarts - Inventory validation before adding/updating items - Price captured at time of adding to cart - Duplicate items update quantity instead of creating new entries - Full CRUD operations with proper error handling - Type-safe API with auto-generated OpenAPI documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
330 lines
9.2 KiB
Python
330 lines
9.2 KiB
Python
# app/exceptions/__init__.py
|
|
"""
|
|
Custom exception classes for the API.
|
|
|
|
This module provides frontend-friendly exceptions with consistent error codes,
|
|
messages, and HTTP status mappings.
|
|
"""
|
|
|
|
# Base exceptions
|
|
from .base import (
|
|
WizamartException,
|
|
ValidationException,
|
|
AuthenticationException,
|
|
AuthorizationException,
|
|
ResourceNotFoundException,
|
|
ConflictException,
|
|
BusinessLogicException,
|
|
ExternalServiceException,
|
|
RateLimitException,
|
|
ServiceUnavailableException,
|
|
)
|
|
|
|
# Authentication exceptions
|
|
from .auth import (
|
|
InvalidCredentialsException,
|
|
TokenExpiredException,
|
|
InvalidTokenException,
|
|
InsufficientPermissionsException,
|
|
UserNotActiveException,
|
|
AdminRequiredException,
|
|
UserAlreadyExistsException
|
|
)
|
|
|
|
# Admin exceptions
|
|
from .admin import (
|
|
UserNotFoundException,
|
|
UserStatusChangeException,
|
|
VendorVerificationException,
|
|
AdminOperationException,
|
|
CannotModifyAdminException,
|
|
CannotModifySelfException,
|
|
InvalidAdminActionException,
|
|
BulkOperationException,
|
|
ConfirmationRequiredException,
|
|
)
|
|
|
|
# Marketplace import job exceptions
|
|
from .marketplace_import_job import (
|
|
MarketplaceImportException,
|
|
ImportJobNotFoundException,
|
|
ImportJobNotOwnedException,
|
|
InvalidImportDataException,
|
|
ImportJobCannotBeCancelledException,
|
|
ImportJobCannotBeDeletedException,
|
|
MarketplaceConnectionException,
|
|
MarketplaceDataParsingException,
|
|
ImportRateLimitException,
|
|
InvalidMarketplaceException,
|
|
ImportJobAlreadyProcessingException,
|
|
)
|
|
|
|
# Marketplace product exceptions
|
|
from .marketplace_product import (
|
|
MarketplaceProductNotFoundException,
|
|
MarketplaceProductAlreadyExistsException,
|
|
InvalidMarketplaceProductDataException,
|
|
MarketplaceProductValidationException,
|
|
InvalidGTINException,
|
|
MarketplaceProductCSVImportException,
|
|
)
|
|
|
|
# Inventory exceptions
|
|
from .inventory import (
|
|
InventoryNotFoundException,
|
|
InsufficientInventoryException,
|
|
InvalidInventoryOperationException,
|
|
InventoryValidationException,
|
|
NegativeInventoryException,
|
|
InvalidQuantityException,
|
|
LocationNotFoundException
|
|
)
|
|
|
|
# Vendor exceptions
|
|
from .vendor import (
|
|
VendorNotFoundException,
|
|
VendorAlreadyExistsException,
|
|
VendorNotActiveException,
|
|
VendorNotVerifiedException,
|
|
UnauthorizedVendorAccessException,
|
|
InvalidVendorDataException,
|
|
MaxVendorsReachedException,
|
|
VendorValidationException,
|
|
)
|
|
|
|
# Vendor domain exceptions
|
|
from .vendor_domain import (
|
|
VendorDomainNotFoundException,
|
|
VendorDomainAlreadyExistsException,
|
|
InvalidDomainFormatException,
|
|
ReservedDomainException,
|
|
DomainNotVerifiedException,
|
|
DomainVerificationFailedException,
|
|
DomainAlreadyVerifiedException,
|
|
MultiplePrimaryDomainsException,
|
|
DNSVerificationException,
|
|
MaxDomainsReachedException,
|
|
UnauthorizedDomainAccessException,
|
|
)
|
|
|
|
# Vendor theme exceptions
|
|
from .vendor_theme import (
|
|
VendorThemeNotFoundException,
|
|
InvalidThemeDataException,
|
|
ThemePresetNotFoundException,
|
|
ThemeValidationException,
|
|
ThemePresetAlreadyAppliedException,
|
|
InvalidColorFormatException,
|
|
InvalidFontFamilyException,
|
|
ThemeOperationException,
|
|
)
|
|
|
|
# Customer exceptions
|
|
from .customer import (
|
|
CustomerNotFoundException,
|
|
CustomerAlreadyExistsException,
|
|
DuplicateCustomerEmailException,
|
|
CustomerNotActiveException,
|
|
InvalidCustomerCredentialsException,
|
|
CustomerValidationException,
|
|
CustomerAuthorizationException,
|
|
)
|
|
|
|
# Team exceptions
|
|
from .team import (
|
|
TeamMemberNotFoundException,
|
|
TeamMemberAlreadyExistsException,
|
|
TeamInvitationNotFoundException,
|
|
TeamInvitationExpiredException,
|
|
TeamInvitationAlreadyAcceptedException,
|
|
UnauthorizedTeamActionException,
|
|
CannotRemoveOwnerException,
|
|
CannotModifyOwnRoleException,
|
|
RoleNotFoundException,
|
|
InvalidRoleException,
|
|
InsufficientTeamPermissionsException,
|
|
MaxTeamMembersReachedException,
|
|
TeamValidationException,
|
|
InvalidInvitationDataException,
|
|
InvalidInvitationTokenException,
|
|
)
|
|
|
|
# Product exceptions
|
|
from .product import (
|
|
ProductNotFoundException,
|
|
ProductAlreadyExistsException,
|
|
ProductNotInCatalogException,
|
|
ProductNotActiveException,
|
|
InvalidProductDataException,
|
|
ProductValidationException,
|
|
CannotDeleteProductWithInventoryException,
|
|
CannotDeleteProductWithOrdersException,
|
|
)
|
|
|
|
# Order exceptions
|
|
from .order import (
|
|
OrderNotFoundException,
|
|
OrderAlreadyExistsException,
|
|
OrderValidationException,
|
|
InvalidOrderStatusException,
|
|
OrderCannotBeCancelledException,
|
|
)
|
|
|
|
# Cart exceptions
|
|
from .cart import (
|
|
CartItemNotFoundException,
|
|
EmptyCartException,
|
|
CartValidationException,
|
|
InsufficientInventoryForCartException,
|
|
InvalidCartQuantityException,
|
|
ProductNotAvailableForCartException,
|
|
)
|
|
|
|
__all__ = [
|
|
# Base exceptions
|
|
"WizamartException",
|
|
"ValidationException",
|
|
"AuthenticationException",
|
|
"AuthorizationException",
|
|
"ResourceNotFoundException",
|
|
"ConflictException",
|
|
"BusinessLogicException",
|
|
"ExternalServiceException",
|
|
"RateLimitException",
|
|
"ServiceUnavailableException",
|
|
|
|
# Auth exceptions
|
|
"InvalidCredentialsException",
|
|
"TokenExpiredException",
|
|
"InvalidTokenException",
|
|
"InsufficientPermissionsException",
|
|
"UserNotActiveException",
|
|
"AdminRequiredException",
|
|
"UserAlreadyExistsException",
|
|
|
|
# Customer exceptions
|
|
"CustomerNotFoundException",
|
|
"CustomerAlreadyExistsException",
|
|
"DuplicateCustomerEmailException",
|
|
"CustomerNotActiveException",
|
|
"InvalidCustomerCredentialsException",
|
|
"CustomerValidationException",
|
|
"CustomerAuthorizationException",
|
|
|
|
# Team exceptions
|
|
"TeamMemberNotFoundException",
|
|
"TeamMemberAlreadyExistsException",
|
|
"TeamInvitationNotFoundException",
|
|
"TeamInvitationExpiredException",
|
|
"TeamInvitationAlreadyAcceptedException",
|
|
"UnauthorizedTeamActionException",
|
|
"CannotRemoveOwnerException",
|
|
"CannotModifyOwnRoleException",
|
|
"RoleNotFoundException",
|
|
"InvalidRoleException",
|
|
"InsufficientTeamPermissionsException",
|
|
"MaxTeamMembersReachedException",
|
|
"TeamValidationException",
|
|
"InvalidInvitationDataException",
|
|
"InvalidInvitationTokenException",
|
|
|
|
# Inventory exceptions
|
|
"InventoryNotFoundException",
|
|
"InsufficientInventoryException",
|
|
"InvalidInventoryOperationException",
|
|
"InventoryValidationException",
|
|
"NegativeInventoryException",
|
|
"InvalidQuantityException",
|
|
"LocationNotFoundException",
|
|
|
|
# Vendor exceptions
|
|
"VendorNotFoundException",
|
|
"VendorAlreadyExistsException",
|
|
"VendorNotActiveException",
|
|
"VendorNotVerifiedException",
|
|
"UnauthorizedVendorAccessException",
|
|
"InvalidVendorDataException",
|
|
"MaxVendorsReachedException",
|
|
"VendorValidationException",
|
|
|
|
# Vendor Domain
|
|
"VendorDomainNotFoundException",
|
|
"VendorDomainAlreadyExistsException",
|
|
"InvalidDomainFormatException",
|
|
"ReservedDomainException",
|
|
"DomainNotVerifiedException",
|
|
"DomainVerificationFailedException",
|
|
"DomainAlreadyVerifiedException",
|
|
"MultiplePrimaryDomainsException",
|
|
"DNSVerificationException",
|
|
"MaxDomainsReachedException",
|
|
"UnauthorizedDomainAccessException",
|
|
|
|
# Vendor Theme
|
|
"VendorThemeNotFoundException",
|
|
"InvalidThemeDataException",
|
|
"ThemePresetNotFoundException",
|
|
"ThemeValidationException",
|
|
"ThemePresetAlreadyAppliedException",
|
|
"InvalidColorFormatException",
|
|
"InvalidFontFamilyException",
|
|
"ThemeOperationException",
|
|
|
|
# Product exceptions
|
|
"ProductNotFoundException",
|
|
"ProductAlreadyExistsException",
|
|
"ProductNotInCatalogException",
|
|
"ProductNotActiveException",
|
|
"InvalidProductDataException",
|
|
"ProductValidationException",
|
|
"CannotDeleteProductWithInventoryException",
|
|
"CannotDeleteProductWithOrdersException",
|
|
|
|
# Order exceptions
|
|
"OrderNotFoundException",
|
|
"OrderAlreadyExistsException",
|
|
"OrderValidationException",
|
|
"InvalidOrderStatusException",
|
|
"OrderCannotBeCancelledException",
|
|
|
|
# Cart exceptions
|
|
"CartItemNotFoundException",
|
|
"EmptyCartException",
|
|
"CartValidationException",
|
|
"InsufficientInventoryForCartException",
|
|
"InvalidCartQuantityException",
|
|
"ProductNotAvailableForCartException",
|
|
|
|
# MarketplaceProduct exceptions
|
|
"MarketplaceProductNotFoundException",
|
|
"MarketplaceProductAlreadyExistsException",
|
|
"InvalidMarketplaceProductDataException",
|
|
"MarketplaceProductValidationException",
|
|
"InvalidGTINException",
|
|
"MarketplaceProductCSVImportException",
|
|
|
|
# Marketplace import exceptions
|
|
"MarketplaceImportException",
|
|
"ImportJobNotFoundException",
|
|
"ImportJobNotOwnedException",
|
|
"InvalidImportDataException",
|
|
"ImportJobCannotBeCancelledException",
|
|
"ImportJobCannotBeDeletedException",
|
|
"MarketplaceConnectionException",
|
|
"MarketplaceDataParsingException",
|
|
"ImportRateLimitException",
|
|
"InvalidMarketplaceException",
|
|
"ImportJobAlreadyProcessingException",
|
|
|
|
# Admin exceptions
|
|
"UserNotFoundException",
|
|
"UserStatusChangeException",
|
|
"VendorVerificationException",
|
|
"AdminOperationException",
|
|
"CannotModifyAdminException",
|
|
"CannotModifySelfException",
|
|
"InvalidAdminActionException",
|
|
"BulkOperationException",
|
|
"ConfirmationRequiredException",
|
|
]
|