diff --git a/src/backend/InvenTree/generic/states/states.py b/src/backend/InvenTree/generic/states/states.py index d94793e748..697166645d 100644 --- a/src/backend/InvenTree/generic/states/states.py +++ b/src/backend/InvenTree/generic/states/states.py @@ -303,7 +303,20 @@ class StatusCodeMixin: return getattr(self, f'{self.STATUS_FIELD}_custom_key', None) def compare_status(self, status: int) -> bool: - """Determine if the current status matches the provided status code.""" + """Determine if the current status matches the provided status code. + + Arguments: + status: The status code to compare against + + Returns: + True if the status matches, False otherwise. + """ + try: + status = int(status) + except (ValueError, TypeError): + # Value cannot be converted to integer - so it cannot match + return False + if status == self.get_status(): return True @@ -327,6 +340,13 @@ class StatusCodeMixin: else custom_values ) + # The status must be an integer + try: + status = int(status) + except (ValueError, TypeError): + logger.warning(f'Invalid status value {status} for class {self.__class__}') + return False + custom_field = f'{self.STATUS_FIELD}_custom_key' result = False diff --git a/src/backend/InvenTree/stock/test_api.py b/src/backend/InvenTree/stock/test_api.py index 5785fc3d56..4634ba40a3 100644 --- a/src/backend/InvenTree/stock/test_api.py +++ b/src/backend/InvenTree/stock/test_api.py @@ -1171,7 +1171,7 @@ class CustomStockItemStatusTest(StockAPITestCase): name='OK - advanced', label='OK - adv.', color='secondary', - logical_key=10, + logical_key=StockStatus.OK.value, model=ContentType.objects.get(model='stockitem'), reference_status='StockStatus', ) @@ -1180,14 +1180,55 @@ class CustomStockItemStatusTest(StockAPITestCase): name='attention 2', label='attention 2', color='secondary', - logical_key=50, + logical_key=StockStatus.ATTENTION.value, model=ContentType.objects.get(model='stockitem'), reference_status='StockStatus', ) def test_custom_status(self): """Tests interaction with states.""" + part = Part.objects.filter(virtual=False).first() + + # Try creating a new stock item with an invalid status code + response = self.post( + reverse('api-stock-list'), + {'part': part.pk, 'quantity': 10, 'status_custom_key': 'xyz'}, + ) + + data = response.data[0] + + # An invalid status value has been set to the default value + self.assertEqual(data['status'], StockStatus.OK.value) + + # Create a stock item with a non-default, built-in status value + response = self.post( + reverse('api-stock-list'), + { + 'part': part.pk, + 'quantity': 10, + 'status_custom_key': StockStatus.QUARANTINED.value, + }, + ) + + data = response.data[0] + + self.assertEqual(data['status'], StockStatus.QUARANTINED.value) + self.assertEqual(data['status_custom_key'], StockStatus.QUARANTINED.value) + self.assertEqual(data['status_text'], 'Quarantined') + + # Create a stock item with a custom status value + response = self.post( + reverse('api-stock-list'), + {'part': part.pk, 'quantity': 10, 'status_custom_key': self.status2.key}, + ) + + data = response.data[0] + + self.assertEqual(data['status'], StockStatus.ATTENTION.value) + self.assertEqual(data['status_custom_key'], self.status2.key) + # Create a stock item with the custom status code via the API + # Note: We test with a string value here response = self.post( self.list_url, { @@ -1195,7 +1236,7 @@ class CustomStockItemStatusTest(StockAPITestCase): 'description': 'Test desc 1', 'quantity': 1, 'part': 1, - 'status_custom_key': self.status.key, + 'status_custom_key': str(self.status.key), }, expected_code=201, ) diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index a7689e30e7..27ff0f1f3c 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -58,6 +58,7 @@ import { useBatchCodeGenerator, useSerialNumberGenerator } from '../hooks/UseGenerator'; +import useStatusCodes from '../hooks/UseStatusCodes'; import { useGlobalSettingsState } from '../states/SettingsStates'; import { StatusFilterOptions } from '../tables/Filter'; @@ -136,6 +137,10 @@ export function useStockFields({ ); }, [globalSettings]); + const stockItemStatusCodes = useStatusCodes({ + modelType: ModelType.stockitem + }); + return useMemo(() => { const fields: ApiFormFieldSet = { part: { @@ -237,7 +242,8 @@ export function useStockFields({ placeholder: batchGenerator.result }, status_custom_key: { - label: t`Stock Status` + label: t`Stock Status`, + default: stockItemStatusCodes.OK }, expiry_date: { icon: ,