mirror of
https://github.com/inventree/InvenTree.git
synced 2026-02-19 13:18:03 +00:00
Code structure refactor (#5582)
* moved docker files to /contrib/container * changed code owners to make more precise * updated CI to use new subdirs * added manual trigger for testing * moved ci files * moved assets into subdir * moved deploy template file to contrib * moved django files to src/backend * updated paths in scripts etc * updated reqs path * fixed version file path * fixed flake8 path * fixed path to node ressources * fixed task paths * added dep path for node * removed unused yarn lockfile * removed unused ci script * updated internal backend paths for tasks * updated translation stats path * fixed source path for coverage * fixed main commit repo path * fit in changes from testing * gather packager improvements (#149) * Matmair/issue5578 (#143) * moved docker files to /contrib/container * changed code owners to make more precise * updated CI to use new subdirs * added manual trigger for testing * moved ci files * moved assets into subdir * moved deploy template file to contrib * moved django files to src/backend * updated paths in scripts etc * updated reqs path * fixed version file path * fixed flake8 path * fixed path to node ressources * fixed task paths * added dep path for node * removed unused yarn lockfile * removed unused ci script * updated internal backend paths for tasks * updated translation stats path * fixed source path for coverage * fixed main commit repo path * fix docker path * use project dir * move project dir command * fixed docker paths * another fix? * seperate tasks out * remove tasks * some debugging * ci: add .deepsource.toml * Update .deepsource.toml * also ignore migrations * more debugging * fix path issues * remove debug script * fix style * change locale path * Fixed paths for requirements * Added dummy requirements to fool packager * fixed exec path * remove deepsource --------- Co-authored-by: deepsource-io[bot] <42547082+deepsource-io[bot]@users.noreply.github.com> * Added docs for file structure * Fixed style errors * updated deepsource paths * fix deepsource paths * fixed reqs * merge fixes * move newly added dirs too * fix reqs files * another dep fix * merge upstream/master * revert removal of tags * merge upstream * enabled detection of old config files * adapt coverage src * also detect and support old location for plugins.txt * style fix * fix ~/init.sh location * fix requirements path * fix config to current master * move new folders * fix import order * fix paths for qc_check * fix docs build * fix fix path * set docker project dir * just use a cd * set image path? * set file correct * fix copy path * fix tasks dir * fix init path * fix copy path * set prject dir * fix paths * remove old prod files * fix dev env path * set docker file * Fix devcontainer docker compose file * fix login attempt values * fix init.sh path * Fix pathing for Docker * Docker build fix - Set INVENTREE_BACKEND_DIR separately * Update init.sh * Fix path * Update requirements.txt * merge * fix rq merge * fix docker compose usage --------- Co-authored-by: deepsource-io[bot] <42547082+deepsource-io[bot]@users.noreply.github.com> Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
"""Sample plugin which demonstrates custom validation functionality."""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from plugin import InvenTreePlugin
|
||||
from plugin.mixins import SettingsMixin, ValidationMixin
|
||||
|
||||
|
||||
class SampleValidatorPlugin(SettingsMixin, ValidationMixin, InvenTreePlugin):
|
||||
"""A sample plugin class for demonstrating custom validation functions.
|
||||
|
||||
Simple of examples of custom validator code.
|
||||
"""
|
||||
|
||||
NAME = 'SampleValidator'
|
||||
SLUG = 'validator'
|
||||
TITLE = 'Sample Validator Plugin'
|
||||
DESCRIPTION = 'A sample plugin for demonstrating custom validation functionality'
|
||||
VERSION = '0.3.0'
|
||||
|
||||
SETTINGS = {
|
||||
'ILLEGAL_PART_CHARS': {
|
||||
'name': 'Illegal Part Characters',
|
||||
'description': 'Characters which are not allowed to appear in Part names',
|
||||
'default': '!@#$%^&*()~`',
|
||||
},
|
||||
'IPN_MUST_CONTAIN_Q': {
|
||||
'name': 'IPN Q Requirement',
|
||||
'description': 'Part IPN field must contain the character Q',
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
'SERIAL_MUST_BE_PALINDROME': {
|
||||
'name': 'Palindromic Serials',
|
||||
'description': 'Serial numbers must be palindromic',
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
'SERIAL_MUST_MATCH_PART': {
|
||||
'name': 'Serial must match part',
|
||||
'description': 'First letter of serial number must match first letter of part name',
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
'BATCH_CODE_PREFIX': {
|
||||
'name': 'Batch prefix',
|
||||
'description': 'Required prefix for batch code',
|
||||
'default': 'B',
|
||||
},
|
||||
'BOM_ITEM_INTEGER': {
|
||||
'name': 'Integer Bom Quantity',
|
||||
'description': 'Bom item quantity must be an integer',
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
}
|
||||
|
||||
def validate_model_instance(self, instance, deltas=None):
|
||||
"""Run validation against any saved model.
|
||||
|
||||
- Check if the instance is a BomItem object
|
||||
- Test if the quantity is an integer
|
||||
"""
|
||||
import part.models
|
||||
|
||||
# Print debug message to console (intentional)
|
||||
print('Validating model instance:', instance.__class__, f'<{instance.pk}>')
|
||||
|
||||
if isinstance(instance, part.models.BomItem):
|
||||
if self.get_setting('BOM_ITEM_INTEGER'):
|
||||
if float(instance.quantity) != int(instance.quantity):
|
||||
self.raise_error({
|
||||
'quantity': 'Bom item quantity must be an integer'
|
||||
})
|
||||
|
||||
if isinstance(instance, part.models.Part):
|
||||
# If the part description is being updated, prevent it from being reduced in length
|
||||
|
||||
if deltas and 'description' in deltas:
|
||||
old_desc = deltas['description']['old']
|
||||
new_desc = deltas['description']['new']
|
||||
|
||||
if len(new_desc) < len(old_desc):
|
||||
self.raise_error({
|
||||
'description': 'Part description cannot be shortened'
|
||||
})
|
||||
|
||||
def validate_part_name(self, name: str, part):
|
||||
"""Custom validation for Part name field.
|
||||
|
||||
Rules:
|
||||
- Name must be shorter than the description field
|
||||
- Name cannot contain illegal characters
|
||||
|
||||
These examples are silly, but serve to demonstrate how the feature could be used.
|
||||
"""
|
||||
if len(part.description) < len(name):
|
||||
self.raise_error('Part description cannot be shorter than the name')
|
||||
|
||||
illegal_chars = self.get_setting('ILLEGAL_PART_CHARS')
|
||||
|
||||
for c in illegal_chars:
|
||||
if c in name:
|
||||
self.raise_error(f"Illegal character in part name: '{c}'")
|
||||
|
||||
def validate_part_ipn(self, ipn: str, part):
|
||||
"""Validate part IPN.
|
||||
|
||||
These examples are silly, but serve to demonstrate how the feature could be used
|
||||
"""
|
||||
if self.get_setting('IPN_MUST_CONTAIN_Q') and 'Q' not in ipn:
|
||||
self.raise_error("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:
|
||||
self.raise_error('Value must be less than 100')
|
||||
|
||||
def validate_serial_number(self, serial: str, part):
|
||||
"""Validate serial number for a given StockItem.
|
||||
|
||||
These examples are silly, but serve to demonstrate how the feature could be used
|
||||
"""
|
||||
if self.get_setting('SERIAL_MUST_BE_PALINDROME'):
|
||||
if serial != serial[::-1]:
|
||||
self.raise_error('Serial must be a palindrome')
|
||||
|
||||
if self.get_setting('SERIAL_MUST_MATCH_PART'):
|
||||
# Serial must start with the same letter as the linked part, for some reason
|
||||
if serial[0] != part.name[0]:
|
||||
self.raise_error('Serial number must start with same letter as part')
|
||||
|
||||
def validate_batch_code(self, batch_code: str, item):
|
||||
"""Ensure that a particular batch code meets specification.
|
||||
|
||||
These examples are silly, but serve to demonstrate how the feature could be used
|
||||
"""
|
||||
prefix = self.get_setting('BATCH_CODE_PREFIX')
|
||||
|
||||
if len(batch_code) > 0:
|
||||
if prefix and not batch_code.startswith(prefix):
|
||||
self.raise_error(f"Batch code must start with '{prefix}'")
|
||||
|
||||
def generate_batch_code(self):
|
||||
"""Generate a new batch code."""
|
||||
now = datetime.now()
|
||||
return f'BATCH-{now.year}:{now.month}:{now.day}'
|
||||
Reference in New Issue
Block a user