mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 07:05:41 +00:00 
			
		
		
		
	Sales order allocation fixes (#2751)
This commit is contained in:
		@@ -860,9 +860,17 @@ class SOAllocationList(generics.ListAPIView):
 | 
				
			|||||||
            outstanding = str2bool(outstanding)
 | 
					            outstanding = str2bool(outstanding)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if outstanding:
 | 
					            if outstanding:
 | 
				
			||||||
                queryset = queryset.filter(line__order__status__in=SalesOrderStatus.OPEN)
 | 
					                # Filter only "open" orders
 | 
				
			||||||
 | 
					                # Filter only allocations which have *not* shipped
 | 
				
			||||||
 | 
					                queryset = queryset.filter(
 | 
				
			||||||
 | 
					                    line__order__status__in=SalesOrderStatus.OPEN,
 | 
				
			||||||
 | 
					                    shipment__shipment_date=None,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                queryset = queryset.exclude(line__order__status__in=SalesOrderStatus.OPEN)
 | 
					                queryset = queryset.exclude(
 | 
				
			||||||
 | 
					                    line__order__status__in=SalesOrderStatus.OPEN,
 | 
				
			||||||
 | 
					                    shipment__shipment_date=None
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return queryset
 | 
					        return queryset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1002,7 +1010,7 @@ order_api_urls = [
 | 
				
			|||||||
        url(r'^.*$', POLineItemList.as_view(), name='api-po-line-list'),
 | 
					        url(r'^.*$', POLineItemList.as_view(), name='api-po-line-list'),
 | 
				
			||||||
    ])),
 | 
					    ])),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # API endpoints for sales ordesr
 | 
					    # API endpoints for sales orders
 | 
				
			||||||
    url(r'^so/', include([
 | 
					    url(r'^so/', include([
 | 
				
			||||||
        url(r'attachment/', include([
 | 
					        url(r'attachment/', include([
 | 
				
			||||||
            url(r'^(?P<pk>\d+)/$', SOAttachmentDetail.as_view(), name='api-so-attachment-detail'),
 | 
					            url(r'^(?P<pk>\d+)/$', SOAttachmentDetail.as_view(), name='api-so-attachment-detail'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -417,7 +417,7 @@ class Part(MPTTModel):
 | 
				
			|||||||
        context['allocated_build_order_quantity'] = self.build_order_allocation_count()
 | 
					        context['allocated_build_order_quantity'] = self.build_order_allocation_count()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context['required_sales_order_quantity'] = self.required_sales_order_quantity()
 | 
					        context['required_sales_order_quantity'] = self.required_sales_order_quantity()
 | 
				
			||||||
        context['allocated_sales_order_quantity'] = self.sales_order_allocation_count()
 | 
					        context['allocated_sales_order_quantity'] = self.sales_order_allocation_count(pending=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context['available'] = self.available_stock
 | 
					        context['available'] = self.available_stock
 | 
				
			||||||
        context['on_order'] = self.on_order
 | 
					        context['on_order'] = self.on_order
 | 
				
			||||||
@@ -1118,7 +1118,9 @@ class Part(MPTTModel):
 | 
				
			|||||||
        quantity = 0
 | 
					        quantity = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for line in open_lines:
 | 
					        for line in open_lines:
 | 
				
			||||||
            quantity += line.quantity
 | 
					            # Determine the quantity "remaining" to be shipped out
 | 
				
			||||||
 | 
					            remaining = max(line.quantity - line.shipped, 0)
 | 
				
			||||||
 | 
					            quantity += remaining
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return quantity
 | 
					        return quantity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1336,19 +1338,36 @@ class Part(MPTTModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return query['total']
 | 
					        return query['total']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def sales_order_allocations(self):
 | 
					    def sales_order_allocations(self, **kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Return all sales-order-allocation objects which allocate this part to a SalesOrder
 | 
					        Return all sales-order-allocation objects which allocate this part to a SalesOrder
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return OrderModels.SalesOrderAllocation.objects.filter(item__part__id=self.id)
 | 
					        queryset = OrderModels.SalesOrderAllocation.objects.filter(item__part__id=self.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def sales_order_allocation_count(self):
 | 
					        pending = kwargs.get('pending', None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if pending is True:
 | 
				
			||||||
 | 
					            # Look only for 'open' orders which have not shipped
 | 
				
			||||||
 | 
					            queryset = queryset.filter(
 | 
				
			||||||
 | 
					                line__order__status__in=SalesOrderStatus.OPEN,
 | 
				
			||||||
 | 
					                shipment__shipment_date=None,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        elif pending is False:
 | 
				
			||||||
 | 
					            # Look only for 'closed' orders or orders which have shipped
 | 
				
			||||||
 | 
					            queryset = queryset.exclude(
 | 
				
			||||||
 | 
					                line__order__status__in=SalesOrderStatus.OPEN,
 | 
				
			||||||
 | 
					                shipment__shipment_date=None,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return queryset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sales_order_allocation_count(self, **kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Return the tutal quantity of this part allocated to sales orders
 | 
					        Return the total quantity of this part allocated to sales orders
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        query = self.sales_order_allocations().aggregate(
 | 
					        query = self.sales_order_allocations(**kwargs).aggregate(
 | 
				
			||||||
            total=Coalesce(
 | 
					            total=Coalesce(
 | 
				
			||||||
                Sum(
 | 
					                Sum(
 | 
				
			||||||
                    'quantity',
 | 
					                    'quantity',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,44 +204,60 @@
 | 
				
			|||||||
            <td>{% decimal on_order %}</td>
 | 
					            <td>{% decimal on_order %}</td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        {% endif %}
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					        {% if part.component %}
 | 
				
			||||||
        {% if required_build_order_quantity > 0 %}
 | 
					        {% if required_build_order_quantity > 0 %}
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
            <td><span class='fas fa-clipboard-list'></span></td>
 | 
					            <td><span class='fas fa-clipboard-list'></span></td>
 | 
				
			||||||
            <td>{% trans "Required for Build Orders" %}</td>
 | 
					            <td>{% trans "Required for Build Orders" %}</td>
 | 
				
			||||||
            <td>{% decimal required_build_order_quantity %}
 | 
					            <td>{% decimal required_build_order_quantity %}</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td><span class='fas fa-dolly'></span></td>
 | 
				
			||||||
 | 
					            <td>{% trans "Allocated to Build Orders" %}</td>
 | 
				
			||||||
 | 
					            <td>
 | 
				
			||||||
 | 
					                {% decimal allocated_build_order_quantity %}
 | 
				
			||||||
 | 
					                {% if allocated_build_order_quantity < required_build_order_quantity %}
 | 
				
			||||||
 | 
					                <span class='fas fa-times-circle icon-red float-right' title='{% trans "Required quantity has not been allocated" %}'></span>
 | 
				
			||||||
 | 
					                {% else %}
 | 
				
			||||||
 | 
					                <span class='fas fa-check-circle icon-green float-right' title='{% trans "Required quantity has been allocated" %}'></span>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        {% endif %}
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					        {% if part.salable %}
 | 
				
			||||||
        {% if required_sales_order_quantity > 0 %}
 | 
					        {% if required_sales_order_quantity > 0 %}
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
            <td><span class='fas fa-clipboard-list'></span></td>
 | 
					            <td><span class='fas fa-clipboard-list'></span></td>
 | 
				
			||||||
            <td>{% trans "Required for Sales Orders" %}</td>
 | 
					            <td>{% trans "Required for Sales Orders" %}</td>
 | 
				
			||||||
            <td>{% decimal required_sales_order_quantity %}
 | 
					            <td>
 | 
				
			||||||
        </tr>
 | 
					                {% decimal required_sales_order_quantity %}
 | 
				
			||||||
        {% endif %}
 | 
					 | 
				
			||||||
        {% if allocated > 0 %}
 | 
					 | 
				
			||||||
        <tr>
 | 
					 | 
				
			||||||
            <td><span class='fas fa-dolly'></span></td>
 | 
					 | 
				
			||||||
            <td>{% trans "Allocated to Orders" %}</td>
 | 
					 | 
				
			||||||
            <td>{% decimal allocated %}</td>
 | 
					 | 
				
			||||||
        </tr>
 | 
					 | 
				
			||||||
        {% endif %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        {% if not part.is_template %}
 | 
					 | 
				
			||||||
        {% if part.assembly %}
 | 
					 | 
				
			||||||
        <tr>
 | 
					 | 
				
			||||||
            <td><h5><span class='fas fa-tools'></span></h5></td>
 | 
					 | 
				
			||||||
            <td colspan='2'>
 | 
					 | 
				
			||||||
                <h5>{% trans "Build Status" %}</h5>
 | 
					 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
            <td></td>
 | 
					            <td><span class='fas fa-dolly'></span></td>
 | 
				
			||||||
 | 
					            <td>{% trans "Allocated to Sales Orders" %}</td>
 | 
				
			||||||
 | 
					            <td>
 | 
				
			||||||
 | 
					                {% decimal allocated_sales_order_quantity %}
 | 
				
			||||||
 | 
					                {% if allocated_sales_order_quantity < required_sales_order_quantity %}
 | 
				
			||||||
 | 
					                <span class='fas fa-times-circle icon-red float-right' title='{% trans "Required quantity has not been allocated" %}'></span>
 | 
				
			||||||
 | 
					                {% else %}
 | 
				
			||||||
 | 
					                <span class='fas fa-check-circle icon-green float-right' title='{% trans "Required quantity has been allocated" %}'></span>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					        {% if not part.is_template %}
 | 
				
			||||||
 | 
					        {% if part.assembly %}
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td><span class='fas fa-tools'></span></td>
 | 
				
			||||||
            <td>{% trans "Can Build" %}</td>
 | 
					            <td>{% trans "Can Build" %}</td>
 | 
				
			||||||
            <td>{% decimal part.can_build %}</td>
 | 
					            <td>{% decimal part.can_build %}</td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        {% if quantity_being_built > 0 %}
 | 
					        {% if quantity_being_built > 0 %}
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
            <td></td>
 | 
					            <td><span class='fas fa-tools'></span></td>
 | 
				
			||||||
            <td>{% trans "Building" %}</td>
 | 
					            <td>{% trans "Building" %}</td>
 | 
				
			||||||
            <td>{% decimal quantity_being_built %}</td>
 | 
					            <td>{% decimal quantity_being_built %}</td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,9 @@
 | 
				
			|||||||
{% if part.assembly %}
 | 
					{% if part.assembly %}
 | 
				
			||||||
{% trans "Bill of Materials" as text %}
 | 
					{% trans "Bill of Materials" as text %}
 | 
				
			||||||
{% include "sidebar_item.html" with label="bom" text=text icon="fa-list" %}
 | 
					{% include "sidebar_item.html" with label="bom" text=text icon="fa-list" %}
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
{% if roles.build.view %}
 | 
					{% if roles.build.view %}
 | 
				
			||||||
 | 
					{% if part.assembly or part.component %}
 | 
				
			||||||
{% trans "Build Orders" as text %}
 | 
					{% trans "Build Orders" as text %}
 | 
				
			||||||
{% include "sidebar_item.html" with label="build-orders" text=text icon="fa-tools" %}
 | 
					{% include "sidebar_item.html" with label="build-orders" text=text icon="fa-tools" %}
 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
@@ -30,10 +32,6 @@
 | 
				
			|||||||
{% trans "Pricing" as text %}
 | 
					{% trans "Pricing" as text %}
 | 
				
			||||||
{% include "sidebar_item.html" with label="pricing" text=text icon="fa-dollar-sign" %}
 | 
					{% include "sidebar_item.html" with label="pricing" text=text icon="fa-dollar-sign" %}
 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if part.salable or part.component %}
 | 
					 | 
				
			||||||
{% trans "Allocations" as text %}
 | 
					 | 
				
			||||||
{% include "sidebar_item.html" with label="allocations" text=text icon="fa-bookmark" %}
 | 
					 | 
				
			||||||
{% endif %}
 | 
					 | 
				
			||||||
{% if part.purchaseable and roles.purchase_order.view %}
 | 
					{% if part.purchaseable and roles.purchase_order.view %}
 | 
				
			||||||
{% trans "Suppliers" as text %}
 | 
					{% trans "Suppliers" as text %}
 | 
				
			||||||
{% include "sidebar_item.html" with label="suppliers" text=text icon="fa-building" %}
 | 
					{% include "sidebar_item.html" with label="suppliers" text=text icon="fa-building" %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,19 +37,36 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class='panel panel-hidden' id='panel-allocations'>
 | 
					<div class='panel panel-hidden' id='panel-allocations'>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if item.part.component %}
 | 
				
			||||||
    <div class='panel-heading'>
 | 
					    <div class='panel-heading'>
 | 
				
			||||||
        <h4>{% trans "Stock Item Allocations" %}</h4>
 | 
					        <h4>{% trans "Build Order Allocations" %}</h4>
 | 
				
			||||||
        {% include "spacer.html" %}
 | 
					        {% include "spacer.html" %}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class='panel-content'>
 | 
					    <div class='panel-content'>
 | 
				
			||||||
        <div id='allocations-button-toolbar'>
 | 
					        <div id='build-order-allocations-toolbar'>
 | 
				
			||||||
            <div class='btn-group' role='group'>
 | 
					            <div class='btn-group' role='group'>
 | 
				
			||||||
                {% include "filter_list.html" with id="allocations" %}
 | 
					                {% include "filter_list.html" with id="buildorderallocation" %}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <table class='table table-striped table-condensed' data-toolbar='#allocatoins-button-toolbar' id='stock-allocation-table'></table>
 | 
					        <table class='table table-striped table-condensed' data-toolbar='#build-order-allocation-toolbar' id='build-order-allocation-table'></table>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if item.part.salable %}
 | 
				
			||||||
 | 
					    <div class='panel-heading'>
 | 
				
			||||||
 | 
					        <h4>{% trans "Sales Order Allocations" %}</h4>
 | 
				
			||||||
 | 
					        {% include "spacer.html" %}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class='panel-content'>
 | 
				
			||||||
 | 
					        <div id='sales-order-allocations-toolbar'>
 | 
				
			||||||
 | 
					            <div class='btn-group' role='group'>
 | 
				
			||||||
 | 
					                {% include "filter_list.html" with id="salesorderallocation" %}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <table class='table table-striped table-condensed' data-toolbar='#sales-order-allocation-toolbar' id='sales-order-allocation-table'></table>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class='panel panel-hidden' id='panel-children'>
 | 
					<div class='panel panel-hidden' id='panel-children'>
 | 
				
			||||||
@@ -164,14 +181,21 @@
 | 
				
			|||||||
    // Load the "allocations" tab
 | 
					    // Load the "allocations" tab
 | 
				
			||||||
    onPanelLoad('allocations', function() {
 | 
					    onPanelLoad('allocations', function() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loadStockAllocationTable(
 | 
					        {% if item.part.component %}
 | 
				
			||||||
            $("#stock-allocation-table"),
 | 
					        loadBuildOrderAllocationTable('#build-order-allocation-table', {
 | 
				
			||||||
            {
 | 
					            params: {
 | 
				
			||||||
                params: { 
 | 
					                stock_item: {{ item.pk }},
 | 
				
			||||||
                    stock_item: {{ item.pk }},
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        );
 | 
					        });
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {% if item.part.salable %}
 | 
				
			||||||
 | 
					        loadSalesOrderAllocationTable('#sales-order-allocation-table', {
 | 
				
			||||||
 | 
					            params: {
 | 
				
			||||||
 | 
					                stock_item: {{ item.pk }},
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $('#stock-item-install').click(function() {
 | 
					    $('#stock-item-install').click(function() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1843,15 +1843,7 @@ function loadSalesOrderAllocationTable(table, options={}) {
 | 
				
			|||||||
                field: 'location',
 | 
					                field: 'location',
 | 
				
			||||||
                title: '{% trans "Location" %}',
 | 
					                title: '{% trans "Location" %}',
 | 
				
			||||||
                formatter: function(value, row) {
 | 
					                formatter: function(value, row) {
 | 
				
			||||||
 | 
					                    return locationDetail(row.item_detail, true);
 | 
				
			||||||
                    if (!value) {
 | 
					 | 
				
			||||||
                        return '{% trans "Location not specified" %}';
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    
 | 
					 | 
				
			||||||
                    var link = `/stock/location/${value}`;
 | 
					 | 
				
			||||||
                    var text = row.location_detail.description;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return renderLink(text, link);
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,6 @@
 | 
				
			|||||||
    findStockItemBySerialNumber,
 | 
					    findStockItemBySerialNumber,
 | 
				
			||||||
    installStockItem,
 | 
					    installStockItem,
 | 
				
			||||||
    loadInstalledInTable,
 | 
					    loadInstalledInTable,
 | 
				
			||||||
    loadStockAllocationTable,
 | 
					 | 
				
			||||||
    loadStockLocationTable,
 | 
					    loadStockLocationTable,
 | 
				
			||||||
    loadStockTable,
 | 
					    loadStockTable,
 | 
				
			||||||
    loadStockTestResultsTable,
 | 
					    loadStockTestResultsTable,
 | 
				
			||||||
@@ -2328,157 +2327,6 @@ function loadStockTable(table, options) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Display a table of allocated stock, for either a part or stock item
 | 
					 | 
				
			||||||
 * Allocations are displayed for:
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * a) Sales Orders
 | 
					 | 
				
			||||||
 * b) Build Orders
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function loadStockAllocationTable(table, options={}) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var params = options.params || {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    params.build_detail = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var filterListElement = options.filterList || '#filter-list-allocations';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var filters = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var filterKey = options.filterKey || options.name || 'allocations';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var original = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (var k in params) {
 | 
					 | 
				
			||||||
        original[k] = params[k];
 | 
					 | 
				
			||||||
        filters[k] = params[k];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setupFilterList(filterKey, table, filterListElement);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*
 | 
					 | 
				
			||||||
     * We have two separate API queries to make here:
 | 
					 | 
				
			||||||
     * a) Build Order Allocations
 | 
					 | 
				
			||||||
     * b) Sales Order Allocations
 | 
					 | 
				
			||||||
     * 
 | 
					 | 
				
			||||||
     * We will let the call to inventreeTable take care of build orders,
 | 
					 | 
				
			||||||
     * and then load sales orders after that.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    table.inventreeTable({
 | 
					 | 
				
			||||||
        url: '{% url "api-build-item-list" %}',
 | 
					 | 
				
			||||||
        name: 'allocations',
 | 
					 | 
				
			||||||
        original: original,
 | 
					 | 
				
			||||||
        method: 'get',
 | 
					 | 
				
			||||||
        queryParams: filters,
 | 
					 | 
				
			||||||
        sidePagination: 'client',
 | 
					 | 
				
			||||||
        showColumns: false,
 | 
					 | 
				
			||||||
        onLoadSuccess: function(tableData) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var query_params = params;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            query_params.customer_detail = true;
 | 
					 | 
				
			||||||
            query_params.order_detail = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            delete query_params.build_detail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Load sales order allocation data
 | 
					 | 
				
			||||||
            inventreeGet('{% url "api-so-allocation-list" %}', query_params, {
 | 
					 | 
				
			||||||
                success: function(data) {
 | 
					 | 
				
			||||||
                    // Update table to include sales order data
 | 
					 | 
				
			||||||
                    $(table).bootstrapTable('append', data);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        columns: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                field: 'order',
 | 
					 | 
				
			||||||
                title: '{% trans "Order" %}',
 | 
					 | 
				
			||||||
                formatter: function(value, row) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    var html = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (row.build) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Add an icon for the part being built
 | 
					 | 
				
			||||||
                        html += thumbnailImage(row.build_detail.part_detail.thumbnail, {
 | 
					 | 
				
			||||||
                            title: row.build_detail.part_detail.full_name
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        html += ' ';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        html += renderLink(
 | 
					 | 
				
			||||||
                            global_settings.BUILDORDER_REFERENCE_PREFIX + row.build_detail.reference,
 | 
					 | 
				
			||||||
                            `/build/${row.build}/`
 | 
					 | 
				
			||||||
                        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        html += makeIconBadge('fa-tools', '{% trans "Build Order" %}');
 | 
					 | 
				
			||||||
                    } else if (row.order) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Add an icon for the customer
 | 
					 | 
				
			||||||
                        html += thumbnailImage(row.customer_detail.thumbnail || row.customer_detail.image, {
 | 
					 | 
				
			||||||
                            title: row.customer_detail.name,
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        html += ' ';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        html += renderLink(
 | 
					 | 
				
			||||||
                            global_settings.SALESORDER_REFERENCE_PREFIX + row.order_detail.reference,
 | 
					 | 
				
			||||||
                            `/order/sales-order/${row.order}/`
 | 
					 | 
				
			||||||
                        );
 | 
					 | 
				
			||||||
                        html += makeIconBadge('fa-truck', '{% trans "Sales Order" %}');
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        return '-';
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return html;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                field: 'description',
 | 
					 | 
				
			||||||
                title: '{% trans "Description" %}',
 | 
					 | 
				
			||||||
                formatter: function(value, row) {
 | 
					 | 
				
			||||||
                    if (row.order_detail) {
 | 
					 | 
				
			||||||
                        return row.order_detail.description;
 | 
					 | 
				
			||||||
                    } else if (row.build_detail) {
 | 
					 | 
				
			||||||
                        return row.build_detail.title;
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        return '-';
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                field: 'status',
 | 
					 | 
				
			||||||
                title: '{% trans "Order Status" %}',
 | 
					 | 
				
			||||||
                formatter: function(value, row) {
 | 
					 | 
				
			||||||
                    if (row.build) {
 | 
					 | 
				
			||||||
                        return buildStatusDisplay(row.build_detail.status);
 | 
					 | 
				
			||||||
                    } else if (row.order) {
 | 
					 | 
				
			||||||
                        return salesOrderStatusDisplay(row.order_detail.status);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        return '-';
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                field: 'quantity',
 | 
					 | 
				
			||||||
                title: '{% trans "Allocated Quantity" %}',
 | 
					 | 
				
			||||||
                formatter: function(value, row) {
 | 
					 | 
				
			||||||
                    var text = value;
 | 
					 | 
				
			||||||
                    var pk = row.stock_item || row.item;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (pk) {
 | 
					 | 
				
			||||||
                        var url = `/stock/item/${pk}/`;
 | 
					 | 
				
			||||||
                        return renderLink(text, url);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        return value;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* 
 | 
					/* 
 | 
				
			||||||
 * Display a table of stock locations
 | 
					 * Display a table of stock locations
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -341,6 +341,15 @@ function getAvailableTableFilters(tableKey) {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (tableKey == 'salesorderallocation') {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            outstanding: {
 | 
				
			||||||
 | 
					                type: 'bool',
 | 
				
			||||||
 | 
					                title: '{% trans "Outstanding" %}',
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (tableKey == 'salesorder') {
 | 
					    if (tableKey == 'salesorder') {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            status: {
 | 
					            status: {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user