awesto / django-shop

A Django based shop system
http://www.django-shop.org
BSD 3-Clause "New" or "Revised" License
3.2k stars 1.04k forks source link

"Can not add/subtract money in different currencies." #855

Closed mliudev closed 2 years ago

mliudev commented 3 years ago

OS: Arch Linux 5.12.1-arch1-1 python: 3.6.13 django-shop: 1.1.4 django: 2.2.16

I get the following stack trace when setting a product price to anything other than 0:

Traceback (most recent call last):
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
    return self.application(environ, start_response)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/wsgi.py", line 141, in __call__
    response = self.get_response(request)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/base.py", line 75, in get_response
    response = self._middleware_chain(request)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/six.py", line 702, in reraise
    raise value.with_traceback(tb)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/cms/utils/decorators.py", line 19, in inner
    return func(request, *args, **kwargs)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/shop/search/views.py", line 139, in __call__
    return self.list_view(request)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
    raise exc
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/shop/views/catalog.py", line 134, in get
    response = self.list(request, *args, **kwargs)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/mixins.py", line 43, in list
    return self.get_paginated_response(serializer.data)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/serializers.py", line 757, in data
    ret = super().data
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/serializers.py", line 261, in data
    self._data = self.to_representation(self.instance)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/serializers.py", line 675, in to_representation
    self.child.to_representation(item) for item in iterable
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/serializers.py", line 675, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/serializers.py", line 526, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/rest_framework/fields.py", line 1873, in to_representation
    return method(value)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/shop/serializers/bases.py", line 58, in get_price
    return '{:f}'.format(price)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/shop/money/money_maker.py", line 58, in __format__
    amount = Decimal.quantize(self, self._cents).__format__(specifier)
  File "/usr/lib/python3.6/_pydecimal.py", line 2625, in quantize
    if ans != self:
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/shop/money/money_maker.py", line 160, in __eq__
    other = self._assert_addable(other)
  File "<redacted>/.virtualenvs/sites-36/lib/python3.6/site-packages/shop/money/money_maker.py", line 233, in _assert_addable
    raise ValueError("Can not add/substract money in different currencies.")
ValueError: Can not add/substract money in different currencies.

After some digging it seems that _assert_addable is comparing a MoneyInUSD to a Decimal which throws this exception. Decimal.quantize(self, self._cents) appears to do ans = self._rescale(exp._exp, rounding) which makes ans a decimal:

[console ready]
>>> ans
Decimal('1.00')

While self is still:

>>> self
MoneyInUSD('1.000')

Not sure where to keep digging from here. Any advice?

jhonvidal commented 3 years ago

I have the same problem and so far I can't find a solution, if you managed to solve it please tell us how

mliudev commented 3 years ago

I have the same problem and so far I can't find a solution, if you managed to solve it please tell us how

It seems like this is platform dependent for us. Users on MacOS don't seem to have this issue nor Ubuntu. It seemed to be only on my Arch distro that this shows up. It could be something specific to my version of Python compiled on Arch.

jhonvidal commented 3 years ago

I have the same problem and so far I can't find a solution, if you managed to solve it please tell us how

It seems like this is platform dependent for us. Users on MacOS don't seem to have this issue nor Ubuntu. It seemed to be only on my Arch distro that this shows up. It could be something specific to my version of Python compiled on Arch.

I go all day trying to solve, what sadness

mliudev commented 2 years ago

No longer working on this issue. Closing.