T2: Pydantic v2 — replace @dataclass with BaseModel
- All domain models now use pydantic.BaseModel
- Removed manual to_dict()/from_dict() — use model_dump(mode='json')/model_validate()
- Added field validators:
- Account.balance >= 0
- Transaction.amount != 0
- RecurringCashflow.amount != 0, frequency in {daily, weekly, monthly, yearly}
- Liability.interest, payment >= 0
- ExchangeRate.rate > 0
- ForecastScenario.multipliers >= 0
- pydantic v2 native UUID handling (auto str in JSON)
- Updated excel_sync.py to use model_validate()
- Updated tests/test_model.py and tests/test_currency.py
- Added pydantic>=2.0 to pyproject.toml
Tests: 63/63 pass.
This commit is contained in:
+16
-23
@@ -1,33 +1,26 @@
|
||||
from dataclasses import dataclass, field
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
@dataclass
|
||||
class RecurringCashflow:
|
||||
id: UUID = field(default_factory=uuid4)
|
||||
|
||||
class RecurringCashflow(BaseModel):
|
||||
id: UUID = Field(default_factory=uuid4)
|
||||
start_date: str = ""
|
||||
end_date: str = ""
|
||||
frequency: str = "monthly"
|
||||
amount: float = 0.0
|
||||
category: str = ""
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"id": str(self.id),
|
||||
"start_date": self.start_date,
|
||||
"end_date": self.end_date,
|
||||
"frequency": self.frequency,
|
||||
"amount": self.amount,
|
||||
"category": self.category,
|
||||
}
|
||||
|
||||
@field_validator("frequency")
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict) -> "RecurringCashflow":
|
||||
return cls(
|
||||
id=UUID(data["id"]),
|
||||
start_date=data.get("start_date", ""),
|
||||
end_date=data.get("end_date", ""),
|
||||
frequency=data.get("frequency", "monthly"),
|
||||
amount=data.get("amount", 0.0),
|
||||
category=data.get("category", ""),
|
||||
)
|
||||
def _frequency_known(cls, v: str) -> str:
|
||||
if v not in {"daily", "weekly", "monthly", "yearly"}:
|
||||
raise ValueError(f"unknown frequency: {v}")
|
||||
return v
|
||||
|
||||
@field_validator("amount")
|
||||
@classmethod
|
||||
def _amount_nonzero(cls, v: float) -> float:
|
||||
if v == 0:
|
||||
raise ValueError("amount must be non-zero")
|
||||
return v
|
||||
|
||||
Reference in New Issue
Block a user