Example #1
0
 def test_defaults(self):
     money = Money(10, "EUR")
     instance, _ = ModelWithVanillaMoneyField.objects.get_or_create(
         integer=1, defaults={"money": money})
     assert instance.money == money
Example #2
0
    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
Example #3
0
class TestGetOrCreate:
    @pytest.mark.parametrize(
        "model, field_name, kwargs, currency",
        (
            (ModelWithVanillaMoneyField, "money", {
                "money_currency": "PLN"
            }, "PLN"),
            (ModelWithVanillaMoneyField, "money", {
                "money": Money(0, "EUR")
            }, "EUR"),
            (ModelWithVanillaMoneyField, "money", {
                "money": OldMoney(0, "EUR")
            }, "EUR"),
            (ModelWithSharedCurrency, "first", {
                "first": 10,
                "second": 15,
                "currency": "CZK"
            }, "CZK"),
        ),
    )
    def test_get_or_create_respects_currency(self, model, field_name, kwargs,
                                             currency):
        instance, created = model.objects.get_or_create(**kwargs)
        field = getattr(instance, field_name)
        assert str(
            field.currency
        ) == currency, "currency should be taken into account in get_or_create"

    def test_get_or_create_respects_defaults(self):
        value = Money(10, "SEK")
        instance = ModelWithUniqueIdAndCurrency.objects.create(money=value)
        instance, created = ModelWithUniqueIdAndCurrency.objects.get_or_create(
            id=instance.id, money_currency=instance.money_currency)
        assert not created
        assert instance.money == value

    def test_defaults(self):
        money = Money(10, "EUR")
        instance, _ = ModelWithVanillaMoneyField.objects.get_or_create(
            integer=1, defaults={"money": money})
        assert instance.money == money

    def test_currency_field_lookup(self):
        value = Money(10, "EUR")
        ModelWithVanillaMoneyField.objects.create(money=value)
        instance, created = ModelWithVanillaMoneyField.objects.get_or_create(
            money_currency__iexact="eur")
        assert not created
        assert instance.money == value

    @pytest.mark.parametrize(
        "model, create_kwargs, get_kwargs",
        (
            (NullMoneyFieldModel, {
                "field": Money(100, "USD")
            }, {
                "field": 100,
                "field_currency": "USD"
            }),
            (ModelWithSharedCurrency, {
                "first": 10,
                "second": 15,
                "currency": "USD"
            }, {
                "first": 10,
                "currency": "USD"
            }),
        ),
    )
    def test_no_default_model(self, model, create_kwargs, get_kwargs):
        model.objects.create(**create_kwargs)
        instance, created = model.objects.get_or_create(**get_kwargs)
        assert not created

    def test_shared_currency(self):
        instance, created = ModelWithSharedCurrency.objects.get_or_create(
            first=10, second=15, currency="USD")
        assert instance.first == Money(10, "USD")
        assert instance.second == Money(15, "USD")
Example #4
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
Example #5
0
 def _money_from_obj(self, obj):
     amount = obj.__dict__[self.field.name]
     currency = obj.__dict__[self.currency_field_name]
     if amount is None:
         return None
     return Money(amount=amount, currency=currency)
Example #6
0
 def test_query_not_null(self):
     money = Money(100, "EUR")
     ModelWithNullableCurrency.objects.create(money=money)
     instance = ModelWithNullableCurrency.objects.get()
     assert instance.money == money
