From 336b05aa4eff2141274b5d08a94ebe537b6923f6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 6 Oct 2021 17:42:00 +1100 Subject: [PATCH] Exclude sales order allocations when searching stock --- InvenTree/order/models.py | 14 +++++++++-- InvenTree/stock/api.py | 28 ++++++++++++++++++++++ InvenTree/templates/js/translated/order.js | 2 +- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 495ea2d333..4ac8925259 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -840,7 +840,13 @@ class SalesOrderLineItem(OrderLineItem): def get_api_url(): return reverse('api-so-line-list') - order = models.ForeignKey(SalesOrder, on_delete=models.CASCADE, related_name='lines', verbose_name=_('Order'), help_text=_('Sales Order')) + order = models.ForeignKey( + SalesOrder, + on_delete=models.CASCADE, + related_name='lines', + verbose_name=_('Order'), + help_text=_('Sales Order') + ) part = models.ForeignKey('part.Part', on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, verbose_name=_('Part'), help_text=_('Part'), limit_choices_to={'salable': True}) @@ -954,7 +960,11 @@ class SalesOrderAllocation(models.Model): if len(errors) > 0: raise ValidationError(errors) - line = models.ForeignKey(SalesOrderLineItem, on_delete=models.CASCADE, verbose_name=_('Line'), related_name='allocations') + line = models.ForeignKey( + SalesOrderLineItem, + on_delete=models.CASCADE, + verbose_name=_('Line'), + related_name='allocations') item = models.ForeignKey( 'stock.StockItem', diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index ad487c7a5a..34045bda43 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -6,6 +6,8 @@ JSON API for the Stock app from __future__ import unicode_literals from datetime import datetime, timedelta +from django.db.models import query +from django.db.models.query import QuerySet from django.utils.translation import ugettext_lazy as _ @@ -34,6 +36,7 @@ from company.models import Company, SupplierPart from company.serializers import CompanySerializer, SupplierPartSerializer from order.models import PurchaseOrder +from order.models import SalesOrder, SalesOrderAllocation from order.serializers import POSerializer import common.settings @@ -645,6 +648,31 @@ class StockList(generics.ListCreateAPIView): # Filter StockItem without build allocations or sales order allocations queryset = queryset.filter(Q(sales_order_allocations__isnull=True) & Q(allocations__isnull=True)) + # Exclude StockItems which are already allocated to a particular SalesOrder + exclude_so_allocation = params.get('exclude_so_allocation', None) + + if exclude_so_allocation is not None: + + try: + order = SalesOrder.objects.get(pk=exclude_so_allocation) + + # Grab all the active SalesOrderAllocations for this order + allocations = SalesOrderAllocation.objects.filter( + line__pk__in=[ + line.pk for line in order.lines.all() + ] + ) + + # Exclude any stock item which is already allocated to the sales order + queryset = queryset.exclude( + pk__in=[ + a.item.pk for a in allocations + ] + ) + + except (ValueError, SalesOrder.DoesNotExist): + pass + # Does the client wish to filter by the Part ID? part_id = params.get('part', None) diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 7bee488b75..870ac9150d 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -1631,7 +1631,7 @@ function loadSalesOrderLineItemTable(table, options={}) { location_detail: true, in_stock: true, part: line_item.part, - // TODO: Exclude items already allocated to this sales order + exclude_so_allocation: options.order, } }, quantity: {