diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 9e393724fa..437d6507cb 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -579,7 +579,7 @@ class BomItemSerializer(InvenTreeModelSerializer): # Annotated fields available_stock = serializers.FloatField(read_only=True) - substitute_stock = serializers.FloatField(read_only=True) + available_substitute_stock = serializers.FloatField(read_only=True) def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. @@ -636,6 +636,12 @@ class BomItemSerializer(InvenTreeModelSerializer): available_stock = total_stock - build_order_allocations - sales_order_allocations """ + build_order_filter = Q(build__status__in=BuildStatus.ACTIVE_CODES) + sales_order_filter = Q( + line__order__status__in=SalesOrderStatus.OPEN, + shipment__shipment_date=None, + ) + # Calculate "total stock" for the referenced sub_part # Calculate the "build_order_allocations" for the sub_part # Note that these fields are only aliased, not annotated @@ -651,10 +657,7 @@ class BomItemSerializer(InvenTreeModelSerializer): allocated_to_sales_orders=Coalesce( SubquerySum( 'sub_part__stock_items__sales_order_allocations__quantity', - filter=Q( - line__order__status__in=SalesOrderStatus.OPEN, - shipment__shipment_date=None, - ) + filter=sales_order_filter, ), Decimal(0), output_field=models.DecimalField(), @@ -662,9 +665,7 @@ class BomItemSerializer(InvenTreeModelSerializer): allocated_to_build_orders=Coalesce( SubquerySum( 'sub_part__stock_items__allocations__quantity', - filter=Q( - build__status__in=BuildStatus.ACTIVE_CODES, - ), + filter=build_order_filter, ), Decimal(0), output_field=models.DecimalField(), @@ -680,7 +681,7 @@ class BomItemSerializer(InvenTreeModelSerializer): ) # Extract similar information for any 'substitute' parts - queryset = queryset.annotate( + queryset = queryset.alias( substitute_stock=Coalesce( SubquerySum( 'substitutes__part__stock_items__quantity', @@ -688,6 +689,30 @@ class BomItemSerializer(InvenTreeModelSerializer): ), Decimal(0), output_field=models.DecimalField(), + ), + substitute_build_allocations=Coalesce( + SubquerySum( + 'substitutes__part__stock_items__allocations__quantity', + filter=build_order_filter, + ), + Decimal(0), + output_field=models.DecimalField(), + ), + substitute_sales_allocations=Coalesce( + SubquerySum( + 'substitutes__part__stock_items__sales_order_allocations__quantity', + filter=sales_order_filter, + ), + Decimal(0), + output_field=models.DecimalField(), + ), + ) + + # Calculate 'available_variant_stock' field + queryset = queryset.annotate( + available_substitute_stock=ExpressionWrapper( + F('substitute_stock') - F('substitute_build_allocations') - F('substitute_sales_allocations'), + output_field=models.DecimalField(), ) ) @@ -765,7 +790,7 @@ class BomItemSerializer(InvenTreeModelSerializer): # Annotated fields describing available quantity 'available_stock', - 'substitute_stock', + 'available_substitute_stock', ]