From 1b1f7634b72af15fff917665878ffcfb5b1173ae Mon Sep 17 00:00:00 2001
From: Oliver <oliver.henry.walters@gmail.com>
Date: Thu, 12 May 2022 11:41:25 +1000
Subject: [PATCH] Adds exporter and download button for PurchaseOrder table

---
 InvenTree/order/admin.py                   | 20 +++++++++++++++++++-
 InvenTree/order/api.py                     | 13 +++++++++++--
 InvenTree/part/admin.py                    |  2 +-
 InvenTree/templates/js/translated/order.js |  4 +++-
 4 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/InvenTree/order/admin.py b/InvenTree/order/admin.py
index 0de28d5668..8ab8b832ef 100644
--- a/InvenTree/order/admin.py
+++ b/InvenTree/order/admin.py
@@ -5,8 +5,9 @@ from django.contrib import admin
 
 from import_export.admin import ImportExportModelAdmin
 
-from import_export.resources import ModelResource
 from import_export.fields import Field
+from import_export.resources import ModelResource
+import import_export.widgets as widgets
 
 from .models import PurchaseOrder, PurchaseOrderLineItem, PurchaseOrderExtraLine
 from .models import SalesOrder, SalesOrderLineItem, SalesOrderExtraLine
@@ -92,6 +93,23 @@ class SalesOrderAdmin(ImportExportModelAdmin):
     autocomplete_fields = ('customer',)
 
 
+class PurchaseOrderResource(ModelResource):
+    """
+    Class for managing import / export of PurchaseOrder data
+    """
+
+    # Add number of line items
+    line_items = Field(attribute='line_count', widget=widgets.IntegerWidget(), readonly=True)
+
+    # Is this order overdue?
+    overdue = Field(attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True)
+
+    class Meta:
+        model = PurchaseOrder
+        skip_unchanged = True
+        clean_model_instances = True
+
+
 class PurchaseOrderLineItemResource(ModelResource):
     """ Class for managing import / export of PurchaseOrderLineItem data """
 
diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py
index 6e74262ac2..da037aa8b7 100644
--- a/InvenTree/order/api.py
+++ b/InvenTree/order/api.py
@@ -20,7 +20,7 @@ from InvenTree.helpers import str2bool, DownloadFile
 from InvenTree.api import AttachmentMixin, APIDownloadMixin
 from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus
 
-from order.admin import PurchaseOrderLineItemResource
+from order.admin import PurchaseOrderResource, PurchaseOrderLineItemResource
 import order.models as models
 import order.serializers as serializers
 from part.models import Part
@@ -110,7 +110,7 @@ class PurchaseOrderFilter(rest_filters.FilterSet):
         ]
 
 
-class PurchaseOrderList(generics.ListCreateAPIView):
+class PurchaseOrderList(APIDownloadMixin, generics.ListCreateAPIView):
     """ API endpoint for accessing a list of PurchaseOrder objects
 
     - GET: Return list of PurchaseOrder objects (with filters)
@@ -160,6 +160,15 @@ class PurchaseOrderList(generics.ListCreateAPIView):
 
         return queryset
 
+    def download_queryset(self, queryset, export_format):
+        dataset = PurchaseOrderResource().export(queryset=queryset)
+
+        filedata = dataset.export(export_format)
+
+        filename = f"InvenTree_PurchaseOrders.{export_format}"
+
+        return DownloadFile(filedata, filename)
+
     def filter_queryset(self, queryset):
 
         # Perform basic filtering
diff --git a/InvenTree/part/admin.py b/InvenTree/part/admin.py
index fd0a16adc2..30dad8e995 100644
--- a/InvenTree/part/admin.py
+++ b/InvenTree/part/admin.py
@@ -4,8 +4,8 @@ from __future__ import unicode_literals
 from django.contrib import admin
 
 from import_export.admin import ImportExportModelAdmin
-from import_export.resources import ModelResource
 from import_export.fields import Field
+from import_export.resources import ModelResource
 import import_export.widgets as widgets
 
 from company.models import SupplierPart
diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js
index 538f37a710..dcd7307628 100644
--- a/InvenTree/templates/js/translated/order.js
+++ b/InvenTree/templates/js/translated/order.js
@@ -1394,7 +1394,9 @@ function loadPurchaseOrderTable(table, options) {
         filters[key] = options.params[key];
     }
 
-    setupFilterList('purchaseorder', $(table));
+    var target = '#filter-list-purchaseorder';
+
+    setupFilterList('purchaseorder', $(table), target, {download: true});
 
     $(table).inventreeTable({
         url: '{% url "api-po-list" %}',