Exemplo n.º 1
0
 def test_price(self):
     with patch('exchange.conversion.ExchangeRates') as exchange_rates:
         exchange_rates.get_instance.return_value = \
             {'USD': {'GBP': 0.5}}
         price = Money(3, 'USD')
         converted_price = price.convert('GBP')
         self.assertEqual(converted_price.amount, 1.50)
         self.assertEqual(converted_price.currency, 'GBP')
Exemplo n.º 2
0
 def __set__(self, obj, value):
     if isinstance(value, tuple):
         value = Money(amount=value[0], currency=value[1])
     if isinstance(value, Money):
         obj.__dict__[self.field.name] = value.amount
         setattr(obj, self.currency_field_name, smart_unicode(value.currency))
     elif isinstance(value, BaseExpression):
         if isinstance(value.children[1], Money):
             value.children[1] = value.children[1].amount
         obj.__dict__[self.field.name] = value
     else:
         if value:
             value = str(value)
         obj.__dict__[self.field.name] = self.field.to_python(value)
Exemplo n.º 3
0
 def __set__(self, obj, value):
     if isinstance(value, tuple):
         if len(value) != 2:
             raise ValueError('Invalid value for MoneyField: %s' % str(value))
         value = Money(amount=value[0], currency=value[1])
     if isinstance(value, Money):
         obj.__dict__[self.field.name] = value.amount
         # we have to determine whether to replace the currency.
         # i.e. if we do the following:
         # .objects.get_or_create(money_currency='EUR')
         # then the currency is already set up, before this code hits
         # __set__ of MoneyField. This is because the currency field
         # has less creation counter than money field.
         obj_curr = obj.__dict__[self.currency_field_name]
         val_curr = str(value.currency)
         def_curr = str(self.field.default_currency)
         if obj_curr != val_curr:
             # in other words, update the currency only if it wasn't
             # changed before.
             if obj_curr == def_curr:
                 setattr(
                     obj, self.currency_field_name,
                     smart_unicode(value.currency))
     elif isinstance(value, BaseExpression):
         # we can only allow this operation if the currency matches.
         # otherwise, one could use F() with different currencies
         # which should not be possible.
         def _check_currency(obj, field, amt):
             currency_field_name = get_currency_field_name(field.name)
             if obj.__dict__[currency_field_name] != str(amt.currency):
                 raise ValueError(
                     'You cannot use F() with different currencies.')
         if VERSION < (1, 8):
             _check_currency(obj, self.field, value.children[1])
             # Django 1.8 removed `children` attribute.
             if isinstance(value.children[1], Money):
                 value.children[1] = value.children[1].amount
         elif VERSION >= (1, 8, 0):
             _check_currency(obj, self.field, value.rhs.value)
             # value.lhs contains F expression, i.e.
             # F(field)
             # rhs contains our value, however we need to extract the amount
             # it is an analogy to the above code (pre Django-1.8)
             value.rhs.value = value.rhs.value.amount
         obj.__dict__[self.field.name] = value
     else:
         if value:
             value = str(value)
         obj.__dict__[self.field.name] = self.field.to_python(value)
Exemplo n.º 4
0
    def test_object_to_money(self):
        data = {'amount': 10, 'currency': 'USD'}

        self.assertEqual(self.serializer.to_internal_value(data),
                         Money(10, 'USD'))
 def to_internal_value(self, data):
     if isinstance(data, Money):
         amount = super(MoneyField, self).to_internal_value(data.amount)
         return Money(amount, data.currency)
     return super(MoneyField, self).to_internal_value(data)
