From 2cb50458367157a3ffbc958a1341215435cadc87 Mon Sep 17 00:00:00 2001 From: Paul de Raaij Date: Wed, 29 Jul 2026 02:20:25 -0400 Subject: [PATCH] feat: set default state to Inactive, optional title/text with defaults, auto-raise ClassifiedAdCreated --- domain/marketplace/classified_ad.py | 13 ++++++-- tests/test_classified_ad.py | 47 +++++++++++++++-------------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/domain/marketplace/classified_ad.py b/domain/marketplace/classified_ad.py index 0bc0242..ad7c415 100644 --- a/domain/marketplace/classified_ad.py +++ b/domain/marketplace/classified_ad.py @@ -9,6 +9,7 @@ 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 ( + ClassifiedAdCreated, ClassifiedAdPriceUpdated, ClassifiedAdSentForReview, ClassifiedAdTextUpdated, @@ -26,12 +27,18 @@ from domain.marketplace.user_id import UserId class ClassifiedAd(Entity): id: ClassifiedAdId _ownerId: UserId - title: ClassifiedAdTitle - text: ClassifiedAdText + title: ClassifiedAdTitle = field(default_factory=lambda: ClassifiedAdTitle(title="")) + text: ClassifiedAdText = field(default_factory=lambda: ClassifiedAdText(text="")) price: Price = field(default_factory=lambda: Price(amount=Decimal("0.00"))) - state: ClassifiedAdState | None = None + state: ClassifiedAdState = ClassifiedAdState.Inactive _events: tuple[DomainEvent, ...] = () + def __post_init__(self): + if not self._events: + object.__setattr__(self, '_events', ( + ClassifiedAdCreated(id=self.id.value, owner_id=self._ownerId.value), + )) + def _ensure_valid_state(self): errors = [] if not self.title.title: diff --git a/tests/test_classified_ad.py b/tests/test_classified_ad.py index 683fc42..6daf006 100644 --- a/tests/test_classified_ad.py +++ b/tests/test_classified_ad.py @@ -10,6 +10,7 @@ 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 ( + ClassifiedAdCreated, ClassifiedAdPriceUpdated, ClassifiedAdSentForReview, ClassifiedAdTextUpdated, @@ -154,10 +155,10 @@ def test_request_to_publish_sets_state_to_pending_review(): assert published.state == ClassifiedAdState.PendingReview changes = published.get_changes() - assert len(changes) == 1 - event = changes[0] - assert isinstance(event, ClassifiedAdSentForReview) - assert event.id == ad.id.value + assert len(changes) == 2 + assert isinstance(changes[0], ClassifiedAdCreated) + assert isinstance(changes[1], ClassifiedAdSentForReview) + assert changes[1].id == ad.id.value def test_request_to_publish_fails_when_title_empty(): @@ -231,7 +232,8 @@ def test_request_to_publish_does_not_mutate_original(): ad.request_to_publish() - assert ad.state is None + assert ad.state == ClassifiedAdState.Inactive + assert ad is not ad.request_to_publish() def test_classified_ad_is_instance_of_entity(): @@ -258,8 +260,9 @@ def test_classified_ad_can_use_entity_raise_event(): updated_ad = ad.raise_event(event) - assert updated_ad.get_changes() == (event,) - assert ad.get_changes() == () + assert updated_ad.get_changes() == (ad.get_changes()[0], event) + assert len(ad.get_changes()) == 1 + assert isinstance(ad.get_changes()[0], ClassifiedAdCreated) def test_set_title_updates_title(): @@ -326,11 +329,11 @@ def test_set_title_raises_classified_ad_title_changed_event(): updated = ad.set_title(ClassifiedAdTitle(title="New Title")) changes = updated.get_changes() - assert len(changes) == 1 - event = changes[0] - assert isinstance(event, ClassifiedAdTitleChanged) - assert event.id == ad.id.value - assert event.title == "New Title" + assert len(changes) == 2 + assert isinstance(changes[0], ClassifiedAdCreated) + assert isinstance(changes[1], ClassifiedAdTitleChanged) + assert changes[1].id == ad.id.value + assert changes[1].title == "New Title" def test_update_text_updates_text(): @@ -376,11 +379,11 @@ def test_update_text_raises_classified_ad_text_updated_event(): updated = ad.update_text(ClassifiedAdText(text="New text")) changes = updated.get_changes() - assert len(changes) == 1 - event = changes[0] - assert isinstance(event, ClassifiedAdTextUpdated) - assert event.id == ad.id.value - assert event.ad_text == "New text" + assert len(changes) == 2 + assert isinstance(changes[0], ClassifiedAdCreated) + assert isinstance(changes[1], ClassifiedAdTextUpdated) + assert changes[1].id == ad.id.value + assert changes[1].ad_text == "New text" def test_update_price_updates_price(): @@ -426,8 +429,8 @@ def test_update_price_raises_classified_ad_price_updated_event(): updated = ad.update_price(Price(amount=Decimal("25.00"))) changes = updated.get_changes() - assert len(changes) == 1 - event = changes[0] - assert isinstance(event, ClassifiedAdPriceUpdated) - assert event.id == ad.id.value - assert event.price == Decimal("25.00") + assert len(changes) == 2 + assert isinstance(changes[0], ClassifiedAdCreated) + assert isinstance(changes[1], ClassifiedAdPriceUpdated) + assert changes[1].id == ad.id.value + assert changes[1].price == Decimal("25.00")