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
203 lines
5.2 KiB
Python
203 lines
5.2 KiB
Python
"""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))
|
|
|