Exemplo n.º 6
0
class TestVanillaMoneyField:
    @pytest.mark.parametrize('model_class, kwargs, expected', (
        (ModelWithVanillaMoneyField, {
            'money': Money('100.0')
        }, Money('100.0')),
        (BaseModel, {}, Money(0, 'USD')),
        (BaseModel, {
            'money': '111.2'
        }, Money('111.2', 'USD')),
        (BaseModel, {
            'money': Money('123', 'PLN')
        }, Money('123', 'PLN')),
        (BaseModel, {
            'money': ('123', 'PLN')
        }, Money('123', 'PLN')),
        (BaseModel, {
            'money': (123.0, 'PLN')
        }, Money('123', 'PLN')),
        (ModelWithDefaultAsMoney, {}, Money('0.01', 'RUB')),
        (ModelWithDefaultAsFloat, {}, Money('12.05', 'PLN')),
        (ModelWithDefaultAsStringWithCurrency, {}, Money('123', 'USD')),
        (ModelWithDefaultAsString, {}, Money('123', 'PLN')),
        (ModelWithDefaultAsInt, {}, Money('123', 'GHS')),
        (ModelWithDefaultAsDecimal, {}, Money('0.01', 'CHF')),
    ))
    def test_create_defaults(self, model_class, kwargs, expected):
        instance = model_class.objects.create(**kwargs)
        assert instance.money == expected

        retrieved = model_class.objects.get(pk=instance.pk)
        assert retrieved.money == expected

    @pytest.mark.parametrize('model_class, other_value', (
        (ModelWithVanillaMoneyField, Money('100.0')),
        (BaseModel, Money(0, 'USD')),
        (ModelWithDefaultAsMoney, Money('0.01', 'RUB')),
        (ModelWithDefaultAsFloat, Money('12.05', 'PLN')),
    ))
    def test_revert_to_default(self, model_class, other_value):
        if hasattr(model_class._meta, 'get_field'):
            default_instance = model_class._meta.get_field(
                'money').get_default()
        else:
            default_instance = model_class._meta.get_field_by_name(
                'money').default
        instance1 = model_class.objects.create()
        pk = instance1.pk
        # Grab a fresh instance, change the currency to something non-default
        # and unexpected
        instance2 = model_class.objects.get(id=pk)
        instance2.money = Money(other_value.amount, "DKK")
        instance2.save()
        instance3 = model_class.objects.get(id=pk)
        assert instance3.money == Money(other_value.amount, "DKK")
        # Now change the field back to the default currency
        instance3.money = copy(default_instance)
        instance3.save()
        instance4 = model_class.objects.get(id=pk)
        assert instance4.money == default_instance

    @pytest.mark.parametrize('value', (
        (1, 'USD', 'extra_string'),
        (1, None),
        (1, ),
    ))
    def test_invalid_values(self, value):
        with pytest.raises(ValidationError):
            BaseModel.objects.create(money=value)

    @pytest.mark.parametrize('field_name', ('money', 'second_money'))
    def test_save_new_value(self, field_name):
        ModelWithVanillaMoneyField.objects.create(
            **{field_name: Money('100.0')})

        # Try setting the value directly
        retrieved = ModelWithVanillaMoneyField.objects.get()
        setattr(retrieved, field_name, Money(1, moneyed.DKK))
        retrieved.save()
        retrieved = ModelWithVanillaMoneyField.objects.get()

        assert getattr(retrieved, field_name) == Money(1, moneyed.DKK)

    def test_rounding(self):
        money = Money('100.0623456781123219')

        instance = ModelWithVanillaMoneyField.objects.create(money=money)
        # TODO. Should instance.money be rounded too?

        retrieved = ModelWithVanillaMoneyField.objects.get(pk=instance.pk)

        assert retrieved.money == Money('100.06')

    @pytest.fixture
    def objects_setup(self):
        ModelWithTwoMoneyFields.objects.bulk_create((
            ModelWithTwoMoneyFields(amount1=Money(1, 'USD'),
                                    amount2=Money(2, 'USD')),
            ModelWithTwoMoneyFields(amount1=Money(2, 'USD'),
                                    amount2=Money(0, 'USD')),
            ModelWithTwoMoneyFields(amount1=Money(3, 'USD'),
                                    amount2=Money(0, 'USD')),
            ModelWithTwoMoneyFields(amount1=Money(4, 'USD'),
                                    amount2=Money(0, 'GHS')),
            ModelWithTwoMoneyFields(amount1=Money(5, 'USD'),
                                    amount2=Money(5, 'USD')),
            ModelWithTwoMoneyFields(amount1=Money(5, 'EUR'),
                                    amount2=Money(5, 'USD')),
        ))

    @pytest.mark.parametrize('filters, expected_count', (
        (Q(amount1=F('amount2')), 1),
        (Q(amount1__gt=F('amount2')), 2),
        (Q(amount1__in=(Money(1, 'USD'), Money(5, 'EUR'))), 2),
        (Q(id__in=(-1, -2)), 0),
        (Q(amount1=Money(1, 'USD')) | Q(amount2=Money(0, 'USD')), 3),
        (Q(amount1=Money(1, 'USD')) | Q(amount1=Money(4, 'USD'))
         | Q(amount2=Money(0, 'GHS')), 2),
        (Q(amount1=Money(1, 'USD')) | Q(amount1=Money(5, 'USD'))
         | Q(amount2=Money(0, 'GHS')), 3),
        (Q(amount1=Money(1, 'USD'))
         | Q(amount1=Money(4, 'USD'), amount2=Money(0, 'GHS')), 2),
        (Q(amount1=Money(1, 'USD'))
         | Q(amount1__gt=Money(4, 'USD'), amount2=Money(0, 'GHS')), 1),
        (Q(amount1=Money(1, 'USD'))
         | Q(amount1__gte=Money(4, 'USD'), amount2=Money(0, 'GHS')), 2),
    ))
    @pytest.mark.usefixtures('objects_setup')
    def test_comparison_lookup(self, filters, expected_count):
        assert ModelWithTwoMoneyFields.objects.filter(
            filters).count() == expected_count

    @pytest.mark.skipif(VERSION < (1, 9),
                        reason='Only Django 1.9+ supports __date lookup')
    def test_date_lookup(self):
        DateTimeModel.objects.create(field=Money(1, 'USD'),
                                     created='2016-12-05')
        assert DateTimeModel.objects.filter(
            created__date='2016-12-01').count() == 0
        assert DateTimeModel.objects.filter(
            created__date='2016-12-05').count() == 1

    @pytest.mark.parametrize(
        'lookup, rhs, expected',
        (('startswith', 2, 1), ('regex', '^[134]', 3), ('iregex', '^[134]', 3),
         ('istartswith', 2, 1), ('contains', 5, 2), ('lt', 5, 4),
         ('endswith', 5, 2), ('iendswith', 5, 2), ('gte', 4, 3),
         ('iexact', 3, 1), ('exact', 3, 1), ('isnull', True, 0), ('range',
                                                                  (3, 5), 4),
         ('lte', 2, 2), ('gt', 3, 3), ('icontains', 5, 2), ('in', (1, 0), 1)))
    @pytest.mark.usefixtures('objects_setup')
    def test_all_lookups(self, lookup, rhs, expected):
        kwargs = {'amount1__' + lookup: rhs}
        assert ModelWithTwoMoneyFields.objects.filter(
            **kwargs).count() == expected

    def test_exact_match(self):
        money = Money('100.0')

        instance = ModelWithVanillaMoneyField.objects.create(money=money)
        retrieved = ModelWithVanillaMoneyField.objects.get(money=money)

        assert instance.pk == retrieved.pk

    def test_range_search(self):
        money = Money('3')

        instance = ModelWithVanillaMoneyField.objects.create(
            money=Money('100.0'))
        retrieved = ModelWithVanillaMoneyField.objects.get(money__gt=money)

        assert instance.pk == retrieved.pk

        assert ModelWithVanillaMoneyField.objects.filter(
            money__lt=money).count() == 0

    @pytest.mark.parametrize(
        'model_class',
        (ModelWithVanillaMoneyField, ModelWithChoicesMoneyField))
    def test_currency_querying(self, model_class):
        model_class.objects.create(money=Money('100.0', moneyed.ZWN))

        assert model_class.objects.filter(
            money__lt=Money('1000', moneyed.USD)).count() == 0
        assert model_class.objects.filter(
            money__lt=Money('1000', moneyed.ZWN)).count() == 1

    @pytest.mark.usefixtures('objects_setup')
    def test_in_lookup(self):
        assert ModelWithTwoMoneyFields.objects.filter(
            amount1__in=(Money(1, 'USD'), Money(5, 'EUR'))).count() == 2
        assert ModelWithTwoMoneyFields.objects.filter(
            Q(amount1__lte=Money(2, 'USD')),
            amount1__in=(Money(1, 'USD'), Money(3, 'USD'))).count() == 1
        assert ModelWithTwoMoneyFields.objects.exclude(
            amount1__in=(Money(1, 'USD'), Money(5, 'EUR'))).count() == 4
        assert ModelWithTwoMoneyFields.objects.filter(
            amount1__in=(1, Money(5, 'EUR'))).count() == 2
        assert ModelWithTwoMoneyFields.objects.filter(
            amount1__in=(1, 5)).count() == 3

    def test_isnull_lookup(self):
        NullMoneyFieldModel.objects.create(field=None)
        NullMoneyFieldModel.objects.create(field=Money(100, 'USD'))

        queryset = NullMoneyFieldModel.objects.filter(field=None)
        assert queryset.count() == 1

    def test_null_default(self):
        instance = NullMoneyFieldModel.objects.create()
        assert instance.field is None
