diff --git a/InvenTree/InvenTree/validators.py b/InvenTree/InvenTree/validators.py index be96affbbd..e85dc40810 100644 --- a/InvenTree/InvenTree/validators.py +++ b/InvenTree/InvenTree/validators.py @@ -43,7 +43,7 @@ def validate_part_name(value): def validate_part_ipn(value): """ Validate the Part IPN against regex rule """ - pattern = common.models.InvenTreeSetting.get_setting('part_ipn_regex') + pattern = common.models.InvenTreeSetting.get_setting('PART_IPN_REGEX') if pattern: match = re.search(pattern, value) @@ -57,7 +57,7 @@ def validate_build_order_reference(value): Validate the 'reference' field of a BuildOrder """ - pattern = common.models.InvenTreeSetting.get_setting('buildorder_reference_regex') + pattern = common.models.InvenTreeSetting.get_setting('BUILDORDER_REFERENCE_REGEX') if pattern: match = re.search(pattern, value) @@ -71,7 +71,7 @@ def validate_purchase_order_reference(value): Validate the 'reference' field of a PurchaseOrder """ - pattern = common.models.InvenTreeSetting.get_setting('purchaseorder_reference_regex') + pattern = common.models.InvenTreeSetting.get_setting('PURCHASEORDER_REFERENCE_REGEX') if pattern: match = re.search(pattern, value) @@ -85,7 +85,7 @@ def validate_sales_order_reference(value): Validate the 'reference' field of a SalesOrder """ - pattern = common.models.InvenTreeSetting.get_setting('salesorder_reference_regex') + pattern = common.models.InvenTreeSetting.get_setting('SALESORDER_REFERENCE_REGEX') if pattern: match = re.search(pattern, value) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 827769c32a..1e545cc68e 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -12,7 +12,7 @@ INVENTREE_SW_VERSION = "0.1.4 pre" def inventreeInstanceName(): """ Returns the InstanceName settings for the current database """ - return common.models.InvenTreeSetting.get_setting("InstanceName", "") + return common.models.InvenTreeSetting.get_setting("INVENTREE_INSTANCE", "") def inventreeVersion(): diff --git a/InvenTree/common/apps.py b/InvenTree/common/apps.py index 83b299ecdf..7106c1b746 100644 --- a/InvenTree/common/apps.py +++ b/InvenTree/common/apps.py @@ -9,6 +9,7 @@ class CommonConfig(AppConfig): """ Will be called when the Common app is first loaded """ self.add_instance_name() + self.add_default_settings() def add_instance_name(self): """ @@ -19,15 +20,70 @@ class CommonConfig(AppConfig): # See note above from .models import InvenTreeSetting + """ + Note: The "old" instance name was stored under the key 'InstanceName', + but has now been renamed to 'INVENTREE_INSTANCE'. + """ + try: - if not InvenTreeSetting.objects.filter(key='InstanceName').exists(): - name = InvenTreeSetting( - key="InstanceName", - value="InvenTree Server" - ) + # Quick exit if a value already exists for 'inventree_instance' + if InvenTreeSetting.objects.filter(key='INVENTREE_INSTANCE').exists(): + return + + # Default instance name + instance_name = 'InvenTree Server' + + # Use the old name if it exists + if InvenTreeSetting.objects.filter(key='InstanceName').exists(): + instance = InvenTreeSetting.objects.get(key='InstanceName') + instance_name = instance.value + + # Create new value + InvenTreeSetting.objects.create( + key='INVENTREE_INSTANCE', + value=instance_name + ) - name.save() except (OperationalError, ProgrammingError): # Migrations have not yet been applied - table does not exist pass + + def add_default_settings(self): + """ + Create all required settings, if they do not exist. + """ + + from .models import InvenTreeSetting + + for key in InvenTreeSetting.DEFAULT_VALUES.keys(): + try: + settings = InvenTreeSetting.objects.filter(key__iexact=key) + + if settings.count() == 0: + value = InvenTreeSetting.DEFAULT_VALUES[key] + + print(f"Creating default setting for {key} -> '{value}'") + + InvenTreeSetting.objects.create( + key=key, + value=value + ) + + return + + elif settings.count() > 1: + # Prevent multiple shadow copies of the same setting! + for setting in settings[1:]: + setting.delete() + + # Ensure that the key has the correct case + setting = settings[0] + + if not setting.key == key: + setting.key = key + setting.save() + + except (OperationalError, ProgrammingError): + # Table might not yet exist + pass diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index 00e6c15c7f..53493faff0 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals from InvenTree.forms import HelperForm -from .models import Currency +from .models import Currency, InvenTreeSetting class CurrencyEditForm(HelperForm): @@ -22,3 +22,17 @@ class CurrencyEditForm(HelperForm): 'value', 'base' ] + + +class SettingEditForm(HelperForm): + """ + Form for creating / editing a settings object + """ + + class Meta: + model = InvenTreeSetting + + fields = [ + 'key', + 'value' + ] diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 1a76183e59..0c110d1366 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -27,6 +27,30 @@ class InvenTreeSetting(models.Model): even if that key does not exist. """ + # Dict of default values for various internal settings + DEFAULT_VALUES = { + # Global inventree settings + 'INVENTREE_INSTANCE': 'InvenTree Server', + + # Part settings + 'PART_IPN_REGEX': '', + 'PART_COPY_BOM': True, + 'PART_COPY_PARAMETERS': True, + 'PART_COPY_TESTS': True, + + # Stock settings + + # Build Order settings + 'BUILDORDER_REFERENCE_PREFIX': 'BO', + 'BUILDORDER_REFERENCE_REGEX': '', + + # Purchase Order Settings + 'PURCHASEORDER_REFERENCE_PREFIX': 'PO', + + # Sales Order Settings + 'SALESORDER_REFERENCE_PREFIX': 'SO', + } + class Meta: verbose_name = "InvenTree Setting" verbose_name_plural = "InvenTree Settings" @@ -39,8 +63,12 @@ class InvenTreeSetting(models.Model): """ try: - setting = InvenTreeSetting.objects.get(key__iexact=key) - return setting.value + settings = InvenTreeSetting.objects.filter(key__iexact=key) + + if len(settings) > 0: + return settings[0].value + else: + return backup_value except InvenTreeSetting.DoesNotExist: return backup_value diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 5da634c6d3..a205b8b915 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -35,3 +35,14 @@ class CurrencyDelete(AjaxDeleteView): model = models.Currency ajax_form_title = _('Delete Currency') ajax_template_name = "common/delete_currency.html" + + +class SettingEdit(AjaxUpdateView): + """ + View for editing an InvenTree key:value settings object, + (or creating it if the key does not already exist) + """ + + model = models.InvenTreeSetting + ajax_form_title = _('Change Setting') + form_class = forms.SettingEditForm diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 6498774285..a1ce33df51 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -493,9 +493,9 @@ class PartDuplicate(AjaxCreateView): else: initials = super(AjaxCreateView, self).get_initial() - initials['bom_copy'] = str2bool(InvenTreeSetting.get_setting('part_deep_copy', True)) - # Create new entry in InvenTree/common/kvp.yaml? - initials['parameters_copy'] = str2bool(InvenTreeSetting.get_setting('part_deep_copy', True)) + initials['bom_copy'] = str2bool(InvenTreeSetting.get_setting('PART_COPY_BOM', True)) + + initials['parameters_copy'] = str2bool(InvenTreeSetting.get_setting('PART_COPY_PARAMETERS', True)) return initials diff --git a/InvenTree/templates/InvenTree/settings/build.html b/InvenTree/templates/InvenTree/settings/build.html index e72536ce6f..6d19e21f1a 100644 --- a/InvenTree/templates/InvenTree/settings/build.html +++ b/InvenTree/templates/InvenTree/settings/build.html @@ -17,12 +17,12 @@ {% trans "Reference Prefix" %} - {% inventree_setting 'buildorder_reference_prefix' backup='PO' %} + {% inventree_setting 'BUILDORDER_REFERENCE_PREFIX' backup='BO' %} {% trans "Prefix for Build Order reference" %} {% trans "Reference Regex" %} - {% inventree_setting 'buildorder_reference_regex' %} + {% inventree_setting 'BUILDORDER_REFERENCE_REGEX' %} {% trans "Regex validator for Build Order reference" %}