示例#1
0
 def test_currency(self):
     Money = MoneyMaker('EUR')
     self.assertEqual(Money.currency, 'EUR')
     self.assertEqual(Money.subunits, 100)
     Money = MoneyMaker('JPY')
     self.assertEqual(Money.currency, 'JPY')
     self.assertEqual(Money.subunits, 1)
示例#2
0
    def test_reduce(self):
        Money = MoneyMaker('EUR')
        value = Money()
        func, args = value.__reduce__()
        self.assertTrue(func is _make_money)
        self.assertEqual(args, ("EUR", "NaN"))

        Money = func(*args)
        self.assertTrue(Money.is_nan())
示例#3
0
 def __init__(self, *args, **kwargs):
     self.currency_code = kwargs.pop('currency', app_settings.DEFAULT_CURRENCY)
     self.Money = MoneyMaker(self.currency_code)
     defaults = {
         'max_digits': 30,
         'decimal_places': CURRENCIES[self.currency_code][1],
     }
     defaults.update(kwargs)
     super().__init__(*args, **defaults)
示例#4
0
    def test_reduce(self):
        Money = MoneyMaker('EUR')
        value = Money()
        func, args = value.__reduce__()
        self.assertTrue(func is _make_money)
        self.assertEqual(args, ("EUR", "NaN"))

        Money = func(*args)
        self.assertTrue(Money.is_nan())
示例#5
0
 def test_filter_with_strings(self):
     amount = MoneyMaker('EUR')('12.34')
     m1 = Manufacturer(name="Rosebutt")
     m1.save()
     bag = Commodity.objects.create(unit_price=amount,
                                    product_code='B',
                                    order=1,
                                    product_name="Bag",
                                    slug='bag',
                                    manufacturer=m1,
                                    caption="This is a bag")
     self.assertEqual(list(Commodity.objects.filter(unit_price='12.34')),
                      [bag])
     self.assertEqual(list(Commodity.objects.filter(unit_price='12.35')),
                      [])
     self.assertEqual(
         list(Commodity.objects.filter(unit_price__gt='12.33')), [bag])
     self.assertEqual(
         list(Commodity.objects.filter(unit_price__gt='12.34')), [])
     self.assertEqual(
         list(Commodity.objects.filter(unit_price__gte='12.34')), [bag])
     self.assertEqual(
         list(Commodity.objects.filter(unit_price__lt='12.35')), [bag])
     self.assertEqual(
         list(Commodity.objects.filter(unit_price__lt='12.34')), [])
     self.assertEqual(
         list(Commodity.objects.filter(unit_price__lte='12.34')), [bag])
示例#6
0
 def test_json(self):
     EUR = MoneyMaker('EUR')
     renderer = JSONRenderer()
     data = {'amount': EUR('1.23')}
     rendered_json = renderer.render(data, 'application/json')
     self.assertDictEqual({'amount': "€ 1.23"},
                          json.loads(rendered_json.decode('utf-8')))
示例#7
0
 def test_to_python(self):
     EUR = MoneyMaker('EUR')
     f = MoneyDbField(currency='EUR', null=True)
     self.assertEqual(f.to_python(3), EUR('3'))
     self.assertEqual(f.to_python('3.14'), EUR('3.14'))
     self.assertEqual(f.to_python(None), EUR())
     with self.assertRaises(ValidationError):
         f.to_python('abc')
示例#8
0
def test_truediv():
    Money = MoneyMaker()
    assert Money(1).__truediv__(2) == Money(0.5)
    assert Money(1).__truediv__(2.0) == Money(0.5)
    with pytest.raises(ValueError):
        Money(1).__truediv__(Money(2))
    with pytest.raises(ValueError):
        Money(1).__rtruediv__(2)
示例#9
0
def test_div():
    Money = MoneyMaker()
    assert Money(1) / 2, Money(0.5)
    assert Money(1) / 2.0, Money(0.5)
    with pytest.raises(ValueError):
        Money(1) / Money(2)
    with pytest.raises(ValueError):
        Money(1).__rdiv__(2)