Exemplo n.º 7
0
 def test_deposit(self):
     """ Add some money to the acc"""
     self.assertRaises(SystemExit, deposit, ['--client', 'Joe', '--amount', 0.5])
     self.assertEqual(Money(1001, settings.CURRENCY), self.acc.current_balance)
Exemplo n.º 8
0
 def aggregated_sum(self, qs):
     qs = qs.aggregate(total=Sum('amount'))
     return Money(qs['total'] or 0, settings.DEFAULT_CURRENCY)
Exemplo n.º 9
0
 def fuzz(self):
     return Money(super().fuzz(), 'SEK')
Exemplo n.º 10
0
 def test_get_stock_price_no_stocks(self):
     price = get_stock_price(ProductFactory(), Location.LOCATION_STORAGE)
     self.assertEqual(price, Money(0, "EUR"))
Exemplo n.º 11
0
 def test_ne(self):
     assert MoneyPatched(1, 'EUR') != Money(2, 'EUR')
Exemplo n.º 12
0
 def test_ne_currency(self):
     assert MoneyPatched(10, 'EUR') != Money(10, 'USD')
Exemplo n.º 13
0
 def test_sub_with_auto_convert(self, settings):
     settings.AUTO_CONVERT_MONEY = True
     result = MoneyPatched(10, 'EUR') - Money(1, 'USD')
     assert Decimal(str(round(result.amount, 2))) == Decimal('9.23')
     assert result.currency == moneyed.EUR
