From 28c9c80f540d0c05bd49f383798e58fd81f16cd8 Mon Sep 17 00:00:00 2001 From: Oliver Walters <oliver.henry.walters@gmail.com> Date: Wed, 17 Feb 2021 10:57:17 +1100 Subject: [PATCH] Calculate quantity required for sales orders - Cache data going to part detail view --- InvenTree/part/models.py | 38 ++++++++++++++++++- InvenTree/part/templates/part/part_base.html | 40 ++++++++------------ InvenTree/part/views.py | 10 +++++ 3 files changed, 63 insertions(+), 25 deletions(-) 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 @@ <td>{% trans "In Stock" %}</td> <td>{% include "part/stock_count.html" %}</td> </tr> - {% if not part.is_template %} - {% if part.required_build_order_quantity > 0 %} - <tr> - <td><span class='fas fa-hand-holding'></span></td> - <td>{% trans "Required for Build Orders" %}</td> - <td>{% decimal part.required_build_order_quantity %}</td> - </tr> - {% endif %} - {% if part.build_order_allocation_count > 0 %} - <tr> - <td><span class='fas fa-dolly'></span></td> - <td>{% trans "Allocated to Build Orders" %}</td> - <td>{% decimal part.build_order_allocation_count %}</td> - </tr> - {% endif %} - {% if part.sales_order_allocation_count > 0 %} - <tr> - <td><span class='fas fa-dolly'></span></td> - <td>{% trans "Allocated to Sales Orders" %}</td> - <td>{% decimal part.sales_order_allocation_count %}</td> - </tr> - {% endif %} {% if part.on_order > 0 %} <tr> <td><span class='fas fa-shopping-cart'></span></td> @@ -155,7 +133,21 @@ <td>{% decimal part.on_order %}</td> </tr> {% endif %} + {% if required > 0 %} + <tr> + <td><span class='fas fa-clipboard-list'></span></td> + <td>{% trans "Required for Orders" %}</td> + <td>{% decimal required %} + </tr> {% 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> @@ -169,11 +161,11 @@ <td>{% trans "Can Build" %}</td> <td>{% decimal part.can_build %}</td> </tr> - {% if part.quantity_being_built > 0 %} + {% if quantity_being_built > 0 %} <tr> <td></td> <td>{% trans "Underway" %}</td> - <td>{% decimal part.quantity_being_built %}</td> + <td>{% decimal quantity_being_built %}</td> </tr> {% 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