awesto / django-shop

A Django based shop system

Home Page:http://www.django-shop.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

problems with money_maker.py

jhonvidal opened this issue · comments

doing tests in python 3.6 everything works correctly.

The problem happens when using python version 3.8.3 it throws the following error:

ValueError at /es/admin/medexample/product/
Can not add/substract money in different currencies.
Request Method:	GET
Request URL:	http://localhost:8000/es/admin/medexample/product/
Django Version:	3.0.7
Exception Type:	ValueError
Exception Value:	
Can not add/substract money in different currencies.
Exception Location:	/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in _assert_addable, line 220
Python Executable:	/home/kira/.virtualenvs/vmedexample/bin/python
Python Version:	3.8.3
Python Path:	
['/home/kira/Desarrollo/implementacion/medexample',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages']
Server time:	Mié, 17 Jun 2020 17:46:00 +0000


/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in _assert_addable
        return 10**CURRENCIES[cls._currency_code][1]
    def _assert_addable(self, other):
        if not other:
            # so that we can add/substract zero or None to any currency
            return self.__class__('0')
        if self._currency_code != getattr(other, '_currency_code', None):
            raise ValueError("Can not add/substract money in different currencies.") …
        return other
    def _assert_multipliable(self, other):
        if hasattr(other, '_currency_code'):
            raise ValueError("Can not multiply currencies.")
        if isinstance(other, float):
▼ Local vars
Variable	Value
other	
Decimal('399.00')
self	
MoneyInEUR('399.000')

It is a project started with "cookiecutter-django-shop",
with all the data loaded with proof.

The error comes out when trying to access:

"http://localhost:8000/es/admin/medexample/product/"

clarify that it ran with python version 3.8.3

Just tried to reproduce this. However, when I access the products list view, I never enter into method _assert_addable, therefore I'm unsure, that your shop is set up the same way as the demo shop. Can you please recheck.

It is default setting with all default data using "cookiecutter-django-shop".

It is important to remember that in python 3.6 the same project works flawlessly.
The problem is when using python with version 3.8.3.
When trying to access several addresses the same error comes out, for example:

http://localhost:8000/en/catalog/


ValueError at /en/catalog/

Can not add/substract money in different currencies.

Request Method: 	GET
Request URL: 	http://localhost:8000/en/catalog/
Django Version: 	3.0.7
Exception Type: 	ValueError
Exception Value: 	

Can not add/substract money in different currencies.

Exception Location: 	/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in _assert_addable, line 220
Python Executable: 	/home/kira/.virtualenvs/vmedexample/bin/python
Python Version: 	3.8.3
Python Path: 	

['/home/kira/Desarrollo/implementacion/medexample',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages']

Server time: 	Wed, 17 Jun 2020 22:27:46 +0000
Traceback Switch to copy-and-paste view

    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/core/handlers/exception.py in inner

                    response = get_response(request)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/core/handlers/base.py in _get_response

                        response = self.process_exception_by_middleware(e, request)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/core/handlers/base.py in _get_response

                        response = wrapped_callback(request, *callback_args, **callback_kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/cms/utils/decorators.py in inner

                return func(request, *args, **kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/views/decorators/csrf.py in wrapped_view

                return view_func(*args, **kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/views/generic/base.py in view

                    return self.dispatch(request, *args, **kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/views.py in dispatch

                    response = self.handle_exception(exc)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/views.py in handle_exception

                    self.raise_uncaught_exception(exc)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/views.py in raise_uncaught_exception

                raise exc

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/views.py in dispatch

                    response = handler(request, *args, **kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/views/catalog.py in get

                response = self.list(request, *args, **kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/mixins.py in list

                    return self.get_paginated_response(serializer.data)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/serializers.py in data

                ret = super().data

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/serializers.py in data

                        self._data = self.to_representation(self.instance)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/serializers.py in to_representation

                return [

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/serializers.py in <listcomp>

                    self.child.to_representation(item) for item in iterable

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/serializers.py in to_representation

                        ret[field.field_name] = field.to_representation(attribute)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/rest_framework/fields.py in to_representation

                return method(value)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/serializers/bases.py in get_price

                return '{:f}'.format(price)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in __format__

                    amount = Decimal.quantize(self, self._cents).__format__(specifier)

         …
    ▶ Local vars
    /usr/lib/python3.8/_pydecimal.py in quantize

                    if ans != self:

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in __eq__

                other = self._assert_addable(other)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in _assert_addable

                    raise ValueError("Can not add/substract money in different currencies.")

         …
    ▶ Local vars 

http://localhost:8000/en/admin/medexample/product/ 👍


ValueError at /en/admin/medexample/product/

Can not add/substract money in different currencies.

Request Method: 	GET
Request URL: 	http://localhost:8000/en/admin/medexample/product/
Django Version: 	3.0.7
Exception Type: 	ValueError
Exception Value: 	

Can not add/substract money in different currencies.

Exception Location: 	/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in _assert_addable, line 220
Python Executable: 	/home/kira/.virtualenvs/vmedexample/bin/python
Python Version: 	3.8.3
Python Path: 	

['/home/kira/Desarrollo/implementacion/medexample',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages']

Server time: 	Wed, 17 Jun 2020 22:35:58 +0000
Error during template rendering

In template /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/templates/admin/base.html, error at line 62
Can not add/substract money in different currencies.
52 	            {% endblock %}
53 	        </div>
54 	        {% endif %}
55 	        {% endblock %}
56 	        {% block nav-global %}{% endblock %}
57 	    </div>
58 	    <!-- END Header -->
59 	    {% block breadcrumbs %}
60 	    <div class="breadcrumbs">
61 	    <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
62 	    {% if title %} &rsaquo; {{ title }}{% endif %}
63 	    </div>
64 	    {% endblock %}
65 	    {% endif %}
66 	
67 	    {% block messages %}
68 	        {% if messages %}
69 	        <ul class="messagelist">{% for message in messages %}
70 	          <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
71 	        {% endfor %}</ul>
72 	        {% endif %}
Traceback Switch to copy-and-paste view

    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/db/models/options.py in get_field

                    return self.fields_map[field_name]

         …
    ▶ Local vars
    During handling of the above exception ('get_price'), another exception occurred:
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/utils.py in lookup_field

                f = _get_non_gfk_field(opts, name)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/utils.py in _get_non_gfk_field

            field = opts.get_field(name)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/db/models/options.py in get_field

                    raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))

         …
    ▶ Local vars
    During handling of the above exception (Product has no field named 'get_price'), another exception occurred:
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/core/handlers/exception.py in inner

                    response = get_response(request)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/core/handlers/base.py in _get_response

                        response = self.process_exception_by_middleware(e, request)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/core/handlers/base.py in _get_response

                        response = response.render()

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/response.py in render

                    self.content = self.rendered_content

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/response.py in rendered_content

                return template.render(context, self._request)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/backends/django.py in render

                    return self.template.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                            return self._render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in _render

                return self.nodelist.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                        bit = node.render_annotated(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render_annotated

                    return self.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/loader_tags.py in render

                    return compiled_parent._render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in _render

                return self.nodelist.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                        bit = node.render_annotated(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render_annotated

                    return self.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/loader_tags.py in render

                    return compiled_parent._render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in _render

                return self.nodelist.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                        bit = node.render_annotated(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render_annotated

                    return self.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/loader_tags.py in render

                    return compiled_parent._render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in _render

                return self.nodelist.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                        bit = node.render_annotated(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render_annotated

                    return self.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/loader_tags.py in render

                        result = block.nodelist.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                        bit = node.render_annotated(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render_annotated

                    return self.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/loader_tags.py in render

                        result = block.nodelist.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render

                        bit = node.render_annotated(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/base.py in render_annotated

                    return self.render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/templatetags/base.py in render

                return super().render(context)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/template/library.py in render

                _dict = self.func(*resolved_args, **resolved_kwargs)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/templatetags/admin_list.py in result_list

                'results': list(results(cl)),

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/templatetags/admin_list.py in results

                    yield ResultList(None, items_for_result(cl, res, None))

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/templatetags/admin_list.py in __init__

                super().__init__(*items)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/templatetags/admin_list.py in items_for_result

                    f, attr, value = lookup_field(field_name, result, cl.model_admin)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/django/contrib/admin/utils.py in lookup_field

                    value = attr(obj)

         …
    ▶ Local vars
    /home/kira/Desarrollo/implementacion/medexample/medexample/admin.py in get_price

                return str(obj.get_real_instance().get_price(None))

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in __str__

                    vals.update(amount=Decimal.__str__(Decimal.quantize(self, self._cents)))

         …
    ▶ Local vars
    /usr/lib/python3.8/_pydecimal.py in quantize

                    if ans != self:

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in __eq__

                other = self._assert_addable(other)

         …
    ▶ Local vars
    /home/kira/.virtualenvs/vmedexample/lib/python3.8/site-packages/shop/money/money_maker.py in _assert_addable

                    raise ValueError("Can not add/substract money in different currencies.")

         …
    ▶ Local vars 

this is the configuration file settings.py:

"""
Django settings for medexample project.

For more information on this file, see
https://docs.djangoproject.com/en/stable/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/stable/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
from decimal import Decimal
import os
from django.urls import reverse_lazy
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
from cmsplugin_cascade.bootstrap4.mixins import BootstrapUtilities
from cmsplugin_cascade.extra_fields.config import PluginExtraFieldsConfig

SHOP_APP_LABEL = 'medexample'
BASE_DIR = os.path.dirname(__file__)

# Root directory for this django project
PROJECT_ROOT = os.path.abspath(os.path.join(BASE_DIR, os.path.pardir))

# Directory where working files, such as media and databases are kept
WORK_DIR = os.environ.get('DJANGO_WORKDIR', os.path.abspath(
    os.path.join(PROJECT_ROOT, 'workdir')))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/

ADMINS = [("John Doe", 'john@example.com')]

# SECURITY WARNING: in production, inject the secret key through the environment
SECRET_KEY = os.environ.get(
    'DJANGO_SECRET_KEY', 'aClgyAEAH3CGIeMPmLRr0MiZLnkn5KFmKQxJP20BX9VkDjxQ7I7GLSoRWdTauUlZ')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']

SITE_ID = 1

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# On Unix systems, a value of None will cause Django to use the same
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'UTC'

USE_THOUSAND_SEPARATOR = True

# Application definition

# replace django.contrib.auth.models.User by implementation
# allowing to login via email address
AUTH_USER_MODEL = 'email_auth.User'

AUTH_PASSWORD_VALIDATORS = [{
    'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    'OPTIONS': {
        'min_length': 6,
    }
}]

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

INSTALLED_APPS = [
    'django.contrib.auth',
    'email_auth',
    'polymorphic',
    # deprecated: 'djangocms_admin_style',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sitemaps',
    'djangocms_text_ckeditor',
    'django_select2',
    'cmsplugin_cascade',
    'cmsplugin_cascade.clipboard',
    'cmsplugin_cascade.sharable',
    'cmsplugin_cascade.extra_fields',
    'cmsplugin_cascade.icon',
    'cmsplugin_cascade.segmentation',
    'cms_bootstrap',
    'adminsortable2',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'django_elasticsearch_dsl',
    'django_fsm',
    'fsm_admin',
    'djng',
    'cms',
    'menus',
    'treebeard',
    'sass_processor',
    'sekizai',
    'django_filters',
    'filer',
    'easy_thumbnails',
    'easy_thumbnails.optimize',
    'parler',
    'post_office',
    'shop',
    'medexample',
]

MIDDLEWARE = [
    # 'django.middleware.cache.UpdateCacheMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'shop.middleware.CustomerMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.gzip.GZipMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.utils.ApphookReloadMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
    # 'django.middleware.cache.FetchFromCacheMiddleware',
]

ROOT_URLCONF = 'medexample.urls'

WSGI_APPLICATION = 'wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(WORK_DIR, 'db.sqlite3'),
    }
}

# Internationalization
# https://docs.djangoproject.com/en/stable/topics/i18n/

LANGUAGE_CODE = 'es'

USE_I18N = True

LANGUAGES = [
    ('es', _("Spanish")),
    ('en', _("English")),
]

PARLER_DEFAULT_LANGUAGE = LANGUAGE_CODE

PARLER_LANGUAGES = {
    1: [
        {'code': 'es'},
        {'code': 'en'},
    ],
    'default': {
        'fallbacks': ['es', 'en'],
    },
}

CMS_LANGUAGES = {
    'default': {
        'fallbacks': ['es', 'en'],
        'redirect_on_fallback': True,
        'public': True,
        'hide_untranslated': False,
    },
    1: [{
        'public': True,
        'code': 'es',
        'hide_untranslated': False,
        'name': 'Es',
        'redirect_on_fallback': True,
    }, {
        'public': True,
        'code': 'en',
        'hide_untranslated': False,
        'name': 'En',
        'redirect_on_fallback': True,
    }]
}
USE_L10N = True

USE_TZ = True

USE_X_FORWARDED_HOST = True

X_FRAME_OPTIONS = 'SAMEORIGIN'

# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = os.path.join(WORK_DIR, 'media')

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'

# Absolute path to the directory that holds static files.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = os.getenv('DJANGO_STATIC_ROOT', os.path.join(WORK_DIR, 'static'))

# URL that handles the static files served from STATIC_ROOT.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

STATICFILES_FINDERS = [
    # or 'django.contrib.staticfiles.finders.FileSystemFinder',
    'medexample.finders.FileSystemFinder',
    # or 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    'medexample.finders.AppDirectoriesFinder',
    'sass_processor.finders.CssFinder',
]

STATICFILES_DIRS = [
    ('node_modules', os.path.join(PROJECT_ROOT, 'node_modules')),
]

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'APP_DIRS': True,
    'DIRS': [],
    'OPTIONS': {
        'context_processors': [
            'django.contrib.auth.context_processors.auth',
            'django.template.context_processors.debug',
            'django.template.context_processors.i18n',
            'django.template.context_processors.media',
            'django.template.context_processors.static',
            'django.template.context_processors.tz',
            'django.template.context_processors.csrf',
            'django.template.context_processors.request',
            'django.contrib.messages.context_processors.messages',
            'sekizai.context_processors.sekizai',
            'cms.context_processors.cms_settings',
            'shop.context_processors.customer',
            'shop.context_processors.shop_settings',
        ]
    }
}, {
    'BACKEND': 'post_office.template.backends.post_office.PostOfficeTemplates',
    'APP_DIRS': True,
    'DIRS': [],
    'OPTIONS': {
        'context_processors': [
            'django.contrib.auth.context_processors.auth',
            'django.template.context_processors.debug',
            'django.template.context_processors.i18n',
            'django.template.context_processors.media',
            'django.template.context_processors.static',
            'django.template.context_processors.tz',
            'django.template.context_processors.request',
        ]
    }
}]

POST_OFFICE = {
    'TEMPLATE_ENGINE': 'post_office',
}

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
    'select2': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
    }
}

############################################
# settings for caching and storing session data
REDIS_HOST = os.getenv('REDIS_HOST')
if REDIS_HOST:
    SESSION_ENGINE = 'redis_sessions.session'

    SESSION_REDIS = {
        'host': REDIS_HOST,
        'port': 6379,
        'db': 0,
        'prefix': 'session-',
        'socket_timeout': 1
    }

    CACHES['default'] = {
        'BACKEND': 'redis_cache.RedisCache',
        'LOCATION': 'redis://{}:6379/1'.format(REDIS_HOST),
    }

    CACHE_MIDDLEWARE_ALIAS = 'default'
    CACHE_MIDDLEWARE_SECONDS = 3600
else:
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

SESSION_SAVE_EVERY_REQUEST = True

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'filters': {'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'}},
    'formatters': {
        'simple': {
            'format': '[%(asctime)s %(module)s] %(levelname)s: %(message)s'
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': True,
        },
        'post_office': {
            'handlers': ['console'],
            'level': 'WARNING',
            'propagate': True,
        },
    },
}

SILENCED_SYSTEM_CHECKS = ['auth.W004']

FIXTURE_DIRS = [
    os.path.join(WORK_DIR, 'fixtures'),
]

############################################
# settings for sending mail

EMAIL_HOST = os.getenv('DJANGO_EMAIL_HOST', 'localhost')
EMAIL_PORT = os.getenv('DJANGO_EMAIL_PORT', 25)
EMAIL_HOST_USER = os.getenv('DJANGO_EMAIL_USER', 'no-reply@localhost')
EMAIL_HOST_PASSWORD = os.getenv('DJANGO_EMAIL_PASSWORD', 'smtp-secret')
EMAIL_USE_TLS = bool(os.getenv('DJANGO_EMAIL_USE_TLS', '1'))
DEFAULT_FROM_EMAIL = os.getenv('DJANGO_EMAIL_FROM', 'no-reply@localhost')
EMAIL_REPLY_TO = os.getenv('DJANGO_EMAIL_REPLY_TO', 'info@localhost')
EMAIL_BACKEND = 'post_office.EmailBackend'


############################################
# settings for third party Django apps

NODE_MODULES_URL = STATIC_URL + 'node_modules/'

SASS_PROCESSOR_INCLUDE_DIRS = [
    os.path.join(PROJECT_ROOT, 'node_modules'),
]

COERCE_DECIMAL_TO_STRING = True

FSM_ADMIN_FORCE_PERMIT = True

ROBOTS_META_TAGS = ('noindex', 'nofollow')

SERIALIZATION_MODULES = {'json': str('shop.money.serializers')}

############################################
# settings for django-restframework and plugins

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'shop.rest.money.JSONRenderer',
        # can be disabled for production environments
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ],
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    # 'PAGE_SIZE': 16,
}

REST_AUTH_SERIALIZERS = {
    'LOGIN_SERIALIZER': 'shop.serializers.auth.LoginSerializer',
}

############################################
# settings for storing files and images

FILER_ADMIN_ICON_SIZES = ('16', '32', '48', '80', '128')

FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS = True

FILER_DUMP_PAYLOAD = False

FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880

THUMBNAIL_HIGH_RESOLUTION = False

THUMBNAIL_PRESERVE_EXTENSIONS = True

THUMBNAIL_PROCESSORS = (
    'easy_thumbnails.processors.colorspace',
    'easy_thumbnails.processors.autocrop',
    'filer.thumbnail_processors.scale_and_crop_with_subject_location',
    'easy_thumbnails.processors.filters',
)


############################################
# settings for django-cms and its plugins

CMS_TEMPLATES = [
    ('medexample/pages/default.html', _("Default Page")),
]

CMS_CACHE_DURATIONS = {
    'content': 600,
    'menus': 3600,
    'permissions': 86400,
}

CMS_PERMISSION = True

CMS_PLACEHOLDER_CONF = {
    'Breadcrumb': {
        'plugins': ['BreadcrumbPlugin'],
        'parent_classes': {'BreadcrumbPlugin': None},
    },
    'Commodity Details': {
        'plugins': ['BootstrapContainerPlugin', 'BootstrapJumbotronPlugin'],
        'parent_classes': {
            'BootstrapContainerPlugin': None,
            'BootstrapJumbotronPlugin': None,
        },
    },
    'Main Content': {
        'plugins': ['BootstrapContainerPlugin', 'BootstrapJumbotronPlugin'],
        'parent_classes': {
            'BootstrapContainerPlugin': None,
            'BootstrapJumbotronPlugin': None,
            'TextLinkPlugin': ['TextPlugin', 'AcceptConditionPlugin'],
        },
    },
    'Static Footer': {
        'plugins': ['BootstrapContainerPlugin', 'BootstrapJumbotronPlugin'],
        'parent_classes': {
            'BootstrapContainerPlugin': None,
            'BootstrapJumbotronPlugin': None,
        },
    },
}

CMSPLUGIN_CASCADE_PLUGINS = [
    'cmsplugin_cascade.bootstrap4',
    'cmsplugin_cascade.segmentation',
    'cmsplugin_cascade.generic',
    'cmsplugin_cascade.icon',
    'cmsplugin_cascade.leaflet',
    'cmsplugin_cascade.link',
    'shop.cascade',
]

CMSPLUGIN_CASCADE = {
    'link_plugin_classes': [
        'shop.cascade.plugin_base.CatalogLinkPluginBase',
        'shop.cascade.plugin_base.CatalogLinkForm',
    ],
    'alien_plugins': ['TextPlugin', 'TextLinkPlugin', 'AcceptConditionPlugin'],
    'bootstrap4': {
        'template_basedir': 'angular-ui/',
    },
    'plugins_with_extra_render_templates': {
        'CustomSnippetPlugin': [
            ('shop/catalog/product-heading.html', _("Product Heading")),
            ('medexample/catalog/manufacturer-filter.html', _("Manufacturer Filter")),
        ],
        # required to purchase real estate
        'ShopAddToCartPlugin': [
            (None, _("Default")),
            ('medexample/catalog/commodity-add2cart.html', _("Add Commodity to Cart")),
        ],
    },
    'plugins_with_sharables': {
        'BootstrapImagePlugin': ['image_shapes', 'image_width_responsive', 'image_width_fixed',
                                 'image_height', 'resize_options'],
        'BootstrapPicturePlugin': ['image_shapes', 'responsive_heights', 'responsive_zoom', 'resize_options'],
    },
    'plugins_with_extra_fields': {
        'BootstrapCardPlugin': PluginExtraFieldsConfig(),
        'BootstrapCardHeaderPlugin': PluginExtraFieldsConfig(),
        'BootstrapCardBodyPlugin': PluginExtraFieldsConfig(),
        'BootstrapCardFooterPlugin': PluginExtraFieldsConfig(),
        'SimpleIconPlugin': PluginExtraFieldsConfig(),
    },
    'plugins_with_extra_mixins': {
        'BootstrapContainerPlugin': BootstrapUtilities(),
        'BootstrapRowPlugin': BootstrapUtilities(BootstrapUtilities.paddings),
        'BootstrapYoutubePlugin': BootstrapUtilities(BootstrapUtilities.margins),
        'BootstrapButtonPlugin': BootstrapUtilities(BootstrapUtilities.floats),
    },
    'leaflet': {
        'tilesURL': 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}',
        'accessToken': 'pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw',
        'apiKey': 'AIzaSyD71sHrtkZMnLqTbgRmY_NsO0A9l9BQmv4',
    },
    'bookmark_prefix': '/',
    'segmentation_mixins': [
        ('shop.cascade.segmentation.EmulateCustomerModelMixin',
         'shop.cascade.segmentation.EmulateCustomerAdminMixin'),
    ],
    'allow_plugin_hiding': True,
    'register_page_editor': True,
}

CKEDITOR_SETTINGS = {
    'language': '{{ language }}',
    'skin': 'moono-lisa',
    'toolbar_CMS': [
        ['Undo', 'Redo'],
        ['cmsplugins', '-', 'ShowBlocks'],
        ['Format'],
        ['TextColor', 'BGColor', '-', 'PasteText', 'PasteFromWord'],
        '/',
        ['Bold', 'Italic', 'Underline', 'Strike', '-',
            'Subscript', 'Superscript', '-', 'RemoveFormat'],
        ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
        ['HorizontalRule'],
        ['NumberedList', 'BulletedList', 'Outdent', 'Indent'],
        ['Table', 'Source']
    ],
    'stylesSet': format_lazy('default:{}', reverse_lazy('admin:cascade_texteditor_config')),
}

CKEDITOR_SETTINGS_CAPTION = {
    'language': '{{ language }}',
    'skin': 'moono-lisa',
    'height': 70,
    'toolbar_HTMLField': [
        ['Undo', 'Redo'],
        ['Format', 'Styles'],
        ['Bold', 'Italic', 'Underline', '-', 'Subscript',
            'Superscript', '-', 'RemoveFormat'],
        ['Source']
    ],
}

CKEDITOR_SETTINGS_DESCRIPTION = {
    'language': '{{ language }}',
    'skin': 'moono-lisa',
    'height': 250,
    'toolbar_HTMLField': [
        ['Undo', 'Redo'],
        ['cmsplugins', '-', 'ShowBlocks'],
        ['Format', 'Styles'],
        ['TextColor', 'BGColor', '-', 'PasteText', 'PasteFromWord'],
        ['Maximize', ''],
        '/',
        ['Bold', 'Italic', 'Underline', '-', 'Subscript',
            'Superscript', '-', 'RemoveFormat'],
        ['JustifyLeft', 'JustifyCenter', 'JustifyRight'],
        ['HorizontalRule'],
        ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'],
        ['Source']
    ],
}

SELECT2_CSS = 'node_modules/select2/dist/css/select2.min.css'
SELECT2_JS = 'node_modules/select2/dist/js/select2.min.js'
SELECT2_I18N_PATH = 'node_modules/select2/dist/js/i18n'


#############################################
# settings for full index text search

ELASTICSEARCH_HOST = os.getenv('ELASTICSEARCH_HOST', 'localhost')

ELASTICSEARCH_DSL = {
    'default': {
        'hosts': '{}:9200'.format(ELASTICSEARCH_HOST)
    },
}

############################################
# settings for django-shop and its plugins

SHOP_VALUE_ADDED_TAX = Decimal(19)
SHOP_DEFAULT_CURRENCY = 'EUR'
SHOP_EDITCART_NG_MODEL_OPTIONS = "{updateOn: 'default blur', debounce: {'default': 2500, 'blur': 0}}"

SHOP_CART_MODIFIERS = [
    'medexample.modifiers.PrimaryCartModifier',
    'shop.modifiers.taxes.CartExcludedTaxModifier',
    'medexample.modifiers.PostalShippingModifier',
    'shop.payment.modifiers.PayInAdvanceModifier',
    'shop.shipping.modifiers.SelfCollectionModifier',
]

SHOP_ORDER_WORKFLOWS = [
    'shop.payment.workflows.ManualPaymentWorkflowMixin',
    'shop.payment.workflows.CancelOrderWorkflowMixin',
    'shop.shipping.workflows.PartialDeliveryWorkflowMixin',
]


SHOP_CASCADE_FORMS = {
    'CustomerForm': 'medexample.forms.CustomerForm',
}

I just retested with version 3.8.1 and here everything works fine.
Closing because I can't reproduce. Feel free to reopen, if you found new evidence for a bug.

I can confirm,
Python 3.8.6, default settings

 File "/home/darek/.local/share/virtualenvs/my-shop-OpEeVNpI/lib/python3.8/site-packages/shop/money/money_maker.py", line 220, in _assert_addable
    raise ValueError("Can not add/substract money in different currencies.")
ValueError: Can not add/substract money in different currencies.

@darekmeco would you mind adding a unit test which reproduces this error on Python-3.8 but works on Python<=3.7?