Exemplo n.º 14
0
 def test_eq(self):
     assert MoneyPatched(1, 'EUR') == Money(1, 'EUR')
Exemplo n.º 15
0
 def test_sub_default(self):
     with pytest.raises(TypeError):
         MoneyPatched(10, 'EUR') - Money(1, 'USD')
Exemplo n.º 16
0
 def test_patching(self):
     ProxyModel.objects.create(money=Money('100.0', 'USD'))
     # This will fail if ProxyModel.objects doesn't have the patched manager
     assert ProxyModel.objects.filter(
         money__gt=Money('50.00', 'GBP')).count() == 0
Exemplo n.º 17
0
 def test_instances(self):
     ProxyModel.objects.create(money=Money('100.0', 'USD'))
     assert isinstance(ProxyModel.objects.get(pk=1), ProxyModel)
Exemplo n.º 18
0
    def clean(self):
        cleaned_data = super(PaypalFundForm, self).clean()

        budget = cleaned_data["budget"]
        bonus = cleaned_data["bonus"]

        if budget.amount < 10:
            raise forms.ValidationError('Ensure budget is greater than or equal to %s' % Money(10, CAD))

        if bonus.amount > budget.amount:
            raise forms.ValidationError('Ensure budget is greater than bonus')

        if bonus > self.account.bonus_budget:
            raise forms.ValidationError('Ensure bonus is lower than or equal to %s' % self.account.bonus_budget)

        return cleaned_data
Exemplo n.º 19
0
 def test_incompatibility(self, settings):
     settings.AUTO_CONVERT_MONEY = True
     with pytest.raises(ImproperlyConfigured) as exc:
         MoneyPatched(10, 'EUR') - Money(1, 'USD')
     assert str(exc.value) == 'djmoney_rates doesn\'t support Django 1.9+'
