mirror of
https://github.com/inventree/InvenTree.git
synced 2025-08-06 20:11:37 +00:00
Add custom state field validation
This commit is contained in:
@@ -319,6 +319,7 @@ class Build(
|
||||
verbose_name=_('Build Status'),
|
||||
default=BuildStatus.PENDING.value,
|
||||
choices=BuildStatus.items(),
|
||||
status_class=BuildStatus,
|
||||
validators=[MinValueValidator(0)],
|
||||
help_text=_('Build status code'),
|
||||
)
|
||||
|
@@ -90,6 +90,20 @@ class InvenTreeCustomStatusModelField(models.PositiveIntegerField):
|
||||
Models using this model field must also include the InvenTreeCustomStatusSerializerMixin in all serializers that create or update the value.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the field."""
|
||||
from generic.states.validators import CustomStatusCodeValidator
|
||||
|
||||
self.status_class = kwargs.pop('status_class', None)
|
||||
|
||||
validators = kwargs.pop('validators', None) or []
|
||||
|
||||
if self.status_class:
|
||||
validators.append(CustomStatusCodeValidator(status_class=self.status_class))
|
||||
|
||||
kwargs['validators'] = validators
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def deconstruct(self):
|
||||
"""Deconstruct the field for migrations."""
|
||||
name, path, args, kwargs = super().deconstruct()
|
||||
@@ -109,14 +123,23 @@ class InvenTreeCustomStatusModelField(models.PositiveIntegerField):
|
||||
"""Ensure that the value is not an empty string."""
|
||||
if value == '':
|
||||
value = None
|
||||
|
||||
return super().clean(value, model_instance)
|
||||
|
||||
def add_field(self, cls, name):
|
||||
"""Adds custom_key_field to the model class to save additional status information."""
|
||||
from generic.states.validators import CustomStatusCodeValidator
|
||||
|
||||
validators = []
|
||||
|
||||
if self.status_class:
|
||||
validators.append(CustomStatusCodeValidator(status_class=self.status_class))
|
||||
|
||||
custom_key_field = ExtraInvenTreeCustomStatusModelField(
|
||||
default=None,
|
||||
verbose_name=_('Custom status key'),
|
||||
help_text=_('Additional status information for this item'),
|
||||
validators=validators,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
@@ -130,6 +153,10 @@ class ExtraInvenTreeCustomStatusModelField(models.PositiveIntegerField):
|
||||
This is not intended to be used directly, if you want to support custom states in your model use InvenTreeCustomStatusModelField.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the field."""
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class InvenTreeCustomStatusSerializerMixin:
|
||||
"""Mixin to ensure custom status fields are set.
|
||||
|
@@ -117,7 +117,7 @@ class StatusCode(BaseEnum):
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def values(cls, key=None, custom=True):
|
||||
def values(cls, key=None):
|
||||
"""Return a dict representation containing all required information."""
|
||||
elements = [itm for itm in cls if cls._is_element(itm.name)]
|
||||
|
||||
@@ -167,14 +167,14 @@ class StatusCode(BaseEnum):
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def keys(cls):
|
||||
def keys(cls, custom=True):
|
||||
"""All status code keys."""
|
||||
return [x.value for x in cls.values()]
|
||||
return [el[0] for el in cls.items(custom=custom)]
|
||||
|
||||
@classmethod
|
||||
def labels(cls):
|
||||
def labels(cls, custom=True):
|
||||
"""All status code labels."""
|
||||
return [x.label for x in cls.values()]
|
||||
return [el[1] for el in cls.items(custom=custom)]
|
||||
|
||||
@classmethod
|
||||
def names(cls):
|
||||
|
21
src/backend/InvenTree/generic/states/validators.py
Normal file
21
src/backend/InvenTree/generic/states/validators.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""Validators for generic state management."""
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import BaseValidator
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class CustomStatusCodeValidator(BaseValidator):
|
||||
"""Custom validator class for checking that a provided status code is valid."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the validator."""
|
||||
self.status_class = kwargs.pop('status_class', None)
|
||||
super().__init__(limit_value=None, **kwargs)
|
||||
|
||||
def __call__(self, value):
|
||||
"""Check that the provided status code is valid."""
|
||||
if status_class := self.status_class:
|
||||
values = status_class.keys(custom=True)
|
||||
if value not in values:
|
||||
raise ValidationError(_('Invalid status code'))
|
@@ -483,6 +483,7 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
||||
status = InvenTreeCustomStatusModelField(
|
||||
default=PurchaseOrderStatus.PENDING.value,
|
||||
choices=PurchaseOrderStatus.items(),
|
||||
status_class=PurchaseOrderStatus,
|
||||
verbose_name=_('Status'),
|
||||
help_text=_('Purchase order status'),
|
||||
)
|
||||
@@ -1029,6 +1030,7 @@ class SalesOrder(TotalPriceMixin, Order):
|
||||
status = InvenTreeCustomStatusModelField(
|
||||
default=SalesOrderStatus.PENDING.value,
|
||||
choices=SalesOrderStatus.items(),
|
||||
status_class=SalesOrderStatus,
|
||||
verbose_name=_('Status'),
|
||||
help_text=_('Sales order status'),
|
||||
)
|
||||
@@ -2231,6 +2233,7 @@ class ReturnOrder(TotalPriceMixin, Order):
|
||||
status = InvenTreeCustomStatusModelField(
|
||||
default=ReturnOrderStatus.PENDING.value,
|
||||
choices=ReturnOrderStatus.items(),
|
||||
status_class=ReturnOrderStatus,
|
||||
verbose_name=_('Status'),
|
||||
help_text=_('Return order status'),
|
||||
)
|
||||
@@ -2522,6 +2525,7 @@ class ReturnOrderLineItem(OrderLineItem):
|
||||
outcome = InvenTreeCustomStatusModelField(
|
||||
default=ReturnOrderLineStatus.PENDING.value,
|
||||
choices=ReturnOrderLineStatus.items(),
|
||||
status_class=ReturnOrderLineStatus,
|
||||
verbose_name=_('Outcome'),
|
||||
help_text=_('Outcome for this line item'),
|
||||
)
|
||||
|
@@ -1020,6 +1020,7 @@ class StockItem(
|
||||
|
||||
status = InvenTreeCustomStatusModelField(
|
||||
default=StockStatus.OK.value,
|
||||
status_class=StockStatus,
|
||||
choices=StockStatus.items(),
|
||||
validators=[MinValueValidator(0)],
|
||||
)
|
||||
|
Reference in New Issue
Block a user