mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-18 10:46:31 +00:00
Stock serialize tweaks (#10017)
* Better item extraction * Improve query efficiency * Further queryset improvements * Return correct data format * Test with hugh number of serials * Improve serialization UX * Revert changes to unit tests
This commit is contained in:
@@ -659,7 +659,8 @@ class BuildOutputCreate(BuildOrderContextMixin, CreateAPI):
|
||||
# Create the build output(s)
|
||||
outputs = serializer.save()
|
||||
|
||||
response = stock.serializers.StockItemSerializer(outputs, many=True)
|
||||
queryset = stock.serializers.StockItemSerializer.annotate_queryset(outputs)
|
||||
response = stock.serializers.StockItemSerializer(queryset, many=True)
|
||||
|
||||
# Return the created outputs
|
||||
return Response(response.data, status=status.HTTP_201_CREATED)
|
||||
|
@@ -1009,7 +1009,8 @@ class Build(
|
||||
},
|
||||
)
|
||||
|
||||
outputs = [output]
|
||||
# Ensure we return a QuerySet object here, too
|
||||
outputs = stock.models.StockItem.objects.filter(pk=output.pk)
|
||||
|
||||
if self.status == BuildStatus.PENDING:
|
||||
self.status = BuildStatus.PRODUCTION.value
|
||||
|
@@ -129,8 +129,10 @@ class StockItemSerialize(StockItemContextMixin, CreateAPI):
|
||||
# Perform the actual serialization step
|
||||
items = serializer.save()
|
||||
|
||||
queryset = StockSerializers.StockItemSerializer.annotate_queryset(items)
|
||||
|
||||
response = StockSerializers.StockItemSerializer(
|
||||
items, many=True, context=self.get_serializer_context()
|
||||
queryset, many=True, context=self.get_serializer_context()
|
||||
)
|
||||
|
||||
return Response(response.data, status=status.HTTP_201_CREATED)
|
||||
@@ -1151,8 +1153,11 @@ class StockList(DataExportViewMixin, StockApiMixin, ListCreateDestroyAPIView):
|
||||
|
||||
StockItemTracking.objects.bulk_create(tracking)
|
||||
|
||||
# Annotate the stock items with part information
|
||||
queryset = StockSerializers.StockItemSerializer.annotate_queryset(items)
|
||||
|
||||
response = StockSerializers.StockItemSerializer(
|
||||
items, many=True, context=self.get_serializer_context()
|
||||
queryset, many=True, context=self.get_serializer_context()
|
||||
)
|
||||
|
||||
response_data = response.data
|
||||
|
@@ -696,7 +696,10 @@ class SerializeStockItemSerializer(serializers.Serializer):
|
||||
|
||||
def validate_quantity(self, quantity):
|
||||
"""Validate that the quantity value is correct."""
|
||||
item = self.context['item']
|
||||
item = self.context.get('item')
|
||||
|
||||
if not item:
|
||||
raise ValidationError(_('No stock item provided'))
|
||||
|
||||
if quantity < 0:
|
||||
raise ValidationError(_('Quantity must be greater than zero'))
|
||||
@@ -736,7 +739,10 @@ class SerializeStockItemSerializer(serializers.Serializer):
|
||||
"""Check that the supplied serial numbers are valid."""
|
||||
data = super().validate(data)
|
||||
|
||||
item = self.context['item']
|
||||
item = self.context.get('item')
|
||||
|
||||
if not item:
|
||||
raise ValidationError(_('No stock item provided'))
|
||||
|
||||
if not item.part.trackable:
|
||||
raise ValidationError(_('Serial numbers cannot be assigned to this part'))
|
||||
@@ -771,7 +777,11 @@ class SerializeStockItemSerializer(serializers.Serializer):
|
||||
Returns:
|
||||
A list of StockItem objects that were created as a result of the serialization.
|
||||
"""
|
||||
item = self.context['item']
|
||||
item = self.context.get('item')
|
||||
|
||||
if not item:
|
||||
raise ValidationError(_('No stock item provided'))
|
||||
|
||||
request = self.context.get('request')
|
||||
user = request.user if request else None
|
||||
|
||||
@@ -905,7 +915,10 @@ class UninstallStockItemSerializer(serializers.Serializer):
|
||||
|
||||
def save(self):
|
||||
"""Uninstall stock item."""
|
||||
item = self.context['item']
|
||||
item = self.context.get('item')
|
||||
|
||||
if not item:
|
||||
raise ValidationError(_('No stock item provided'))
|
||||
|
||||
data = self.validated_data
|
||||
request = self.context['request']
|
||||
@@ -1035,7 +1048,11 @@ class ReturnStockItemSerializer(serializers.Serializer):
|
||||
|
||||
def save(self):
|
||||
"""Save the serializer to return the item into stock."""
|
||||
item = self.context['item']
|
||||
item = self.context.get('item')
|
||||
|
||||
if not item:
|
||||
raise ValidationError(_('No stock item provided'))
|
||||
|
||||
request = self.context['request']
|
||||
|
||||
data = self.validated_data
|
||||
|
@@ -66,6 +66,15 @@ export function useInstance<T = any>({
|
||||
JSON.stringify(pathParams),
|
||||
disabled
|
||||
],
|
||||
retry: (failureCount, error: any) => {
|
||||
// If it's a 404, don't retry
|
||||
if (error.response?.status == 404) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, retry up to 3 times
|
||||
return failureCount < 3;
|
||||
},
|
||||
queryFn: async () => {
|
||||
if (disabled) {
|
||||
return defaultValue;
|
||||
|
@@ -744,12 +744,14 @@ export default function StockDetail() {
|
||||
quantity: stockitem.quantity,
|
||||
destination: stockitem.location ?? stockitem.part_detail?.default_location
|
||||
},
|
||||
onFormSuccess: () => {
|
||||
const partId = stockitem.part;
|
||||
refreshInstancePromise().catch(() => {
|
||||
// Part may have been deleted - redirect to the part detail page
|
||||
navigate(getDetailUrl(ModelType.part, partId));
|
||||
});
|
||||
onFormSuccess: (response: any) => {
|
||||
if (response.length >= stockitem.quantity) {
|
||||
// Entire item was serialized
|
||||
// Navigate to the first result
|
||||
navigate(getDetailUrl(ModelType.stockitem, response[0].pk));
|
||||
} else {
|
||||
refreshInstance();
|
||||
}
|
||||
},
|
||||
successMessage: t`Stock item serialized`
|
||||
});
|
||||
|
Reference in New Issue
Block a user