diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 550884608f..a1968c317e 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -47,7 +47,7 @@ width: 100%; left: 0px; font-weight: bold; - font-size: 120%; + font-size: 110%; } .progress-bar-inner { diff --git a/InvenTree/InvenTree/static/script/inventree/inventree.js b/InvenTree/InvenTree/static/script/inventree/inventree.js index 04539c6d96..1e060cd6d3 100644 --- a/InvenTree/InvenTree/static/script/inventree/inventree.js +++ b/InvenTree/InvenTree/static/script/inventree/inventree.js @@ -78,6 +78,33 @@ function getImageUrlFromTransfer(transfer) { return url; } +function makeProgressBar(value, maximum, opts) { + /* + * Render a progessbar! + * + * @param value is the current value of the progress bar + * @param maximum is the maximum value of the progress bar + */ + + var options = opts || {}; + + value = parseFloat(value); + maximum = parseFloat(maximum); + + var percent = parseInt(value / maximum * 100); + + if (percent > 100) { + percent = 100; + } + + return ` +
+
+
${value} / ${maximum}
+
+ `; +} + function enableDragAndDrop(element, url, options) { /* Enable drag-and-drop file uploading for a given element. diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 9c6d5dcbb8..ba8e6b0337 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -19,9 +19,7 @@ import os from datetime import datetime from decimal import Decimal -from stock.models import StockItem from company.models import Company, SupplierPart -from part.models import Part from InvenTree.fields import RoundingDecimalField from InvenTree.helpers import decimal2string @@ -372,7 +370,7 @@ class SalesOrderLineItem(OrderLineItem): order = models.ForeignKey(SalesOrder, on_delete=models.CASCADE, related_name='lines', help_text=_('Sales Order')) - part = models.ForeignKey(Part, on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, help_text=_('Part'), limit_choices_to={'salable': True}) + part = models.ForeignKey('part.Part', on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, help_text=_('Part'), limit_choices_to={'salable': True}) def allocated_quantity(self): """ Return the total stock quantity allocated to this LineItem. @@ -380,6 +378,6 @@ class SalesOrderLineItem(OrderLineItem): This is a summation of the quantity of each attached StockItem """ - query = self.stock_items.aggregate(allocated=Coalesce(Sum('stock_item__quantity'), Decimal(0))) + query = self.stock_items.aggregate(allocated=Coalesce(Sum('quantity'), Decimal(0))) return query['allocated'] diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 64b75358da..59ac73cd0a 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -72,12 +72,7 @@ $("#so-lines-table").inventreeTable({ field: 'quantity', title: 'Quantity', formatter: function(value, row, index, field) { - return ` -
-
-
${row.allocated} / ${row.quantity}
-
- `; + return makeProgressBar(row.allocated, row.quantity); } }, { diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index f009f09791..1129a3ce79 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -29,6 +29,7 @@ from InvenTree.models import InvenTreeTree from InvenTree.fields import InvenTreeURLField from part.models import Part +from order.models import PurchaseOrder, SalesOrderLineItem class StockLocation(InvenTreeTree): @@ -262,6 +263,20 @@ class StockItem(MPTTModel): # TODO - Find a test than can be perfomed... pass + try: + # If this StockItem is assigned to a SalesOrderLineItem, + # the "Part" that the line item references is the same as the part that THIS references + if self.sales_order is not None: + + if self.sales_order.part == None: + raise ValidationError({'sales_order': _('Stock item cannot be assigned to a LineItem which does not reference a part')}) + + if not self.sales_order.part == self.part: + raise ValidationError({'sales_order': _('Stock item does not reference the same part object as the LineItem')}) + + except SalesOrderLineItem.DoesNotExist: + pass + if self.belongs_to and self.belongs_to.pk == self.pk: raise ValidationError({ 'belongs_to': _('Item cannot belong to itself') @@ -347,7 +362,7 @@ class StockItem(MPTTModel): ) purchase_order = models.ForeignKey( - 'order.PurchaseOrder', + PurchaseOrder, on_delete=models.SET_NULL, related_name='stock_items', blank=True, null=True, @@ -355,7 +370,7 @@ class StockItem(MPTTModel): ) sales_order = models.ForeignKey( - 'order.SalesOrderLineItem', + SalesOrderLineItem, on_delete=models.SET_NULL, related_name='stock_items', null=True)