mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-01 13:06:45 +00:00
Sales order variant stock (#5415)
* Annotate available variant stock to SalesOrderLine serializer * Filter variant stock by: - active = True - salable = True * Add 'salable' filter to StockList API * Filter available stock in sales order table: - Must be salable - Must be active * Update table display * Bump API version
This commit is contained in:
parent
1fe382e318
commit
62362455b8
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 130
|
INVENTREE_API_VERSION = 131
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||||
|
|
||||||
|
v131 -> 2023-08-09 : https://github.com/inventree/InvenTree/pull/5415
|
||||||
|
- Annotate 'available_variant_stock' to the SalesOrderLine serializer
|
||||||
|
|
||||||
v130 -> 2023-07-14 : https://github.com/inventree/InvenTree/pull/5251
|
v130 -> 2023-07-14 : https://github.com/inventree/InvenTree/pull/5251
|
||||||
- Refactor label printing interface
|
- Refactor label printing interface
|
||||||
|
|
||||||
|
@ -862,6 +862,7 @@ class SalesOrderLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
'allocated',
|
'allocated',
|
||||||
'allocations',
|
'allocations',
|
||||||
'available_stock',
|
'available_stock',
|
||||||
|
'available_variant_stock',
|
||||||
'customer_detail',
|
'customer_detail',
|
||||||
'quantity',
|
'quantity',
|
||||||
'reference',
|
'reference',
|
||||||
@ -934,6 +935,26 @@ class SalesOrderLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Filter for "variant" stock: Variant stock items must be salable and active
|
||||||
|
variant_stock_query = part.filters.variant_stock_query(reference='part__').filter(
|
||||||
|
part__salable=True,
|
||||||
|
part__active=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Also add in available "variant" stock
|
||||||
|
queryset = queryset.alias(
|
||||||
|
variant_stock_total=part.filters.annotate_variant_quantity(variant_stock_query, reference='quantity'),
|
||||||
|
variant_bo_allocations=part.filters.annotate_variant_quantity(variant_stock_query, reference='sales_order_allocations__quantity'),
|
||||||
|
variant_so_allocations=part.filters.annotate_variant_quantity(variant_stock_query, reference='allocations__quantity'),
|
||||||
|
)
|
||||||
|
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
available_variant_stock=ExpressionWrapper(
|
||||||
|
F('variant_stock_total') - F('variant_bo_allocations') - F('variant_so_allocations'),
|
||||||
|
output_field=models.DecimalField(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
customer_detail = CompanyBriefSerializer(source='order.customer', many=False, read_only=True)
|
customer_detail = CompanyBriefSerializer(source='order.customer', many=False, read_only=True)
|
||||||
@ -944,6 +965,7 @@ class SalesOrderLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
# Annotated fields
|
# Annotated fields
|
||||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||||
available_stock = serializers.FloatField(read_only=True)
|
available_stock = serializers.FloatField(read_only=True)
|
||||||
|
available_variant_stock = serializers.FloatField(read_only=True)
|
||||||
|
|
||||||
quantity = InvenTreeDecimalField()
|
quantity = InvenTreeDecimalField()
|
||||||
|
|
||||||
|
@ -387,6 +387,7 @@ class StockFilter(rest_filters.FilterSet):
|
|||||||
# Part attribute filters
|
# Part attribute filters
|
||||||
assembly = rest_filters.BooleanFilter(label="Assembly", field_name='part__assembly')
|
assembly = rest_filters.BooleanFilter(label="Assembly", field_name='part__assembly')
|
||||||
active = rest_filters.BooleanFilter(label="Active", field_name='part__active')
|
active = rest_filters.BooleanFilter(label="Active", field_name='part__active')
|
||||||
|
salable = rest_filters.BooleanFilter(label="Salable", field_name='part__salable')
|
||||||
|
|
||||||
min_stock = rest_filters.NumberFilter(label='Minimum stock', field_name='quantity', lookup_expr='gte')
|
min_stock = rest_filters.NumberFilter(label='Minimum stock', field_name='quantity', lookup_expr='gte')
|
||||||
max_stock = rest_filters.NumberFilter(label='Maximum stock', field_name='quantity', lookup_expr='lte')
|
max_stock = rest_filters.NumberFilter(label='Maximum stock', field_name='quantity', lookup_expr='lte')
|
||||||
|
@ -1308,6 +1308,8 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) {
|
|||||||
part_detail: true,
|
part_detail: true,
|
||||||
location_detail: true,
|
location_detail: true,
|
||||||
available: true,
|
available: true,
|
||||||
|
salable: true,
|
||||||
|
active: true,
|
||||||
},
|
},
|
||||||
model: 'stockitem',
|
model: 'stockitem',
|
||||||
required: true,
|
required: true,
|
||||||
@ -1881,17 +1883,20 @@ function loadSalesOrderLineItemTable(table, options={}) {
|
|||||||
field: 'stock',
|
field: 'stock',
|
||||||
title: '{% trans "Available Stock" %}',
|
title: '{% trans "Available Stock" %}',
|
||||||
formatter: function(value, row) {
|
formatter: function(value, row) {
|
||||||
var available = row.available_stock;
|
|
||||||
var required = Math.max(row.quantity - row.allocated - row.shipped, 0);
|
|
||||||
|
|
||||||
var html = '';
|
let available = row.available_stock + row.available_variant_stock;
|
||||||
|
let required = Math.max(row.quantity - row.allocated - row.shipped, 0);
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
|
||||||
if (available > 0) {
|
if (available > 0) {
|
||||||
var url = `/part/${row.part}/?display=part-stock`;
|
let url = `/part/${row.part}/?display=part-stock`;
|
||||||
|
|
||||||
var text = available;
|
html = renderLink(available, url);
|
||||||
|
|
||||||
html = renderLink(text, url);
|
if (row.available_variant_stock && row.available_variant_stock > 0) {
|
||||||
|
html += makeIconBadge('fa-info-circle icon-blue', '{% trans "Includes variant stock" %}');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
html += `<span class='badge rounded-pill bg-danger'>{% trans "No Stock Available" %}</span>`;
|
html += `<span class='badge rounded-pill bg-danger'>{% trans "No Stock Available" %}</span>`;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user