Fix state changes on stock items (#7976)

* Revert changes from https://github.com/inventree/InvenTree/pull/7965

* Add error handling for wrong key

* Add e2e test case for error condition
Fixes #7964

* Better code code / flow

* [BUG] Order of states in schema descriptions is not stable
Fixes #7977
This commit is contained in:
Matthias Mair 2024-08-24 01:18:09 +02:00 committed by GitHub
parent df8efa902e
commit ed2da62a46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 30 additions and 14 deletions

View File

@ -41,7 +41,7 @@ class CustomChoiceField(serializers.ChoiceField):
if self.is_custom:
return logical.key
return logical.logical_key
except ObjectDoesNotExist:
except (ObjectDoesNotExist, Exception):
raise serializers.ValidationError('Invalid choice')
def get_field_info(self, field, field_info):
@ -145,24 +145,32 @@ class InvenTreeCustomStatusSerializerMixin:
def update(self, instance, validated_data):
"""Ensure the custom field is updated if the leader was changed."""
self.gather_custom_fields()
# Mirror values from leader to follower
for field in self._custom_fields_leader:
follower_field_name = f'{field}_custom_key'
if (
field in self.initial_data
and self.instance
and self.initial_data[field]
!= getattr(self.instance, f'{field}_custom_key', None)
!= getattr(self.instance, follower_field_name, None)
):
setattr(self.instance, f'{field}_custom_key', self.initial_data[field])
setattr(self.instance, follower_field_name, self.initial_data[field])
# Mirror values from follower to leader
for field in self._custom_fields_follower:
if (
field in validated_data
and field.replace('_custom_key', '') not in self.initial_data
):
reference = get_logical_value(
validated_data[field],
self.fields[field].choice_mdl._meta.model_name,
)
validated_data[field.replace('_custom_key', '')] = reference.logical_key
leader_field_name = field.replace('_custom_key', '')
if field in validated_data and leader_field_name not in self.initial_data:
try:
reference = get_logical_value(
validated_data[field],
self.fields[field].choice_mdl._meta.model_name,
)
validated_data[leader_field_name] = reference.logical_key
except (ObjectDoesNotExist, Exception):
if validated_data[field] in self.fields[leader_field_name].choices:
validated_data[leader_field_name] = validated_data[field]
else:
raise serializers.ValidationError('Invalid choice')
return super().update(instance, validated_data)
def to_representation(self, instance):

View File

@ -1004,6 +1004,14 @@ class CustomStockItemStatusTest(StockAPITestCase):
self.assertEqual(response.data['status'], self.status.logical_key)
self.assertEqual(response.data['status_custom_key'], self.status.logical_key)
# Test case with wrong key
response = self.patch(
reverse('api-stock-detail', kwargs={'pk': pk}),
{'status_custom_key': 23456789},
expected_code=400,
)
self.assertIn('Invalid choice', str(response.data))
def test_options(self):
"""Test the StockItem OPTIONS endpoint to contain custom StockStatuses."""
response = self.options(self.list_url)

View File

@ -380,7 +380,7 @@ function stockItemFields(options={}) {
batch: {
icon: 'fa-layer-group',
},
status: {},
status_custom_key: {},
expiry_date: {
icon: 'fa-calendar-alt',
},

View File

@ -138,7 +138,7 @@ export function useStockFields({
value: batchCode,
onValueChange: (value) => setBatchCode(value)
},
status: {},
status_custom_key: {},
expiry_date: {
// TODO: icon
},