示例#10
0
 def test_default(self):
     EUR = MoneyMaker('EUR')
     f = MoneyDbField(currency='EUR', null=False)
     self.assertEqual(f.get_default(), EUR())
     f = MoneyDbField(currency='EUR', null=True)
     self.assertEqual(f.get_default(), EUR())
     f = MoneyDbField(currency='EUR')
     self.assertEqual(f.get_default(), EUR())
示例#11
0
 def test_as_bool(self):
     Money = MoneyMaker()
     amount = Money('1.23')
     self.assertTrue(bool(amount))
     amount = Money(0)
     self.assertFalse(bool(amount))
     amount = Money()
     self.assertFalse(bool(amount))
示例#12
0
 def __init__(self, *args, **kwargs):
     self.currency_code = kwargs.pop('currency', app_settings.DEFAULT_CURRENCY)
     self.Money = MoneyMaker(self.currency_code)
     defaults = {
         'max_digits': 30,
         'decimal_places': CURRENCIES[self.currency_code][1],
     }
     defaults.update(kwargs)
     super(MoneyField, self).__init__(*args, **defaults)
示例#13
0
 def __init__(self, money_class=None, **kwargs):
     if money_class is None:
         money_class = MoneyMaker()
     if not issubclass(money_class, AbstractMoney):
         raise AttributeError("Given `money_class` does not declare a valid money type")
     self.Money = money_class
     if 'widget' not in kwargs:
         kwargs['widget'] = MoneyFieldWidget(attrs={'currency_code': money_class.currency})
     super().__init__(**kwargs)
示例#14
0
 def test_default(self):
     EUR = MoneyMaker('EUR')
     OneEuro = EUR(1)
     f = MoneyDbField(currency='EUR', null=True)
     self.assertEqual(f.get_default(), None)
     f = MoneyDbField(currency='EUR', null=True, default=EUR())
     self.assertEqual(f.get_default(), EUR())
     f = MoneyDbField(currency='EUR', null=False, default=OneEuro)
     self.assertEqual(f.get_default(), OneEuro)
示例#15
0
 def test_wrong_currency_raises_assertion_error(self):
     # If we try to call a money class with a value that has a
     # different currency than the class, and the value is an
     # instance of the money class, there should be an
     # AssertionError.
     Money = MoneyMaker(currency_code='EUR')
     value = Money()
     value._currency_code = 'USD'
     self.assertRaises(AssertionError, lambda: Money(value))
示例#16
0
def test_float():
    Money = MoneyMaker()
    money = Money(Decimal('sNaN'))
    with pytest.raises(ValueError):
        float(money)
    money = Money(Decimal('NaN'))
    assert math.isnan(float(money)) is True
    money = Money(Decimal('-NaN'))
    assert math.isnan(float(money)) is True
    money = Money(Decimal('1.0'))
    assert float(money) == 1.0
示例#17
0
 def test_float_format(self):
     EUR = MoneyMaker('EUR')
     d = Decimal(1.99)
     e = EUR(d)
     self.assertEqual('{}'.format(e), "€ 1.99")
     self.assertEqual('{:}'.format(e), "€ 1.99")
     self.assertEqual('{:f}'.format(e), "€ 1.99")
     self.assertEqual('{:.5}'.format(e), "€ 1.9900")
     self.assertEqual('{:.5f}'.format(e), "€ 1.99000")
     self.assertEqual('{:.20}'.format(e), "€ {:.20}".format(d))
     self.assertEqual('{:.20f}'.format(e), "€ {:.20f}".format(d))
示例#18
0
 def test_mul(self):
     Money = MoneyMaker()
     self.assertEqual(Money(1) * 1, Money(1))
     self.assertEqual(Money(1) * 0, Money(0))
     self.assertEqual(Money(1) * -1, Money(-1))
     self.assertEqual(Money(1) * 1, Money(1))
     self.assertEqual(Money(1) * 0, Money(0))
     self.assertEqual(Money(1).__rmul__(-1), Money(-1))
     self.assertEqual(Money(1).__rmul__(1.0), Money(1))
     self.assertEqual(format(Money(1) * None), "€ –")
     self.assertRaises(ValueError, lambda: Money(1) * (Money(1)))
