[INIT-001] Initial project setup with Clean Architecture (feat)
Some checks failed
CD - Build & Deploy / build-and-push (push) Has been cancelled
CD - Build & Deploy / package-helm (push) Has been cancelled
CD - Build & Deploy / deploy-staging (push) Has been cancelled
CD - Build & Deploy / deploy-production (push) Has been cancelled
CD - Build & Deploy / release (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / security (push) Has been cancelled
Some checks failed
CD - Build & Deploy / build-and-push (push) Has been cancelled
CD - Build & Deploy / package-helm (push) Has been cancelled
CD - Build & Deploy / deploy-staging (push) Has been cancelled
CD - Build & Deploy / deploy-production (push) Has been cancelled
CD - Build & Deploy / release (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / security (push) Has been cancelled
- Implemented Clean Architecture with Domain, Application, Infrastructure, Presentation layers - Added comprehensive project structure following SOLID principles - Created Kubernetes deployment with Helm charts (HPA, PDB, NetworkPolicy) - Configured ArgoCD for automated deployment (production + staging) - Implemented CI/CD pipeline with GitHub Actions - Added comprehensive documentation (handbook, architecture, coding standards) - Configured PostgreSQL, Redis, Celery for backend services - Created modern landing page with Persian fonts (Vazirmatn) - Added Docker multi-stage build for production - Configured development tools (pytest, black, flake8, mypy, isort) - Added pre-commit hooks for code quality - Implemented Makefile for common operations
This commit is contained in:
202
src/core/domain/value_objects/money.py
Normal file
202
src/core/domain/value_objects/money.py
Normal file
@@ -0,0 +1,202 @@
|
||||
"""Money value object.
|
||||
|
||||
Money represents a monetary amount with currency.
|
||||
"""
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import Any, Union
|
||||
|
||||
|
||||
class Money:
|
||||
"""Money value object.
|
||||
|
||||
Represents a monetary amount with currency.
|
||||
Immutable and provides monetary operations.
|
||||
|
||||
Attributes:
|
||||
amount: Decimal amount
|
||||
currency: Currency code (e.g., 'IRR', 'USD')
|
||||
"""
|
||||
|
||||
def __init__(self, amount: Union[Decimal, int, float, str], currency: str = "IRR"):
|
||||
"""Initialize money.
|
||||
|
||||
Args:
|
||||
amount: Monetary amount
|
||||
currency: Currency code (default: IRR for Iranian Rial)
|
||||
|
||||
Raises:
|
||||
ValueError: If amount is negative or currency is invalid
|
||||
"""
|
||||
self._amount = Decimal(str(amount))
|
||||
|
||||
if self._amount < 0:
|
||||
raise ValueError("Amount cannot be negative")
|
||||
|
||||
if not currency or len(currency) != 3:
|
||||
raise ValueError(f"Invalid currency code: {currency}")
|
||||
|
||||
self._currency = currency.upper()
|
||||
|
||||
@property
|
||||
def amount(self) -> Decimal:
|
||||
"""Get amount.
|
||||
|
||||
Returns:
|
||||
Decimal: Amount
|
||||
"""
|
||||
return self._amount
|
||||
|
||||
@property
|
||||
def currency(self) -> str:
|
||||
"""Get currency.
|
||||
|
||||
Returns:
|
||||
str: Currency code
|
||||
"""
|
||||
return self._currency
|
||||
|
||||
def add(self, other: "Money") -> "Money":
|
||||
"""Add two money values.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Returns:
|
||||
Money: New money object with sum
|
||||
|
||||
Raises:
|
||||
ValueError: If currencies don't match
|
||||
"""
|
||||
self._check_currency(other)
|
||||
return Money(self._amount + other._amount, self._currency)
|
||||
|
||||
def subtract(self, other: "Money") -> "Money":
|
||||
"""Subtract money value.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Returns:
|
||||
Money: New money object with difference
|
||||
|
||||
Raises:
|
||||
ValueError: If currencies don't match or result is negative
|
||||
"""
|
||||
self._check_currency(other)
|
||||
result = self._amount - other._amount
|
||||
if result < 0:
|
||||
raise ValueError("Result cannot be negative")
|
||||
return Money(result, self._currency)
|
||||
|
||||
def multiply(self, multiplier: Union[int, float, Decimal]) -> "Money":
|
||||
"""Multiply amount by a factor.
|
||||
|
||||
Args:
|
||||
multiplier: Multiplication factor
|
||||
|
||||
Returns:
|
||||
Money: New money object
|
||||
"""
|
||||
result = self._amount * Decimal(str(multiplier))
|
||||
return Money(result, self._currency)
|
||||
|
||||
def _check_currency(self, other: "Money") -> None:
|
||||
"""Check if currencies match.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Raises:
|
||||
ValueError: If currencies don't match
|
||||
"""
|
||||
if self._currency != other._currency:
|
||||
raise ValueError(
|
||||
f"Currency mismatch: {self._currency} vs {other._currency}"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""String representation.
|
||||
|
||||
Returns:
|
||||
str: Formatted money string
|
||||
"""
|
||||
return f"{self._amount:,.2f} {self._currency}"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Developer representation.
|
||||
|
||||
Returns:
|
||||
str: Money representation
|
||||
"""
|
||||
return f"Money({self._amount}, '{self._currency}')"
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
"""Check equality.
|
||||
|
||||
Args:
|
||||
other: Other object
|
||||
|
||||
Returns:
|
||||
bool: True if equal
|
||||
"""
|
||||
if not isinstance(other, Money):
|
||||
return False
|
||||
return self._amount == other._amount and self._currency == other._currency
|
||||
|
||||
def __lt__(self, other: "Money") -> bool:
|
||||
"""Less than comparison.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Returns:
|
||||
bool: True if less than
|
||||
"""
|
||||
self._check_currency(other)
|
||||
return self._amount < other._amount
|
||||
|
||||
def __le__(self, other: "Money") -> bool:
|
||||
"""Less than or equal comparison.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Returns:
|
||||
bool: True if less than or equal
|
||||
"""
|
||||
self._check_currency(other)
|
||||
return self._amount <= other._amount
|
||||
|
||||
def __gt__(self, other: "Money") -> bool:
|
||||
"""Greater than comparison.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Returns:
|
||||
bool: True if greater than
|
||||
"""
|
||||
self._check_currency(other)
|
||||
return self._amount > other._amount
|
||||
|
||||
def __ge__(self, other: "Money") -> bool:
|
||||
"""Greater than or equal comparison.
|
||||
|
||||
Args:
|
||||
other: Other money value
|
||||
|
||||
Returns:
|
||||
bool: True if greater than or equal
|
||||
"""
|
||||
self._check_currency(other)
|
||||
return self._amount >= other._amount
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""Hash value.
|
||||
|
||||
Returns:
|
||||
int: Hash
|
||||
"""
|
||||
return hash((self._amount, self._currency))
|
||||
|
||||
Reference in New Issue
Block a user