From fb8c221ee9fe40cea1ba20b7e0ff76bdc6939016 Mon Sep 17 00:00:00 2001 From: Paul de Raaij Date: Sun, 26 Jul 2026 07:09:37 -0400 Subject: [PATCH] feat: add UserId value object and update ClassifiedAd to use it --- .agent/current-plan.md | 32 +++++++++++------------------ domain/__init__.py | 2 +- domain/marketplace/__init__.py | 3 ++- domain/marketplace/classified_ad.py | 6 ++++-- domain/marketplace/user_id.py | 7 +++++++ tests/test_classified_ad.py | 11 +++++----- tests/test_user_id.py | 25 ++++++++++++++++++++++ 7 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 domain/marketplace/user_id.py create mode 100644 tests/test_user_id.py diff --git a/.agent/current-plan.md b/.agent/current-plan.md index ef75c1b..52fdc05 100644 --- a/.agent/current-plan.md +++ b/.agent/current-plan.md @@ -1,35 +1,27 @@ -# Plan: ClassifiedAd Domain Entity +# Plan: UserId Value Object ## Status: COMPLETED ## Objective -Create the first Domain Entity representing a ClassifiedAd with the specified attributes. +Create a UserId value object in the marketplace domain with an immutable UUID value. ## Decisions Made -- **Location**: `domain/marketplace/classified_ad.py` +- **Location**: `domain/marketplace/user_id.py` - **Class style**: `@dataclass(frozen=True)` for immutability -- **Validation**: No validation, just hold data -- **Tests**: Yes, create unit tests +- **Tests**: Yes -## Entity Structure +## Value Object Structure ```python @dataclass(frozen=True) -class ClassifiedAd: - id: UUID - _ownerId: UUID - title: str - text: str - _price: Decimal +class UserId: + value: UUID ``` ## Files Created -- `domain/__init__.py` -- `domain/marketplace/__init__.py` -- `domain/marketplace/classified_ad.py` -- `tests/test_classified_ad.py` -- `pyproject.toml` +- `domain/marketplace/user_id.py` +- `tests/test_user_id.py` ## Test Results -- `test_classified_ad_creation` - PASSED -- `test_classified_ad_is_immutable` - PASSED -- `test_classified_ad_equality` - PASSED \ No newline at end of file +- `test_user_id_creation` - PASSED +- `test_user_id_is_immutable` - PASSED +- `test_user_id_equality` - PASSED \ No newline at end of file diff --git a/domain/__init__.py b/domain/__init__.py index 2dc0adf..d27fd9a 100644 --- a/domain/__init__.py +++ b/domain/__init__.py @@ -1 +1 @@ -from .marketplace import classified_ad \ No newline at end of file +from .marketplace import classified_ad as classified_ad \ No newline at end of file diff --git a/domain/marketplace/__init__.py b/domain/marketplace/__init__.py index b39d335..daa252c 100644 --- a/domain/marketplace/__init__.py +++ b/domain/marketplace/__init__.py @@ -1 +1,2 @@ -from .classified_ad import ClassifiedAd \ No newline at end of file +from .classified_ad import ClassifiedAd as ClassifiedAd +from .user_id import UserId as UserId \ No newline at end of file diff --git a/domain/marketplace/classified_ad.py b/domain/marketplace/classified_ad.py index 663d3d6..22ab7ec 100644 --- a/domain/marketplace/classified_ad.py +++ b/domain/marketplace/classified_ad.py @@ -2,11 +2,13 @@ from dataclasses import dataclass from decimal import Decimal from uuid import UUID +from domain.marketplace.user_id import UserId + @dataclass(frozen=True) class ClassifiedAd: id: UUID - _ownerId: UUID + _ownerId: UserId title: str text: str - _price: Decimal \ No newline at end of file + _price: Decimal diff --git a/domain/marketplace/user_id.py b/domain/marketplace/user_id.py new file mode 100644 index 0000000..f708208 --- /dev/null +++ b/domain/marketplace/user_id.py @@ -0,0 +1,7 @@ +from dataclasses import dataclass +from uuid import UUID + + +@dataclass(frozen=True) +class UserId: + value: UUID diff --git a/tests/test_classified_ad.py b/tests/test_classified_ad.py index 6433bfc..0d3b884 100644 --- a/tests/test_classified_ad.py +++ b/tests/test_classified_ad.py @@ -1,12 +1,13 @@ from decimal import Decimal -from uuid import UUID, uuid4 +from uuid import uuid4 from domain.marketplace.classified_ad import ClassifiedAd +from domain.marketplace.user_id import UserId def test_classified_ad_creation(): ad_id = uuid4() - owner_id = uuid4() + owner_id = UserId(value=uuid4()) ad = ClassifiedAd( id=ad_id, @@ -26,7 +27,7 @@ def test_classified_ad_creation(): def test_classified_ad_is_immutable(): ad = ClassifiedAd( id=uuid4(), - _ownerId=uuid4(), + _ownerId=UserId(value=uuid4()), title="Title", text="Text", _price=Decimal("10.00"), @@ -41,7 +42,7 @@ def test_classified_ad_is_immutable(): def test_classified_ad_equality(): ad_id = uuid4() - owner_id = uuid4() + owner_id = UserId(value=uuid4()) ad1 = ClassifiedAd( id=ad_id, @@ -58,4 +59,4 @@ def test_classified_ad_equality(): _price=Decimal("10.00"), ) - assert ad1 == ad2 \ No newline at end of file + assert ad1 == ad2 diff --git a/tests/test_user_id.py b/tests/test_user_id.py new file mode 100644 index 0000000..3d9f6e9 --- /dev/null +++ b/tests/test_user_id.py @@ -0,0 +1,25 @@ +from uuid import UUID, uuid4 + +from domain.marketplace.user_id import UserId + + +def test_user_id_creation(): + user_id = UserId(value=uuid4()) + assert isinstance(user_id.value, UUID) + + +def test_user_id_is_immutable(): + user_id = UserId(value=uuid4()) + + try: + user_id.value = uuid4() # type: ignore + assert False, "Should have raised FrozenInstanceError" + except AttributeError: + pass + + +def test_user_id_equality(): + uid = uuid4() + user_id1 = UserId(value=uid) + user_id2 = UserId(value=uid) + assert user_id1 == user_id2