示例#19
0
def test_mul():
    Money = MoneyMaker()
    assert Money(1) * 1 == Money(1)
    assert Money(1) * 0 == Money(0)
    assert Money(1) * -1 == Money(-1)
    assert Money(1) * 1 == Money(1)
    assert Money(1) * 0 == Money(0)
    assert Money(1).__rmul__(-1) == Money(-1)
    assert Money(1).__rmul__(1.0) == Money(1)
    assert format(Money(1) * None) == "€ –"
    with pytest.raises(ValueError):
        Money(1) * (Money(1))
示例#20
0
 def test_add_zero(self):
     Money = MoneyMaker()
     self.assertEqual(Money('1.23') + 0, Money('1.23'))
     self.assertEqual(Money('1.23') + 0.0, Money('1.23'))
     self.assertEqual(Money('1.23') + Money('NaN'), Money('1.23'))
     self.assertEqual(0 + Money('1.23'), Money('1.23'))
     self.assertEqual(0.0 + Money('1.23'), Money('1.23'))
     self.assertEqual(Money('NaN') + Money('1.23'), Money('1.23'))
     self.assertRaises(ValueError, lambda: Money(1) + 1)
     self.assertRaises(ValueError, lambda: Money(1) + 1.0)
     self.assertRaises(ValueError, lambda: 1 + Money(1))
     self.assertRaises(ValueError, lambda: 1.0 + Money(1))
示例#21
0
    def test_float(self):
        Money = MoneyMaker()

        money = Money(Decimal('sNaN'))
        self.assertRaises(ValueError, lambda: float(money))

        money = Money(Decimal('NaN'))
        self.assertTrue(math.isnan(float(money)))

        money = Money(Decimal('-NaN'))
        self.assertTrue(math.isnan(float(money)))

        money = Money(Decimal('1.0'))
        self.assertEqual(float(money), 1.0)
示例#22
0
def test_add_zero():
    Money = MoneyMaker()
    assert Money('1.23') + 0 == Money('1.23')
    assert Money('1.23') + 0.0 == Money('1.23')
    assert Money('1.23') + Money('NaN') == Money('1.23')
    assert 0 + Money('1.23') == Money('1.23')
    assert 0.0 + Money('1.23') == Money('1.23')
    assert Money('NaN') + Money('1.23') == Money('1.23')
    with pytest.raises(ValueError):
        Money(1) + 1
    with pytest.raises(ValueError):
        Money(1) + 1.0
    with pytest.raises(ValueError):
        1 + Money(1)
    with pytest.raises(ValueError):
        1.0 + Money(1)
示例#23
0
 def test_str(self):
     EUR = MoneyMaker('EUR')
     value = EUR()
     self.assertEqual(text_type(value), "€ –")
     value = EUR('999999.99')
     self.assertEqual(text_type(value), "€ 999,999.99")
     value = EUR('999999.995')  # check rounding
     self.assertEqual(text_type(value), "€ 1,000,000.00")
     value = EUR('-111111.114')
     self.assertEqual(text_type(value), "-€ 111,111.11")
     with self.settings(USE_THOUSAND_SEPARATOR=False):
         self.assertEqual(text_type(value), "-€ 111111.11")
     with self.settings(LANGUAGE_CODE='de'):
         self.assertEqual(text_type(value), "-€ 111.111,11")
         value.MONEY_FORMAT = '{minus}{amount} {code}'
         self.assertEqual(text_type(value), "-111.111,11 EUR")
示例#24
0
 def test_create_money_type_without_decimal_places(self):
     Money = MoneyMaker(currency_code='JPY')
     self.assertEqual(Money._cents, 0)
示例#25
0
 def test_format(self):
     EUR, JPY = MoneyMaker('EUR'), MoneyMaker('JPY')
     self.assertEqual(format(EUR()), "€ –")
     self.assertEqual(format(JPY()), "¥ –")
     self.assertEqual(format(EUR(1.1)), "€ 1.10")
     self.assertEqual(format(JPY(1)), "¥ 1")
