2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 21:15:41 +00:00

Enhance plugin SN validation (#7942)

* Update function signature for 'validate_serial_number'

- Pass through stock item parameter
- Required if we want to exclude a particular item from that test

* Update documentation

* Docs fixes

* Add type annotations
This commit is contained in:
Oliver
2024-08-21 15:45:47 +10:00
committed by GitHub
parent f2f90dd1e4
commit e837e5d7d7
5 changed files with 129 additions and 20 deletions

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import decimal
import hashlib
import inspect
import logging
import math
import os
@ -775,7 +776,22 @@ class Part(
for plugin in registry.with_mixin('validation'):
# Run the serial number through each custom validator
# If the plugin returns 'True' we will skip any subsequent validation
if plugin.validate_serial_number(serial, self):
result = False
if hasattr(plugin, 'validate_serial_number'):
signature = inspect.signature(plugin.validate_serial_number)
if 'stock_item' in signature.parameters:
# 2024-08-21: New method signature accepts a 'stock_item' parameter
result = plugin.validate_serial_number(
serial, self, stock_item=stock_item
)
else:
# Old method signature - does not accept a 'stock_item' parameter
result = plugin.validate_serial_number(serial, self)
if result is True:
return True
except ValidationError as exc:
if raise_error:

View File

@ -63,7 +63,7 @@ class ValidationMixin:
None: or True (refer to class docstring)
Raises:
ValidationError: if the instance cannot be deleted
ValidationError: If the instance cannot be deleted
"""
return None
@ -81,11 +81,11 @@ class ValidationMixin:
None: or True (refer to class docstring)
Raises:
ValidationError: if the instance is invalid
ValidationError: If the instance is invalid
"""
return None
def validate_part_name(self, name: str, part: part.models.Part):
def validate_part_name(self, name: str, part: part.models.Part) -> None:
"""Perform validation on a proposed Part name.
Arguments:
@ -96,11 +96,11 @@ class ValidationMixin:
None or True (refer to class docstring)
Raises:
ValidationError if the proposed name is objectionable
ValidationError: If the proposed name is objectionable
"""
return None
def validate_part_ipn(self, ipn: str, part: part.models.Part):
def validate_part_ipn(self, ipn: str, part: part.models.Part) -> None:
"""Perform validation on a proposed Part IPN (internal part number).
Arguments:
@ -111,11 +111,13 @@ class ValidationMixin:
None or True (refer to class docstring)
Raises:
ValidationError if the proposed IPN is objectionable
ValidationError: If the proposed IPN is objectionable
"""
return None
def validate_batch_code(self, batch_code: str, item: stock.models.StockItem):
def validate_batch_code(
self, batch_code: str, item: stock.models.StockItem
) -> None:
"""Validate the supplied batch code.
Arguments:
@ -126,11 +128,11 @@ class ValidationMixin:
None or True (refer to class docstring)
Raises:
ValidationError if the proposed batch code is objectionable
ValidationError: If the proposed batch code is objectionable
"""
return None
def generate_batch_code(self, **kwargs):
def generate_batch_code(self, **kwargs) -> str:
"""Generate a new batch code.
This method is called when a new batch code is required.
@ -143,22 +145,28 @@ class ValidationMixin:
"""
return None
def validate_serial_number(self, serial: str, part: part.models.Part):
def validate_serial_number(
self,
serial: str,
part: part.models.Part,
stock_item: stock.models.StockItem = None,
) -> None:
"""Validate the supplied serial number.
Arguments:
serial: The proposed serial number (string)
part: The Part instance for which this serial number is being validated
stock_item: The StockItem instance for which this serial number is being validated (if applicable)
Returns:
None or True (refer to class docstring)
Raises:
ValidationError if the proposed serial is objectionable
ValidationError: If the proposed serial is objectionable
"""
return None
def convert_serial_to_int(self, serial: str):
def convert_serial_to_int(self, serial: str) -> int:
"""Convert a serial number (string) into an integer representation.
This integer value is used for efficient sorting based on serial numbers.
@ -179,7 +187,7 @@ class ValidationMixin:
"""
return None
def increment_serial_number(self, serial: str):
def increment_serial_number(self, serial: str) -> str:
"""Return the next sequential serial based on the provided value.
A plugin which implements this method can either return:
@ -189,10 +197,15 @@ class ValidationMixin:
Arguments:
serial: Current serial value (string)
Returns:
The next serial number in the sequence (string), or None
"""
return None
def validate_part_parameter(self, parameter, data):
def validate_part_parameter(
self, parameter: part.models.PartParameter, data: str
) -> None:
"""Validate a parameter value.
Arguments:
@ -203,6 +216,6 @@ class ValidationMixin:
None or True (refer to class docstring)
Raises:
ValidationError if the proposed parameter value is objectionable
ValidationError: If the proposed parameter value is objectionable
"""
pass

View File

@ -121,7 +121,7 @@ class SampleValidatorPlugin(SettingsMixin, ValidationMixin, InvenTreePlugin):
if d >= 100:
self.raise_error('Value must be less than 100')
def validate_serial_number(self, serial: str, part):
def validate_serial_number(self, serial: str, part, stock_item=None):
"""Validate serial number for a given StockItem.
These examples are silly, but serve to demonstrate how the feature could be used