mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 15:15:42 +00:00 
			
		
		
		
	Adds "stock value" calculation to stock table (#4471)
* Add part pricing data to stockitem list serializer * Add "stock value" column to stock list table
This commit is contained in:
		@@ -281,6 +281,8 @@ class PartBriefSerializer(InvenTreeModelSerializer):
 | 
			
		||||
            'trackable',
 | 
			
		||||
            'virtual',
 | 
			
		||||
            'units',
 | 
			
		||||
            'pricing_min',
 | 
			
		||||
            'pricing_max',
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        read_only_fields = [
 | 
			
		||||
@@ -289,6 +291,10 @@ class PartBriefSerializer(InvenTreeModelSerializer):
 | 
			
		||||
 | 
			
		||||
    thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
 | 
			
		||||
 | 
			
		||||
    # Pricing fields
 | 
			
		||||
    pricing_min = InvenTreeMoneySerializer(source='pricing_data.overall_min', allow_null=True, read_only=True)
 | 
			
		||||
    pricing_max = InvenTreeMoneySerializer(source='pricing_data.overall_max', allow_null=True, read_only=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DuplicatePartSerializer(serializers.Serializer):
 | 
			
		||||
    """Serializer for specifying options when duplicating a Part.
 | 
			
		||||
 
 | 
			
		||||
@@ -165,6 +165,8 @@ class StockItemSerializer(InvenTree.serializers.InvenTreeModelSerializer):
 | 
			
		||||
        queryset = queryset.prefetch_related(
 | 
			
		||||
            'sales_order',
 | 
			
		||||
            'purchase_order',
 | 
			
		||||
            'part',
 | 
			
		||||
            'part__pricing_data',
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Annotate the queryset with the total allocated to sales orders
 | 
			
		||||
 
 | 
			
		||||
@@ -136,7 +136,7 @@ function calculateTotalPrice(dataset, value_func, currency_func, options={}) {
 | 
			
		||||
 | 
			
		||||
    var currency = options.currency;
 | 
			
		||||
 | 
			
		||||
    var rates = getCurrencyConversionRates();
 | 
			
		||||
    var rates = options.rates || getCurrencyConversionRates();
 | 
			
		||||
 | 
			
		||||
    if (!rates) {
 | 
			
		||||
        console.error('Could not retrieve currency conversion information from the server');
 | 
			
		||||
 
 | 
			
		||||
@@ -2065,6 +2065,86 @@ function loadStockTable(table, options) {
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Total value of stock
 | 
			
		||||
    // This is not sortable, and may default to the 'price range' for the parent part
 | 
			
		||||
    columns.push({
 | 
			
		||||
        field: 'stock_value',
 | 
			
		||||
        title: '{% trans "Stock Value" %}',
 | 
			
		||||
        sortable: false,
 | 
			
		||||
        switchable: true,
 | 
			
		||||
        formatter: function(value, row) {
 | 
			
		||||
            let min_price = row.purchase_price;
 | 
			
		||||
            let max_price = row.purchase_price;
 | 
			
		||||
            let currency = row.purchase_price_currency;
 | 
			
		||||
 | 
			
		||||
            if (min_price == null && max_price == null && row.part_detail) {
 | 
			
		||||
                min_price = row.part_detail.pricing_min;
 | 
			
		||||
                max_price = row.part_detail.pricing_max;
 | 
			
		||||
                currency = baseCurrency();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return formatPriceRange(
 | 
			
		||||
                min_price,
 | 
			
		||||
                max_price,
 | 
			
		||||
                {
 | 
			
		||||
                    quantity: row.quantity,
 | 
			
		||||
                    currency: currency
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        },
 | 
			
		||||
        footerFormatter: function(data) {
 | 
			
		||||
            // Display overall range of value for the selected items
 | 
			
		||||
            let rates = getCurrencyConversionRates();
 | 
			
		||||
            let base = baseCurrency();
 | 
			
		||||
 | 
			
		||||
            let min_price = calculateTotalPrice(
 | 
			
		||||
                data,
 | 
			
		||||
                function(row) {
 | 
			
		||||
                    return row.quantity * (row.purchase_price || row.part_detail.pricing_min);
 | 
			
		||||
                },
 | 
			
		||||
                function(row) {
 | 
			
		||||
                    if (row.purchase_price) {
 | 
			
		||||
                        return row.purchase_price_currency;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return base;
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    currency: base,
 | 
			
		||||
                    rates: rates,
 | 
			
		||||
                    raw: true,
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            let max_price = calculateTotalPrice(
 | 
			
		||||
                data,
 | 
			
		||||
                function(row) {
 | 
			
		||||
                    return row.quantity * (row.purchase_price || row.part_detail.pricing_max);
 | 
			
		||||
                },
 | 
			
		||||
                function(row) {
 | 
			
		||||
                    if (row.purchase_price) {
 | 
			
		||||
                        return row.purchase_price_currency;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return base;
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    currency: base,
 | 
			
		||||
                    rates: rates,
 | 
			
		||||
                    raw: true,
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            return formatPriceRange(
 | 
			
		||||
                min_price,
 | 
			
		||||
                max_price,
 | 
			
		||||
                {
 | 
			
		||||
                    currency: base,
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    columns.push({
 | 
			
		||||
        field: 'packaging',
 | 
			
		||||
        title: '{% trans "Packaging" %}',
 | 
			
		||||
@@ -2085,6 +2165,7 @@ function loadStockTable(table, options) {
 | 
			
		||||
        name: 'stock',
 | 
			
		||||
        original: original,
 | 
			
		||||
        showColumns: true,
 | 
			
		||||
        showFooter: true,
 | 
			
		||||
        columns: columns,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user