feat: set default state to Inactive, optional title/text with defaults, auto-raise ClassifiedAdCreated

This commit is contained in:
2026-07-29 02:20:25 -04:00
parent b8507e8941
commit 2cb5045836
2 changed files with 35 additions and 25 deletions

View File

@@ -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_text import ClassifiedAdText
from domain.marketplace.classified_ad_title import ClassifiedAdTitle from domain.marketplace.classified_ad_title import ClassifiedAdTitle
from domain.marketplace.domain_event import ( from domain.marketplace.domain_event import (
ClassifiedAdCreated,
ClassifiedAdPriceUpdated, ClassifiedAdPriceUpdated,
ClassifiedAdSentForReview, ClassifiedAdSentForReview,
ClassifiedAdTextUpdated, ClassifiedAdTextUpdated,
@@ -26,12 +27,18 @@ from domain.marketplace.user_id import UserId
class ClassifiedAd(Entity): class ClassifiedAd(Entity):
id: ClassifiedAdId id: ClassifiedAdId
_ownerId: UserId _ownerId: UserId
title: ClassifiedAdTitle title: ClassifiedAdTitle = field(default_factory=lambda: ClassifiedAdTitle(title=""))
text: ClassifiedAdText text: ClassifiedAdText = field(default_factory=lambda: ClassifiedAdText(text=""))
price: Price = field(default_factory=lambda: Price(amount=Decimal("0.00"))) price: Price = field(default_factory=lambda: Price(amount=Decimal("0.00")))
state: ClassifiedAdState | None = None state: ClassifiedAdState = ClassifiedAdState.Inactive
_events: tuple[DomainEvent, ...] = () _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): def _ensure_valid_state(self):
errors = [] errors = []
if not self.title.title: if not self.title.title:

View File

@@ -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_text import ClassifiedAdText
from domain.marketplace.classified_ad_title import ClassifiedAdTitle from domain.marketplace.classified_ad_title import ClassifiedAdTitle
from domain.marketplace.domain_event import ( from domain.marketplace.domain_event import (
ClassifiedAdCreated,
ClassifiedAdPriceUpdated, ClassifiedAdPriceUpdated,
ClassifiedAdSentForReview, ClassifiedAdSentForReview,
ClassifiedAdTextUpdated, ClassifiedAdTextUpdated,
@@ -154,10 +155,10 @@ def test_request_to_publish_sets_state_to_pending_review():
assert published.state == ClassifiedAdState.PendingReview assert published.state == ClassifiedAdState.PendingReview
changes = published.get_changes() changes = published.get_changes()
assert len(changes) == 1 assert len(changes) == 2
event = changes[0] assert isinstance(changes[0], ClassifiedAdCreated)
assert isinstance(event, ClassifiedAdSentForReview) assert isinstance(changes[1], ClassifiedAdSentForReview)
assert event.id == ad.id.value assert changes[1].id == ad.id.value
def test_request_to_publish_fails_when_title_empty(): 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() 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(): 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) updated_ad = ad.raise_event(event)
assert updated_ad.get_changes() == (event,) assert updated_ad.get_changes() == (ad.get_changes()[0], event)
assert ad.get_changes() == () assert len(ad.get_changes()) == 1
assert isinstance(ad.get_changes()[0], ClassifiedAdCreated)
def test_set_title_updates_title(): 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")) updated = ad.set_title(ClassifiedAdTitle(title="New Title"))
changes = updated.get_changes() changes = updated.get_changes()
assert len(changes) == 1 assert len(changes) == 2
event = changes[0] assert isinstance(changes[0], ClassifiedAdCreated)
assert isinstance(event, ClassifiedAdTitleChanged) assert isinstance(changes[1], ClassifiedAdTitleChanged)
assert event.id == ad.id.value assert changes[1].id == ad.id.value
assert event.title == "New Title" assert changes[1].title == "New Title"
def test_update_text_updates_text(): 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")) updated = ad.update_text(ClassifiedAdText(text="New text"))
changes = updated.get_changes() changes = updated.get_changes()
assert len(changes) == 1 assert len(changes) == 2
event = changes[0] assert isinstance(changes[0], ClassifiedAdCreated)
assert isinstance(event, ClassifiedAdTextUpdated) assert isinstance(changes[1], ClassifiedAdTextUpdated)
assert event.id == ad.id.value assert changes[1].id == ad.id.value
assert event.ad_text == "New text" assert changes[1].ad_text == "New text"
def test_update_price_updates_price(): 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"))) updated = ad.update_price(Price(amount=Decimal("25.00")))
changes = updated.get_changes() changes = updated.get_changes()
assert len(changes) == 1 assert len(changes) == 2
event = changes[0] assert isinstance(changes[0], ClassifiedAdCreated)
assert isinstance(event, ClassifiedAdPriceUpdated) assert isinstance(changes[1], ClassifiedAdPriceUpdated)
assert event.id == ad.id.value assert changes[1].id == ad.id.value
assert event.price == Decimal("25.00") assert changes[1].price == Decimal("25.00")