diff --git a/pit38/domain/crypto/profit_calculator.py b/pit38/domain/crypto/profit_calculator.py index 20506d4..8f2671f 100644 --- a/pit38/domain/crypto/profit_calculator.py +++ b/pit38/domain/crypto/profit_calculator.py @@ -2,7 +2,7 @@ from typing import List from loguru import logger -from pit38.domain.currency_exchange_service.currencies import FiatValue +from pit38.domain.currency_exchange_service.currencies import Currency, FiatValue from pit38.domain.currency_exchange_service.exchanger import Exchanger from pit38.domain.tax_service.profit_per_year import ProfitPerYear from pit38.domain.transactions import Transaction, Action @@ -22,7 +22,7 @@ def profit_per_year(self, transactions: List[Transaction]) -> ProfitPerYear: def _sum_transactions_per_year(self, transactions: List[Transaction], transaction_type: Action) \ -> defaultdict[int, FiatValue]: - transactions_sum_per_year: defaultdict[int, FiatValue] = defaultdict(lambda: FiatValue(0)) + transactions_sum_per_year: defaultdict[int, FiatValue] = defaultdict(lambda: FiatValue.zero(Currency.ZLOTY)) for transaction in transactions: if transaction.action != transaction_type: continue diff --git a/pit38/domain/currency_exchange_service/currencies.py b/pit38/domain/currency_exchange_service/currencies.py index 9f9b50f..8cbaaa8 100644 --- a/pit38/domain/currency_exchange_service/currencies.py +++ b/pit38/domain/currency_exchange_service/currencies.py @@ -30,10 +30,14 @@ def parse_currency(currency: str) -> Currency: class FiatValue: - def __init__(self, amount: float = 0, currency: Currency = Currency.ZLOTY): + def __init__(self, amount: float, currency: Currency): self.amount = amount self.currency = currency + @classmethod + def zero(cls, currency: Currency): + return cls(0, currency) + def __add__(self, other): if self.currency != other.currency: raise InvalidCurrencyException(f"Cannot add different currencies: {self.currency} and {other.currency}") diff --git a/pit38/domain/stock/profit/per_stock_calculator.py b/pit38/domain/stock/profit/per_stock_calculator.py index 36dc7a0..4b228ff 100644 --- a/pit38/domain/stock/profit/per_stock_calculator.py +++ b/pit38/domain/stock/profit/per_stock_calculator.py @@ -2,7 +2,7 @@ from loguru import logger -from pit38.domain.currency_exchange_service.currencies import FiatValue +from pit38.domain.currency_exchange_service.currencies import Currency, FiatValue from pit38.domain.currency_exchange_service.exchanger import Exchanger from pit38.domain.tax_service.profit_per_year import ProfitPerYear from pit38.domain.stock.queue import Queue @@ -51,7 +51,7 @@ def _get_company_name(self, transaction: List[Transaction]) -> str: def _calculate_cost_for_sell(self, buy_queue: Queue, transaction: Transaction) -> FiatValue: stock_amount_to_account = transaction.asset.amount - cost = FiatValue(0) + cost = FiatValue.zero(Currency.ZLOTY) while stock_amount_to_account > self.EPSILON: try: diff --git a/pit38/domain/tax_service/crypto_tax_calculator.py b/pit38/domain/tax_service/crypto_tax_calculator.py index b0a5f5c..4a0c988 100644 --- a/pit38/domain/tax_service/crypto_tax_calculator.py +++ b/pit38/domain/tax_service/crypto_tax_calculator.py @@ -1,4 +1,4 @@ -from pit38.domain.currency_exchange_service.currencies import FiatValue +from pit38.domain.currency_exchange_service.currencies import Currency, FiatValue from pit38.domain.tax_service.profit_per_year import ProfitPerYear from pit38.domain.tax_service.tax_year_result import TaxYearResult @@ -17,12 +17,12 @@ def calculate_tax_per_year( deductible_loss: float = -1, ) -> TaxYearResult: if deductible_loss != -1: - loss = FiatValue(deductible_loss) + loss = FiatValue(deductible_loss, Currency.ZLOTY) else: loss = self._deductible_loss(profit_per_year, tax_year) profit_in_tax_year = profit_per_year.get_profit(tax_year) - if loss > FiatValue(0): + if loss > FiatValue.zero(Currency.ZLOTY): profit_in_tax_year = profit_in_tax_year - loss return TaxYearResult( @@ -37,15 +37,15 @@ def calculate_tax_per_year( def _deductible_loss( self, profit_per_year: ProfitPerYear, tax_year: int ) -> FiatValue: - accumulated_loss = FiatValue(0) + accumulated_loss = FiatValue.zero(Currency.ZLOTY) for year in sorted(y for y in profit_per_year.all_years() if y < tax_year): profit_this_year = profit_per_year.get_profit(year) if profit_this_year >= accumulated_loss: - accumulated_loss = FiatValue(0) + accumulated_loss = FiatValue.zero(Currency.ZLOTY) continue accumulated_loss = accumulated_loss - profit_this_year return accumulated_loss def _calculate_tax(self, profit: FiatValue) -> FiatValue: - zero = FiatValue(0) + zero = FiatValue.zero(Currency.ZLOTY) return profit * self.tax_rate if profit > zero else zero diff --git a/pit38/domain/tax_service/loss_deduction.py b/pit38/domain/tax_service/loss_deduction.py index 46546a6..b47672b 100644 --- a/pit38/domain/tax_service/loss_deduction.py +++ b/pit38/domain/tax_service/loss_deduction.py @@ -1,18 +1,18 @@ from dataclasses import dataclass, field from typing import List -from pit38.domain.currency_exchange_service.currencies import FiatValue +from pit38.domain.currency_exchange_service.currencies import Currency, FiatValue from pit38.domain.tax_service.profit_per_year import ProfitPerYear -FIVE_MILLION = FiatValue(5_000_000) -ZERO = FiatValue(0) +FIVE_MILLION = FiatValue(5_000_000, Currency.ZLOTY) +ZERO = FiatValue.zero(Currency.ZLOTY) @dataclass class LossRecord: year: int original_amount: FiatValue - already_deducted: FiatValue = field(default_factory=FiatValue) + already_deducted: FiatValue = field(default_factory=lambda: FiatValue.zero(Currency.ZLOTY)) @property def remaining(self) -> FiatValue: @@ -44,7 +44,7 @@ def calculate_deductible_loss( if profit <= ZERO: return ZERO - total_deducted = FiatValue(0) + total_deducted = FiatValue.zero(Currency.ZLOTY) remaining_profit = profit for loss in losses: diff --git a/pit38/domain/tax_service/profit_per_year.py b/pit38/domain/tax_service/profit_per_year.py index 173f678..e6a6db5 100644 --- a/pit38/domain/tax_service/profit_per_year.py +++ b/pit38/domain/tax_service/profit_per_year.py @@ -1,12 +1,12 @@ from collections import defaultdict -from pit38.domain.currency_exchange_service.currencies import FiatValue +from pit38.domain.currency_exchange_service.currencies import Currency, FiatValue class ProfitPerYear: def __init__(self, income: defaultdict[int, FiatValue] = None, cost: defaultdict[int, FiatValue] = None): - self.income = income if income is not None else defaultdict(FiatValue) - self.cost = cost if cost is not None else defaultdict(FiatValue) + self.income = income if income is not None else defaultdict(lambda: FiatValue.zero(Currency.ZLOTY)) + self.cost = cost if cost is not None else defaultdict(lambda: FiatValue.zero(Currency.ZLOTY)) def add_income(self, year: int, value: FiatValue): self.income[year] += value diff --git a/pit38/domain/tax_service/stock_tax_calculator.py b/pit38/domain/tax_service/stock_tax_calculator.py index 41ad3b3..d6366a9 100644 --- a/pit38/domain/tax_service/stock_tax_calculator.py +++ b/pit38/domain/tax_service/stock_tax_calculator.py @@ -1,4 +1,4 @@ -from pit38.domain.currency_exchange_service.currencies import FiatValue +from pit38.domain.currency_exchange_service.currencies import Currency, FiatValue from pit38.domain.tax_service.loss_deduction import StockLossDeductionStrategy from pit38.domain.tax_service.profit_per_year import ProfitPerYear from pit38.domain.tax_service.tax_year_result import TaxYearResult @@ -16,14 +16,14 @@ def calculate_tax_per_year( deductible_loss: float = -1, ) -> TaxYearResult: if deductible_loss != -1: - loss = FiatValue(deductible_loss) + loss = FiatValue(deductible_loss, Currency.ZLOTY) else: loss = self._loss_strategy.calculate_deductible_loss( profit_per_year, tax_year ) profit_in_tax_year = profit_per_year.get_profit(tax_year) - if loss > FiatValue(0): + if loss > FiatValue.zero(Currency.ZLOTY): profit_in_tax_year = profit_in_tax_year - loss return TaxYearResult( @@ -36,5 +36,5 @@ def calculate_tax_per_year( ) def _calculate_tax(self, profit: FiatValue) -> FiatValue: - zero = FiatValue(0) + zero = FiatValue.zero(Currency.ZLOTY) return profit * self.tax_rate if profit > zero else zero diff --git a/tests/test_currencies.py b/tests/test_currencies.py index f691ced..823ef7d 100644 --- a/tests/test_currencies.py +++ b/tests/test_currencies.py @@ -29,6 +29,9 @@ def test_mul_by_non_numeric(self): with self.assertRaises(ValueError): a * "a" + def test_zero(self): + self.assertEqual(FiatValue.zero(Currency.DOLLAR), FiatValue(0, Currency.DOLLAR)) + def test_gt(self): a = usd(100) b = usd(200)