diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index f45381525e..e02f0d2b99 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -26,20 +26,22 @@ from InvenTree.helpers import DownloadFile, str2bool from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, RetrieveUpdateAPI, RetrieveUpdateDestroyAPI) from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus -from order.admin import (PurchaseOrderLineItemResource, PurchaseOrderResource, - SalesOrderResource) +from order.admin import (PurchaseOrderExtraLineResource, + PurchaseOrderLineItemResource, PurchaseOrderResource, + SalesOrderExtraLineResource, + SalesOrderLineItemResource, SalesOrderResource) from part.models import Part from plugin.serializers import MetadataSerializer from users.models import Owner -class GeneralExtraLineList: +class GeneralExtraLineList(APIDownloadMixin): """General template for ExtraLine API classes.""" def get_serializer(self, *args, **kwargs): """Return the serializer instance for this endpoint""" try: - params = self.request.query_params + params = self.request.query_params3 kwargs['order_detail'] = str2bool(params.get('order_detail', False)) except AttributeError: @@ -606,6 +608,15 @@ class PurchaseOrderExtraLineList(GeneralExtraLineList, ListCreateAPI): queryset = models.PurchaseOrderExtraLine.objects.all() serializer_class = serializers.PurchaseOrderExtraLineSerializer + def download_queryset(self, queryset, export_format): + """Download this queryset as a file""" + + dataset = PurchaseOrderExtraLineResource().export(queryset=queryset) + filedata = dataset.export(export_format) + filename = f"InvenTree_ExtraPurchaseOrderLines.{export_format}" + + return DownloadFile(filedata, filename) + class PurchaseOrderExtraLineDetail(RetrieveUpdateDestroyAPI): """API endpoint for detail view of a PurchaseOrderExtraLine object.""" @@ -686,6 +697,7 @@ class SalesOrderList(APIDownloadMixin, ListCreateAPI): def download_queryset(self, queryset, export_format): """Download this queryset as a file""" + dataset = SalesOrderResource().export(queryset=queryset) filedata = dataset.export(export_format) @@ -857,7 +869,7 @@ class SalesOrderLineItemFilter(rest_filters.FilterSet): return queryset -class SalesOrderLineItemList(ListCreateAPI): +class SalesOrderLineItemList(APIDownloadMixin, ListCreateAPI): """API endpoint for accessing a list of SalesOrderLineItem objects.""" queryset = models.SalesOrderLineItem.objects.all() @@ -898,6 +910,16 @@ class SalesOrderLineItemList(ListCreateAPI): return queryset + def download_queryset(self, queryset, export_format): + """Download the requested queryset as a file""" + + dataset = SalesOrderLineItemResource().export(queryset=queryset) + filedata = dataset.export(export_format) + + filename = f"InvenTree_SalesOrderItems.{export_format}" + + return DownloadFile(filedata, filename) + filter_backends = [ rest_filters.DjangoFilterBackend, filters.SearchFilter, @@ -924,6 +946,15 @@ class SalesOrderExtraLineList(GeneralExtraLineList, ListCreateAPI): queryset = models.SalesOrderExtraLine.objects.all() serializer_class = serializers.SalesOrderExtraLineSerializer + def download_queryset(self, queryset, export_format): + """Download this queryset as a file""" + + dataset = SalesOrderExtraLineResource().export(queryset=queryset) + filedata = dataset.export(export_format) + filename = f"InvenTree_ExtraSalesOrderLines.{export_format}" + + return DownloadFile(filedata, filename) + class SalesOrderExtraLineDetail(RetrieveUpdateDestroyAPI): """API endpoint for detail view of a SalesOrderExtraLine object.""" diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index a3c25391f9..5b28b88f1a 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -31,8 +31,6 @@
- {% include "expand_rows.html" with label="sales-lines" %} - {% include "collapse_rows.html" with label="sales-lines" %} {% include "filter_list.html" with id="sales-order-lines" %}
@@ -93,8 +91,6 @@ {% if roles.sales_order.change %}
- {% include "expand_rows.html" with label="pending-shipments" %} - {% include "collapse_rows.html" with label="pending-shipments" %} {% include "filter_list.html" with id="pending-shipments" %}
@@ -111,8 +107,6 @@
- {% include "expand_rows.html" with label="completed-shipments" %} - {% include "collapse_rows.html" with label="completed-shipments" %} {% include "filter_list.html" with id="completed-shipments" %}
diff --git a/InvenTree/templates/collapse_rows.html b/InvenTree/templates/collapse_rows.html deleted file mode 100644 index f9fb454268..0000000000 --- a/InvenTree/templates/collapse_rows.html +++ /dev/null @@ -1,5 +0,0 @@ -{% load i18n %} - - diff --git a/InvenTree/templates/expand_rows.html b/InvenTree/templates/expand_rows.html deleted file mode 100644 index bf6ac54425..0000000000 --- a/InvenTree/templates/expand_rows.html +++ /dev/null @@ -1,5 +0,0 @@ -{% load i18n %} - - diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 9bdef47dd0..3272f41a9f 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -2231,7 +2231,14 @@ function loadPurchaseOrderLineItemTable(table, options={}) { var target = options.filter_target || '#filter-list-purchase-order-lines'; - setupFilterList('purchaseorderlineitem', $(table), target, {download: true}); + setupFilterList( + 'purchaseorderlineitem', + $(table), + target, + { + download: true + } + ); function setupCallbacks() { if (options.allow_edit) { @@ -2596,7 +2603,7 @@ function loadPurchaseOrderExtraLineTable(table, options={}) { var filter_target = options.filter_target || '#filter-list-purchase-order-extra-lines'; - setupFilterList('purchaseorderextraline', $(table), filter_target); + setupFilterList('purchaseorderextraline', $(table), filter_target, {download: true}); // Table columns to display var columns = [ @@ -3072,6 +3079,7 @@ function loadSalesOrderShipmentTable(table, options={}) { showColumns: true, detailView: true, detailViewByClick: false, + buttons: constructExpandCollapseButtons(table), detailFilter: function(index, row) { return row.allocations.length > 0; }, @@ -3871,7 +3879,14 @@ function loadSalesOrderLineItemTable(table, options={}) { var filter_target = options.filter_target || '#filter-list-sales-order-lines'; - setupFilterList('salesorderlineitem', $(table), filter_target); + setupFilterList( + 'salesorderlineitem', + $(table), + filter_target, + { + download: true, + } + ); // Is the order pending? var pending = options.pending; @@ -4333,6 +4348,7 @@ function loadSalesOrderLineItemTable(table, options={}) { uniqueId: 'pk', detailView: show_detail, detailViewByClick: false, + buttons: constructExpandCollapseButtons(table), detailFilter: function(index, row) { if (pending) { // Order is pending @@ -4395,7 +4411,7 @@ function loadSalesOrderExtraLineTable(table, options={}) { var filter_target = options.filter_target || '#filter-list-sales-order-extra-lines'; - setupFilterList('salesorderextraline', $(table), filter_target); + setupFilterList('salesorderextraline', $(table), filter_target, {download: true}); // Table columns to display var columns = [ diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index 807051e65f..6de27fb9cb 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -12,6 +12,7 @@ reloadtable, renderLink, reloadTableFilters, + constructExpandCollapseButtons, constructOrderTableButtons, */ @@ -98,6 +99,28 @@ function constructOrderTableButtons(options={}) { } +/* + * Construct buttons to expand / collapse all rows in a table + */ +function constructExpandCollapseButtons(table, idx=0) { + + return [ + { + html: ``, + event: function() { + $(table).bootstrapTable('expandAllRows'); + } + }, + { + html: ``, + event: function() { + $(table).bootstrapTable('collapseAllRows'); + } + } + ]; +} + + /* Return the 'selected' data rows from a bootstrap table. * If allowEmpty = false, and the returned dataset is empty, * then instead try to return *all* the data