from __future__ import annotations from dataclasses import dataclass, field, replace from decimal import Decimal from domain.framework.entity import Entity from domain.marketplace.classified_ad_id import ClassifiedAdId from domain.marketplace.classified_ad_state import ClassifiedAdState from domain.marketplace.classified_ad_text import ClassifiedAdText from domain.marketplace.classified_ad_title import ClassifiedAdTitle from domain.marketplace.domain_event import ( ClassifiedAdTitleChanged, DomainEvent, ) from domain.marketplace.invalid_entity_state_exception import ( InvalidEntityStateException, ) from domain.marketplace.price import Price from domain.marketplace.user_id import UserId @dataclass(frozen=True) class ClassifiedAd(Entity): id: ClassifiedAdId _ownerId: UserId title: ClassifiedAdTitle text: ClassifiedAdText price: Price = field(default_factory=lambda: Price(amount=Decimal("0.00"))) state: ClassifiedAdState | None = None _events: tuple[DomainEvent, ...] = () def _ensure_valid_state(self): errors = [] if not self.title.title: errors.append("title") if not self.text.text: errors.append("text") if self.price.amount <= 0: errors.append("price") if errors: raise InvalidEntityStateException( f"Cannot publish classified ad with missing or invalid: {', '.join(errors)}" ) def request_to_publish(self): self._ensure_valid_state() return replace(self, state=ClassifiedAdState.PendingReview) def set_title(self, title: ClassifiedAdTitle) -> ClassifiedAd: updated = replace(self, title=title) updated._ensure_valid_state() return updated.raise_event( ClassifiedAdTitleChanged(id=self.id.value, title=title.title) )