feat: add ClassifiedAd domain entity
This commit is contained in:
35
.agent/current-plan.md
Normal file
35
.agent/current-plan.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Plan: ClassifiedAd Domain Entity
|
||||||
|
|
||||||
|
## Status: COMPLETED
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Create the first Domain Entity representing a ClassifiedAd with the specified attributes.
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
- **Location**: `domain/marketplace/classified_ad.py`
|
||||||
|
- **Class style**: `@dataclass(frozen=True)` for immutability
|
||||||
|
- **Validation**: No validation, just hold data
|
||||||
|
- **Tests**: Yes, create unit tests
|
||||||
|
|
||||||
|
## Entity Structure
|
||||||
|
```python
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ClassifiedAd:
|
||||||
|
id: UUID
|
||||||
|
_ownerId: UUID
|
||||||
|
title: str
|
||||||
|
text: str
|
||||||
|
_price: Decimal
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files Created
|
||||||
|
- `domain/__init__.py`
|
||||||
|
- `domain/marketplace/__init__.py`
|
||||||
|
- `domain/marketplace/classified_ad.py`
|
||||||
|
- `tests/test_classified_ad.py`
|
||||||
|
- `pyproject.toml`
|
||||||
|
|
||||||
|
## Test Results
|
||||||
|
- `test_classified_ad_creation` - PASSED
|
||||||
|
- `test_classified_ad_is_immutable` - PASSED
|
||||||
|
- `test_classified_ad_equality` - PASSED
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
env/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.pytest_cache/
|
||||||
|
*.egg-info/
|
||||||
33
AGENTS.md
Normal file
33
AGENTS.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Project Context
|
||||||
|
|
||||||
|
This is a training project to learn functional programming in Python. Both Python and functional programming are relatively new. The learning approach uses an example project based on "Hands-on Domain Driven Design with .NET Core".
|
||||||
|
|
||||||
|
## Collaboration Principles
|
||||||
|
|
||||||
|
### Communication Style
|
||||||
|
- Be honest and objective. Evaluate all suggestions, ideas, and feedback on their technical merits.
|
||||||
|
- Do not be overly complementary or sycophantic.
|
||||||
|
- If something does not align with best practices or could be improved, say so directly and constructively.
|
||||||
|
- Technical accuracy and project quality take precedence over being agreeable.
|
||||||
|
|
||||||
|
### Command and Code Style
|
||||||
|
- Prefer simple commands over complex ones.
|
||||||
|
- Default to simple, single-purpose commands.
|
||||||
|
- Avoid one-liners that sacrifice clarity for brevity.
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
- We build production code together.
|
||||||
|
- User handles implementation details; AI guides architecture and catches complexity early.
|
||||||
|
- Challenge assumptions and ideas when it's useful. Be critical, not agreeable.
|
||||||
|
|
||||||
|
## Core Workflow: Research → Plan → Implement → Validate
|
||||||
|
Start every feature with: "Let me research the codebase and create a plan before implementing."
|
||||||
|
|
||||||
|
Research - Understand existing patterns and architecture
|
||||||
|
Plan - Propose approach and verify with you
|
||||||
|
Implement - Build with tests and error handling
|
||||||
|
Validate - ALWAYS run formatters, linters, and tests after implementation
|
||||||
|
Whenever working on a feature or issue, let's always come up with a plan first, then save it to a file called /.agent/current-plan.md, before getting started with code changes. Update this file as the work progresses.
|
||||||
|
Let's use pure functions where possible to improve readability and testing.
|
||||||
1
domain/__init__.py
Normal file
1
domain/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .marketplace import classified_ad
|
||||||
1
domain/marketplace/__init__.py
Normal file
1
domain/marketplace/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .classified_ad import ClassifiedAd
|
||||||
12
domain/marketplace/classified_ad.py
Normal file
12
domain/marketplace/classified_ad.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from decimal import Decimal
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ClassifiedAd:
|
||||||
|
id: UUID
|
||||||
|
_ownerId: UUID
|
||||||
|
title: str
|
||||||
|
text: str
|
||||||
|
_price: Decimal
|
||||||
11
pyproject.toml
Normal file
11
pyproject.toml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools"]
|
||||||
|
build-backend = "setuptools.backends._legacy:_Backend"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "python-fun"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
pythonpath = ["."]
|
||||||
61
tests/test_classified_ad.py
Normal file
61
tests/test_classified_ad.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from domain.marketplace.classified_ad import ClassifiedAd
|
||||||
|
|
||||||
|
|
||||||
|
def test_classified_ad_creation():
|
||||||
|
ad_id = uuid4()
|
||||||
|
owner_id = uuid4()
|
||||||
|
|
||||||
|
ad = ClassifiedAd(
|
||||||
|
id=ad_id,
|
||||||
|
_ownerId=owner_id,
|
||||||
|
title="Test Title",
|
||||||
|
text="Test text content",
|
||||||
|
_price=Decimal("99.99"),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ad.id == ad_id
|
||||||
|
assert ad._ownerId == owner_id
|
||||||
|
assert ad.title == "Test Title"
|
||||||
|
assert ad.text == "Test text content"
|
||||||
|
assert ad._price == Decimal("99.99")
|
||||||
|
|
||||||
|
|
||||||
|
def test_classified_ad_is_immutable():
|
||||||
|
ad = ClassifiedAd(
|
||||||
|
id=uuid4(),
|
||||||
|
_ownerId=uuid4(),
|
||||||
|
title="Title",
|
||||||
|
text="Text",
|
||||||
|
_price=Decimal("10.00"),
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ad.title = "New Title" # type: ignore
|
||||||
|
assert False, "Should have raised FrozenInstanceError"
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_classified_ad_equality():
|
||||||
|
ad_id = uuid4()
|
||||||
|
owner_id = uuid4()
|
||||||
|
|
||||||
|
ad1 = ClassifiedAd(
|
||||||
|
id=ad_id,
|
||||||
|
_ownerId=owner_id,
|
||||||
|
title="Title",
|
||||||
|
text="Text",
|
||||||
|
_price=Decimal("10.00"),
|
||||||
|
)
|
||||||
|
ad2 = ClassifiedAd(
|
||||||
|
id=ad_id,
|
||||||
|
_ownerId=owner_id,
|
||||||
|
title="Title",
|
||||||
|
text="Text",
|
||||||
|
_price=Decimal("10.00"),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ad1 == ad2
|
||||||
Reference in New Issue
Block a user