from __future__ import annotations
from decimal import Decimal # noqa: TC003
from uuid import UUID # noqa: TC003
from eventsourcing.domain import event
from examples.aggregate7.immutablemodel import Immutable
from examples.aggregate8.mutablemodel import Aggregate
from examples.shopstandard.exceptions import (
CartAlreadySubmittedError,
CartFullError,
ProductNotInCartError,
)
[docs]
class ProductDetails(Immutable):
id: UUID
name: str
description: str
price: Decimal
inventory: int
[docs]
class Product(Aggregate):
[docs]
def __init__(self, id: UUID, name: str, description: str, price: Decimal):
self._id = id
self.name = name
self.description = description
self.price = price
self.inventory = 0
[docs]
class InventoryAdjusted(Aggregate.Event):
adjustment: int
[docs]
@event(InventoryAdjusted)
def adjust_inventory(self, adjustment: int) -> None:
self.inventory += adjustment
[docs]
class CartItem(Immutable):
product_id: UUID
name: str
description: str
price: Decimal
[docs]
class Cart(Aggregate):
[docs]
def __init__(self, id: UUID):
self._id = id
self.items: list[CartItem] = []
self.is_submitted = False
[docs]
class ItemAdded(Aggregate.Event):
product_id: UUID
name: str
description: str
price: Decimal
[docs]
class ItemRemoved(Aggregate.Event):
product_id: UUID
[docs]
class Cleared(Aggregate.Event):
pass
[docs]
class Submitted(Aggregate.Event):
pass
[docs]
@event(ItemAdded)
def add_item(
self, product_id: UUID, name: str, description: str, price: Decimal
) -> None:
if self.is_submitted:
raise CartAlreadySubmittedError
if len(self.items) >= 3:
raise CartFullError
self.items.append(
CartItem(
product_id=product_id,
name=name,
description=description,
price=price,
)
)
[docs]
@event(ItemRemoved)
def remove_item(self, product_id: UUID) -> None:
if self.is_submitted:
raise CartAlreadySubmittedError
for i, item in enumerate(self.items):
if item.product_id == product_id:
self.items.pop(i)
break
else:
raise ProductNotInCartError
[docs]
@event(Cleared)
def clear(self) -> None:
if self.is_submitted:
raise CartAlreadySubmittedError
self.items = []
[docs]
@event(Submitted)
def submit(self) -> None:
if self.is_submitted:
raise CartAlreadySubmittedError
self.is_submitted = True