diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index c75a827cc7..9981e52ff7 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,4 +1,5 @@ from common.settings import currency_code_default, currency_codes +from urllib.error import HTTPError, URLError from djmoney.contrib.exchange.backends.base import SimpleExchangeBackend @@ -26,4 +27,8 @@ class InvenTreeExchange(SimpleExchangeBackend): symbols = ','.join(currency_codes()) - super().update_rates(base=base_currency, symbols=symbols) + try: + super().update_rates(base=base_currency, symbols=symbols) + # catch connection errors + except (HTTPError, URLError): + print('Encountered connection error while updating') diff --git a/InvenTree/InvenTree/management/commands/clean_settings.py b/InvenTree/InvenTree/management/commands/clean_settings.py new file mode 100644 index 0000000000..e0fd09e6c7 --- /dev/null +++ b/InvenTree/InvenTree/management/commands/clean_settings.py @@ -0,0 +1,38 @@ +""" +Custom management command to cleanup old settings that are not defined anymore +""" + +from django.core.management.base import BaseCommand + + +class Command(BaseCommand): + """ + Cleanup old (undefined) settings in the database + """ + + def handle(self, *args, **kwargs): + + print("Collecting settings") + from common.models import InvenTreeSetting, InvenTreeUserSetting + + # general settings + db_settings = InvenTreeSetting.objects.all() + model_settings = InvenTreeSetting.GLOBAL_SETTINGS + + # check if key exist and delete if not + for setting in db_settings: + if setting.key not in model_settings: + setting.delete() + print(f"deleted setting '{setting.key}'") + + # user settings + db_settings = InvenTreeUserSetting.objects.all() + model_settings = InvenTreeUserSetting.GLOBAL_SETTINGS + + # check if key exist and delete if not + for setting in db_settings: + if setting.key not in model_settings: + setting.delete() + print(f"deleted user setting '{setting.key}'") + + print("checked all settings") diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 54dc21c1b5..5d75a4dd74 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -20,6 +20,7 @@ from djmoney.contrib.exchange.models import convert_money from djmoney.contrib.exchange.exceptions import MissingRate from django.utils.translation import ugettext_lazy as _ +from django.utils.html import format_html from django.core.validators import MinValueValidator, URLValidator from django.core.exceptions import ValidationError @@ -58,12 +59,13 @@ class BaseInvenTreeSetting(models.Model): # Query the database for setting in results: - settings.append({ - "key": setting.key.upper(), - "value": setting.value - }) + if setting.key: + settings.append({ + "key": setting.key.upper(), + "value": setting.value + }) - keys.add(setting.key.upper()) + keys.add(setting.key.upper()) # Specify any "default" values which are not in the database for key in cls.GLOBAL_SETTINGS.keys(): @@ -90,10 +92,10 @@ class BaseInvenTreeSetting(models.Model): # Numerical values remain the same elif cls.validator_is_int(validator): pass - + # Wrap strings with quotes else: - value = f"'{value}'" + value = format_html("'{}'", value) setting["value"] = value diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index d7b196917d..5191399f0a 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -10,132 +10,253 @@ {% block content %} -
+
{{ part.description }}
- {% endif %} --
{% trans "Available Stock" %} |
+ {% decimal available %}{% if part.units %} {{ part.units }}{% endif %} |
+ |
| + | {% trans "In Stock" %} | +{% include "part/stock_count.html" %} | +
| + | {% trans "On Order" %} | +{% decimal on_order %} | +
| + | {% trans "Required for Build Orders" %} | +{% decimal required_build_order_quantity %} + |
| + | {% trans "Required for Sales Orders" %} | +{% decimal required_sales_order_quantity %} + |
| + | {% trans "Allocated to Orders" %} | +{% decimal allocated %} | +
+ {% trans "Build Status" %}+ |
+ ||
| + | {% trans "Can Build" %} | +{% decimal part.can_build %} | +
| + | {% trans "Building" %} | +{% decimal quantity_being_built %} | +
+
+
| + | {% trans "IPN" %} | +{{ part.IPN }}{% include "clip.html"%} | +|
| + | {% trans "Name" %} | +{{ part.name }}{% include "clip.html"%} | +|
| + | {% trans "Description" %} | +{{ part.description }}{% include "clip.html"%} | +|
| + | {% trans "Revision" %} | +{{ part.revision }}{% include "clip.html"%} | +|
| {% trans "Keywords" %} | -{{ part.keywords }} | +{{ part.keywords }}{% include "clip.html"%} | |
| {% trans "External Link" %} | -{{ part.link }} | +{{ part.link }}{% include "clip.html"%} | |
| {% trans "Latest Serial Number" %} | {{ part.getLatestSerialNumber }}{% include "clip.html"%} | ||
| + | {% trans "Default Location" %} | +{{ part.default_location }} | +|
| + | {% trans "Default Supplier" %} | +{{ part.default_supplier }} | +
| - |
- {% trans "Available Stock" %}- |
- {% decimal available %}{% if part.units %} {{ part.units }}{% endif %} |
-
| - | {% trans "In Stock" %} | -{% include "part/stock_count.html" %} | -
| - | {% trans "On Order" %} | -{% decimal on_order %} | -
| - | {% trans "Required for Build Orders" %} | -{% decimal required_build_order_quantity %} - |
| - | {% trans "Required for Sales Orders" %} | -{% decimal required_sales_order_quantity %} - |
| - | {% trans "Allocated to Orders" %} | -{% decimal allocated %} | -
| - | - {% trans "Build Status" %} - | -|
| - | {% trans "Can Build" %} | -{% decimal part.can_build %} | -
| - | {% trans "Building" %} | -{% decimal quantity_being_built %} | -