mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +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 = 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
|
||||
|
||||
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
|
||||
- Refactor label printing interface
|
||||
|
||||
|
@ -862,6 +862,7 @@ class SalesOrderLineItemSerializer(InvenTreeModelSerializer):
|
||||
'allocated',
|
||||
'allocations',
|
||||
'available_stock',
|
||||
'available_variant_stock',
|
||||
'customer_detail',
|
||||
'quantity',
|
||||
'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
|
||||
|
||||
customer_detail = CompanyBriefSerializer(source='order.customer', many=False, read_only=True)
|
||||
@ -944,6 +965,7 @@ class SalesOrderLineItemSerializer(InvenTreeModelSerializer):
|
||||
# Annotated fields
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
available_stock = serializers.FloatField(read_only=True)
|
||||
available_variant_stock = serializers.FloatField(read_only=True)
|
||||
|
||||
quantity = InvenTreeDecimalField()
|
||||
|
||||
|
@ -387,6 +387,7 @@ class StockFilter(rest_filters.FilterSet):
|
||||
# Part attribute filters
|
||||
assembly = rest_filters.BooleanFilter(label="Assembly", field_name='part__assembly')
|
||||
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')
|
||||
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,
|
||||
location_detail: true,
|
||||
available: true,
|
||||
salable: true,
|
||||
active: true,
|
||||
},
|
||||
model: 'stockitem',
|
||||
required: true,
|
||||
@ -1881,17 +1883,20 @@ function loadSalesOrderLineItemTable(table, options={}) {
|
||||
field: 'stock',
|
||||
title: '{% trans "Available Stock" %}',
|
||||
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) {
|
||||
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 {
|
||||
html += `<span class='badge rounded-pill bg-danger'>{% trans "No Stock Available" %}</span>`;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user