2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-28 03:49:20 +00:00

Plugin validation tweak (#12013)

* Prevent plugin validation actions during data import/export

* Simplify logic

* Further checks
This commit is contained in:
Oliver
2026-05-27 20:35:36 +10:00
committed by GitHub
parent 19182bacd0
commit 33483a3824
5 changed files with 128 additions and 102 deletions
@@ -550,12 +550,14 @@ def increment_serial_number(serial, part=None):
incremented value, or None if incrementing could not be performed. incremented value, or None if incrementing could not be performed.
""" """
from InvenTree.exceptions import log_error from InvenTree.exceptions import log_error
from InvenTree.ready import isReadOnlyCommand
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
# Ensure we start with a string value # Ensure we start with a string value
if serial is not None: if serial is not None:
serial = str(serial).strip() serial = str(serial).strip()
if not isReadOnlyCommand():
# First, let any plugins attempt to increment the serial number # First, let any plugins attempt to increment the serial number
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
try: try:
+14
View File
@@ -92,10 +92,23 @@ class PluginValidationMixin(DiffMixin):
Any model class which inherits from this mixin will be exposed to the plugin validation system. Any model class which inherits from this mixin will be exposed to the plugin validation system.
""" """
def should_plugin_validate(self):
"""Return True if this model instance should be validated by plugins.
The default implementation returns True, but this can be overridden in the implementing class if required.
"""
from InvenTree.ready import isReadOnlyCommand
# Prevent plugin validation when importing or exporting data
return not isReadOnlyCommand()
def run_plugin_validation(self): def run_plugin_validation(self):
"""Throw this model against the plugin validation interface.""" """Throw this model against the plugin validation interface."""
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
if not self.should_plugin_validate():
return
deltas = self.get_field_deltas() deltas = self.get_field_deltas()
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
@@ -139,6 +152,7 @@ class PluginValidationMixin(DiffMixin):
from InvenTree.exceptions import log_error from InvenTree.exceptions import log_error
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
if self.should_plugin_validate():
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
try: try:
plugin.validate_model_deletion(self) plugin.validate_model_deletion(self)
+4
View File
@@ -2875,6 +2875,10 @@ class Parameter(
except ValidationError as e: except ValidationError as e:
raise ValidationError({'data': e.message}) raise ValidationError({'data': e.message})
if InvenTree.ready.isReadOnlyCommand():
# Skip plugin validation checks during read-only management commands
return
# Finally, run custom validation checks (via plugins) # Finally, run custom validation checks (via plugins)
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
+9 -4
View File
@@ -724,6 +724,8 @@ class Part(
""" """
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
# Skip plugin validation checks during read-only management commands
if not InvenTree.ready.isReadOnlyCommand():
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
# Run the name through each custom validator # Run the name through each custom validator
# If the plugin returns 'True' we will skip any subsequent validation # If the plugin returns 'True' we will skip any subsequent validation
@@ -746,6 +748,8 @@ class Part(
""" """
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
# Skip plugin validation checks during read-only management commands
if not InvenTree.ready.isReadOnlyCommand():
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
try: try:
result = plugin.validate_part_ipn(self.IPN, self) result = plugin.validate_part_ipn(self.IPN, self)
@@ -835,11 +839,12 @@ class Part(
Raises: Raises:
ValidationError if serial number is invalid and raise_error = True ValidationError if serial number is invalid and raise_error = True
""" """
serial = str(serial).strip()
# First, throw the serial number against each of the loaded validation plugins
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
serial = str(serial).strip()
if not InvenTree.ready.isReadOnlyCommand():
# First, throw the serial number against each of the loaded validation plugins
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
# Run the serial number through each custom validator # Run the serial number through each custom validator
# If the plugin returns 'True' we will skip any subsequent validation # If the plugin returns 'True' we will skip any subsequent validation
@@ -960,7 +965,7 @@ class Part(
""" """
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
if allow_plugins: if allow_plugins and not InvenTree.ready.isReadOnlyCommand():
# Check with plugin system # Check with plugin system
# If any plugin returns a non-null result, that takes priority # If any plugin returns a non-null result, that takes priority
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
+2 -1
View File
@@ -779,7 +779,7 @@ class StockItem(
# First, let any plugins convert this serial number to an integer value # First, let any plugins convert this serial number to an integer value
# If a non-null value is returned (by any plugin) we will use that # If a non-null value is returned (by any plugin) we will use that
if not InvenTree.ready.isReadOnlyCommand():
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
try: try:
serial_int = plugin.convert_serial_to_int(serial) serial_int = plugin.convert_serial_to_int(serial)
@@ -922,6 +922,7 @@ class StockItem(
""" """
from plugin import PluginMixinEnum, registry from plugin import PluginMixinEnum, registry
if not InvenTree.ready.isReadOnlyCommand():
for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION): for plugin in registry.with_mixin(PluginMixinEnum.VALIDATION):
try: try:
plugin.validate_batch_code(self.batch, self) plugin.validate_batch_code(self.batch, self)