diff --git a/src/backend/InvenTree/InvenTree/models.py b/src/backend/InvenTree/InvenTree/models.py index fdab2c7198..16639f0b0d 100644 --- a/src/backend/InvenTree/InvenTree/models.py +++ b/src/backend/InvenTree/InvenTree/models.py @@ -78,6 +78,57 @@ class DiffMixin: return field_name in self.get_field_deltas() +class StatusCodeMixin: + """Mixin class which handles custom 'status' fields. + + - Implements a 'set_stutus' method which can be used to set the status of an object + - Implements a 'get_status' method which can be used to retrieve the status of an object + + This mixin assumes that the implementing class has a 'status' field, + which must be an instance of the InvenTreeCustomStatusModelField class. + """ + + STATUS_CLASS = None + STATUS_FIELD = 'status' + + @property + def status_class(self): + """Return the status class associated with this model.""" + return self.STATUS_CLASS + + def get_status(self) -> int: + """Return the status code for this object.""" + return self.status + + def set_status(self, status: int) -> bool: + """Set the status code for this object.""" + if not self.status_class: + raise NotImplementedError('Status class not defined') + + base_values = self.status_class.values() + custom_value_set = self.status_class.custom_values() + + custom_field = f'{self.STATUS_FIELD}_custom_key' + + result = False + + if status in base_values: + # Set the status to a 'base' value + setattr(self, self.STATUS_FIELD, status) + setattr(self, custom_field, None) + result = True + else: + for item in custom_value_set: + if item.key == status: + # Set the status to a 'custom' value + setattr(self, self.STATUS_FIELD, item.logical_key) + setattr(self, custom_field, item.key) + result = True + break + + return result + + class PluginValidationMixin(DiffMixin): """Mixin class which exposes the model instance to plugin validation. @@ -508,6 +559,13 @@ class InvenTreeModel(PluginValidationMixin, models.Model): abstract = True + def save(self): + """Custom save method for InvenTreeModel. + + - Ensure custom status code values are correctly updated + """ + super().save() + class InvenTreeMetadataModel(MetadataMixin, InvenTreeModel): """Base class for an InvenTree model which includes a metadata field.""" diff --git a/src/backend/InvenTree/build/models.py b/src/backend/InvenTree/build/models.py index 8b8af8eb51..a7c81beb74 100644 --- a/src/backend/InvenTree/build/models.py +++ b/src/backend/InvenTree/build/models.py @@ -55,6 +55,7 @@ class Build( InvenTree.models.InvenTreeAttachmentMixin, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.InvenTreeNotesMixin, + InvenTree.models.StatusCodeMixin, InvenTree.models.MetadataMixin, InvenTree.models.PluginValidationMixin, InvenTree.models.ReferenceIndexingMixin, @@ -84,6 +85,8 @@ class Build( priority: Priority of the build """ + STATUS_CLASS = BuildStatus + class Meta: """Metaclass options for the BuildOrder model.""" diff --git a/src/backend/InvenTree/order/models.py b/src/backend/InvenTree/order/models.py index fafc707a58..294569fb7c 100644 --- a/src/backend/InvenTree/order/models.py +++ b/src/backend/InvenTree/order/models.py @@ -183,6 +183,7 @@ class Order( InvenTree.models.InvenTreeAttachmentMixin, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.InvenTreeNotesMixin, + InvenTree.models.StatusCodeMixin, report.mixins.InvenTreeReportMixin, InvenTree.models.MetadataMixin, InvenTree.models.ReferenceIndexingMixin, @@ -379,6 +380,7 @@ class PurchaseOrder(TotalPriceMixin, Order): REFERENCE_PATTERN_SETTING = 'PURCHASEORDER_REFERENCE_PATTERN' REQUIRE_RESPONSIBLE_SETTING = 'PURCHASEORDER_REQUIRE_RESPONSIBLE' + STATUS_CLASS = PurchaseOrderStatus class Meta: """Model meta options.""" @@ -913,6 +915,7 @@ class SalesOrder(TotalPriceMixin, Order): REFERENCE_PATTERN_SETTING = 'SALESORDER_REFERENCE_PATTERN' REQUIRE_RESPONSIBLE_SETTING = 'SALESORDER_REQUIRE_RESPONSIBLE' + STATUS_CLASS = SalesOrderStatus class Meta: """Model meta options.""" @@ -2157,6 +2160,7 @@ class ReturnOrder(TotalPriceMixin, Order): REFERENCE_PATTERN_SETTING = 'RETURNORDER_REFERENCE_PATTERN' REQUIRE_RESPONSIBLE_SETTING = 'RETURNORDER_REQUIRE_RESPONSIBLE' + STATUS_CLASS = ReturnOrderStatus class Meta: """Model meta options.""" @@ -2449,9 +2453,11 @@ class ReturnOrder(TotalPriceMixin, Order): ) -class ReturnOrderLineItem(OrderLineItem): +class ReturnOrderLineItem(InvenTree.models.StatusCodeMixin, OrderLineItem): """Model for a single LineItem in a ReturnOrder.""" + STATUS_CLASS = ReturnOrderLineStatus + class Meta: """Metaclass options for this model.""" diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py index 23e4d3d1f0..4233d82a05 100644 --- a/src/backend/InvenTree/stock/models.py +++ b/src/backend/InvenTree/stock/models.py @@ -340,6 +340,7 @@ class StockItem( InvenTree.models.InvenTreeAttachmentMixin, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.InvenTreeNotesMixin, + InvenTree.models.StatusCodeMixin, report.mixins.InvenTreeReportMixin, InvenTree.models.MetadataMixin, InvenTree.models.PluginValidationMixin, @@ -373,6 +374,8 @@ class StockItem( packaging: Description of how the StockItem is packaged (e.g. "reel", "loose", "tape" etc) """ + STATUS_CLASS = StockStatus + class Meta: """Model meta options."""