From 12821b80fbc30698dda47661ea7a13d3988ec007 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 12 Feb 2021 20:28:12 +1100 Subject: [PATCH] Add BOMReport model --- InvenTree/report/admin.py | 8 +++- .../migrations/0011_auto_20210212_2024.py | 35 ++++++++++++++++ InvenTree/report/models.py | 41 ++++++++++++++++++- 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 InvenTree/report/migrations/0011_auto_20210212_2024.py diff --git a/InvenTree/report/admin.py b/InvenTree/report/admin.py index 610b32dd4c..66f6a1cd6d 100644 --- a/InvenTree/report/admin.py +++ b/InvenTree/report/admin.py @@ -3,7 +3,9 @@ from __future__ import unicode_literals from django.contrib import admin -from .models import ReportSnippet, TestReport, ReportAsset +from .models import ReportSnippet, ReportAsset +from .models import TestReport +from .models import BillOfMaterialsReport class ReportTemplateAdmin(admin.ModelAdmin): @@ -22,5 +24,7 @@ class ReportAssetAdmin(admin.ModelAdmin): admin.site.register(ReportSnippet, ReportSnippetAdmin) -admin.site.register(TestReport, ReportTemplateAdmin) admin.site.register(ReportAsset, ReportAssetAdmin) + +admin.site.register(TestReport, ReportTemplateAdmin) +admin.site.register(BillOfMaterialsReport, ReportTemplateAdmin) diff --git a/InvenTree/report/migrations/0011_auto_20210212_2024.py b/InvenTree/report/migrations/0011_auto_20210212_2024.py new file mode 100644 index 0000000000..b1a93656cf --- /dev/null +++ b/InvenTree/report/migrations/0011_auto_20210212_2024.py @@ -0,0 +1,35 @@ +# Generated by Django 3.0.7 on 2021-02-12 09:24 + +import django.core.validators +from django.db import migrations, models +import report.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0010_auto_20210205_1201'), + ] + + operations = [ + migrations.CreateModel( + name='BillOfMaterialsReport', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Template name', max_length=100, verbose_name='Name')), + ('template', models.FileField(help_text='Report template file', upload_to=report.models.rename_template, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['html', 'htm'])], verbose_name='Template')), + ('description', models.CharField(help_text='Report template description', max_length=250, verbose_name='Description')), + ('revision', models.PositiveIntegerField(default=1, editable=False, help_text='Report revision number (auto-increments)', verbose_name='Revision')), + ('enabled', models.BooleanField(default=True, help_text='Report template is enabled', verbose_name='Enabled')), + ('filters', models.CharField(blank=True, help_text='Part query filters (comma-separated list of key=value pairs', max_length=250, validators=[report.models.validate_part_report_filters], verbose_name='Part Filters')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='testreport', + name='filters', + field=models.CharField(blank=True, help_text='StockItem query filters (comma-separated list of key=value pairs)', max_length=250, validators=[report.models.validate_stock_item_report_filters], verbose_name='Filters'), + ), + ] diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index ce1a01e872..42d308dcbc 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -20,6 +20,7 @@ from django.template.loader import render_to_string from django.core.files.storage import FileSystemStorage from django.core.validators import FileExtensionValidator +import part.models import stock.models import common.models @@ -70,10 +71,21 @@ def rename_template(instance, filename): def validate_stock_item_report_filters(filters): + """ + Validate filter string against StockItem model + """ return validateFilterString(filters, model=stock.models.StockItem) +def validate_part_report_filters(filters): + """ + Validate filter string against Part model + """ + + return validateFilterString(filters, model=part.models.Part) + + class WeasyprintReportMixin(WeasyTemplateResponseMixin): """ Class for rendering a HTML template to a PDF. @@ -252,7 +264,7 @@ class TestReport(ReportTemplateBase): blank=True, max_length=250, verbose_name=_('Filters'), - help_text=_("Part query filters (comma-separated list of key=value pairs)"), + help_text=_("StockItem query filters (comma-separated list of key=value pairs)"), validators=[ validate_stock_item_report_filters ] @@ -302,6 +314,33 @@ def rename_snippet(instance, filename): return path +class BillOfMaterialsReport(ReportTemplateBase): + """ + Render a Bill of Materials against a Part object + """ + + def getSubDir(self): + return 'bom' + + # Requires a part object to be given to it before rendering + + filters = models.CharField( + blank=True, + max_length=250, + verbose_name=_('Part Filters'), + help_text=_('Part query filters (comma-separated list of key=value pairs'), + validators=[ + validate_part_report_filters + ] + ) + + def get_context_data(self, request): + return { + 'part': self.part, + 'category': self.category, + } + + class ReportSnippet(models.Model): """ Report template 'snippet' which can be used to make templates