mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-17 12:35:46 +00:00
Parameter validation via plugin (#4958)
* Expose part parameter validation to plugins - Allow ValidationMixin plugins to validate part parameter values * Update sample plugin * Catch and re-throw error * Update docs * Improve plugin docs * Simplify validation sample * Calculate numeric value first
This commit is contained in:
@ -572,7 +572,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
|
||||
"""Ensure that the IPN (internal part number) is valid for this Part"
|
||||
|
||||
- Validation is handled by custom plugins
|
||||
- By default, no validation checks are perfomed
|
||||
- By default, no validation checks are performed
|
||||
"""
|
||||
|
||||
from plugin.registry import registry
|
||||
@ -3505,6 +3505,24 @@ class PartParameter(MetadataMixin, models.Model):
|
||||
'data': _('Invalid choice for parameter value')
|
||||
})
|
||||
|
||||
self.calculate_numeric_value()
|
||||
|
||||
# Run custom validation checks (via plugins)
|
||||
from plugin.registry import registry
|
||||
|
||||
for plugin in registry.with_mixin('validation'):
|
||||
|
||||
# Note: The validate_part_parameter function may raise a ValidationError
|
||||
try:
|
||||
result = plugin.validate_part_parameter(self, self.data)
|
||||
if result:
|
||||
break
|
||||
except ValidationError as exc:
|
||||
# Re-throw the ValidationError against the 'data' field
|
||||
raise ValidationError({
|
||||
'data': exc.message
|
||||
})
|
||||
|
||||
def calculate_numeric_value(self):
|
||||
"""Calculate a numeric value for the parameter data.
|
||||
|
||||
|
@ -21,6 +21,7 @@ class ValidationMixin:
|
||||
|
||||
- Part names
|
||||
- Part IPN (internal part number) values
|
||||
- Part parameter values
|
||||
- Serial numbers
|
||||
- Batch codes
|
||||
|
||||
@ -150,6 +151,21 @@ class ValidationMixin:
|
||||
"""
|
||||
return None
|
||||
|
||||
def validate_part_parameter(self, parameter, data):
|
||||
"""Validate a parameter value.
|
||||
|
||||
Arguments:
|
||||
parameter: The parameter we are validating
|
||||
data: The proposed parameter value
|
||||
|
||||
Returns:
|
||||
None or True (refer to class docstring)
|
||||
|
||||
Raises:
|
||||
ValidationError if the proposed parameter value is objectionable
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NavigationMixin:
|
||||
"""Mixin that enables custom navigation links with the plugin."""
|
||||
|
@ -18,7 +18,7 @@ class CustomValidationMixin(SettingsMixin, ValidationMixin, InvenTreePlugin):
|
||||
SLUG = "validator"
|
||||
TITLE = "Custom Validator Plugin"
|
||||
DESCRIPTION = "A sample plugin for demonstrating custom validation functionality"
|
||||
VERSION = "0.2"
|
||||
VERSION = "0.3.0"
|
||||
|
||||
SETTINGS = {
|
||||
'ILLEGAL_PART_CHARS': {
|
||||
@ -78,6 +78,17 @@ class CustomValidationMixin(SettingsMixin, ValidationMixin, InvenTreePlugin):
|
||||
if self.get_setting('IPN_MUST_CONTAIN_Q') and 'Q' not in ipn:
|
||||
raise ValidationError("IPN must contain 'Q'")
|
||||
|
||||
def validate_part_parameter(self, parameter, data):
|
||||
"""Validate part parameter data.
|
||||
|
||||
These examples are silly, but serve to demonstrate how the feature could be used
|
||||
"""
|
||||
|
||||
if parameter.template.name.lower() in ['length', 'width']:
|
||||
d = int(data)
|
||||
if d >= 100:
|
||||
raise ValidationError("Value must be less than 100")
|
||||
|
||||
def validate_serial_number(self, serial: str, part):
|
||||
"""Validate serial number for a given StockItem
|
||||
|
||||
|
Reference in New Issue
Block a user