diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 2177521480..23f83a7587 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -1249,6 +1249,13 @@ class InvenTreeSetting(BaseInvenTreeSetting): 'default': '', }, + 'PART_PARAMETER_ENFORCE_UNITS': { + 'name': _('Enforce Parameter Units'), + 'description': _('If units are provided, parameter values must match the specified units'), + 'default': True, + 'validator': bool, + }, + 'PRICING_DECIMAL_PLACES_MIN': { 'name': _('Minimum Pricing Decimal Places'), 'description': _('Minimum number of decimal places to display when rendering pricing data'), diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index cd993ed826..7b1d228696 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -3532,6 +3532,16 @@ class PartParameter(MetadataMixin, models.Model): super().clean() + # Validate the parameter data against the template units + if InvenTreeSetting.get_setting('PART_PARAMETER_ENFORCE_UNITS', True, cache=False, create=False): + if self.template.units: + try: + InvenTree.conversion.convert_physical_value(self.data, self.template.units) + except ValidationError as e: + raise ValidationError({ + 'data': e.message + }) + # Validate the parameter data against the template choices if choices := self.template.get_choices(): if self.data not in choices: diff --git a/InvenTree/part/test_param.py b/InvenTree/part/test_param.py index 13767676c7..8ae2ca5d7c 100644 --- a/InvenTree/part/test_param.py +++ b/InvenTree/part/test_param.py @@ -4,6 +4,7 @@ import django.core.exceptions as django_exceptions from django.test import TestCase, TransactionTestCase from django.urls import reverse +from common.models import InvenTreeSetting from InvenTree.unit_test import InvenTreeAPITestCase from .models import (Part, PartCategory, PartCategoryParameterTemplate, @@ -168,11 +169,24 @@ class ParameterTests(TestCase): param = PartParameter(part=prt, template=template, data=value) param.full_clean() + bad_values = ['3 Amps', '-3 zogs', '3.14F'] + + # Disable enforcing of part parameter units + InvenTreeSetting.set_setting('PART_PARAMETER_ENFORCE_UNITS', False, change_user=None) + # Invalid units also pass, but will be converted to the template units - for value in ['3 Amps', '-3 zogs', '3.14F']: + for value in bad_values: param = PartParameter(part=prt, template=template, data=value) param.full_clean() + # Enable enforcing of part parameter units + InvenTreeSetting.set_setting('PART_PARAMETER_ENFORCE_UNITS', True, change_user=None) + + for value in bad_values: + param = PartParameter(part=prt, template=template, data=value) + with self.assertRaises(django_exceptions.ValidationError): + param.full_clean() + def test_param_unit_conversion(self): """Test that parameters are correctly converted to template units""" diff --git a/InvenTree/templates/InvenTree/settings/part_parameters.html b/InvenTree/templates/InvenTree/settings/part_parameters.html index d2b15edf87..95812ef51e 100644 --- a/InvenTree/templates/InvenTree/settings/part_parameters.html +++ b/InvenTree/templates/InvenTree/settings/part_parameters.html @@ -4,22 +4,37 @@ {% block label %}part-parameters{% endblock label %} {% block heading %} -{% trans "Part Parameter Templates" %} +{% trans "Part Parameters" %} {% endblock heading %} -{% block actions %} - -{% endblock actions %} +{% block panel_content %} -{% block content %} -
-
- {% include "filter_list.html" with id="parameter-templates" %} -
-
- +
+ + {% include "InvenTree/settings/setting.html" with key="PART_PARAMETER_ENFORCE_UNITS" icon="fa-clipboard-check" %} +
-{% endblock content %} +
+
+

{% trans "Part Parameter Templates" %}

+ {% include "spacer.html" %} +
+ +
+
+
+ +
+
+
+ {% include "filter_list.html" with id="parameter-templates" %} +
+
+ +
+
+ +{% endblock panel_content %} diff --git a/docs/docs/assets/images/part/part_parameters_enforce.png b/docs/docs/assets/images/part/part_parameters_enforce.png new file mode 100644 index 0000000000..2ce41ad2f3 Binary files /dev/null and b/docs/docs/assets/images/part/part_parameters_enforce.png differ diff --git a/docs/docs/part/parameter.md b/docs/docs/part/parameter.md index 2bb87c8273..a2047b2767 100644 --- a/docs/docs/part/parameter.md +++ b/docs/docs/part/parameter.md @@ -92,6 +92,12 @@ If a part parameter is created with a value which is incompatible with the units {% include 'img.html' %} {% endwith %} +This behaviour can be disabled if required, so that any parameter value is accepted: + +{% with id="enforce_units", url="part/part_parameters_enforce.png", description="Enforce part parameters" %} +{% include 'img.html' %} +{% endwith %} + ### Parameter Sorting Parameter sorting takes unit conversion into account, meaning that values provided in different (but compatible) units are sorted correctly: