2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-01-28 09:03:41 +00:00

Stock status fix (#11183)

* Fill in default value

* Ensure status values are converted to integer in set_status

* Updated unit testing

* Additional unit testing
This commit is contained in:
Oliver
2026-01-22 11:46:36 +11:00
committed by GitHub
parent d43c4e08f0
commit 00c36e9366
3 changed files with 72 additions and 5 deletions

View File

@@ -303,7 +303,20 @@ class StatusCodeMixin:
return getattr(self, f'{self.STATUS_FIELD}_custom_key', None) return getattr(self, f'{self.STATUS_FIELD}_custom_key', None)
def compare_status(self, status: int) -> bool: 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(): if status == self.get_status():
return True return True
@@ -327,6 +340,13 @@ class StatusCodeMixin:
else custom_values 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' custom_field = f'{self.STATUS_FIELD}_custom_key'
result = False result = False

View File

@@ -1171,7 +1171,7 @@ class CustomStockItemStatusTest(StockAPITestCase):
name='OK - advanced', name='OK - advanced',
label='OK - adv.', label='OK - adv.',
color='secondary', color='secondary',
logical_key=10, logical_key=StockStatus.OK.value,
model=ContentType.objects.get(model='stockitem'), model=ContentType.objects.get(model='stockitem'),
reference_status='StockStatus', reference_status='StockStatus',
) )
@@ -1180,14 +1180,55 @@ class CustomStockItemStatusTest(StockAPITestCase):
name='attention 2', name='attention 2',
label='attention 2', label='attention 2',
color='secondary', color='secondary',
logical_key=50, logical_key=StockStatus.ATTENTION.value,
model=ContentType.objects.get(model='stockitem'), model=ContentType.objects.get(model='stockitem'),
reference_status='StockStatus', reference_status='StockStatus',
) )
def test_custom_status(self): def test_custom_status(self):
"""Tests interaction with states.""" """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 # Create a stock item with the custom status code via the API
# Note: We test with a string value here
response = self.post( response = self.post(
self.list_url, self.list_url,
{ {
@@ -1195,7 +1236,7 @@ class CustomStockItemStatusTest(StockAPITestCase):
'description': 'Test desc 1', 'description': 'Test desc 1',
'quantity': 1, 'quantity': 1,
'part': 1, 'part': 1,
'status_custom_key': self.status.key, 'status_custom_key': str(self.status.key),
}, },
expected_code=201, expected_code=201,
) )

View File

@@ -58,6 +58,7 @@ import {
useBatchCodeGenerator, useBatchCodeGenerator,
useSerialNumberGenerator useSerialNumberGenerator
} from '../hooks/UseGenerator'; } from '../hooks/UseGenerator';
import useStatusCodes from '../hooks/UseStatusCodes';
import { useGlobalSettingsState } from '../states/SettingsStates'; import { useGlobalSettingsState } from '../states/SettingsStates';
import { StatusFilterOptions } from '../tables/Filter'; import { StatusFilterOptions } from '../tables/Filter';
@@ -136,6 +137,10 @@ export function useStockFields({
); );
}, [globalSettings]); }, [globalSettings]);
const stockItemStatusCodes = useStatusCodes({
modelType: ModelType.stockitem
});
return useMemo(() => { return useMemo(() => {
const fields: ApiFormFieldSet = { const fields: ApiFormFieldSet = {
part: { part: {
@@ -237,7 +242,8 @@ export function useStockFields({
placeholder: batchGenerator.result placeholder: batchGenerator.result
}, },
status_custom_key: { status_custom_key: {
label: t`Stock Status` label: t`Stock Status`,
default: stockItemStatusCodes.OK
}, },
expiry_date: { expiry_date: {
icon: <IconCalendarExclamation />, icon: <IconCalendarExclamation />,