From 6de44a59217d167d7547c790a39819446ed2c85b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 13 May 2021 13:23:51 +1000 Subject: [PATCH 1/2] Adds a "filename_template" field to reports - Allows users to define the naming scheme for generated reports - Templated, can use any context variable already available to the report instance - Adds some more context variables to various reports --- InvenTree/report/api.py | 10 ++++- .../migrations/0016_auto_20210513_1303.py | 38 +++++++++++++++++++ InvenTree/report/models.py | 26 ++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 InvenTree/report/migrations/0016_auto_20210513_1303.py diff --git a/InvenTree/report/api.py b/InvenTree/report/api.py index 351a988601..f09a52f272 100644 --- a/InvenTree/report/api.py +++ b/InvenTree/report/api.py @@ -208,16 +208,24 @@ class ReportPrintMixin: # In debug mode, generate single HTML output, rather than PDF debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE') + # Start with a default report name + report_name = "report.pdf" + # Merge one or more PDF files into a single download for item in items_to_print: report = self.get_object() report.object_to_print = item + report_name = report.generate_filename(request) + if debug_mode: outputs.append(report.render_as_string(request)) else: outputs.append(report.render(request)) + if not report_name.endswith('.pdf'): + report_name += '.pdf' + if debug_mode: """ Contatenate all rendered templates into a single HTML string, @@ -248,7 +256,7 @@ class ReportPrintMixin: return InvenTree.helpers.DownloadFile( pdf, - 'inventree_report.pdf', + report_name, content_type='application/pdf' ) diff --git a/InvenTree/report/migrations/0016_auto_20210513_1303.py b/InvenTree/report/migrations/0016_auto_20210513_1303.py new file mode 100644 index 0000000000..5b1e950dea --- /dev/null +++ b/InvenTree/report/migrations/0016_auto_20210513_1303.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2 on 2021-05-13 03:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0015_auto_20210403_1837'), + ] + + operations = [ + migrations.AddField( + model_name='billofmaterialsreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='buildreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='purchaseorderreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='salesorderreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='testreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + ] diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index fa7ae2b271..dfb7c09679 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -16,6 +16,7 @@ from django.conf import settings from django.core.exceptions import ValidationError, FieldError from django.template.loader import render_to_string +from django.template import Template, Context from django.core.files.storage import FileSystemStorage from django.core.validators import FileExtensionValidator @@ -224,6 +225,7 @@ class ReportTemplateBase(ReportBase): All context to be passed to the renderer. """ + # Generate custom context data based on the particular report subclass context = self.get_context_data(request) context['base_url'] = common.models.InvenTreeSetting.get_setting('INVENTREE_BASE_URL') @@ -238,9 +240,22 @@ class ReportTemplateBase(ReportBase): return context + def generate_filename(self, request, **kwargs): + """ + Generate a filename for this report + """ + + template_string = Template(self.filename_pattern) + + ctx = self.context(request) + + context = Context(ctx) + + return template_string.render(context) + def render_as_string(self, request, **kwargs): """ - Render the report to a HTML stiring. + Render the report to a HTML string. Useful for debug mode (viewing generated code) """ @@ -269,6 +284,13 @@ class ReportTemplateBase(ReportBase): self.context(request), **kwargs) + filename_pattern = models.CharField( + default="report.pdf", + verbose_name=_('Filename Pattern'), + help_text=_('Pattern for generating report filenames'), + max_length=100, + ) + enabled = models.BooleanField( default=True, verbose_name=_('Enabled'), @@ -326,6 +348,7 @@ class TestReport(ReportTemplateBase): return { 'stock_item': stock_item, + 'serial': stock_item.serial, 'part': stock_item.part, 'results': stock_item.testResultMap(include_installed=self.include_installed), 'result_list': stock_item.testResultList(include_installed=self.include_installed) @@ -367,6 +390,7 @@ class BuildReport(ReportTemplateBase): 'bom_items': my_build.part.get_bom_items(), 'reference': my_build.reference, 'quantity': my_build.quantity, + 'title': str(my_build), } From 82a3d9ca967f80d25e9bf09fe56d79acd81e779f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 13 May 2021 13:40:40 +1000 Subject: [PATCH 2/2] Implements custom naming for generated labels --- InvenTree/label/api.py | 9 +++++++- .../migrations/0007_auto_20210513_1327.py | 23 +++++++++++++++++++ InvenTree/label/models.py | 22 ++++++++++++++++++ InvenTree/report/models.py | 1 + 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 InvenTree/label/migrations/0007_auto_20210513_1327.py diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py index fc082e4a50..8522857e30 100644 --- a/InvenTree/label/api.py +++ b/InvenTree/label/api.py @@ -63,16 +63,23 @@ class LabelPrintMixin: # In debug mode, generate single HTML output, rather than PDF debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE') + label_name = "label.pdf" + # Merge one or more PDF files into a single download for item in items_to_print: label = self.get_object() label.object_to_print = item + label_name = label.generate_filename(request) + if debug_mode: outputs.append(label.render_as_string(request)) else: outputs.append(label.render(request)) + if not label_name.endswith(".pdf"): + label_name += ".pdf" + if debug_mode: """ Contatenate all rendered templates into a single HTML string, @@ -103,7 +110,7 @@ class LabelPrintMixin: return InvenTree.helpers.DownloadFile( pdf, - 'inventree_label.pdf', + label_name, content_type='application/pdf' ) diff --git a/InvenTree/label/migrations/0007_auto_20210513_1327.py b/InvenTree/label/migrations/0007_auto_20210513_1327.py new file mode 100644 index 0000000000..d49c83c92b --- /dev/null +++ b/InvenTree/label/migrations/0007_auto_20210513_1327.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2 on 2021-05-13 03:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('label', '0006_auto_20210222_1535'), + ] + + operations = [ + migrations.AddField( + model_name='stockitemlabel', + name='filename_pattern', + field=models.CharField(default='label.pdf', help_text='Pattern for generating label filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='stocklocationlabel', + name='filename_pattern', + field=models.CharField(default='label.pdf', help_text='Pattern for generating label filenames', max_length=100, verbose_name='Filename Pattern'), + ), + ] diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index 71ccc73ac9..a5d8314193 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -15,6 +15,7 @@ from django.db import models from django.core.validators import FileExtensionValidator, MinValueValidator from django.core.exceptions import ValidationError, FieldError +from django.template import Template, Context from django.template.loader import render_to_string from django.utils.translation import gettext_lazy as _ @@ -138,6 +139,13 @@ class LabelTemplate(models.Model): validators=[MinValueValidator(2)] ) + filename_pattern = models.CharField( + default="label.pdf", + verbose_name=_('Filename Pattern'), + help_text=_('Pattern for generating label filenames'), + max_length=100, + ) + @property def template_name(self): """ @@ -162,6 +170,19 @@ class LabelTemplate(models.Model): return {} + def generate_filename(self, request, **kwargs): + """ + Generate a filename for this label + """ + + template_string = Template(self.filename_pattern) + + ctx = self.context(request) + + context = Context(ctx) + + return template_string.render(context) + def context(self, request): """ Provides context data to the template. @@ -201,6 +222,7 @@ class LabelTemplate(models.Model): self.template_name, base_url=request.build_absolute_uri("/"), presentational_hints=True, + filename=self.generate_filename(request), **kwargs ) diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index dfb7c09679..ecb4d91492 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -278,6 +278,7 @@ class ReportTemplateBase(ReportBase): self.template_name, base_url=request.build_absolute_uri("/"), presentational_hints=True, + filename=self.generate_filename(request), **kwargs) return wp.render_to_response(