Implement cascading export of BOM

This commit is contained in:
Oliver Walters 2020-02-11 22:32:36 +11:00
parent 434d084371
commit f865573e48
3 changed files with 40 additions and 9 deletions

View File

@ -129,15 +129,17 @@ class PartStarAdmin(admin.ModelAdmin):
class BomItemResource(ModelResource):
""" Class for managing BomItem data import/export """
level = Field(attribute='level', readonly=True)
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
part_name = Field(attribute='part__full_name', readonly=True)
parent_part_name = Field(attribute='part__full_name', readonly=True)
sub_part = Field(attribute='sub_part', widget=widgets.ForeignKeyWidget(Part))
id = Field(attribute='sub_part', widget=widgets.ForeignKeyWidget(Part))
sub_part_name = Field(attribute='sub_part__full_name', readonly=True)
stock = Field(attribute='sub_part__total_stock', readonly=True)
sub_assembly = Field(attribute='sub_part__assembly', readonly=True)
class Meta:
model = BomItem
@ -145,7 +147,7 @@ class BomItemResource(ModelResource):
report_skipped = False
clean_model_instances = True
exclude = ('checksum')
exclude = ['checksum', ]
class BomItemAdmin(ImportExportModelAdmin):

View File

@ -40,16 +40,43 @@ def MakeBomTemplate(fmt):
return DownloadFile(data, filename)
def ExportBom(part, fmt='csv'):
def ExportBom(part, fmt='csv', cascade=False):
""" Export a BOM (Bill of Materials) for a given part.
Args:
fmt: File format (default = 'csv')
cascade: If True, multi-level BOM output is supported. Otherwise, a flat top-level-only BOM is exported.
"""
if not IsValidBOMFormat(fmt):
fmt = 'csv'
bom_items = part.bom_items.all().order_by('id')
bom_items = []
dataset = BomItemResource().export(queryset=bom_items)
def add_items(items, level):
# Add items at a given layer
for item in items:
item.level = '-' * level
bom_items.append(item)
if item.sub_part.assembly:
add_items(item.sub_part.bom_items.all().order_by('id'), level + 1)
if cascade:
# Cascading (multi-level) BOM
# Start with the top level
items_to_process = part.bom_items.all().order_by('id')
add_items(items_to_process, 1)
else:
# No cascading needed - just the top-level items
bom_items = [item for item in part.bom_items.all().order_by('id')]
dataset = BomItemResource().export(queryset=bom_items, cascade=cascade)
data = dataset.export(fmt)
filename = '{n}_BOM.{fmt}'.format(n=part.full_name, fmt=fmt)

View File

@ -1334,10 +1334,12 @@ class BomDownload(AjaxView):
export_format = request.GET.get('file_format', 'csv')
cascade = str2bool(request.GET.get('cascade', False))
if not IsValidBOMFormat(export_format):
export_format = 'csv'
return ExportBom(part, fmt=export_format)
return ExportBom(part, fmt=export_format, cascade=cascade)
def get_data(self):
return {