def test_money_property_set(): w = get_wallet() w.amount = Money(3, 'EUR') assert w.amount == Money(3, 'EUR') assert w.value == 3 assert type(w.value) == Decimal assert w.currency == 'EUR'
def test_money_basics(): m1 = Money(1, 'EUR') m2 = Money(2, 'EUR') m3 = Money(3, 'EUR') assert m1 + m2 == m3 assert m3 - m1 == m2 assert m3.value == 3 assert m3 / m2 == m3.value / m2.value
def test_units_match(): class XxxMoney(int): currency = 'XXX' m1 = Money(1, 'EUR') m2 = Money(2, 'EUR') m3 = Money(3, 'XXX') m4 = XxxMoney(4) assert m1.unit_matches_with(m2) assert not m1.unit_matches_with(m3) assert m3.unit_matches_with(m4)
def test_basic_order(): PRODUCTS_TO_SEND = 10 product = get_default_product() supplier = get_default_supplier() order = create_order_with_product(product, supplier=supplier, quantity=PRODUCTS_TO_SEND, taxless_base_unit_price=10, tax_rate=Decimal("0.5")) assert order.shop.prices_include_tax is False price = order.shop.create_price currency = order.currency discount_order_line = OrderLine(order=order, quantity=1, type=OrderLineType.OTHER) discount_order_line.discount_amount = price(30) assert discount_order_line.price == price(-30) discount_order_line.save() order.cache_prices() order.check_all_verified() order.save() assert order.taxful_total_price == TaxfulPrice( PRODUCTS_TO_SEND * (10 + 5) - 30, currency) shipment = order.create_shipment_of_all_products(supplier=supplier) assert shipment.total_products == PRODUCTS_TO_SEND, "All products were shipped" assert shipment.weight == product.net_weight * PRODUCTS_TO_SEND, "Gravity works" assert not order.get_unshipped_products( ), "Nothing was left in the warehouse" order.shipping_status = ShippingStatus.FULLY_SHIPPED order.create_payment(order.taxful_total_price) assert order.payments.exists(), "A payment was created" with pytest.raises(NoPaymentToCreateException): order.create_payment(Money(6, currency)) assert order.is_paid(), "Order got paid" assert order.can_set_complete(), "Finalization is possible" order.status = OrderStatus.objects.get_default_complete() assert order.is_complete(), "Finalization done" summary = order.get_tax_summary() assert len(summary) == 2 assert summary[0].tax_id is None assert summary[0].tax_code == '' assert summary[0].tax_amount == Money(0, currency) assert summary[0].tax_rate == 0 assert summary[1].tax_rate * 100 == 50 assert summary[1].based_on == Money(100, currency) assert summary[1].tax_amount == Money(50, currency) assert summary[1].taxful == summary[1].based_on + summary[1].tax_amount
def test_module(address, expected_taxes): """ Test the DefaultTaxModule. """ # Create a product shop = get_shop(prices_include_tax=False, currency='USD') product = create_product('PROD', shop=shop, default_price=1000) price = product.get_shop_instance(shop).default_price # Put the tax rules into database for ruledef in shuffled(TAX_RULE_DEFS): rule = ruledef.get_tax_rule() rule.tax.save() rule.tax = rule.tax # refresh the id rule.save() rule.tax_classes.add(product.tax_class) assert TaxRule.objects.count() == len(TAX_RULE_DEFS) with override_settings(SHOOP_TAX_MODULE='default_tax'): module = get_tax_module() assert isinstance(module, DefaultTaxModule) context = TaxingContext(location=address) taxed_price = module.get_taxed_price_for(context, product, price) expected_codes = set(sum([x.split() for x in expected_taxes], [])) assert set(x.tax.code for x in taxed_price.taxes) == expected_codes expected_tax = Money(TAX_AMOUNTS[expected_taxes], 'USD') assert taxed_price.taxful.amount == price.amount + expected_tax # Clean-up the rules TaxRule.objects.all().delete()
def amount(self): """ Money amount of this price. :rtype: Money """ return Money(self.value, self.currency)
def test_init_with_currency(): m42eur = TaxlessPrice(42, 'EUR') assert m42eur.amount == Money(42, 'EUR') assert m42eur.value == 42 assert m42eur.currency == 'EUR' assert TaxlessPrice(1, 'USD').currency == 'USD'
def from_line_taxes(cls, line_taxes, untaxed): """ Create TaxSummary from LineTaxes. :param line_taxes: List of line taxes to summarize :type line_taxes: list[LineTax] :param untaxed: Sum of taxless prices that have no taxes added :type untaxed: shoop.core.pricing.TaxlessPrice """ zero_amount = Money(0, untaxed.currency) tax_amount_by_tax = defaultdict(lambda: zero_amount) base_amount_by_tax = defaultdict(lambda: zero_amount) for line_tax in line_taxes: assert isinstance(line_tax, LineTax) tax_amount_by_tax[line_tax.tax] += line_tax.amount base_amount_by_tax[line_tax.tax] += line_tax.base_amount lines = [ TaxSummaryLine.from_tax(tax, base_amount_by_tax[tax], tax_amount) for (tax, tax_amount) in tax_amount_by_tax.items() ] if untaxed: lines.append( TaxSummaryLine(tax_id=None, tax_code='', tax_name=_("Untaxed"), tax_rate=Decimal(0), based_on=untaxed.amount, tax_amount=zero_amount)) return cls(sorted(lines, key=(lambda x: (x.tax_rate or 0))))
def test_tax_special_cases3(): taxless_line = Line(base_unit_price=TaxfulPrice(0, 'EUR'), quantity=0, discount_amount=TaxfulPrice(0, 'EUR'), tax_amount=Money(0, 'EUR')) assert taxless_line.taxful_price == TaxfulPrice(0, 'EUR') assert taxless_line.taxless_price == TaxlessPrice(0, 'EUR') assert taxless_line.base_unit_price == TaxfulPrice(0, 'EUR') assert taxless_line.taxful_base_unit_price == TaxfulPrice(0, 'EUR') assert taxless_line.taxless_base_unit_price == TaxlessPrice(0, 'EUR') assert taxless_line.discount_amount == TaxfulPrice(0, 'EUR') assert taxless_line.taxful_discount_amount == TaxfulPrice(0, 'EUR') assert taxless_line.taxless_discount_amount == TaxlessPrice(0, 'EUR') assert taxless_line.price == TaxfulPrice(0, 'EUR') assert taxless_line.taxful_price == TaxfulPrice(0, 'EUR') assert taxless_line.taxless_price == TaxlessPrice(0, 'EUR') assert taxless_line.base_price == TaxfulPrice(0, 'EUR') assert taxless_line.taxful_base_price == TaxfulPrice(0, 'EUR') assert taxless_line.taxless_base_price == TaxlessPrice(0, 'EUR') assert taxless_line.unit_discount_amount == TaxfulPrice(0, 'EUR') assert taxless_line.taxful_unit_discount_amount == TaxfulPrice(0, 'EUR') assert taxless_line.taxless_unit_discount_amount == TaxlessPrice(0, 'EUR') assert taxless_line.discount_rate == 0 assert taxless_line.tax_rate == 0
def test_units_match(): class XxxMoney(int): currency = 'XXX' m1 = Money(1) m2 = Money(2) m3 = Money(3) m3._currency = 'XXX' m4 = XxxMoney(4) assert m1._units_match(m2) assert not m1._units_match(m3) assert m3._units_match(m4)
def test_money_formatter_en(): with translation.override("en-US"): assert money(Money("29.99", "USD")) == "$29.99" assert money(Money("29.99", "EUR")) == "€29.99" assert money(Money("29.99", "GBP")) == "£29.99" assert money(Money("29.99", "CAD")) == "CA$29.99" assert money(Money("29.99", "JPY")) == "¥29.99" assert money(Money("29.99", "CNY")) == "CN¥29.99" assert money(Money("29.99", "KRW")) == "₩29.99" assert money(Money("29.99", "SEK")) == "SEK29.99"
def test_money_formatter_fi(): with translation.override("fi-FI"): assert money(Money("29.99", "USD")) == nbsp("29,99 $") assert money(Money("29.99", "EUR")) == nbsp("29,99 €") assert money(Money("29.99", "GBP")) == nbsp("29,99 £") assert money(Money("29.99", "CAD")) == nbsp("29,99 CAD") assert money(Money("29.99", "JPY")) == nbsp("29,99 ¥") assert money(Money("29.99", "CNY")) == nbsp("29,99 CNY") assert money(Money("29.99", "KRW")) == nbsp("29,99 KRW") assert money(Money("29.99", "SEK")) == nbsp("29,99 SEK")
def test_aliases(): line = Line( base_unit_price=TaxfulPrice(100, 'EUR'), quantity=3, discount_amount=TaxfulPrice(5, 'EUR'), tax_amount=Money(1, 'EUR'), ) assert line.total_price == line.price assert line.total_price == TaxfulPrice(295, 'EUR')
def test_money_formatter_fi(): with translation.override("fi-FI"): assert money(Money("29.99", "USD")) == nbsp("29,99 $") assert money(Money("29.99", "EUR")) == nbsp("29,99 €") assert money(Money("29.99", "GBP")) == nbsp("29,99 £") assert money(Money("29.99", "CAD")) == nbsp("29,99 CAD") assert money(Money("29.99", "JPY")) == nbsp( "30 ¥") # No such thing as a decimal yen! assert money(Money("29.99", "CNY")) == nbsp("29,99 CNY") assert money(Money("29.99", "KRW")) == nbsp( "30 KRW") # the 1/100 subunit "jeon" is theoretical and not in use assert money(Money("29.99", "SEK")) == nbsp("29,99 SEK")
def create_tax_from_string(string): if ' ' in string: (spec, name) = string.split(' ', 1) else: name = spec = string if spec.startswith('$'): return create_tax(name, amount=Money(spec[1:], 'USD')) elif spec.endswith('%'): return create_tax(name, rate=(Decimal(spec[:-1]) / 100)) raise ValueError('Unknown tax string: %r' % (string, ))
def test_money_formatter_en(): with translation.override("en-US"): assert money(Money("29.99", "USD")) == "$29.99" assert money(Money("29.99", "EUR")) == "€29.99" assert money(Money("29.99", "GBP")) == "£29.99" assert money(Money("29.99", "CAD")) == "CA$29.99" assert money(Money("29.99", "JPY")) == "¥30" # No such thing as a decimal yen! assert money(Money("29.99", "CNY")) == "CN¥29.99" assert money( Money("29.99", "KRW") ) == "₩30" # the 1/100 subunit "jeon" is theoretical and not in use assert money(Money("29.99", "SEK")) == "kr29.99"
def test_tax_special_cases1(): all_tax_line1 = Line(base_unit_price=TaxfulPrice(25, 'EUR'), quantity=5, discount_amount=TaxfulPrice(25, 'EUR'), tax_amount=Money(100, 'EUR')) assert all_tax_line1.taxful_price == TaxfulPrice(100, 'EUR') assert all_tax_line1.taxless_price == TaxlessPrice(0, 'EUR') assert all_tax_line1.taxful_discount_amount == TaxfulPrice(25, 'EUR') assert all_tax_line1.taxless_discount_amount == TaxlessPrice(0, 'EUR') assert all_tax_line1.tax_rate == 0 assert all_tax_line1.taxful_base_unit_price == TaxfulPrice(25, 'EUR') assert all_tax_line1.taxless_base_unit_price == TaxlessPrice(0, 'EUR')
def form_valid(self, form): order = self.object amount = Money(form.cleaned_data["amount"], order.currency) if amount.value == 0: messages.error(self.request, _("Payment amount cannot be 0")) return self.form_invalid(form) try: payment = order.create_payment(amount, description="Manual payment") messages.success(self.request, _("Payment %s created.") % payment.payment_identifier) except NoPaymentToCreateException: messages.error(self.request, _("Order has already been paid")) return self.form_invalid(form) else: return HttpResponseRedirect(get_model_url(order))
def test_convert_taxness_taxful_to_taxless(): request = get_request() tax_class = TaxClass() item = Product(tax_class=tax_class) priceful = _get_price_info(TaxfulPrice) calcs_done_before = DummyTaxModule.calculations_done result = convert_taxness(request, item, priceful, with_taxes=False) calcs_done_after = DummyTaxModule.calculations_done assert result != priceful assert (result.price - TaxlessPrice(400, 'USD')).value < 0.00001 assert result.base_price == TaxlessPrice(550, 'USD') assert result.quantity == 2 assert result.tax_amount == Money(80, 'USD') assert result.taxless_price == result.price assert result.taxful_price == priceful.price assert calcs_done_after == calcs_done_before + 2
def test_str(): assert str(Money('42.25', 'EUR')) == '42.25 EUR' assert str(Money('100', 'USD')) == '100 USD' assert str(Money(42, 'EUR')) == '42 EUR' assert str(Money('12.345', 'EUR')) == '12.345 EUR'
def test_repr(): assert repr(Money(42, 'EUR')) == "Money('42', 'EUR')" assert repr(Money('42.123', 'EUR')) == "Money('42.123', 'EUR')" assert repr(Money('42.0', 'EUR')) == "Money('42.0', 'EUR')" assert repr(Money('42.123', 'EUR')) == "Money('42.123', 'EUR')" assert repr(Money('42.123', 'USD')) == "Money('42.123', 'USD')"
def test_money_init_from_value_with_currency(): class Dollar(int): currency = 'USD' assert Money(Dollar(42)) == Money(42, 'USD')
def test_money_init_from_money(): assert Money(Money(123, 'GBP')) == Money(123, 'GBP')
def get_total_paid_amount(self): amounts = self.payments.values_list('amount_value', flat=True) return Money(sum(amounts, Decimal(0)), self.currency)
def money_sum(iterable): return sum(iterable, Money(0, price.currency))
def tax_amount(self): """ :rtype: shoop.utils.money.Money """ zero = Money(0, self.order.currency) return sum((x.amount for x in self.taxes.all()), zero)
def usd(value): """ Get Money with USD currency for given value. """ return Money(value, "USD")
def test_money_init_does_not_call_settings(): def guarded_getattr(self, name): assert False, 'nobody should read settings yet' with patch.object(type(settings), '__getattr__', guarded_getattr): Money(42, 'EUR')
def test_money_without_currency(): with pytest.raises(TypeError): Money(42)
base_unit_price = None quantity = None discount_amount = None tax_amount = None def __init__(self, base_unit_price, quantity, discount_amount, tax_amount): self.base_unit_price = base_unit_price self.quantity = quantity self.discount_amount = discount_amount self.tax_amount = tax_amount line = Line(base_unit_price=TaxfulPrice(5, 'EUR'), quantity=9, discount_amount=TaxfulPrice(12, 'EUR'), tax_amount=Money(3, 'EUR')) line2 = Line(base_unit_price=TaxfulPrice(10, 'EUR'), quantity=123, discount_amount=TaxfulPrice(0, 'EUR'), tax_amount=Money(123, 'EUR')) def test_price(): assert line.price == TaxfulPrice(33, 'EUR') # 5 * 9 - 12 def test_discounted_unit_price(): assert line.discounted_unit_price == TaxfulPrice(33, 'EUR') / 9 def test_discount_rate():