Example #7
0
class TestVanillaMoneyField:
    @pytest.mark.parametrize(
        "model_class, kwargs, expected",
        (
            (ModelWithVanillaMoneyField, {
                "money": Money("100.0")
            }, Money("100.0")),
            (ModelWithVanillaMoneyField, {
                "money": OldMoney("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": OldMoney("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")),
            (CryptoModel, {
                "money": Money(10, "USDT")
            }, Money(10, "USDT")),
        ),
    )
    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

    def test_old_money_defaults(self):
        instance = ModelWithDefaultAsOldMoney.objects.create()
        assert instance.money == Money(".01", "RUB")

    @pytest.mark.parametrize(
        "model_class, other_value",
        (
            (ModelWithVanillaMoneyField, Money("100.0")),
            (BaseModel, Money(0, "USD")),
            (ModelWithDefaultAsMoney, Money("0.01", "RUB")),
            (ModelWithDefaultAsFloat, OldMoney("12.05", "PLN")),
            (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("money_class", (Money, OldMoney))
    @pytest.mark.parametrize("field_name", ("money", "second_money"))
    def test_save_new_value(self, field_name, money_class):
        ModelWithVanillaMoneyField.objects.create(
            **{field_name: money_class("100.0")})

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

        assert getattr(retrieved, field_name) == Money(1, "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(params=[Money, OldMoney])
    def objects_setup(self, request):
        Money = request.param
        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=OldMoney(1, "USD")) | Q(amount1=OldMoney(4, "USD"))
             | Q(amount2=OldMoney(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

    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_issue_300_regression(self):
        date = datetime.datetime(year=2017, month=2, day=1)
        ModelIssue300.objects.filter(money__created=date)
        ModelIssue300.objects.filter(money__created__gt=date)

    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

    def test_filter_chaining(self):
        usd_instance = ModelWithVanillaMoneyField.objects.create(
            money=Money(100, "USD"))
        ModelWithVanillaMoneyField.objects.create(money=Money(100, "EUR"))
        query = ModelWithVanillaMoneyField.objects.filter().filter(
            money=Money(100, "USD"))
        assert usd_instance in query
        assert query.count() == 1

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

        assert model_class.objects.filter(
            money__lt=Money("1000", "USD")).count() == 0
        assert model_class.objects.filter(
            money__lt=Money("1000", "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

    @pytest.mark.usefixtures("objects_setup")
    def test_in_lookup_f_expression(self):
        assert ModelWithTwoMoneyFields.objects.filter(
            amount1__in=(Money(4, "USD"), F("amount2"))).count() == 2

    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
Example #8
0
def test_default_truediv():
    assert Money(10, "USD") / 2 == Money(5, "USD")
Example #9
0
def test_round():
    assert round(Money("1.69", "USD"), 1) == Money("1.7", "USD")
Example #10
0
def test_html_safe():
    assert Money("10.5", "EUR").__html__() == u"10.50\xa0€"
Example #11
0
def test_default_mul():
    assert Money(10, "USD") * 2 == Money(20, "USD")
    def handle(self, *args, **options):
        '''
        Create the default store of our application.
        '''
        store, was_created = Store.objects.update_or_create(
            id=1,
            defaults={
                'id': 1,
                'name': 'Mikaponics',
                'currency': 'CAD',
                'timezone_name': "America/Toronto",
                'tax_rates': { # http://www.calculconversion.com/sales-tax-calculator-hst-gst.html
                    'CA': {
                        'NL': 15,      # Newfoundland and Labrador
                        'PE': 15,      # Prince Edward Island
                        'NS': 15,      # Nova Scotia
                        'NB': 15,      # New Brunswick
                        'QC': 14.975,  # Quebec
                        'ON': 13,      # Ontario
                        'MB': 13,      # Manitoba
                        'SK': 11,      # Saskatchewan
                        'AB': 5,       # Alberta
                        'BC': 12,      # British Columbia
                        'YT': 5,       # Yukon
                        'NT': 5,       # Northwest Territories
                        'NU': 5,       # Nunavut
                    },
                    'international': 13,
                },
                'referrer_credit':  Money(10, 'CAD'),
                'referee_credit': Money(5, 'CAD'),
            }
        )

        '''
        Create the product which integrates with our MIKAPOD project. See via
        link: https://github.com/mikaponics/mikapod-py. This is our default
        product to offer in the onboarding code.
        '''
        Product.objects.update_or_create(
            id=MIKAPONICS_SOIL_PRODUCT_ID,
            store=store,
            defaults={
                'id': MIKAPONICS_SOIL_PRODUCT_ID,
                'store': store,
                'slug': 'soil',
                'sort_number': 1,
                'icon': 'seedling',
                'name': "Mikapod - Soil",
                "short_description": "Device used for monitoring soil based planting solution.",
                'description': 'Mikapod soil telemetry device',
                'price': Money(249.99, 'CAD'),
                'state': Product.STATE.PUBLISHED
            }
        )
        Product.objects.update_or_create(
            id=MIKAPONICS_HYDROPONICS_PRODUCT_ID,
            store=store,
            defaults={
                'id': MIKAPONICS_HYDROPONICS_PRODUCT_ID,
                'store': store,
                'slug': 'hydroponic',
                'sort_number': 2,
                'icon': 'water',
                'name': "Mikapod - Hydroponics",
                "short_description": "Device used for monitoring pure water based planting solution.",
                'description': 'Mikapod hydroponics telemetry device',
                "price": Money(249.99, 'CAD'),
                'state': Product.STATE.COMING_SOON
            }
        )
        Product.objects.update_or_create(
            id=MIKAPONICS_AQUAPONICS_PRODUCT_ID,
            store=store,
            defaults={
                'id': MIKAPONICS_AQUAPONICS_PRODUCT_ID,
                'store': store,
                'slug': 'aquaponic',
                'sort_number': 3,
                'icon': 'fish',
                'name': "Mikapod - Aquaponics",
                "short_description": "Device used for monitoring a water and aquaculture mixed planting solution.",
                'description': 'Mikapod aquaponics telemetry device',
                "price": Money(249.99, 'CAD'),
                'state': Product.STATE.COMING_SOON
            }
        )
        Product.objects.update_or_create(
            id=MIKAPONICS_ALGAE_PRODUCT_ID,
            store=store,
            defaults={
                'id': MIKAPONICS_ALGAE_PRODUCT_ID,
                'store': store,
                'slug': 'algae',
                'sort_number': 4,
                'icon': 'vial',
                'name': "Mikapod - Algae",
                "short_description": "Device used for monitoring algae (ex. Sparilina) based planting solution.",
                'description': 'Mikapod algae telemetry device',
                "price": Money(249.99, 'CAD'),
                'state': Product.STATE.COMING_SOON
            }
        )
        Product.objects.update_or_create(
            id=MIKAPONICS_AUTHORIZED_DEVICE_PRODUCT_ID,
            store=store,
            defaults={
                'id': MIKAPONICS_AUTHORIZED_DEVICE_PRODUCT_ID,
                'store': store,
                'slug': 'authorized-device',
                'sort_number': 5,
                'icon': 'seedling',
                'name': "Authorized Device",
                "short_description": "Custom device authorized to us Mikaponics.",
                'description': '',
                'price': Money(249.99, 'CAD'),
                'state': Product.STATE.HIDDEN
            }
        )

        '''
        Create the default shipper for our store.
        '''
        Shipper.objects.update_or_create(
            id=MIKAPONICS_DEFAULT_SHIPPER_ID,
            store=store,
            name='Generic shipper',
            shipping_price=Money(amount=10,currency='CAD')
        )
    def create(self, validated_data):
        #---------------------------------------
        # Get the user inputs from the request.
        #---------------------------------------

        order = validated_data.get('order', None)
        paid_at = validated_data.get('paid_at', None)
        deposit_method = validated_data.get('deposit_method', None)
        paid_to = validated_data.get('paid_to', None)
        paid_for = validated_data.get('paid_for', None)
        amount = validated_data.get('amount', None)

        #---------------------------------------
        # Create our `OngoingWorkOrder` objects.
        #---------------------------------------

        deposit = WorkOrderDeposit.objects.create(
            order=order,
            paid_at=paid_at,
            deposit_method=deposit_method,
            paid_to=paid_to,
            paid_for=paid_for,
            amount=amount,
            created_by=self.context['created_by'],
            created_from=self.context['created_from'],
            created_from_is_public=self.context['created_from_is_public'],
            last_modified_by=self.context['created_by'],
            last_modified_from=self.context['created_from'],
            last_modified_from_is_public=self.
            context['created_from_is_public'],
        )

        #---------------------------------------
        # Calculate the new deposit amount.
        #---------------------------------------

        deposits = WorkOrderDeposit.objects.filter(order=order)
        amount = 0
        for deposit in deposits.all():
            amount += deposit.amount.amount

        order.invoice_deposit_amount = Money(
            amount, constants.WORKERY_APP_DEFAULT_MONEY_CURRENCY)
        order.invoice_amount_due = order.invoice_total_amount - order.invoice_deposit_amount
        order.last_modified_by = self.context['created_by']
        order.last_modified_from = self.context['created_from']
        order.last_modified_from_is_public = self.context[
            'created_from_is_public']
        order.save()

        #---------------------------------------
        # Create a comment with special text.
        #---------------------------------------
        comment_text = str(
            self.context['created_by']) + " recorded a payment of $" + str(
                amount) + " on " + str(
                    self.context['franchise'].get_todays_date_plus_days())
        comment = Comment.objects.create(
            created_by=self.context['created_by'],
            created_from=self.context['created_from'],
            created_from_is_public=self.context['created_from_is_public'],
            last_modified_by=self.context['created_by'],
            last_modified_from=self.context['created_from'],
            last_modified_from_is_public=self.
            context['created_from_is_public'],
            text=comment_text,
        )
        WorkOrderComment.objects.create(
            about=order,
            comment=comment,
        )
        logger.info("Created and attached comment to order.")

        # Return our validated data.
        return deposit
                         term=15,
                         down_payment=Money(40_000, 'USD'),
                         interest_rate=4.25),
     Loan.objects.create(rental_property=self.mock_properties[3],
                         term=20,
                         down_payment=Money(10_000, 'USD'),
                         interest_rate=3.375),
     Loan.objects.create(rental_property=self.mock_properties[4],
                         term=30,
                         down_payment=Money(90_000, 'USD'),
                         interest_rate=5.00))
 self.mock_tenants = (
     Tenant.objects.create(rental_property=self.mock_properties[0],
                           name="James",
                           email="*****@*****.**",
                           rent_payment=Money(2000, 'USD')),
     Tenant.objects.create(rental_property=self.mock_properties[1],
                           name="John",
                           email="*****@*****.**",
                           rent_payment=Money(2200, 'USD')),
     Tenant.objects.create(rental_property=self.mock_properties[2],
                           name="Juliet",
                           email="*****@*****.**",
                           rent_payment=Money(2400, 'USD')),
     Tenant.objects.create(rental_property=self.mock_properties[3],
                           name="Peter",
                           email="*****@*****.**",
                           rent_payment=Money(1800, 'USD')),
     Tenant.objects.create(rental_property=self.mock_properties[4],
                           name="Marie",
                           email="*****@*****.**",
Example #15
0
 def test_shared_currency(self):
     instance, created = ModelWithSharedCurrency.objects.get_or_create(
         first=10, second=15, currency="USD")
     assert instance.first == Money(10, "USD")
     assert instance.second == Money(15, "USD")
Example #16
0
def test_configurable_decimal_number():
    # Override default configuration per instance
    assert str(Money("10.543", "USD", decimal_places=3)) == "$10.543"
Example #17
0
 def test_create_default(self):
     money = Money(100, "SEK")
     instance = ModelWithNullableCurrency.objects.create(money=money)
     assert instance.money == money
Example #18
0
def test_repr():
    assert repr(Money("10.5", "USD")) == "<Money: 10.5 USD>"
Example #19
0
class TestFExpressions:

    parametrize_f_objects = pytest.mark.parametrize(
        "f_obj, expected",
        (
            (F("money") + Money(100, "USD"), Money(200, "USD")),
            (F("money") + OldMoney(100, "USD"), Money(200, "USD")),
            (Money(100, "USD") + F("money"), Money(200, "USD")),
            (F("money") - Money(100, "USD"), Money(0, "USD")),
            (Money(100, "USD") - F("money"), Money(0, "USD")),
            (F("money") * 2, Money(200, "USD")),
            (F("money") * F("integer"), Money(200, "USD")),
            (Money(50, "USD") * F("integer"), Money(100, "USD")),
            (F("integer") * Money(50, "USD"), Money(100, "USD")),
            (Money(50, "USD") / F("integer"), Money(25, "USD")),
            (Money(51, "USD") % F("integer"), Money(1, "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.refresh_from_db()
        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.refresh_from_db()
        assert instance.money == expected

    def test_default_update(self):
        instance = ModelWithVanillaMoneyField.objects.create(money=Money(
            100, "USD"),
                                                             integer=2)
        second_money = Money(100, "USD")
        ModelWithVanillaMoneyField.objects.update(second_money=second_money)
        instance.refresh_from_db()
        assert instance.second_money == second_money

    @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.refresh_from_db()
        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
Example #20
0
 def objects_setup(self, request):
     Money = request.param
     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")),
     ))
Example #21
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
Example #22
0
 def test_in_lookup_f_expression(self):
     assert ModelWithTwoMoneyFields.objects.filter(
         amount1__in=(Money(4, "USD"), F("amount2"))).count() == 2
Example #23
0
 def test_objects_creation(self):
     SimpleModel.objects.create(money=Money("100.0", "USD"))
     assert SimpleModel.objects.count() == 1
Example #24
0
def m2m_object():
    return ModelWithDefaultAsInt.objects.create(money=Money(100, "USD"))