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 %} -
-