Exemplo n.º 20
0
class WalletFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Wallet

    owner_id = factory.Sequence(lambda n: str(uuid.uuid4()))
    balance = Money(0, 'SEK')
Exemplo n.º 21
0
def test_properties_access():
    with pytest.raises(TypeError) as exc:
        ModelWithVanillaMoneyField(money=Money(1, 'USD'), bla=1)
    assert str(
        exc.value) == "'bla' is an invalid keyword argument for this function"
Exemplo n.º 22
0
 def test_get_stock_price(self):
     price = get_stock_price(self.product_a, Location.LOCATION_STORAGE)
     self.assertEqual(price, Money(2.6, "EUR"))
Exemplo n.º 23
0
 def test_it_should_prevent_paying_a_zero_amount(self):
     with raises(PreconditionError,
                 match='Can only pay stricty positive amounts.'):
         initiate_payment(self.account, Money(0, 'CHF'))
Exemplo n.º 24
0
    def create(self, validated_data):
        """
          'title',
          'image', - mock
          'description',
          'duration',
          'weight',
          'task_address',
          'customer_address',
          'created_at',
          'pay_type',
          'delivery_cost',
          'product_cost',
          'total_money',
          'note',
          'worker_id',
          'worker_rate',
          'status',
          'id',
          'currency',
          'items'
        """
        task_data = validated_data
        title = task_data['title']
        desc = task_data['description']
        duration = task_data['duration']
        weight = task_data['weight']
        pay_type = task_data['pay_type']
        note = task_data['note']
        service = task_data['service']
        customer = task_data['customer']
        task_address = task_data['task_address']
        place = task_data['place']

        customer_address = validated_data.pop('customer_address')
        c_address = Address.objects.get_or_create(
            **customer_address
        )
        customer_address = c_address[0]

        delivery_cost = Money(task_data['delivery_cost'])
        product_cost = Money(task_data['product_cost'])
        if self.initial_data.get('currency'):
            delivery_cost.currency = self.initial_data.get('currency')
            product_cost.currency = self.initial_data.get('currency')

        task = Task.objects.create(
            description=desc,
            title=title,
            duration=duration,
            weight=weight,
            pay_type=pay_type,
            delivery_cost=delivery_cost,
            product_cost=product_cost,
            note=note,
            service=service,
            customer=customer,
            place=place,
            customer_address=customer_address,
            task_address=task_address
        )
        task_items = task_data["task_to_product"]
        for items in task_items:
            s = TaskItem.objects.create(
                task=task,
                product=items['product'],
                quantity=items['quantity']
            )
            s.save()

        task.save()
        return task
Exemplo n.º 25
0
def test_allow_expression_nodes_without_money():
    """Allow querying on expression nodes that are not Money"""
    desc = 'hundred'
    ModelWithNonMoneyField.objects.create(money=Money(100.0), desc=desc)
    instance = ModelWithNonMoneyField.objects.filter(desc=F('desc')).get()
    assert instance.desc == desc
Exemplo n.º 26
0
 def test_withdraw(self):
     """ Remove some money from the acc"""
     self.assertRaises(SystemExit, withdraw, ['--client', 'Joe', '--amount', 1000])
     self.assertEqual(Money(0.5, settings.CURRENCY), self.acc.current_balance)
Exemplo n.º 27
0
 def test_invalid_expressions_access(self, f_obj):
     instance = ModelWithVanillaMoneyField.objects.create(
         money=Money(100, 'USD'))
     with pytest.raises(ValidationError):
         instance.money = f_obj
Exemplo n.º 28
0
def zero_dollars(currency=CAD):
    return Money('0', currency)
Exemplo n.º 29
0
    def test_float_to_money(self):
        data = 10.0

        self.assertEqual(self.serializer.to_internal_value(data),
                         Money(10.0, 'EUR'))
Exemplo n.º 30
0
 def test_it_should_prepare_payment_when_all_is_right(self):
     params = initiate_payment(self.account, Money(10, 'CHF'))
     assert params
     assert not params.use_alias
Exemplo n.º 31
0
 def test_objects_creation(self):
     SimpleModel.objects.create(money=Money('100.0', 'USD'))
     assert SimpleModel.objects.count() == 1
