From 61e5244789ffd28ff8c7aca0d8f66b036860adba Mon Sep 17 00:00:00 2001 From: bloemp Date: Tue, 24 Jan 2023 23:35:26 +0100 Subject: [PATCH] Bom export with substitute part numbers (#4203) * Added BOM export option to export substitute part numbers * Small documentation fix * Fixed the behaviour for multiple lines with different amount of substitutes * Changed UI naming to "alternative parts" --- InvenTree/part/bom.py | 35 +++++++++++++++++++++++- InvenTree/part/views.py | 5 +++- InvenTree/templates/js/translated/bom.js | 9 +++++- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/InvenTree/part/bom.py b/InvenTree/part/bom.py index c8642bc97b..f644191129 100644 --- a/InvenTree/part/bom.py +++ b/InvenTree/part/bom.py @@ -12,7 +12,7 @@ from InvenTree.helpers import (DownloadFile, GetExportFormats, normalize, str2bool) from .admin import BomItemResource -from .models import BomItem, Part +from .models import BomItem, BomItemSubstitute, Part def IsValidBOMFormat(fmt): @@ -58,6 +58,7 @@ def ExportBom(part: Part, fmt='csv', cascade: bool = False, max_levels: int = No supplier_data (bool, optional): Additonal data that should be added. Defaults to False. manufacturer_data (bool, optional): Additonal data that should be added. Defaults to False. pricing_data (bool, optional): Include pricing data in exported BOM. Defaults to False + substitute_part_data (bool, optional): Include substitute part numbers in exported BOM. Defaults to False Returns: StreamingHttpResponse: Response that can be passed to the endpoint @@ -68,6 +69,7 @@ def ExportBom(part: Part, fmt='csv', cascade: bool = False, max_levels: int = No supplier_data = str2bool(kwargs.get('supplier_data', False)) manufacturer_data = str2bool(kwargs.get('manufacturer_data', False)) pricing_data = str2bool(kwargs.get('pricing_data', False)) + substitute_part_data = str2bool(kwargs.get('substitute_part_data', False)) if not IsValidBOMFormat(fmt): fmt = 'csv' @@ -112,6 +114,37 @@ def ExportBom(part: Part, fmt='csv', cascade: bool = False, max_levels: int = No except AttributeError: pass + if substitute_part_data: + """If requested, add extra columns for all substitute part numbers associated with each line item.""" + + col_index = 0 + substitute_cols = {} + + for bom_item in bom_items: + substitutes = BomItemSubstitute.objects.filter(bom_item=bom_item) + for s_idx, substitute in enumerate(substitutes): + + """Create substitute part name column""" + name = f'{_("Substitute Part")}{s_idx + 1}' + value = substitute.part.name + try: + substitute_cols[name].update({col_index: value}) + except KeyError: + substitute_cols[name] = {col_index: value} + + """Create substitute part description column""" + name = f'{_("Substitute Description")}{s_idx + 1}' + value = substitute.part.description + try: + substitute_cols[name].update({col_index: value}) + except KeyError: + substitute_cols[name] = {col_index: value} + + col_index = col_index + 1 + + # Add substitute columns to dataset + add_columns_to_dataset(substitute_cols, len(bom_items)) + if parameter_data: """If requested, add extra columns for each PartParameter associated with each line item.""" diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index f227725230..b662f535d2 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -468,6 +468,8 @@ class BomDownload(AjaxView): parameter_data = str2bool(request.GET.get('parameter_data', False)) + substitute_part_data = str2bool(request.GET.get('substitute_part_data', False)) + stock_data = str2bool(request.GET.get('stock_data', False)) supplier_data = str2bool(request.GET.get('supplier_data', False)) @@ -500,10 +502,11 @@ class BomDownload(AjaxView): supplier_data=supplier_data, manufacturer_data=manufacturer_data, pricing_data=pricing_data, + substitute_part_data=substitute_part_data, ) def get_data(self): - """Return a cutsom message""" + """Return a custom message""" return { 'info': 'Exported BOM' } diff --git a/InvenTree/templates/js/translated/bom.js b/InvenTree/templates/js/translated/bom.js index 2331bf1625..4e94c014b0 100644 --- a/InvenTree/templates/js/translated/bom.js +++ b/InvenTree/templates/js/translated/bom.js @@ -330,9 +330,15 @@ function exportBom(part_id, options={}) { required: true, min_value: 0, }, + substitute_part_data: { + label: '{% trans "Include Alternative Parts" %}', + help_text: '{% trans "Include alternative parts in exported BOM" %}', + type: 'boolean', + value: inventreeLoad('bom-export-substitute_part_data', false), + }, parameter_data: { label: '{% trans "Include Parameter Data" %}', - help_text: '{% trans "Include part parameter data in exported BOM" %}', + help_text: '{% trans "Include part parameter data in exported BOM" %}', type: 'boolean', value: inventreeLoad('bom-export-parameter_data', false), }, @@ -366,6 +372,7 @@ function exportBom(part_id, options={}) { // Extract values from the form var field_names = [ 'format', 'cascade', 'levels', + 'substitute_part_data', 'parameter_data', 'stock_data', 'manufacturer_data',