def test_quantize(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) result = price_range.quantize() assert str(result.start.amount) == "10.00" assert str(result.stop.amount) == "30.00"
def test_construction(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) assert price_range.start == price1 assert price_range.stop == price2 with pytest.raises(ValueError): CurrencyRange(price1, Currency(20, "PLN")) with pytest.raises(ValueError): CurrencyRange(price2, price1)
def test_replace(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price3 = Currency(20, "EUR") price_range = CurrencyRange(price1, price2) result = price_range.replace(stop=price3) assert result.start == price1 assert result.stop == price3 result = price_range.replace(start=price3) assert result.start == price3 assert result.stop == price2
def test_addition_with_money_range(): price1 = CurrencyWithTax(Currency(10, "EUR"), Currency(15, "EUR")) price2 = CurrencyWithTax(Currency(30, "EUR"), Currency(45, "EUR")) price_range1 = CurrencyRangeTax(price1, price2) price3 = Currency(40, "EUR") price4 = Currency(80, "EUR") price_range2 = CurrencyRange(price3, price4) result = price_range1 + price_range2 assert result.start == price1 + price3 assert result.stop == price2 + price4 with pytest.raises(ValueError): price_range1 + CurrencyRange(Currency(1, "BTC"), Currency(2, "BTC"))
def test_subtraction_with_money_range(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range1 = CurrencyRange(price1, price2) price3 = CurrencyWithTax(Currency(40, "EUR"), Currency(60, "EUR")) price4 = CurrencyWithTax(Currency(80, "EUR"), Currency(120, "EUR")) price_range2 = CurrencyRangeTax(price3, price4) result = price_range2 - price_range1 assert result.start == price3 - price1 assert result.stop == price4 - price2 with pytest.raises(ValueError): price_range2 - CurrencyRange(Currency(1, "BTC"), Currency(2, "BTC"))
def test_comparison(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range1 = CurrencyRange(price1, price2) price3 = Currency(40, "EUR") price4 = Currency(80, "EUR") price_range2 = CurrencyRange(price3, price4) assert price_range1 == CurrencyRange(price1, price2) assert price_range1 != price_range2 assert price_range1 != CurrencyRange(price1, price1) assert price_range1 != CurrencyRange(Currency(10, "USD"), Currency(30, "USD")) assert price_range1 != price1
def test_addition_with_money(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) price3 = Currency(40, "EUR") result = price_range + price3 assert result.start == price1 + price3 assert result.stop == price2 + price3 with pytest.raises(ValueError): price_range + Currency(1, "BTC")
def test_membership(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) assert price1 in price_range assert price2 in price_range assert (price1 + price2) / 2 in price_range assert price1 + price2 not in price_range with pytest.raises(TypeError): 15 in price_range
def test_subtraction_with_money(): price1 = Currency(40, "EUR") price2 = Currency(80, "EUR") price_range = CurrencyRange(price1, price2) price3 = Currency(10, "EUR") result = price_range - price3 assert result.start == price1 - price3 assert result.stop == price2 - price3 with pytest.raises(ValueError): price_range - Currency(1, "BTC")
def test_range(): price_range = CurrencyRange(Currency(10, "BTC"), Currency(20, "BTC")) result = flat_tax(price_range, 1) assert result.start == CurrencyWithTax(Currency(10, "BTC"), Currency(20, "BTC")) assert result.stop == CurrencyWithTax(Currency(20, "BTC"), Currency(40, "BTC")) price_range = CurrencyRangeTax( CurrencyWithTax(Currency(10, "BTC"), Currency(10, "BTC")), CurrencyWithTax(Currency(20, "BTC"), Currency(20, "BTC")), ) result = flat_tax(price_range, 1) assert result.start == CurrencyWithTax(Currency(10, "BTC"), Currency(20, "BTC")) assert result.stop == CurrencyWithTax(Currency(20, "BTC"), Currency(40, "BTC"))
def test_application(): price = CurrencyWithTax(Currency(30, "BTC"), Currency(30, "BTC")) discount = partial(fixed_discount, discount=Currency(10, "BTC")) result = discount(price) assert result.net == Currency(20, "BTC") assert result.gross == Currency(20, "BTC") price_range = CurrencyRange(price.net, price.net) result = discount(price_range) assert result.start == Currency(20, "BTC") assert result.stop == Currency(20, "BTC") price_range = CurrencyRangeTax(price, price) result = discount(price_range) assert result.start == CurrencyWithTax(Currency(20, "BTC"), Currency(20, "BTC")) assert result.stop == CurrencyWithTax(Currency(20, "BTC"), Currency(20, "BTC")) with pytest.raises(TypeError): discount(1)
def fixed_discount(base: T, discount: Currency) -> T: """Apply a fixed discount to any currency type.""" if isinstance(base, CurrencyRange): return CurrencyRange( fixed_discount(base.start, discount), fixed_discount(base.stop, discount) ) if isinstance(base, CurrencyRangeTax): return CurrencyRangeTax( fixed_discount(base.start, discount), fixed_discount(base.stop, discount) ) if isinstance(base, CurrencyWithTax): return CurrencyWithTax( net=fixed_discount(base.net, discount), gross=fixed_discount(base.gross, discount), ) if isinstance(base, Currency): return max(base - discount, Currency(0, base.currency)) raise TypeError("Unknown base for fixed_discount: %r" % (base,))
def fractional_discount(base: T, fraction: Decimal, *, from_gross=True) -> T: """Apply a fractional discount based on either gross or net amount.""" if isinstance(base, CurrencyRange): return CurrencyRange( fractional_discount(base.start, fraction, from_gross=from_gross), fractional_discount(base.stop, fraction, from_gross=from_gross), ) if isinstance(base, CurrencyRangeTax): return CurrencyRangeTax( fractional_discount(base.start, fraction, from_gross=from_gross), fractional_discount(base.stop, fraction, from_gross=from_gross), ) if isinstance(base, CurrencyWithTax): if from_gross: discount = (base.gross * fraction).quantize(rounding=ROUND_DOWN) else: discount = (base.net * fraction).quantize(rounding=ROUND_DOWN) return fixed_discount(base, discount) if isinstance(base, Currency): discount = (base * fraction).quantize(rounding=ROUND_DOWN) return fixed_discount(base, discount) raise TypeError("Unknown base for fractional_discount: %r" % (base,))
def test_currency(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) assert price_range.currency == "EUR"
def test_str(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) assert str(price_range) == ("CurrencyRange(10 EUR 30 EUR)")
def test_subtraction_with_other_types(): price1 = Currency(40, "EUR") price2 = Currency(80, "EUR") price_range = CurrencyRange(price1, price2) with pytest.raises(TypeError): price_range - 1
def test_addition_with_other_types(): price1 = Currency(10, "EUR") price2 = Currency(30, "EUR") price_range = CurrencyRange(price1, price2) with pytest.raises(TypeError): price_range + 1