From 0c19a94f5c060a82a4f3dde495ed2197d8c7cb51 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 22:50:58 +1000 Subject: [PATCH] Add run-time addition of extra data to the API --- InvenTree/stock/api.py | 58 ++++++++++- InvenTree/templates/js/stock.js | 175 ++++++++++++++++++++++++-------- 2 files changed, 192 insertions(+), 41 deletions(-) diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index c7914827e7..3443c9982f 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -22,7 +22,10 @@ from part.models import Part, PartCategory from part.serializers import PartBriefSerializer from company.models import SupplierPart -from company.serializers import SupplierPartSerializer +from company.serializers import CompanySerializer, SupplierPartSerializer + +from order.models import PurchaseOrder +from order.serializers import POSerializer import common.settings import common.models @@ -992,6 +995,59 @@ class StockTrackingList(generics.ListAPIView): return self.serializer_class(*args, **kwargs) + def list(self, request, *args, **kwargs): + + queryset = self.filter_queryset(self.get_queryset()) + + serializer = self.get_serializer(queryset, many=True) + + data = serializer.data + + # Attempt to add extra context information to the historical data + for item in data: + deltas = item['deltas'] + + # Add location detail + if 'location' in deltas: + try: + location = StockLocation.objects.get(pk=deltas['location']) + serializer = LocationSerializer(location) + deltas['location_detail'] = serializer.data + except: + pass + + # Add stockitem detail + if 'stockitem' in deltas: + try: + stockitem = StockItem.objects.get(pk=deltas['stockitem']) + serializer = StockItemSerializer(stockitem) + deltas['stockitem_detail'] = serializer.data + except: + pass + + # Add customer detail + if 'customer' in deltas: + try: + customer = Company.objects.get(pk=deltas['customer']) + serializer = CompanySerializer(location) + deltas['customer_detail'] = serializer.data + except: + pass + + # Add purchaseorder detail + if 'purchaseorder' in deltas: + try: + order = PurchaseOrder.objects.get(pk=deltas['purchaseorder']) + serializer = POSerializer(order) + deltas['purchaseorder_detail'] = serializer.data + except: + pass + + if request.is_ajax(): + return JsonResponse(data, safe=False) + else: + return Response(data) + def create(self, request, *args, **kwargs): """ Create a new StockItemTracking object diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index 4e5d78d8cd..f3f1c7a6bd 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -976,42 +976,28 @@ function loadStockLocationTable(table, options) { function loadStockTrackingTable(table, options) { - var cols = [ - { - field: 'pk', - visible: false, - }, - { - field: 'date', - title: '{% trans "Date" %}', - sortable: true, - formatter: function(value, row, index, field) { - var m = moment(value); - if (m.isValid()) { - var html = m.format('dddd MMMM Do YYYY'); // + '
' + m.format('h:mm a'); - return html; - } + var cols = []; - return 'N/A'; - } - }, - ]; + // Date + cols.push({ + field: 'date', + title: '{% trans "Date" %}', + sortable: true, + formatter: function(value, row, index, field) { + var m = moment(value); - // If enabled, provide a link to the referenced StockItem - if (options.partColumn) { - cols.push({ - field: 'item', - title: '{% trans "Stock Item" %}', - sortable: true, - formatter: function(value, row, index, field) { - return renderLink(value.part_name, value.url); + if (m.isValid()) { + var html = m.format('dddd MMMM Do YYYY'); // + '
' + m.format('h:mm a'); + return html; } - }); - } + + return '{% trans "Invalid date" %}'; + } + }); // Stock transaction description cols.push({ - field: 'title', + field: 'label', title: '{% trans "Description" %}', formatter: function(value, row, index, field) { var html = "" + value + ""; @@ -1020,20 +1006,129 @@ function loadStockTrackingTable(table, options) { html += "
" + row.notes + ""; } - if (row.link) { - html += "
" + row.link + ""; - } - return html; } }); + // Stock transaction details cols.push({ - field: 'quantity', - title: '{% trans "Quantity" %}', - formatter: function(value, row, index, field) { - return parseFloat(value); - }, + field: 'deltas', + title: '{% trans "Details" %}', + formatter: function(details, row, index, field) { + var html = ``; + + // Location information + if (details.location) { + + html += ``; + + html += ''; + } + + // Purchase Order Information + if (details.purchaseorder) { + + html += `'; + } + + // Customer information + if (details.customer) { + + html += `'; + } + + // Stockitem information + if (details.stockitem) { + html += ''; + } + + // Status information + if (details.status) { + + } + + // Quantity information + if (details.added) { + html += ''; + + html += ``; + + html += ''; + } + + if (details.removed) { + html += ''; + + html += ``; + + html += ''; + } + + if (details.quantity) { + html += ''; + + html += ``; + + html += ''; + } + + html += '
{% trans "Location" %}'; + + if (details.location_detail) { + // A valid location is provided + + html += renderLink( + details.location_detail.pathstring, + details.location_detail.url, + ); + } else { + // An invalid location (may have been deleted?) + html += `{% trans "Location no longer exists" %}`; + } + + html += '
{% trans "Purchase Order" %}`; + + html += ''; + + if (details.purchaseorder_detail) { + html += renderLink( + details.purchaseorder_detail.reference, + `/order/purchase-order/${details.purchaseorder}/` + ); + } else { + html += `{% trans "Purchase order no longer exists" %}`; + } + + html += '
{% trans "Customer" %}`; + + html += ''; + + if (details.customer_detail) { + html += renderLink( + details.customer_detail.name, + details.customer_detail.url + ); + } else { + html += `{% trans "Customer no longer exists" %}`; + } + + html += '
{% trans "Stock Item" %}'; + + html += ''; + + if (details.stockitem_detail) { + html += renderLink( + details.stockitem, + `/stock/item/${details.stockitem}/` + ); + } else { + html += `{% trans "Stock item no longer exists" %}`; + } + + html += '
{% trans "Added" %}${details.added}
{% trans "Removed" %}${details.removed}
{% trans "Quantity" %}${details.quantity}
'; + + return html; + } }); cols.push({ @@ -1056,7 +1151,7 @@ function loadStockTrackingTable(table, options) { sortable: false, formatter: function(value, row, index, field) { // Manually created entries can be edited or deleted - if (!row.system) { + if (false && !row.system) { var bEdit = ""; var bDel = "";