From b75e817447c2048b5cc7d07e5470232e1e9c3876 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 5 Oct 2021 14:57:50 +1100 Subject: [PATCH 01/11] Construct bare-bones API form --- .../order/templates/order/order_base.html | 23 ++- InvenTree/templates/js/translated/build.js | 1 - InvenTree/templates/js/translated/order.js | 142 +++++++++++++++++- 3 files changed, 163 insertions(+), 3 deletions(-) diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html index 0d46207c33..6f01d0a172 100644 --- a/InvenTree/order/templates/order/order_base.html +++ b/InvenTree/order/templates/order/order_base.html @@ -49,7 +49,7 @@ src="{% static 'img/blank_image.png' %}" {% elif order.status == PurchaseOrderStatus.PLACED %} {% trans "Upload File" %} + {% elif order.status == PurchaseOrderStatus.PLACED %} + + {% endif %} {% endif %} @@ -207,6 +213,22 @@ $('#new-po-line').click(function() { }); }); +{% elif order.status == PurchaseOrderStatus.PLACED %} + + $('#receive-selected-items').click(function() { + var items = $("#po-line-table").bootstrapTable('getSelections'); + + receivePurchaseOrderItems( + {{ order.id }}, + items, + { + success: function() { + $("#po-line-table").bootstrapTable('refresh'); + } + } + ); + }); + {% endif %} loadPurchaseOrderLineItemTable('#po-line-table', { From 5e951ef64bd2bc5e4ab92e2b6f325b689ed17133 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 5 Oct 2021 16:57:33 +1100 Subject: [PATCH 09/11] Add 'filtering' for purchase order line item table --- .../order/templates/order/purchase_order_detail.html | 3 +++ InvenTree/templates/js/translated/filters.js | 5 +++++ InvenTree/templates/js/translated/order.js | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index 2bc2c29617..987ab79d58 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -32,6 +32,9 @@ {% endif %} {% endif %} +
+ +
diff --git a/InvenTree/templates/js/translated/filters.js b/InvenTree/templates/js/translated/filters.js index d7e8f45ca5..3e41003696 100644 --- a/InvenTree/templates/js/translated/filters.js +++ b/InvenTree/templates/js/translated/filters.js @@ -273,6 +273,11 @@ function setupFilterList(tableKey, table, target) { var element = $(target); + if (!element) { + console.log(`WARNING: setupFilterList could not find target '${target}'`); + return; + } + // One blank slate, please element.empty(); diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index af6582957d..0bb6696f98 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -665,6 +665,18 @@ function loadPurchaseOrderTable(table, options) { */ function loadPurchaseOrderLineItemTable(table, options={}) { + options.params = options.params || {}; + + var filters = loadTableFilters('purchaseorderlineitem'); + + for (var key in options.params) { + filters[key] = options.params[key]; + } + + var target = options.filter_target || '#filter-list-purchase-order-lines'; + + setupFilterList('purchaseorderlineitem', $(table), target); + function setupCallbacks() { if (options.allow_edit) { $(table).find('.button-line-edit').click(function() { From dd760bfecdf35993a717d2ac7e624de3813a0a7d Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 5 Oct 2021 17:15:41 +1100 Subject: [PATCH 10/11] Add filtering by "completed" status for purchase order line items --- InvenTree/order/api.py | 35 +++++++++++++++++++ InvenTree/templates/js/translated/order.js | 15 ++++---- .../templates/js/translated/table_filters.js | 11 +++++- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index b8f54ba72b..26e6ed3546 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals from django.utils.translation import ugettext_lazy as _ from django.conf.urls import url, include +from django.db.models import Q, F from django_filters import rest_framework as rest_filters from rest_framework import generics @@ -251,6 +252,39 @@ class POReceive(generics.CreateAPIView): return order +class POLineItemFilter(rest_filters.FilterSet): + """ + Custom filters for the POLineItemList endpoint + """ + + class Meta: + model = PurchaseOrderLineItem + fields = [ + 'order', + 'part' + ] + + completed = rest_filters.BooleanFilter(label='completed', method='filter_completed') + + def filter_completed(self, queryset, name, value): + """ + Filter by lines which are "completed" (or "not" completed) + + A line is completed when received >= quantity + """ + + value = str2bool(value) + + q = Q(received__gte=F('quantity')) + + if value: + queryset = queryset.filter(q) + else: + queryset = queryset.exclude(q) + + return queryset + + class POLineItemList(generics.ListCreateAPIView): """ API endpoint for accessing a list of POLineItem objects @@ -260,6 +294,7 @@ class POLineItemList(generics.ListCreateAPIView): queryset = PurchaseOrderLineItem.objects.all() serializer_class = POLineItemSerializer + filterset_class = POLineItemFilter def get_queryset(self, *args, **kwargs): diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 0bb6696f98..43d4b56936 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -566,12 +566,10 @@ function loadPurchaseOrderTable(table, options) { filters[key] = options.params[key]; } - options.url = options.url || '{% url "api-po-list" %}'; - setupFilterList('purchaseorder', $(table)); $(table).inventreeTable({ - url: options.url, + url: '{% url "api-po-list" %}', queryParams: filters, name: 'purchaseorder', groupBy: false, @@ -667,12 +665,15 @@ function loadPurchaseOrderLineItemTable(table, options={}) { options.params = options.params || {}; + options.params['order'] = options.order; + options.params['part_detail'] = true; + var filters = loadTableFilters('purchaseorderlineitem'); for (var key in options.params) { filters[key] = options.params[key]; } - + var target = options.filter_target || '#filter-list-purchase-order-lines'; setupFilterList('purchaseorderlineitem', $(table), target); @@ -751,10 +752,8 @@ function loadPurchaseOrderLineItemTable(table, options={}) { formatNoMatches: function() { return '{% trans "No line items found" %}'; }, - queryParams: { - order: options.order, - part_detail: true - }, + queryParams: filters, + original: options.params, url: '{% url "api-po-line-list" %}', showFooter: true, uniqueId: 'pk', diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index b94bc324c7..4d12f69780 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -274,7 +274,16 @@ function getAvailableTableFilters(tableKey) { }; } - // Filters for the "Order" table + // Filters for PurchaseOrderLineItem table + if (tableKey == 'purchaseorderlineitem') { + return { + completed: { + type: 'bool', + title: '{% trans "Completed" %}', + }, + }; + } + // Filters for the PurchaseOrder table if (tableKey == 'purchaseorder') { return { From 93c53315cc39a3bc393535396e301808335ba1ae Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 5 Oct 2021 17:35:10 +1100 Subject: [PATCH 11/11] Unit test fixes --- InvenTree/order/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/order/test_api.py b/InvenTree/order/test_api.py index 765c58cc3d..1f7905d1e3 100644 --- a/InvenTree/order/test_api.py +++ b/InvenTree/order/test_api.py @@ -251,7 +251,7 @@ class PurchaseOrderReceiveTest(OrderTest): expected_code=400 ).data - self.assertIn('Line items must be provided', str(data['items'])) + self.assertIn('Line items must be provided', str(data)) # No new stock items have been created self.assertEqual(self.n, StockItem.objects.count())