diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index c36487a7dd..1c59a0bb31 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -1766,9 +1766,6 @@ class ReturnOrder(TotalPriceMixin, Order): stock_item = line.item - # Remove any allocations against the returned StockItem - stock_item.clearAllocations() - deltas = { 'status': StockStatus.QUARANTINED, 'returnorder': self.pk, diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 09b49fb4d3..0d3a28d09f 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -33,7 +33,8 @@ from InvenTree.fields import (InvenTreeModelMoneyField, InvenTreeNotesField, InvenTreeURLField) from InvenTree.models import (InvenTreeAttachment, InvenTreeBarcodeMixin, InvenTreeTree, extract_int) -from InvenTree.status_codes import StockHistoryCode, StockStatus +from InvenTree.status_codes import (SalesOrderStatus, StockHistoryCode, + StockStatus) from part import models as PartModels from plugin.events import trigger_event from plugin.models import MetadataMixin @@ -1013,7 +1014,6 @@ class StockItem(InvenTreeBarcodeMixin, MetadataMixin, common.models.MetaMixin, M location=location ) - self.clearAllocations() self.customer = None self.belongs_to = None self.sales_order = None @@ -1059,9 +1059,33 @@ class StockItem(InvenTreeBarcodeMixin, MetadataMixin, common.models.MetaMixin, M return total - def sales_order_allocation_count(self): + def get_sales_order_allocations(self, active=True): + """Return a queryset for SalesOrderAllocations against this StockItem, with optional filters. + + Arguments: + active: Filter by 'active' status of the allocation + """ + query = self.sales_order_allocations.all() + + if active is True: + query = query.filter( + line__order__status__in=SalesOrderStatus.OPEN, + shipment__shipment_date=None + ) + elif active is False: + query = query.exclude( + line__order__status__in=SalesOrderStatus.OPEN + ).exclude( + shipment__shipment_date=None + ) + + return query + + def sales_order_allocation_count(self, active=True): """Return the total quantity allocated to SalesOrders.""" - query = self.sales_order_allocations.aggregate(q=Coalesce(Sum('quantity'), Decimal(0))) + + query = self.get_sales_order_allocations(active=active) + query = query.aggregate(q=Coalesce(Sum('quantity'), Decimal(0))) total = query['q'] diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html index 71df55c5b1..a886e71b6c 100644 --- a/InvenTree/stock/templates/stock/item.html +++ b/InvenTree/stock/templates/stock/item.html @@ -59,7 +59,7 @@ {% include "filter_list.html" with id="salesorderallocation" %} -
+
{% endif %} diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index f897d7405c..369a50454a 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -266,6 +266,12 @@
+ {% if not item.in_stock %} +
+ {% trans "This stock item is unavailable" %} +
+ {% endif %} + {% if item.is_building %}
{% trans "This stock item is in production and cannot be edited." %}
@@ -281,12 +287,12 @@ {% endif %} {% if item.hasRequiredTests and not item.passedAllRequiredTests %} -
+
{% trans "This stock item has not passed all required tests" %}
{% endif %} - {% for allocation in item.sales_order_allocations.all %} + {% for allocation in item.get_sales_order_allocations.all %}
{% object_link 'so-detail' allocation.line.order.id allocation.line.order as link %} {% decimal allocation.quantity as qty %} @@ -301,12 +307,6 @@ {% trans "This stock item is allocated to Build Order" %} {{ link }} {% if qty < item.quantity %}({% trans "Quantity" %}: {{ qty }}){% endif %}
{% endfor %} - - {% if item.serialized %} -
- {% trans "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." %} -
- {% endif %}
{% endblock details %} @@ -320,7 +320,7 @@
-
{% trans "Serial Number" %}
+
{% trans "Serial Number" %}
{{ item.serial }} @@ -348,7 +348,11 @@
+ {% if item.in_stock %}
{% trans "Available Quantity" %}
+ {% else %} +
{% trans "Quantity" %}
+ {% endif %}
{% if item.quantity != available %}{% decimal available %} / {% endif %}{% decimal item.quantity %} {% include "part/part_units.html" with part=item.part %}
@@ -367,7 +371,7 @@ {% elif item.sales_order %} - + {% trans "Sales Order" %} {{ item.sales_order.reference }} - {{ item.sales_order.customer.name }} diff --git a/InvenTree/templates/js/translated/sales_order.js b/InvenTree/templates/js/translated/sales_order.js index af8488f6b1..89fd155c1e 100644 --- a/InvenTree/templates/js/translated/sales_order.js +++ b/InvenTree/templates/js/translated/sales_order.js @@ -1387,6 +1387,7 @@ function loadSalesOrderAllocationTable(table, options={}) { }, { field: 'item', + switchable: false, title: '{% trans "Stock Item" %}', formatter: function(value, row) { // Render a link to the particular stock item @@ -1409,6 +1410,18 @@ function loadSalesOrderAllocationTable(table, options={}) { title: '{% trans "Quantity" %}', sortable: true, }, + { + field: 'shipment_date', + title: '{% trans "Shipped" %}', + sortable: true, + formatter: function(value, row) { + if (value) { + return renderDate(value); + } else { + return `{% trans "Not shipped" %}`; + } + } + } ] }); }