diff --git a/src/backend/InvenTree/InvenTree/models.py b/src/backend/InvenTree/InvenTree/models.py index 16639f0b0d..5be73ae54b 100644 --- a/src/backend/InvenTree/InvenTree/models.py +++ b/src/backend/InvenTree/InvenTree/models.py @@ -96,10 +96,31 @@ class StatusCodeMixin: """Return the status class associated with this model.""" return self.STATUS_CLASS + def save(self): + """Custom save method for StatusCodeMixin. + + - Ensure custom status code values are correctly updated + """ + if self.status_class: + # Check that the current 'logical key' actually matches the current status code + custom_values = self.status_class.custom_queryset().filter( + logical_key=self.get_status(), key=self.get_custom_status() + ) + + if not custom_values.exists(): + # No match - null out the custom value + setattr(self, f'{self.STATUS_FIELD}_custom_key', None) + + super().save() + def get_status(self) -> int: """Return the status code for this object.""" return self.status + def get_custom_status(self) -> int: + """Return the custom status code for this object.""" + return getattr(self, f'{self.STATUS_FIELD}_custom_key', None) + def set_status(self, status: int) -> bool: """Set the status code for this object.""" if not self.status_class: @@ -126,6 +147,9 @@ class StatusCodeMixin: result = True break + if not result: + logger.warning(f'Failed to set status {status} for class {self.__class__}') + return result diff --git a/src/backend/InvenTree/generic/states/states.py b/src/backend/InvenTree/generic/states/states.py index 906ec5ec56..f2d237285e 100644 --- a/src/backend/InvenTree/generic/states/states.py +++ b/src/backend/InvenTree/generic/states/states.py @@ -103,18 +103,23 @@ class StatusCode(BaseEnum): return isinstance(value.value, int) @classmethod - def custom_values(cls): - """Return all user-defined custom values for this status class.""" + def custom_queryset(cls): + """Return a queryset of all custom values for this status class.""" from common.models import InvenTreeCustomUserStateModel try: - return list( - InvenTreeCustomUserStateModel.objects.filter( - reference_status=cls.__name__ - ) + return InvenTreeCustomUserStateModel.objects.filter( + reference_status=cls.__name__ ) except Exception: - return [] + return None + + @classmethod + def custom_values(cls): + """Return all user-defined custom values for this status class.""" + if query := cls.custom_queryset(): + return list(query) + return [] @classmethod def values(cls, key=None): diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py index 4233d82a05..9032588d56 100644 --- a/src/backend/InvenTree/stock/models.py +++ b/src/backend/InvenTree/stock/models.py @@ -2144,7 +2144,7 @@ class StockItem( status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None) if status and status != self.status: - self.status_custom_key = status + self.set_status(status) tracking_info['status'] = status # Optional fields which can be supplied in a 'move' call @@ -2229,7 +2229,7 @@ class StockItem( status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None) if status and status != self.status: - self.status_custom_key = status + self.set_status(status) tracking_info['status'] = status if self.updateQuantity(count): @@ -2292,7 +2292,7 @@ class StockItem( status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None) if status and status != self.status: - self.status_custom_key = status + self.set_status(status) tracking_info['status'] = status if self.updateQuantity(self.quantity + quantity): @@ -2346,7 +2346,7 @@ class StockItem( status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None) if status and status != self.status: - self.status_custom_key = status + self.set_status(status) deltas['status'] = status if self.updateQuantity(self.quantity - quantity):