mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 11:10:54 +00:00
[bug] Custom state fix (#9858)
* Set status correctly when returning from customer * Fix for stock item status change - Reduced set of changes from #9781 * Handle API updates * Fix variable shadowing * More intelligent comparison * Remove debug statement
This commit is contained in:
@ -301,6 +301,13 @@ class StatusCodeMixin:
|
||||
"""Return the custom status code for this object."""
|
||||
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."""
|
||||
if status == self.get_status():
|
||||
return True
|
||||
|
||||
return status is not None and status == self.get_custom_status()
|
||||
|
||||
def set_status(self, status: int) -> bool:
|
||||
"""Set the status code for this object."""
|
||||
if not self.status_class:
|
||||
|
@ -1067,6 +1067,11 @@ class StockList(DataExportViewMixin, StockApiMixin, ListCreateDestroyAPIView):
|
||||
# Do this regardless of results above
|
||||
data.pop('use_pack_size', None)
|
||||
|
||||
# Extract 'status' flag from data
|
||||
status_raw = data.pop('status', None)
|
||||
status_custom = data.pop('status_custom_key', None)
|
||||
status_value = status_custom or status_raw
|
||||
|
||||
# Assign serial numbers for a trackable part
|
||||
if serial_numbers:
|
||||
if not part.trackable:
|
||||
@ -1130,10 +1135,14 @@ class StockList(DataExportViewMixin, StockApiMixin, ListCreateDestroyAPIView):
|
||||
tracking = []
|
||||
|
||||
for item in items:
|
||||
if status_value and not item.compare_status(status_value):
|
||||
item.set_status(status_value)
|
||||
item.save()
|
||||
|
||||
if entry := item.add_tracking_entry(
|
||||
StockHistoryCode.CREATED,
|
||||
user,
|
||||
deltas={'status': item.status},
|
||||
deltas={'status': status_value},
|
||||
location=location,
|
||||
quantity=float(item.quantity),
|
||||
commit=False,
|
||||
@ -1152,6 +1161,10 @@ class StockList(DataExportViewMixin, StockApiMixin, ListCreateDestroyAPIView):
|
||||
# Create a single StockItem object
|
||||
# Note: This automatically creates a tracking entry
|
||||
item = serializer.save()
|
||||
|
||||
if status_value and not item.compare_status(status_value):
|
||||
item.set_status(status_value)
|
||||
|
||||
item.save(user=user)
|
||||
|
||||
response_data = serializer.data
|
||||
|
@ -1332,9 +1332,10 @@ class StockItem(
|
||||
self.sales_order = None
|
||||
self.location = location
|
||||
|
||||
if status := kwargs.get('status'):
|
||||
self.status = status
|
||||
tracking_info['status'] = status
|
||||
if status := kwargs.pop('status', None):
|
||||
if not self.compare_status(status):
|
||||
self.set_status(status)
|
||||
tracking_info['status'] = status
|
||||
|
||||
self.save()
|
||||
|
||||
@ -2240,7 +2241,7 @@ class StockItem(
|
||||
|
||||
status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None)
|
||||
|
||||
if status and status != self.status:
|
||||
if status and not self.compare_status(status):
|
||||
self.set_status(status)
|
||||
tracking_info['status'] = status
|
||||
|
||||
@ -2325,7 +2326,7 @@ class StockItem(
|
||||
|
||||
status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None)
|
||||
|
||||
if status and status != self.status:
|
||||
if status and not self.compare_status(status):
|
||||
self.set_status(status)
|
||||
tracking_info['status'] = status
|
||||
|
||||
@ -2388,7 +2389,7 @@ class StockItem(
|
||||
|
||||
status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None)
|
||||
|
||||
if status and status != self.status:
|
||||
if status and not self.compare_status(status):
|
||||
self.set_status(status)
|
||||
tracking_info['status'] = status
|
||||
|
||||
@ -2442,7 +2443,7 @@ class StockItem(
|
||||
|
||||
status = kwargs.pop('status', None) or kwargs.pop('status_custom_key', None)
|
||||
|
||||
if status and status != self.status:
|
||||
if status and not self.compare_status(status):
|
||||
self.set_status(status)
|
||||
deltas['status'] = status
|
||||
|
||||
|
@ -521,7 +521,17 @@ class StockItemSerializer(
|
||||
"""Custom update method to pass the user information through to the instance."""
|
||||
instance._user = self.context['user']
|
||||
|
||||
return super().update(instance, validated_data)
|
||||
status_custom_key = validated_data.pop('status_custom_key', None)
|
||||
status = validated_data.pop('status', None)
|
||||
|
||||
instance = super().update(instance, validated_data=validated_data)
|
||||
|
||||
if status_code := status_custom_key or status:
|
||||
if not instance.compare_status(status_code):
|
||||
instance.set_status(status_code)
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
@ -1123,7 +1133,6 @@ class StockChangeStatusSerializer(serializers.Serializer):
|
||||
|
||||
note = data.get('note', '')
|
||||
|
||||
items_to_update = []
|
||||
transaction_notes = []
|
||||
|
||||
deltas = {'status': status}
|
||||
@ -1135,12 +1144,11 @@ class StockChangeStatusSerializer(serializers.Serializer):
|
||||
|
||||
for item in items:
|
||||
# Ignore items which are already in the desired status
|
||||
if item.status == status:
|
||||
if item.compare_status(status):
|
||||
continue
|
||||
|
||||
item.updated = now
|
||||
item.status = status
|
||||
items_to_update.append(item)
|
||||
item.set_status(status)
|
||||
item.save(add_note=False)
|
||||
|
||||
# Create a new transaction note for each item
|
||||
transaction_notes.append(
|
||||
@ -1154,10 +1162,7 @@ class StockChangeStatusSerializer(serializers.Serializer):
|
||||
)
|
||||
)
|
||||
|
||||
# Update status
|
||||
StockItem.objects.bulk_update(items_to_update, ['status', 'updated'])
|
||||
|
||||
# Create entries
|
||||
# Create tracking entries
|
||||
StockItemTracking.objects.bulk_create(transaction_notes)
|
||||
|
||||
|
||||
|
@ -11,7 +11,7 @@ from users.models import Owner
|
||||
|
||||
|
||||
class StockViewTestCase(InvenTreeTestCase):
|
||||
"""Mixin for Stockview tests."""
|
||||
"""Mixin for StockView tests."""
|
||||
|
||||
fixtures = ['category', 'part', 'company', 'location', 'supplier_part', 'stock']
|
||||
|
||||
@ -46,7 +46,7 @@ class StockOwnershipTest(StockViewTestCase):
|
||||
"""Helper function to get response to API change."""
|
||||
return self.client.patch(
|
||||
reverse('api-stock-detail', args=(self.test_item_id,)),
|
||||
{'status': StockStatus.DAMAGED.value},
|
||||
{'status_custom_key': StockStatus.DAMAGED.value},
|
||||
content_type='application/json',
|
||||
)
|
||||
|
||||
@ -96,7 +96,7 @@ class StockOwnershipTest(StockViewTestCase):
|
||||
self.assertTrue(location.check_ownership(self.user)) # Owner is group -> True
|
||||
self.assertContains(
|
||||
self.assert_api_change(),
|
||||
f'"status":{StockStatus.DAMAGED.value}',
|
||||
f'"status_custom_key":{StockStatus.DAMAGED.value}',
|
||||
status_code=200,
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user