diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py
index 85e7c051bf..6041c2827e 100644
--- a/InvenTree/part/models.py
+++ b/InvenTree/part/models.py
@@ -41,7 +41,7 @@ from InvenTree.models import InvenTreeTree, InvenTreeAttachment
from InvenTree.fields import InvenTreeURLField
from InvenTree.helpers import decimal2string, normalize
-from InvenTree.status_codes import BuildStatus, PurchaseOrderStatus
+from InvenTree.status_codes import BuildStatus, PurchaseOrderStatus, SalesOrderStatus
from build import models as BuildModels
from order import models as OrderModels
@@ -940,6 +940,42 @@ class Part(MPTTModel):
return quantity
+ def requiring_sales_orders(self):
+ """
+ Return a list of sales orders which require this part
+ """
+
+ orders = set()
+
+ # Get a list of line items for open orders which match this part
+ open_lines = OrderModels.SalesOrderLineItem.objects.filter(
+ order__status__in=SalesOrderStatus.OPEN,
+ part=self
+ )
+
+ for line in open_lines:
+ orders.add(line.order)
+
+ return orders
+
+ def required_sales_order_quantity(self):
+ """
+ Return the quantity of this part required for active sales orders
+ """
+
+ # Get a list of line items for open orders which match this part
+ open_lines = OrderModels.SalesOrderLineItem.objects.filter(
+ order__status__in=SalesOrderStatus.OPEN,
+ part=self
+ )
+
+ quantity = 0
+
+ for line in open_lines:
+ quantity += line.quantity
+
+ return quantity
+
@property
def quantity_to_order(self):
""" Return the quantity needing to be ordered for this part. """
diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html
index 0ddb5d2180..24c0c0b234 100644
--- a/InvenTree/part/templates/part/part_base.html
+++ b/InvenTree/part/templates/part/part_base.html
@@ -126,28 +126,6 @@
{% trans "In Stock" %} |
{% include "part/stock_count.html" %} |
- {% if not part.is_template %}
- {% if part.required_build_order_quantity > 0 %}
-
- |
- {% trans "Required for Build Orders" %} |
- {% decimal part.required_build_order_quantity %} |
-
- {% endif %}
- {% if part.build_order_allocation_count > 0 %}
-
- |
- {% trans "Allocated to Build Orders" %} |
- {% decimal part.build_order_allocation_count %} |
-
- {% endif %}
- {% if part.sales_order_allocation_count > 0 %}
-
- |
- {% trans "Allocated to Sales Orders" %} |
- {% decimal part.sales_order_allocation_count %} |
-
- {% endif %}
{% if part.on_order > 0 %}
|
@@ -155,7 +133,21 @@
{% decimal part.on_order %} |
{% endif %}
+ {% if required > 0 %}
+
+ |
+ {% trans "Required for Orders" %} |
+ {% decimal required %}
+ |
{% endif %}
+ {% if allocated > 0 %}
+
+ |
+ {% trans "Allocated to Orders" %} |
+ {% decimal allocated %} |
+
+ {% endif %}
+
{% if not part.is_template %}
{% if part.assembly %}
@@ -169,11 +161,11 @@
{% trans "Can Build" %} |
{% decimal part.can_build %} |
- {% if part.quantity_being_built > 0 %}
+ {% if quantity_being_built > 0 %}
|
{% trans "Underway" %} |
- {% decimal part.quantity_being_built %} |
+ {% decimal quantity_being_built %} |
{% endif %}
{% endif %}
diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py
index 8f1c86fdfc..42c48c8cab 100644
--- a/InvenTree/part/views.py
+++ b/InvenTree/part/views.py
@@ -792,6 +792,16 @@ class PartDetail(InvenTreeRoleMixin, DetailView):
context['starred'] = part.isStarredBy(self.request.user)
context['disabled'] = not part.active
+ # Pre-calculate complex queries so they only need to be performed once
+ context['required_build_order_quantity'] = part.required_build_order_quantity()
+ context['allocated_build_order_quantity'] = part.build_order_allocation_count()
+
+ context['required_sales_order_quantity'] = part.required_sales_order_quantity()
+ context['allocated_sales_order_quantity'] = part.sales_order_allocation_count()
+
+ context['required'] = context['required_build_order_quantity'] + context['required_sales_order_quantity']
+ context['allocated'] = context['allocated_build_order_quantity'] + context['allocated_sales_order_quantity']
+
return context