Source code for examples.shopvertical.slices.submit_cart.cmd

from __future__ import annotations

from collections import defaultdict
from uuid import UUID  # noqa: TC003

from examples.shopvertical.common import Command, get_events, put_events
from examples.shopvertical.events import (
    AddedItemToCart,
    AdjustedProductInventory,
    ClearedCart,
    DomainEvents,
    RemovedItemFromCart,
    SubmittedCart,
)
from examples.shopvertical.exceptions import (
    CartAlreadySubmittedError,
    InsufficientInventoryError,
)


[docs] class SubmitCart(Command): cart_id: UUID
[docs] def handle(self, events: DomainEvents) -> DomainEvents: requested_products: dict[UUID, int] = defaultdict(int) is_submitted = False for event in events: if isinstance(event, AddedItemToCart): requested_products[event.product_id] += 1 elif isinstance(event, RemovedItemFromCart): requested_products[event.product_id] -= 1 elif isinstance(event, ClearedCart): requested_products.clear() elif isinstance(event, SubmittedCart): is_submitted = True if is_submitted: raise CartAlreadySubmittedError # Check inventory. for product_id, requested_amount in requested_products.items(): current_inventory = 0 for product_event in get_events(product_id): if isinstance(product_event, AdjustedProductInventory): current_inventory += product_event.adjustment if current_inventory < requested_amount: msg = f"Insufficient inventory for product with ID {product_id}" raise InsufficientInventoryError(msg) return ( SubmittedCart( originator_id=self.cart_id, originator_version=len(events) + 1, ), )
[docs] def execute(self) -> int | None: return put_events(self.handle(get_events(self.cart_id)))