From db04f399c17bf524b17ba737f42abfae98ff9336 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 15 Sep 2019 22:21:12 +1000 Subject: [PATCH] Simplify exporting of BOM for a part --- InvenTree/part/admin.py | 10 ++++- InvenTree/part/bom.py | 31 ++++++++++---- InvenTree/part/models.py | 72 --------------------------------- InvenTree/part/test_bom_item.py | 9 ----- InvenTree/part/views.py | 10 ++--- 5 files changed, 36 insertions(+), 96 deletions(-) diff --git a/InvenTree/part/admin.py b/InvenTree/part/admin.py index 601815caec..2146f76de6 100644 --- a/InvenTree/part/admin.py +++ b/InvenTree/part/admin.py @@ -131,7 +131,13 @@ class BomItemResource(ModelResource): part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) - sub_part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) + part_name = Field(attribute='part__name', readonly=True) + + sub_part = Field(attribute='sub_part', widget=widgets.ForeignKeyWidget(Part)) + + sub_part_name = Field(attribute='sub_part__name', readonly=True) + + stock = Field(attribute='sub_part__total_stock', readonly=True) class Meta: model = BomItem @@ -139,6 +145,8 @@ class BomItemResource(ModelResource): report_skipped = False clean_model_instances = True + exclude = ('checksum') + class BomItemAdmin(ImportExportModelAdmin): diff --git a/InvenTree/part/bom.py b/InvenTree/part/bom.py index d23cb02032..394314d461 100644 --- a/InvenTree/part/bom.py +++ b/InvenTree/part/bom.py @@ -12,6 +12,9 @@ from django.core.exceptions import ValidationError from InvenTree.helpers import DownloadFile, GetExportFormats +from .admin import BomItemResource +from .models import BomItem + def IsValidBOMFormat(fmt): """ Test if a file format specifier is in the valid list of BOM file formats """ @@ -27,21 +30,33 @@ def MakeBomTemplate(fmt): if not IsValidBOMFormat(fmt): fmt = 'csv' - fields = [ - 'Part', - 'Quantity', - 'Overage', - 'Reference', - 'Notes' - ] + query = BomItem.objects.filter(pk=None) + dataset = BomItemResource().export(queryset=query) - data = tablib.Dataset(headers=fields).export(fmt) + data = dataset.export(fmt) filename = 'InvenTree_BOM_Template.' + fmt return DownloadFile(data, filename) +def ExportBom(part, fmt='csv'): + """ Export a BOM (Bill of Materials) for a given part. + """ + + if not IsValidBOMFormat(fmt): + fmt = 'csv' + + bom_items = part.bom_items.all().order_by('id') + + dataset = BomItemResource().export(queryset=bom_items) + data = dataset.export(fmt) + + filename = '{n}_BOM.{fmt}'.format(n=part.full_name, fmt=fmt) + + return DownloadFile(data, filename) + + class BomUploadManager: """ Class for managing an uploaded BOM file """ diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 76d9f606d0..5040bdc2f0 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -7,8 +7,6 @@ from __future__ import unicode_literals import os -import tablib - from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError from django.urls import reverse @@ -857,76 +855,6 @@ class Part(models.Model): self.save() - def export_bom(self, **kwargs): - """ Export Bill of Materials to a spreadsheet file. - Includes a row for each item in the BOM. - Also includes extra information such as supplier data. - """ - - items = self.bom_items.all().order_by('id') - - supplier_names = set() - - headers = [ - 'Part', - 'Description', - 'Quantity', - 'Overage', - 'Reference', - 'Note', - '', - 'In Stock', - ] - - # Contstruct list of suppliers for each part - for item in items: - part = item.sub_part - supplier_parts = part.supplier_parts.all() - item.suppliers = {} - - for sp in supplier_parts: - name = sp.supplier.name - supplier_names.add(name) - item.suppliers[name] = sp - - if len(supplier_names) > 0: - headers.append('') - for name in supplier_names: - headers.append(name) - - data = tablib.Dataset(headers=headers) - - for it in items: - line = [] - - # Information about each BOM item - line.append(it.sub_part.full_name) - line.append(it.sub_part.description) - line.append(it.quantity) - line.append(it.overage) - line.append(it.reference) - line.append(it.note) - - # Extra information about the part - line.append('') - line.append(it.sub_part.available_stock) - - if len(supplier_names) > 0: - line.append('') # Blank column separates supplier info - - for name in supplier_names: - sp = it.suppliers.get(name, None) - if sp: - line.append(sp.SKU) - else: - line.append('') - - data.append(line) - - file_format = kwargs.get('format', 'csv').lower() - - return data.export(file_format) - @property def attachment_count(self): """ Count the number of attachments for this part. diff --git a/InvenTree/part/test_bom_item.py b/InvenTree/part/test_bom_item.py index ec29dbaab3..e5d94744c0 100644 --- a/InvenTree/part/test_bom_item.py +++ b/InvenTree/part/test_bom_item.py @@ -32,15 +32,6 @@ class BomItemTest(TestCase): self.assertIn(self.orphan, parts) - def test_bom_export(self): - parts = self.bob.required_parts() - - data = self.bob.export_bom(format='csv') - - for p in parts: - self.assertIn(p.name, data) - self.assertIn(p.description, data) - def test_used_in(self): self.assertEqual(self.bob.used_in_count, 0) self.assertEqual(self.orphan.used_in_count, 1) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index f8bbd0e841..7d1a3ab633 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -26,7 +26,7 @@ from common.models import Currency from company.models import SupplierPart from . import forms as part_forms -from .bom import MakeBomTemplate, BomUploadManager +from .bom import MakeBomTemplate, BomUploadManager, ExportBom, IsValidBOMFormat from .admin import PartResource @@ -1249,12 +1249,10 @@ class BomDownload(AjaxView): export_format = request.GET.get('format', 'csv') - # Placeholder to test file export - filename = '"' + part.name + '_BOM.' + export_format + '"' + if not IsValidBOMFormat(export_format): + export_format = 'csv' - filedata = part.export_bom(format=export_format) - - return DownloadFile(filedata, filename) + return ExportBom(part, fmt=export_format) def get_data(self): return {