From b8e28c003d099fd4a33985935a9a8672d31d1593 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 14 Apr 2019 00:35:19 +1000 Subject: [PATCH] Provide download link to export BOM file - Helper function for generating temporary file (in memory) for exporting --- InvenTree/InvenTree/helpers.py | 32 +++++++++++++++++++++ InvenTree/part/templates/part/bom.html | 10 +++---- InvenTree/part/views.py | 39 ++++++++++++++------------ 3 files changed, 57 insertions(+), 24 deletions(-) create mode 100644 InvenTree/InvenTree/helpers.py diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py new file mode 100644 index 0000000000..84ca1f8881 --- /dev/null +++ b/InvenTree/InvenTree/helpers.py @@ -0,0 +1,32 @@ +import io +import os +from wsgiref.util import FileWrapper +from django.http import StreamingHttpResponse, HttpResponse + + +def WrapWithQuotes(text): + # TODO - Make this better + if not text.startswith('"'): + text = '"' + text + + if not text.endswith('"'): + text = text + '"' + + return text + + +def DownloadFile(data, filename, content_type='application/text'): + """ + Create a dynamic file for the user to download. + @param data is the raw file data + """ + + filename = WrapWithQuotes(filename) + + wrapper = FileWrapper(io.StringIO(data)) + + response = StreamingHttpResponse(wrapper, content_type=content_type) + response['Content-Length'] = len(data) + response['Content-Disposition'] = 'attachment; filename={f}'.format(f=filename) + + return response diff --git a/InvenTree/part/templates/part/bom.html b/InvenTree/part/templates/part/bom.html index 139cc81961..3debd65076 100644 --- a/InvenTree/part/templates/part/bom.html +++ b/InvenTree/part/templates/part/bom.html @@ -62,16 +62,14 @@ }); $("#export-bom").click(function () { + /* launchModalForm( "{% url 'bom-export' part.id %}", { - /* - reload: true, - data: { - format: 'csv', - } - */ }); + */ + //TODO - Select format of the data + location.href = "{% url 'bom-export' part.id %}"; }); $("#bom-table").bootstrapTable({ diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 6463352d88..ea1dcc5a52 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -21,6 +21,7 @@ from .forms import EditSupplierPartForm from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView, AjaxDeleteView +from InvenTree.helpers import DownloadFile class PartIndex(ListView): model = Part @@ -111,34 +112,36 @@ class PartEdit(AjaxUpdateView): ajax_form_title = 'Edit Part Properties' -class BomExport(AjaxUpdateView): +class BomExport(AjaxView): + # TODO - This should no longer extend an AjaxView! model = Part - form_class = BomExportForm - template_name = 'part/bom_export.html' - ajax_form_title = 'Export Bill of Materials' - ajax_submit_text = 'Export' - context_object_name = 'part' + #form_class = BomExportForm + #template_name = 'part/bom_export.html' + #ajax_form_title = 'Export Bill of Materials' + #ajax_submit_text = 'Export' + #context_object_name = 'part' def get(self, request, *args, **kwargs): part = get_object_or_404(Part, pk=self.kwargs['pk']) - form = self.form_class(instance=part, data=request.POST, files=request.FILES) - return self.renderJsonResponse(request, form=form, context={'part': part}) + export_format = request.GET.get('format', 'csv') + + # Placeholder to test file export + filename = '"' + part.name + '_BOM.' + export_format + '"' - def post(self, request, *args, **kwargs): + filedata = "Part,Quantity,Available\n" - part = get_object_or_404(Part, pk=self.kwargs['pk']) - form = self.form_class(instance=part, data=request.POST, files=request.FILES) + for bom_item in part.bom_items.all(): + filedata += bom_item.sub_part.name + filedata += "," + filedata += str(bom_item.quantity) + filedata += "," + filedata += str(bom_item.sub_part.available_stock) + filedata += "\n" - export_format = request.POST.get('format', None) - - if not export_format: - # TODO - pass - - return self.renderJsonResponse(request, form=form, context={'part': part}) + return DownloadFile(filedata, filename) def get_data(self): return {