From 88f57a211f06865a028e25e20f3d75cae49047dc Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 30 Jun 2021 23:35:57 +0200 Subject: [PATCH 01/20] setting for default currency --- InvenTree/common/models.py | 1 + InvenTree/templates/InvenTree/settings/currencies.html | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 7e56429c51..9bd3612e55 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -14,6 +14,7 @@ from django.db import models, transaction from django.db.utils import IntegrityError, OperationalError from django.conf import settings +from djmoney.settings import CURRENCY_CHOICES from djmoney.models.fields import MoneyField from djmoney.contrib.exchange.models import convert_money from djmoney.contrib.exchange.exceptions import MissingRate diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index 78598236f9..6e61533e6b 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -12,6 +12,13 @@ {% block settings %} + + {% include "InvenTree/settings/header.html" %} + + {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-globe" %} + +
+ From 92645d790bfdfc600adeac2200a25329a8034641 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 30 Jun 2021 23:36:46 +0200 Subject: [PATCH 02/20] use setting for currency_code_default --- InvenTree/common/settings.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/InvenTree/common/settings.py b/InvenTree/common/settings.py index 60265f4cb9..299d142ea9 100644 --- a/InvenTree/common/settings.py +++ b/InvenTree/common/settings.py @@ -8,7 +8,6 @@ from __future__ import unicode_literals from moneyed import CURRENCIES import common.models -from django.conf import settings def currency_code_default(): @@ -16,7 +15,7 @@ def currency_code_default(): Returns the default currency code (or USD if not specified) """ - code = settings.BASE_CURRENCY + code = common.models.InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') if code not in CURRENCIES: code = 'USD' From 2c7a4a124659824a607b6e2b62c1b8f371738111 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 30 Jun 2021 23:38:48 +0200 Subject: [PATCH 03/20] switching out BASE_CURRENCY --- InvenTree/InvenTree/apps.py | 3 ++- InvenTree/InvenTree/exchange.py | 3 ++- InvenTree/InvenTree/settings.py | 4 ---- InvenTree/InvenTree/tasks.py | 3 ++- InvenTree/InvenTree/views.py | 3 ++- InvenTree/part/views.py | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/InvenTree/InvenTree/apps.py b/InvenTree/InvenTree/apps.py index aeddb714a0..79269d7b74 100644 --- a/InvenTree/InvenTree/apps.py +++ b/InvenTree/InvenTree/apps.py @@ -66,10 +66,11 @@ class InvenTreeConfig(AppConfig): from djmoney.contrib.exchange.models import ExchangeBackend from datetime import datetime, timedelta from InvenTree.tasks import update_exchange_rates + from common.settings import currency_code_default except AppRegistryNotReady: pass - base_currency = settings.BASE_CURRENCY + base_currency = currency_code_default() update = False diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 0695e69f48..f5c1ad4d48 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,4 +1,5 @@ from django.conf import settings as inventree_settings +from common.settings import currency_code_default from djmoney.contrib.exchange.backends.base import SimpleExchangeBackend @@ -22,7 +23,7 @@ class InvenTreeExchange(SimpleExchangeBackend): return { } - def update_rates(self, base_currency=inventree_settings.BASE_CURRENCY): + def update_rates(self, base_currency=currency_code_default()): symbols = ','.join(inventree_settings.CURRENCIES) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index e0bc1ccb95..6c1d52487d 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -522,10 +522,6 @@ for currency in CURRENCIES: print(f"Currency code '{currency}' is not supported") sys.exit(1) -BASE_CURRENCY = get_setting( - 'INVENTREE_BASE_CURRENCY', - CONFIG.get('base_currency', 'USD') -) # Custom currency exchange backend EXCHANGE_BACKEND = 'InvenTree.exchange.InvenTreeExchange' diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index f0fe504072..6397ea72e7 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -171,6 +171,7 @@ def update_exchange_rates(): from InvenTree.exchange import InvenTreeExchange from djmoney.contrib.exchange.models import ExchangeBackend, Rate from django.conf import settings + from common.settings import currency_code_default except AppRegistryNotReady: # Apps not yet loaded! logger.info("Could not perform 'update_exchange_rates' - App registry not ready") @@ -192,7 +193,7 @@ def update_exchange_rates(): backend = InvenTreeExchange() print(f"Updating exchange rates from {backend.url}") - base = settings.BASE_CURRENCY + base = currency_code_default() print(f"Using base currency '{base}'") diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 17caeb872d..9a5e7176a1 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -21,6 +21,7 @@ from django.views.generic import ListView, DetailView, CreateView, FormView, Del from django.views.generic.base import RedirectView, TemplateView from djmoney.contrib.exchange.models import ExchangeBackend, Rate +from common.settings import currency_code_default from part.models import Part, PartCategory from stock.models import StockLocation, StockItem @@ -820,7 +821,7 @@ class CurrencySettingsView(TemplateView): ctx = super().get_context_data(**kwargs).copy() ctx['settings'] = InvenTreeSetting.objects.all().order_by('key') - ctx["base_currency"] = settings.BASE_CURRENCY + ctx["base_currency"] = currency_code_default() ctx["currencies"] = settings.CURRENCIES ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange") diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 2f129dd30b..294f89223e 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -2949,7 +2949,7 @@ class PartSalePriceBreakCreate(AjaxCreateView): initials['part'] = self.get_part() - default_currency = settings.BASE_CURRENCY + default_currency = inventree_settings.currency_code_default() currency = CURRENCIES.get(default_currency, None) if currency is not None: From 4fa57aee16ba46880de16a8019e0c040bb9c7b7d Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 30 Jun 2021 23:48:43 +0200 Subject: [PATCH 04/20] changing method call to avoid circle ref --- InvenTree/common/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 9bd3612e55..ca60c1bf9a 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -19,7 +19,7 @@ from djmoney.models.fields import MoneyField from djmoney.contrib.exchange.models import convert_money from djmoney.contrib.exchange.exceptions import MissingRate -from common.settings import currency_code_default +import common.settings from django.utils.translation import ugettext_lazy as _ from django.core.validators import MinValueValidator, URLValidator @@ -739,7 +739,7 @@ class PriceBreak(models.Model): price = MoneyField( max_digits=19, decimal_places=4, - default_currency=currency_code_default(), + default_currency=lambda: common.settings.currency_code_default(), null=True, verbose_name=_('Price'), help_text=_('Unit price at specified quantity'), @@ -792,7 +792,7 @@ def get_price(instance, quantity, moq=True, multiples=True, currency=None, break if currency is None: # Default currency selection - currency = currency_code_default() + currency = common.settings.currency_code_default() pb_min = None for pb in price_breaks: From 56b23389d3a3188315b119b7dbac971f40419780 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 30 Jun 2021 23:54:56 +0200 Subject: [PATCH 05/20] missed the settings definition --- InvenTree/common/models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index ca60c1bf9a..55dc760d55 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -82,6 +82,13 @@ class InvenTreeSetting(models.Model): 'default': '', }, + 'INVENTREE_DEFAULT_CURRENCY': { + 'name': _('Default Currency'), + 'description': _('Default currency'), + 'default': 'USD', + 'choices': CURRENCY_CHOICES, + }, + 'INVENTREE_DOWNLOAD_FROM_URL': { 'name': _('Download from URL'), 'description': _('Allow download of remote images and files from external URL'), From 3a57093b4ede3eb0f46f5f9a11a88e486af4308d Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:13:38 +0200 Subject: [PATCH 06/20] replace MoneyFields with inherited classes --- InvenTree/InvenTree/fields.py | 10 ++++++++++ InvenTree/common/models.py | 3 +-- InvenTree/company/forms.py | 5 ++--- InvenTree/order/forms.py | 6 ++---- InvenTree/order/models.py | 8 +++----- InvenTree/stock/models.py | 6 ++---- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index c496c1bb22..25fbf77c90 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -13,6 +13,8 @@ from django.core import validators from django import forms from decimal import Decimal +from djmoney.models.fields import MoneyField as ModelMoneyField +from djmoney.forms.fields import MoneyField import InvenTree.helpers @@ -34,6 +36,14 @@ class InvenTreeURLField(models.URLField): }) +class InvenTreeModelMoneyField(ModelMoneyField): + pass + + +class InvenTreeMoneyField(MoneyField): + pass + + class DatePickerFormField(forms.DateField): """ Custom date-picker field diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 55dc760d55..cb6329bb39 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -15,7 +15,6 @@ from django.db.utils import IntegrityError, OperationalError from django.conf import settings from djmoney.settings import CURRENCY_CHOICES -from djmoney.models.fields import MoneyField from djmoney.contrib.exchange.models import convert_money from djmoney.contrib.exchange.exceptions import MissingRate @@ -743,7 +742,7 @@ class PriceBreak(models.Model): help_text=_('Price break quantity'), ) - price = MoneyField( + price = InvenTree.fields.InvenTreeModelMoneyField( max_digits=19, decimal_places=4, default_currency=lambda: common.settings.currency_code_default(), diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py index 80673b4fa4..c9497ab89f 100644 --- a/InvenTree/company/forms.py +++ b/InvenTree/company/forms.py @@ -6,13 +6,12 @@ Django Forms for interacting with Company app from __future__ import unicode_literals from InvenTree.forms import HelperForm -from InvenTree.fields import RoundingDecimalFormField +from InvenTree.fields import InvenTreeMoneyField, RoundingDecimalFormField from django.utils.translation import ugettext_lazy as _ import django.forms import djmoney.settings -from djmoney.forms.fields import MoneyField from common.settings import currency_code_default @@ -129,7 +128,7 @@ class EditSupplierPartForm(HelperForm): 'note': 'fa-pencil-alt', } - single_pricing = MoneyField( + single_pricing = InvenTreeMoneyField( label=_('Single Price'), default_currency=currency_code_default(), help_text=_('Single quantity price'), diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 48b5245a5f..3dd687c685 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -10,10 +10,8 @@ from django.utils.translation import ugettext_lazy as _ from mptt.fields import TreeNodeChoiceField -from djmoney.forms.fields import MoneyField - from InvenTree.forms import HelperForm -from InvenTree.fields import RoundingDecimalFormField +from InvenTree.fields import InvenTreeMoneyField, RoundingDecimalFormField from InvenTree.fields import DatePickerFormField from InvenTree.helpers import clean_decimal @@ -321,7 +319,7 @@ class OrderMatchItemForm(MatchItemForm): ) # set price field elif 'price' in col_guess.lower(): - return MoneyField( + return InvenTreeMoneyField( label=_(col_guess), default_currency=InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY'), decimal_places=5, diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index c150331f94..8e5c881ebd 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -22,14 +22,12 @@ from common.settings import currency_code_default from markdownx.models import MarkdownxField from mptt.models import TreeForeignKey -from djmoney.models.fields import MoneyField - from users import models as UserModels from part import models as PartModels from stock import models as stock_models from company.models import Company, SupplierPart -from InvenTree.fields import RoundingDecimalField +from InvenTree.fields import InvenTreeModelMoneyField, RoundingDecimalField from InvenTree.helpers import decimal2string, increment, getSetting from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus, StockHistoryCode from InvenTree.models import InvenTreeAttachment @@ -664,7 +662,7 @@ class PurchaseOrderLineItem(OrderLineItem): received = models.DecimalField(decimal_places=5, max_digits=15, default=0, verbose_name=_('Received'), help_text=_('Number of items received')) - purchase_price = MoneyField( + purchase_price = InvenTreeModelMoneyField( max_digits=19, decimal_places=4, default_currency=currency_code_default(), @@ -716,7 +714,7 @@ class SalesOrderLineItem(OrderLineItem): part = models.ForeignKey('part.Part', on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, verbose_name=_('Part'), help_text=_('Part'), limit_choices_to={'salable': True}) - sale_price = MoneyField( + sale_price = InvenTreeModelMoneyField( max_digits=19, decimal_places=4, default_currency=currency_code_default(), diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 9786b360d9..cab3ed0d1b 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -26,8 +26,6 @@ from markdownx.models import MarkdownxField from mptt.models import MPTTModel, TreeForeignKey -from djmoney.models.fields import MoneyField - from decimal import Decimal, InvalidOperation from datetime import datetime, timedelta from InvenTree import helpers @@ -38,7 +36,7 @@ import label.models from InvenTree.status_codes import StockStatus, StockHistoryCode from InvenTree.models import InvenTreeTree, InvenTreeAttachment -from InvenTree.fields import InvenTreeURLField +from InvenTree.fields import InvenTreeModelMoneyField, InvenTreeURLField from users.models import Owner @@ -533,7 +531,7 @@ class StockItem(MPTTModel): help_text=_('Stock Item Notes') ) - purchase_price = MoneyField( + purchase_price = InvenTreeModelMoneyField( max_digits=19, decimal_places=4, default_currency=currency_code_default(), From 4b7e8c7d21e3821337f0e53ab16c5e75942fb32f Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:14:23 +0200 Subject: [PATCH 07/20] style fixes --- InvenTree/InvenTree/apps.py | 1 - 1 file changed, 1 deletion(-) diff --git a/InvenTree/InvenTree/apps.py b/InvenTree/InvenTree/apps.py index 79269d7b74..feb46ee667 100644 --- a/InvenTree/InvenTree/apps.py +++ b/InvenTree/InvenTree/apps.py @@ -4,7 +4,6 @@ import logging from django.apps import AppConfig from django.core.exceptions import AppRegistryNotReady -from django.conf import settings from InvenTree.ready import isInTestMode, canAppAccessDatabase import InvenTree.tasks From e2278fc26125d0da31c39e9b6fd9eac2973d6155 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:33:24 +0200 Subject: [PATCH 08/20] removing lambda --- InvenTree/common/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index cb6329bb39..30940027ec 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -745,7 +745,7 @@ class PriceBreak(models.Model): price = InvenTree.fields.InvenTreeModelMoneyField( max_digits=19, decimal_places=4, - default_currency=lambda: common.settings.currency_code_default(), + default_currency=common.settings.currency_code_default, null=True, verbose_name=_('Price'), help_text=_('Unit price at specified quantity'), From fcdefc4f839265f2eaaa5117beedd66a65246070 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:40:26 +0200 Subject: [PATCH 09/20] removing default_currency in fields --- InvenTree/common/models.py | 1 - InvenTree/company/forms.py | 1 - InvenTree/order/forms.py | 1 - InvenTree/order/models.py | 2 -- InvenTree/stock/models.py | 1 - 5 files changed, 6 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 30940027ec..c8a5839f4e 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -745,7 +745,6 @@ class PriceBreak(models.Model): price = InvenTree.fields.InvenTreeModelMoneyField( max_digits=19, decimal_places=4, - default_currency=common.settings.currency_code_default, null=True, verbose_name=_('Price'), help_text=_('Unit price at specified quantity'), diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py index c9497ab89f..564b5fab53 100644 --- a/InvenTree/company/forms.py +++ b/InvenTree/company/forms.py @@ -130,7 +130,6 @@ class EditSupplierPartForm(HelperForm): single_pricing = InvenTreeMoneyField( label=_('Single Price'), - default_currency=currency_code_default(), help_text=_('Single quantity price'), decimal_places=4, max_digits=19, diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 3dd687c685..aa91e114eb 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -321,7 +321,6 @@ class OrderMatchItemForm(MatchItemForm): elif 'price' in col_guess.lower(): return InvenTreeMoneyField( label=_(col_guess), - default_currency=InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY'), decimal_places=5, max_digits=19, required=False, diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 8e5c881ebd..c3e794c3e3 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -665,7 +665,6 @@ class PurchaseOrderLineItem(OrderLineItem): purchase_price = InvenTreeModelMoneyField( max_digits=19, decimal_places=4, - default_currency=currency_code_default(), null=True, blank=True, verbose_name=_('Purchase Price'), help_text=_('Unit purchase price'), @@ -717,7 +716,6 @@ class SalesOrderLineItem(OrderLineItem): sale_price = InvenTreeModelMoneyField( max_digits=19, decimal_places=4, - default_currency=currency_code_default(), null=True, blank=True, verbose_name=_('Sale Price'), help_text=_('Unit sale price'), diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index cab3ed0d1b..f485771017 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -534,7 +534,6 @@ class StockItem(MPTTModel): purchase_price = InvenTreeModelMoneyField( max_digits=19, decimal_places=4, - default_currency=currency_code_default(), blank=True, null=True, verbose_name=_('Purchase Price'), From dbb9fbd9fde23bdd870096e9143192ac1c566057 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:46:53 +0200 Subject: [PATCH 10/20] set default currency in field --- InvenTree/InvenTree/fields.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 25fbf77c90..9010203199 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -17,6 +17,7 @@ from djmoney.models.fields import MoneyField as ModelMoneyField from djmoney.forms.fields import MoneyField import InvenTree.helpers +from common.settings import currency_code_default class InvenTreeURLFormField(FormURLField): @@ -37,6 +38,10 @@ class InvenTreeURLField(models.URLField): class InvenTreeModelMoneyField(ModelMoneyField): + def __init__(self, **kwargs): + default_currency=currency_code_default + + super().__init__(default_currency=default_currency, **kwargs) pass From 7c6a58e936f51b6c9a7a2b535a35c8fd1618400e Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:48:16 +0200 Subject: [PATCH 11/20] handle default in kwargs --- InvenTree/InvenTree/fields.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 9010203199..79724636d3 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -41,6 +41,11 @@ class InvenTreeModelMoneyField(ModelMoneyField): def __init__(self, **kwargs): default_currency=currency_code_default + # remove from kwargs if set + if 'default_currency' in kwargs: + default_currency = kwargs['default_currency'] + kwargs.pop('default_currency') + super().__init__(default_currency=default_currency, **kwargs) pass From ea8b102897b3c17a98d7cf7e2ca2cc5da38a394d Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 00:50:50 +0200 Subject: [PATCH 12/20] style fix --- InvenTree/InvenTree/fields.py | 2 +- InvenTree/order/forms.py | 1 - InvenTree/order/models.py | 2 -- InvenTree/stock/models.py | 2 -- 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 79724636d3..aae3ab8049 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -39,7 +39,7 @@ class InvenTreeURLField(models.URLField): class InvenTreeModelMoneyField(ModelMoneyField): def __init__(self, **kwargs): - default_currency=currency_code_default + default_currency = currency_code_default # remove from kwargs if set if 'default_currency' in kwargs: diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index aa91e114eb..f094caafbe 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -16,7 +16,6 @@ from InvenTree.fields import DatePickerFormField from InvenTree.helpers import clean_decimal -from common.models import InvenTreeSetting from common.forms import MatchItemForm import part.models diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index c3e794c3e3..669603f5ec 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -17,8 +17,6 @@ from django.contrib.auth.models import User from django.urls import reverse from django.utils.translation import ugettext_lazy as _ -from common.settings import currency_code_default - from markdownx.models import MarkdownxField from mptt.models import TreeForeignKey diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index f485771017..446dce5c75 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -20,8 +20,6 @@ from django.contrib.auth.models import User from django.db.models.signals import pre_delete from django.dispatch import receiver -from common.settings import currency_code_default - from markdownx.models import MarkdownxField from mptt.models import MPTTModel, TreeForeignKey From 4d86f33e2357499a059f126316e85c8af881f60e Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 07:07:02 +0200 Subject: [PATCH 13/20] clean Money migrations! --- InvenTree/InvenTree/fields.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index aae3ab8049..9d7f7f4464 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -11,13 +11,14 @@ from django.forms.fields import URLField as FormURLField from django.db import models as models from django.core import validators from django import forms +from django.conf import settings from decimal import Decimal from djmoney.models.fields import MoneyField as ModelMoneyField from djmoney.forms.fields import MoneyField import InvenTree.helpers -from common.settings import currency_code_default +import common.settings class InvenTreeURLFormField(FormURLField): @@ -38,20 +39,27 @@ class InvenTreeURLField(models.URLField): class InvenTreeModelMoneyField(ModelMoneyField): + """ custom MoneyField for clean migrations while havoing dynamic currency settings """ def __init__(self, **kwargs): - default_currency = currency_code_default + # remove currency information for a clean migration + kwargs['default_currency'] = '' + kwargs['currency_choices'] = [] - # remove from kwargs if set - if 'default_currency' in kwargs: - default_currency = kwargs['default_currency'] - kwargs.pop('default_currency') + super().__init__(**kwargs) - super().__init__(default_currency=default_currency, **kwargs) - pass + def formfield(self, **kwargs): + """ override form class to use own function """ + kwargs['form_class'] = InvenTreeMoneyField + return super().formfield(**kwargs) class InvenTreeMoneyField(MoneyField): - pass + """ custom MoneyField for clean migrations while havoing dynamic currency settings """ + def __init__(self, *args, **kwargs): + # override initial values with the real info from database + kwargs['currency_choices'] = [(a, a) for a in settings.CURRENCIES] + kwargs['default_currency'] = common.settings.currency_code_default + super().__init__(*args, **kwargs) class DatePickerFormField(forms.DateField): From 9b7a08f50f05fcb82ae9b07604a20da4d4135224 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 07:07:40 +0200 Subject: [PATCH 14/20] fixed doc --- InvenTree/InvenTree/fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 9d7f7f4464..c461c0e752 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -39,7 +39,7 @@ class InvenTreeURLField(models.URLField): class InvenTreeModelMoneyField(ModelMoneyField): - """ custom MoneyField for clean migrations while havoing dynamic currency settings """ + """ custom MoneyField for clean migrations while using dynamic currency settings """ def __init__(self, **kwargs): # remove currency information for a clean migration kwargs['default_currency'] = '' @@ -54,7 +54,7 @@ class InvenTreeModelMoneyField(ModelMoneyField): class InvenTreeMoneyField(MoneyField): - """ custom MoneyField for clean migrations while havoing dynamic currency settings """ + """ custom MoneyField for clean migrations while using dynamic currency settings """ def __init__(self, *args, **kwargs): # override initial values with the real info from database kwargs['currency_choices'] = [(a, a) for a in settings.CURRENCIES] From 3c6c9c59d6a53226c47bad58feb3f6f401f28281 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 07:11:15 +0200 Subject: [PATCH 15/20] added clean migration steps for all price fields --- .../migrations/0039_auto_20210701_0509.py | 25 +++++++++++++ .../migrations/0047_auto_20210701_0509.py | 35 +++++++++++++++++++ .../migrations/0069_auto_20210701_0509.py | 35 +++++++++++++++++++ .../migrations/0065_auto_20210701_0509.py | 25 +++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 InvenTree/company/migrations/0039_auto_20210701_0509.py create mode 100644 InvenTree/order/migrations/0047_auto_20210701_0509.py create mode 100644 InvenTree/part/migrations/0069_auto_20210701_0509.py create mode 100644 InvenTree/stock/migrations/0065_auto_20210701_0509.py diff --git a/InvenTree/company/migrations/0039_auto_20210701_0509.py b/InvenTree/company/migrations/0039_auto_20210701_0509.py new file mode 100644 index 0000000000..094c7a5009 --- /dev/null +++ b/InvenTree/company/migrations/0039_auto_20210701_0509.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.4 on 2021-07-01 05:09 + +import InvenTree.fields +from django.db import migrations +import djmoney.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0038_manufacturerpartparameter'), + ] + + operations = [ + migrations.AlterField( + model_name='supplierpricebreak', + name='price', + field=InvenTree.fields.InvenTreeModelMoneyField(currency_choices=[], decimal_places=4, default_currency='', help_text='Unit price at specified quantity', max_digits=19, null=True, verbose_name='Price'), + ), + migrations.AlterField( + model_name='supplierpricebreak', + name='price_currency', + field=djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3), + ), + ] diff --git a/InvenTree/order/migrations/0047_auto_20210701_0509.py b/InvenTree/order/migrations/0047_auto_20210701_0509.py new file mode 100644 index 0000000000..1f732e5f61 --- /dev/null +++ b/InvenTree/order/migrations/0047_auto_20210701_0509.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.4 on 2021-07-01 05:09 + +import InvenTree.fields +from django.db import migrations +import djmoney.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0046_purchaseorderlineitem_destination'), + ] + + operations = [ + migrations.AlterField( + model_name='purchaseorderlineitem', + name='purchase_price', + field=InvenTree.fields.InvenTreeModelMoneyField(blank=True, currency_choices=[], decimal_places=4, default_currency='', help_text='Unit purchase price', max_digits=19, null=True, verbose_name='Purchase Price'), + ), + migrations.AlterField( + model_name='purchaseorderlineitem', + name='purchase_price_currency', + field=djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3), + ), + migrations.AlterField( + model_name='salesorderlineitem', + name='sale_price', + field=InvenTree.fields.InvenTreeModelMoneyField(blank=True, currency_choices=[], decimal_places=4, default_currency='', help_text='Unit sale price', max_digits=19, null=True, verbose_name='Sale Price'), + ), + migrations.AlterField( + model_name='salesorderlineitem', + name='sale_price_currency', + field=djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3), + ), + ] diff --git a/InvenTree/part/migrations/0069_auto_20210701_0509.py b/InvenTree/part/migrations/0069_auto_20210701_0509.py new file mode 100644 index 0000000000..86d8d2d44c --- /dev/null +++ b/InvenTree/part/migrations/0069_auto_20210701_0509.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.4 on 2021-07-01 05:09 + +import InvenTree.fields +from django.db import migrations +import djmoney.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0068_part_unique_part'), + ] + + operations = [ + migrations.AlterField( + model_name='partinternalpricebreak', + name='price', + field=InvenTree.fields.InvenTreeModelMoneyField(currency_choices=[], decimal_places=4, default_currency='', help_text='Unit price at specified quantity', max_digits=19, null=True, verbose_name='Price'), + ), + migrations.AlterField( + model_name='partinternalpricebreak', + name='price_currency', + field=djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3), + ), + migrations.AlterField( + model_name='partsellpricebreak', + name='price', + field=InvenTree.fields.InvenTreeModelMoneyField(currency_choices=[], decimal_places=4, default_currency='', help_text='Unit price at specified quantity', max_digits=19, null=True, verbose_name='Price'), + ), + migrations.AlterField( + model_name='partsellpricebreak', + name='price_currency', + field=djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3), + ), + ] diff --git a/InvenTree/stock/migrations/0065_auto_20210701_0509.py b/InvenTree/stock/migrations/0065_auto_20210701_0509.py new file mode 100644 index 0000000000..99cde1e7f7 --- /dev/null +++ b/InvenTree/stock/migrations/0065_auto_20210701_0509.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.4 on 2021-07-01 05:09 + +import InvenTree.fields +from django.db import migrations +import djmoney.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0064_auto_20210621_1724'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitem', + name='purchase_price', + field=InvenTree.fields.InvenTreeModelMoneyField(blank=True, currency_choices=[], decimal_places=4, default_currency='', help_text='Single unit purchase price at time of purchase', max_digits=19, null=True, verbose_name='Purchase Price'), + ), + migrations.AlterField( + model_name='stockitem', + name='purchase_price_currency', + field=djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3), + ), + ] From 66c1e9c97d97b76e9c35ce070b3f7860769a1baa Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 10:32:07 +0200 Subject: [PATCH 16/20] currency codes in own function --- InvenTree/InvenTree/fields.py | 24 ++++++++++++++++++------ InvenTree/common/settings.py | 9 +++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index c461c0e752..6fd0637045 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import sys from .validators import allowable_url_schemes @@ -11,7 +12,6 @@ from django.forms.fields import URLField as FormURLField from django.db import models as models from django.core import validators from django import forms -from django.conf import settings from decimal import Decimal from djmoney.models.fields import MoneyField as ModelMoneyField @@ -38,12 +38,25 @@ class InvenTreeURLField(models.URLField): }) +def money_kwargs(): + """ returns the database settings for MoneyFields """ + kwargs = {} + kwargs['currency_choices'] = common.settings.currency_codes() + kwargs['default_currency'] = common.settings.currency_code_default + return kwargs + + class InvenTreeModelMoneyField(ModelMoneyField): """ custom MoneyField for clean migrations while using dynamic currency settings """ def __init__(self, **kwargs): - # remove currency information for a clean migration - kwargs['default_currency'] = '' - kwargs['currency_choices'] = [] + # detect if creating migration + if 'makemigrations' in sys.argv: + # remove currency information for a clean migration + kwargs['default_currency'] = '' + kwargs['currency_choices'] = [] + else: + # set defaults + kwargs.update(money_kwargs()) super().__init__(**kwargs) @@ -57,8 +70,7 @@ class InvenTreeMoneyField(MoneyField): """ custom MoneyField for clean migrations while using dynamic currency settings """ def __init__(self, *args, **kwargs): # override initial values with the real info from database - kwargs['currency_choices'] = [(a, a) for a in settings.CURRENCIES] - kwargs['default_currency'] = common.settings.currency_code_default + kwargs.update(money_kwargs()) super().__init__(*args, **kwargs) diff --git a/InvenTree/common/settings.py b/InvenTree/common/settings.py index 299d142ea9..9b107e9282 100644 --- a/InvenTree/common/settings.py +++ b/InvenTree/common/settings.py @@ -6,6 +6,7 @@ User-configurable settings for the common app from __future__ import unicode_literals from moneyed import CURRENCIES +from django.conf import settings import common.models @@ -23,6 +24,14 @@ def currency_code_default(): return code +def currency_codes(): + """ + Returns the current currency choices + """ + return [(a, a) for a in settings.CURRENCIES] + + + def stock_expiry_enabled(): """ Returns True if the stock expiry feature is enabled From 983255a05e8f39b1be598ed1f954a4e4c507602b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 10:37:16 +0200 Subject: [PATCH 17/20] naming refactor --- InvenTree/InvenTree/fields.py | 2 +- InvenTree/common/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 6fd0637045..8d9ab77463 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -41,7 +41,7 @@ class InvenTreeURLField(models.URLField): def money_kwargs(): """ returns the database settings for MoneyFields """ kwargs = {} - kwargs['currency_choices'] = common.settings.currency_codes() + kwargs['currency_choices'] = common.settings.currency_code_mappings() kwargs['default_currency'] = common.settings.currency_code_default return kwargs diff --git a/InvenTree/common/settings.py b/InvenTree/common/settings.py index 9b107e9282..4d3b0c7940 100644 --- a/InvenTree/common/settings.py +++ b/InvenTree/common/settings.py @@ -24,7 +24,7 @@ def currency_code_default(): return code -def currency_codes(): +def currency_code_mappings(): """ Returns the current currency choices """ From 951e8910ba1cf50b9af75d3a1d629c74e2204d18 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 10:41:23 +0200 Subject: [PATCH 18/20] using functions for currency codes --- InvenTree/InvenTree/exchange.py | 4 ++-- InvenTree/InvenTree/tasks.py | 4 ++-- InvenTree/InvenTree/tests.py | 5 ++--- InvenTree/InvenTree/views.py | 4 ++-- InvenTree/common/settings.py | 7 +++++++ 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index f5c1ad4d48..149ef6b794 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,5 +1,5 @@ from django.conf import settings as inventree_settings -from common.settings import currency_code_default +from common.settings import currency_code_default, currency_codes from djmoney.contrib.exchange.backends.base import SimpleExchangeBackend @@ -25,6 +25,6 @@ class InvenTreeExchange(SimpleExchangeBackend): def update_rates(self, base_currency=currency_code_default()): - symbols = ','.join(inventree_settings.CURRENCIES) + symbols = ','.join(currency_codes()) super().update_rates(base=base_currency, symbols=symbols) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 6397ea72e7..b01b362760 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -171,7 +171,7 @@ def update_exchange_rates(): from InvenTree.exchange import InvenTreeExchange from djmoney.contrib.exchange.models import ExchangeBackend, Rate from django.conf import settings - from common.settings import currency_code_default + from common.settings import currency_code_default, currency_codes except AppRegistryNotReady: # Apps not yet loaded! logger.info("Could not perform 'update_exchange_rates' - App registry not ready") @@ -200,7 +200,7 @@ def update_exchange_rates(): backend.update_rates(base_currency=base) # Remove any exchange rates which are not in the provided currencies - Rate.objects.filter(backend="InvenTreeExchange").exclude(currency__in=settings.CURRENCIES).delete() + Rate.objects.filter(backend="InvenTreeExchange").exclude(currency__in=currency_codes()).delete() def send_email(subject, body, recipients, from_email=None): diff --git a/InvenTree/InvenTree/tests.py b/InvenTree/InvenTree/tests.py index b7e5b98c1b..44f907e21a 100644 --- a/InvenTree/InvenTree/tests.py +++ b/InvenTree/InvenTree/tests.py @@ -22,6 +22,7 @@ from decimal import Decimal import InvenTree.tasks from stock.models import StockLocation +from common.settings import currency_codes class ValidatorTest(TestCase): @@ -337,13 +338,11 @@ class CurrencyTests(TestCase): with self.assertRaises(MissingRate): convert_money(Money(100, 'AUD'), 'USD') - currencies = settings.CURRENCIES - InvenTree.tasks.update_exchange_rates() rates = Rate.objects.all() - self.assertEqual(rates.count(), len(currencies)) + self.assertEqual(rates.count(), len(currency_codes())) # Now that we have some exchange rate information, we can perform conversions diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 9a5e7176a1..9ce9e91ee9 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -21,7 +21,7 @@ from django.views.generic import ListView, DetailView, CreateView, FormView, Del from django.views.generic.base import RedirectView, TemplateView from djmoney.contrib.exchange.models import ExchangeBackend, Rate -from common.settings import currency_code_default +from common.settings import currency_code_default, currency_codes from part.models import Part, PartCategory from stock.models import StockLocation, StockItem @@ -822,7 +822,7 @@ class CurrencySettingsView(TemplateView): ctx['settings'] = InvenTreeSetting.objects.all().order_by('key') ctx["base_currency"] = currency_code_default() - ctx["currencies"] = settings.CURRENCIES + ctx["currencies"] = currency_codes ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange") diff --git a/InvenTree/common/settings.py b/InvenTree/common/settings.py index 4d3b0c7940..de543c2620 100644 --- a/InvenTree/common/settings.py +++ b/InvenTree/common/settings.py @@ -31,6 +31,13 @@ def currency_code_mappings(): return [(a, a) for a in settings.CURRENCIES] +def currency_codes(): + """ + Returns the current currency codes + """ + return [a for a in settings.CURRENCIES] + + def stock_expiry_enabled(): """ From 14c904c0c5cb3b0358b90f4e65e3335fb9b681f1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 10:45:33 +0200 Subject: [PATCH 19/20] style fixes --- InvenTree/InvenTree/exchange.py | 1 - InvenTree/InvenTree/tasks.py | 1 - InvenTree/InvenTree/tests.py | 2 -- InvenTree/InvenTree/views.py | 1 - InvenTree/common/settings.py | 1 - 5 files changed, 6 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 149ef6b794..c75a827cc7 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,4 +1,3 @@ -from django.conf import settings as inventree_settings from common.settings import currency_code_default, currency_codes from djmoney.contrib.exchange.backends.base import SimpleExchangeBackend diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index b01b362760..cab87ee64b 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -170,7 +170,6 @@ def update_exchange_rates(): try: from InvenTree.exchange import InvenTreeExchange from djmoney.contrib.exchange.models import ExchangeBackend, Rate - from django.conf import settings from common.settings import currency_code_default, currency_codes except AppRegistryNotReady: # Apps not yet loaded! diff --git a/InvenTree/InvenTree/tests.py b/InvenTree/InvenTree/tests.py index 44f907e21a..150662cb8e 100644 --- a/InvenTree/InvenTree/tests.py +++ b/InvenTree/InvenTree/tests.py @@ -5,8 +5,6 @@ from django.test import TestCase import django.core.exceptions as django_exceptions from django.core.exceptions import ValidationError -from django.conf import settings - from djmoney.money import Money from djmoney.contrib.exchange.models import Rate, convert_money from djmoney.contrib.exchange.exceptions import MissingRate diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 9ce9e91ee9..4b559642ca 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -12,7 +12,6 @@ from django.utils.translation import gettext_lazy as _ from django.template.loader import render_to_string from django.http import HttpResponse, JsonResponse, HttpResponseRedirect from django.urls import reverse_lazy -from django.conf import settings from django.contrib.auth.mixins import PermissionRequiredMixin diff --git a/InvenTree/common/settings.py b/InvenTree/common/settings.py index de543c2620..e255ed0904 100644 --- a/InvenTree/common/settings.py +++ b/InvenTree/common/settings.py @@ -38,7 +38,6 @@ def currency_codes(): return [a for a in settings.CURRENCIES] - def stock_expiry_enabled(): """ Returns True if the stock expiry feature is enabled From 5aaced6e66bfb8317f691e7fafe655da1070100f Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 1 Jul 2021 18:20:39 +0200 Subject: [PATCH 20/20] migration for file-based currency setting --- .../0010_migrate_currency_setting.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 InvenTree/common/migrations/0010_migrate_currency_setting.py diff --git a/InvenTree/common/migrations/0010_migrate_currency_setting.py b/InvenTree/common/migrations/0010_migrate_currency_setting.py new file mode 100644 index 0000000000..23076ff200 --- /dev/null +++ b/InvenTree/common/migrations/0010_migrate_currency_setting.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.4 on 2021-07-01 15:39 + +from django.db import migrations +from common.models import InvenTreeSetting +from InvenTree.settings import get_setting, CONFIG + +def set_default_currency(apps, schema_editor): + """ migrate the currency setting from config.yml to db """ + # get value from settings-file + base_currency = get_setting('INVENTREE_BASE_CURRENCY', CONFIG.get('base_currency', 'USD')) + # write to database + InvenTreeSetting.set_setting('INVENTREE_DEFAULT_CURRENCY', base_currency, None, create=True) + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0009_delete_currency'), + ] + + operations = [ + migrations.RunPython(set_default_currency), + ]