示例#26
0
class MoneyField(models.DecimalField):
    """
    A MoneyField shall be used to store money related amounts in the database, keeping track of
    the used currency. Accessing a model field of type MoneyField, returns a MoneyIn<CURRENCY> type.
    """
    description = _("Money in %(currency_code)s")

    def __init__(self, *args, **kwargs):
        self.currency_code = kwargs.pop('currency', app_settings.DEFAULT_CURRENCY)
        self.Money = MoneyMaker(self.currency_code)
        defaults = {
            'max_digits': 30,
            'decimal_places': CURRENCIES[self.currency_code][1],
        }
        defaults.update(kwargs)
        super(MoneyField, self).__init__(*args, **defaults)

    def deconstruct(self):
        name, path, args, kwargs = super(MoneyField, self).deconstruct()
        if kwargs['max_digits'] == 30:
            kwargs.pop('max_digits')
        if kwargs['decimal_places'] == CURRENCIES[self.currency_code][1]:
            kwargs.pop('decimal_places')
        return name, path, args, kwargs

    def to_python(self, value):
        if isinstance(value, AbstractMoney):
            return value
        if value is None:
            return self.Money('NaN')
        value = super(MoneyField, self).to_python(value)
        return self.Money(value)

    def get_prep_value(self, value):
        # force to type Decimal by using grandparent super
        value = super(models.DecimalField, self).get_prep_value(value)
        return super(MoneyField, self).to_python(value)

    def from_db_value(self, value, expression, connection, context):
        if value is None:
            return
        if isinstance(value, float):
            value = str(value)
        return self.Money(value)

    def get_db_prep_save(self, value, connection):
        if isinstance(value, Decimal) and value.is_nan():
            return None
        return super(MoneyField, self).get_db_prep_save(value, connection)

    def get_prep_lookup(self, lookup_type, value):
        if isinstance(value, AbstractMoney):
            if value.get_currency() != self.Money.get_currency():
                msg = "This field stores money in {}, but the lookup amount is in {}"
                raise ValueError(msg.format(value.get_currency(), self.Money.get_currency()))
            value = value.as_decimal()
        result = super(MoneyField, self).get_prep_lookup(lookup_type, value)
        return result

    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        # grandparent super
        value = super(models.DecimalField, self).get_prep_value(value)
        return self.to_python(value)

    def formfield(self, **kwargs):
        widget = MoneyFieldWidget(attrs={'currency_code': self.Money.currency})
        defaults = {'form_class': MoneyFormField, 'widget': widget, 'money_class': self.Money}
        defaults.update(**kwargs)
        formfield = super(MoneyField, self).formfield(**defaults)
        return formfield
示例#27
0
 def test_str(self):
     EUR = MoneyMaker('EUR')
     value = EUR()
     self.assertEqual(text_type(value), "€ –")
示例#28
0
 def test_str_with_too_much_precision(self):
     EUR = MoneyMaker('EUR')
     value = EUR(1)
     prec = getcontext().prec
     value._cents = Decimal("0." + ("0" * prec))
     self.assertRaises(ValueError, lambda: str(value))
示例#29
0
 def test_create_instance_from_decimal(self):
     value = Decimal('1.2')
     EUR = MoneyMaker('EUR')
     self.assertTrue(issubclass(EUR, Decimal))
     self.assertIsInstance(EUR(value), Decimal)
示例#30
0
 def test_create_instance_with_invalid_value(self):
     Money = MoneyMaker()
     self.assertRaises(ValueError, lambda: Money(value="invalid"))
示例#31
0
 def test_create_instance_with_value_as_none(self):
     Money = MoneyMaker()
     money = Money(value=None)
     self.assertTrue(money.is_nan())
示例#32
0
 def test_create_money_type_with_unknown_currency(self):
     self.assertRaises(ValueError, lambda: MoneyMaker(currency_code="ABC"))
示例#33
0
 def test_create_money_type_without_arguments(self):
     Money = MoneyMaker()
     amount = Money()
     self.assertTrue(amount.is_nan())