From c89547f58c98c6e1338d25df0ee8a04615508579 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 12 May 2022 12:44:15 +1000 Subject: [PATCH] Adds exporter and download functionality for BuildOrder table --- InvenTree/InvenTree/api.py | 2 +- InvenTree/build/admin.py | 49 +++++++++++++++++++++- InvenTree/build/api.py | 18 ++++++-- InvenTree/part/api.py | 1 - InvenTree/templates/js/translated/build.js | 2 +- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/InvenTree/InvenTree/api.py b/InvenTree/InvenTree/api.py index 3b440a1f3d..e468e8d1cf 100644 --- a/InvenTree/InvenTree/api.py +++ b/InvenTree/InvenTree/api.py @@ -87,7 +87,7 @@ class APIDownloadMixin: export_format = request.query_params.get('export', None) - if export_format: + if export_format and export_format in ['csv', 'tsv', 'xls', 'xlsx']: queryset = self.filter_queryset(self.get_queryset()) return self.download_queryset(queryset, export_format) diff --git a/InvenTree/build/admin.py b/InvenTree/build/admin.py index a612ad8460..55d7a1e2d2 100644 --- a/InvenTree/build/admin.py +++ b/InvenTree/build/admin.py @@ -2,9 +2,54 @@ from __future__ import unicode_literals from django.contrib import admin -from import_export.admin import ImportExportModelAdmin -from .models import Build, BuildItem +from import_export.admin import ImportExportModelAdmin +from import_export.fields import Field +from import_export.resources import ModelResource +import import_export.widgets as widgets + +from build.models import Build, BuildItem + +import part.models + + +class BuildResource(ModelResource): + """Class for managing import/export of Build data""" + # For some reason, we need to specify the fields individually for this ModelResource, + # but we don't for other ones. + # TODO: 2022-05-12 - Need to investigate why this is the case! + + pk = Field(attribute='pk') + + reference = Field(attribute='reference') + + title = Field(attribute='title') + + part = Field(attribute='part', widget=widgets.ForeignKeyWidget(part.models.Part)) + + part_name = Field(attribute='part__full_name', readonly=True) + + overdue = Field(attribute='is_overdue', readonly=True, widget=widgets.BooleanWidget()) + + completed = Field(attribute='completed', readonly=True) + + quantity = Field(attribute='quantity') + + status = Field(attribute='status') + + batch = Field(attribute='batch') + + notes = Field(attribute='notes') + + class Meta: + models = Build + skip_unchanged = True + report_skipped = False + clean_model_instances = True + exclude = [ + 'lft', 'rght', 'tree_id', 'level', + ] + class BuildAdmin(ImportExportModelAdmin): diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py index e32b404ae2..4453232823 100644 --- a/InvenTree/build/api.py +++ b/InvenTree/build/api.py @@ -12,13 +12,15 @@ from rest_framework import filters, generics from django_filters.rest_framework import DjangoFilterBackend from django_filters import rest_framework as rest_filters -from InvenTree.api import AttachmentMixin -from InvenTree.helpers import str2bool, isNull +from InvenTree.api import AttachmentMixin, APIDownloadMixin +from InvenTree.helpers import str2bool, isNull, DownloadFile from InvenTree.filters import InvenTreeOrderingFilter from InvenTree.status_codes import BuildStatus -from .models import Build, BuildItem, BuildOrderAttachment +import build.admin import build.serializers +from build.models import Build, BuildItem, BuildOrderAttachment + from users.models import Owner @@ -71,7 +73,7 @@ class BuildFilter(rest_filters.FilterSet): return queryset -class BuildList(generics.ListCreateAPIView): +class BuildList(APIDownloadMixin, generics.ListCreateAPIView): """ API endpoint for accessing a list of Build objects. - GET: Return list of objects (with filters) @@ -123,6 +125,14 @@ class BuildList(generics.ListCreateAPIView): return queryset + def download_queryset(self, queryset, export_format): + dataset = build.admin.BuildResource().export(queryset=queryset) + + filedata = dataset.export(export_format) + filename = f"InvenTree_BuildOrders.{export_format}" + + return DownloadFile(filedata, filename) + def filter_queryset(self, queryset): queryset = super().filter_queryset(queryset) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 0e0e918665..622ca38669 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -901,7 +901,6 @@ class PartList(APIDownloadMixin, generics.ListCreateAPIView): dataset = PartResource().export(queryset=queryset) filedata = dataset.export(export_format) - filename = f"InvenTree_Parts.{export_format}" return DownloadFile(filedata, filename) diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index 94c2780a28..814f2a3247 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -2355,7 +2355,7 @@ function loadBuildTable(table, options) { var filterTarget = options.filterTarget || null; - setupFilterList('build', table, filterTarget); + setupFilterList('build', table, filterTarget, {download: true}); $(table).inventreeTable({ method: 'get',