Exemplo n.º 32
0
 def _zero_balance(self):
     """Get a balance for this account with all currencies set to zero"""
     return Balance([Money("0", currency) for currency in self.currencies])
Exemplo n.º 33
0
class TestFExpressions:

    parametrize_f_objects = pytest.mark.parametrize('f_obj, expected', (
        (F('money') + Money(100, 'USD'), Money(200, 'USD')),
        (F('money') - Money(100, 'USD'), Money(0, 'USD')),
        (F('money') * 2, Money(200, 'USD')),
        (F('money') * F('integer'), Money(200, 'USD')),
        (F('money') / 2, Money(50, 'USD')),
        (F('money') % 98, Money(2, 'USD')),
        (F('money') / F('integer'), Money(50, 'USD')),
        (F('money') + F('money'), Money(200, 'USD')),
        (F('money') - F('money'), Money(0, 'USD')),
    ))

    @parametrize_f_objects
    def test_save(self, f_obj, expected):
        instance = ModelWithVanillaMoneyField.objects.create(money=Money(
            100, 'USD'),
                                                             integer=2)
        instance.money = f_obj
        instance.save()
        instance = ModelWithVanillaMoneyField.objects.get(pk=instance.pk)
        assert instance.money == expected

    @parametrize_f_objects
    def test_f_update(self, f_obj, expected):
        instance = ModelWithVanillaMoneyField.objects.create(money=Money(
            100, 'USD'),
                                                             integer=2)
        ModelWithVanillaMoneyField.objects.update(money=f_obj)
        instance = ModelWithVanillaMoneyField.objects.get(pk=instance.pk)
        assert instance.money == expected

    @pytest.mark.parametrize('create_kwargs, filter_value, in_result', (
        ({
            'money': Money(100, 'USD'),
            'second_money': Money(100, 'USD')
        }, {
            'money': F('money')
        }, True),
        ({
            'money': Money(100, 'USD'),
            'second_money': Money(100, 'USD')
        }, {
            'money': F('second_money')
        }, True),
        ({
            'money': Money(100, 'USD'),
            'second_money': Money(100, 'EUR')
        }, {
            'money': F('second_money')
        }, False),
        ({
            'money': Money(50, 'USD'),
            'second_money': Money(100, 'USD')
        }, {
            'second_money': F('money') * 2
        }, True),
        ({
            'money': Money(50, 'USD'),
            'second_money': Money(100, 'USD')
        }, {
            'second_money': F('money') + Money(50, 'USD')
        }, True),
        ({
            'money': Money(50, 'USD'),
            'second_money': Money(100, 'EUR')
        }, {
            'second_money': F('money') * 2
        }, False),
        ({
            'money': Money(50, 'USD'),
            'second_money': Money(100, 'EUR')
        }, {
            'second_money': F('money') + Money(50, 'USD')
        }, False),
    ))
    def test_filtration(self, create_kwargs, filter_value, in_result):
        instance = ModelWithVanillaMoneyField.objects.create(**create_kwargs)
        assert (instance in ModelWithVanillaMoneyField.objects.filter(
            **filter_value)) is in_result

    def test_update_fields_save(self):
        instance = ModelWithVanillaMoneyField.objects.create(money=Money(
            100, 'USD'),
                                                             integer=2)
        instance.money = F('money') + Money(100, 'USD')
        instance.save(update_fields=['money'])
        instance = ModelWithVanillaMoneyField.objects.get(pk=instance.pk)
        assert instance.money == Money(200, 'USD')

    INVALID_EXPRESSIONS = [
        F('money') + Money(100, 'EUR'),
        F('money') * F('money'),
        F('money') / F('money'),
        F('money') % F('money'),
        F('money') + F('integer'),
        F('money') + F('second_money'),
        F('money')**F('money'),
        F('money')**F('integer'),
        F('money')**2,
    ]

    @pytest.mark.parametrize('f_obj', INVALID_EXPRESSIONS)
    def test_invalid_expressions_access(self, f_obj):
        instance = ModelWithVanillaMoneyField.objects.create(
            money=Money(100, 'USD'))
        with pytest.raises(ValidationError):
            instance.money = f_obj