From 90bef69a5954cc0b3671a6aa17f2cb90be3e8dea Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 3 Feb 2021 16:58:06 +1100 Subject: [PATCH 01/17] Adds "report snippet" class allowing re-usable report snippets to be uploaded --- InvenTree/report/admin.py | 8 ++- .../report/migrations/0006_reportsnippet.py | 27 ++++++++ InvenTree/report/models.py | 69 +++++++++++++------ 3 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 InvenTree/report/migrations/0006_reportsnippet.py diff --git a/InvenTree/report/admin.py b/InvenTree/report/admin.py index 7d6403f5d9..32340921c3 100644 --- a/InvenTree/report/admin.py +++ b/InvenTree/report/admin.py @@ -3,7 +3,12 @@ from __future__ import unicode_literals from django.contrib import admin -from .models import TestReport, ReportAsset +from .models import ReportSnippet, TestReport, ReportAsset + + +class ReportSnippetAdmin(admin.ModelAdmin): + + list_display = ('name', 'description', 'template') class ReportTemplateAdmin(admin.ModelAdmin): @@ -16,5 +21,6 @@ class ReportAssetAdmin(admin.ModelAdmin): list_display = ('asset', 'description') +admin.site.register(ReportSnippet, ReportSnippetAdmin) admin.site.register(TestReport, ReportTemplateAdmin) admin.site.register(ReportAsset, ReportAssetAdmin) diff --git a/InvenTree/report/migrations/0006_reportsnippet.py b/InvenTree/report/migrations/0006_reportsnippet.py new file mode 100644 index 0000000000..c503678345 --- /dev/null +++ b/InvenTree/report/migrations/0006_reportsnippet.py @@ -0,0 +1,27 @@ +# Generated by Django 3.0.7 on 2021-02-03 05:57 + +import django.core.validators +from django.db import migrations, models +import report.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0005_auto_20210119_0815'), + ] + + operations = [ + migrations.CreateModel( + name='ReportSnippet', + 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, unique=True, 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', 'tex'])], verbose_name='Template')), + ('description', models.CharField(help_text='Report template description', max_length=250, verbose_name='Description')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index 224f2800d8..6b064999d5 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -77,14 +77,18 @@ class WeasyprintReportMixin(WeasyTemplateResponseMixin): self.pdf_filename = kwargs.get('filename', 'report.pdf') -class ReportTemplateBase(models.Model): +class ReportBase(models.Model): """ - Reporting template model. + Base class for uploading html templates """ + class Meta: + abstract = True + def __str__(self): return "{n} - {d}".format(n=self.name, d=self.description) + def getSubdir(self): return '' @@ -105,6 +109,47 @@ class ReportTemplateBase(models.Model): return template + name = models.CharField( + blank=False, max_length=100, + verbose_name=_('Name'), + help_text=_('Template name'), + unique=True, + ) + + template = models.FileField( + upload_to=rename_template, + verbose_name=_('Template'), + help_text=_("Report template file"), + validators=[FileExtensionValidator(allowed_extensions=['html', 'htm', 'tex'])], + ) + + description = models.CharField( + max_length=250, + verbose_name=_('Description'), + help_text=_("Report template description") + ) + + +class ReportSnippet(ReportBase): + """ + Report template 'snippet' which can be used to make templates + that can then be included in other reports. + + Useful for 'common' template actions, sub-templates, etc + """ + + def getSubdir(self): + return "" + + +class ReportTemplateBase(ReportBase): + """ + Reporting template model. + + Able to be passed context data + + """ + def get_context_data(self, request): """ Supply context data to the template for rendering @@ -147,26 +192,6 @@ class ReportTemplateBase(models.Model): wp = WeasyprintReportMixin(request, self.template_name, **kwargs) return wp.render_to_response(context, **kwargs) - name = models.CharField( - blank=False, max_length=100, - verbose_name=_('Name'), - help_text=_('Template name'), - unique=True, - ) - - template = models.FileField( - upload_to=rename_template, - verbose_name=_('Template'), - help_text=_("Report template file"), - validators=[FileExtensionValidator(allowed_extensions=['html', 'htm', 'tex'])], - ) - - description = models.CharField( - max_length=250, - verbose_name=_('Description'), - help_text=_("Report template description") - ) - enabled = models.BooleanField( default=True, verbose_name=_('Enabled'), From cbadb2a888f20c64f6fbffd37e5829d95fbbb3ca Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 3 Feb 2021 21:54:11 +1100 Subject: [PATCH 02/17] Small refactor, and allow editing of ReportAsset in the admin interface --- InvenTree/report/admin.py | 2 +- InvenTree/report/models.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/InvenTree/report/admin.py b/InvenTree/report/admin.py index 32340921c3..5034934ccf 100644 --- a/InvenTree/report/admin.py +++ b/InvenTree/report/admin.py @@ -18,7 +18,7 @@ class ReportTemplateAdmin(admin.ModelAdmin): class ReportAssetAdmin(admin.ModelAdmin): - list_display = ('asset', 'description') + list_display = ('id', 'asset', 'description') admin.site.register(ReportSnippet, ReportSnippetAdmin) diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index 6b064999d5..ba8672f8c1 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -52,9 +52,7 @@ class TexResponse(HttpResponse): def rename_template(instance, filename): - filename = os.path.basename(filename) - - return os.path.join('report', 'report_template', instance.getSubdir(), filename) + return instance.rename_file(filename) def validate_stock_item_report_filters(filters): @@ -92,6 +90,13 @@ class ReportBase(models.Model): def getSubdir(self): return '' + def rename_file(self, filename): + # Function for renaming uploaded file + + filename = os.path.basename(filename) + + return os.path.join('report', 'report_template', self.getSubdir(), filename) + @property def extension(self): return os.path.splitext(self.template.name)[1].lower() From 3ccc500e8ec10f6bdd94794d857f121a2d1ba8ff Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 4 Feb 2021 12:58:19 +1100 Subject: [PATCH 03/17] Add more context data to report --- InvenTree/report/models.py | 16 ++++++++++++++-- InvenTree/templates/js/report.js | 9 +++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index ba8672f8c1..c2b5d729fe 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -175,6 +175,10 @@ class ReportTemplateBase(ReportBase): context = self.get_context_data(request) + context['media'] = settings.MEDIA_ROOT + + context['report_name'] = self.name + context['report_description'] = self.description context['request'] = request context['user'] = request.user context['datetime'] = datetime.datetime.now() @@ -194,8 +198,16 @@ class ReportTemplateBase(ReportBase): raise ValidationError("Enable LaTeX support in config.yaml") elif self.extension in ['.htm', '.html']: # Render HTML template to PDF - wp = WeasyprintReportMixin(request, self.template_name, **kwargs) - return wp.render_to_response(context, **kwargs) + wp = WeasyprintReportMixin( + request, + self.template_name, + base_url=request.build_absolute_uri("/"), + presentational_hints=True, + **kwargs) + + return wp.render_to_response( + context, + **kwargs) enabled = models.BooleanField( default=True, diff --git a/InvenTree/templates/js/report.js b/InvenTree/templates/js/report.js index da84433bac..6e47706917 100644 --- a/InvenTree/templates/js/report.js +++ b/InvenTree/templates/js/report.js @@ -10,6 +10,15 @@ function selectTestReport(reports, items, options={}) { * (via AJAX) from the server. */ + // If there is only a single report available, just print! + if (reports.length == 1) { + if (options.success) { + options.success(reports[0].pk); + } + + return; + } + var modal = options.modal || '#modal-form'; var report_list = makeOptionsList( From 801b945438e112b4727be31606ab211aec6e6274 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 4 Feb 2021 13:33:14 +1100 Subject: [PATCH 04/17] Add current date to report context --- InvenTree/report/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index c2b5d729fe..56d06090a1 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -181,6 +181,7 @@ class ReportTemplateBase(ReportBase): context['report_description'] = self.description context['request'] = request context['user'] = request.user + context['date'] = datetime.datetime.now().date() context['datetime'] = datetime.datetime.now() if self.extension == '.tex': From 6230fb3614d8555cfbb0c60b917f4f37d8b29a0f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 4 Feb 2021 13:41:47 +1100 Subject: [PATCH 05/17] Add custom report template tags --- InvenTree/part/templatetags/report.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 InvenTree/part/templatetags/report.py diff --git a/InvenTree/part/templatetags/report.py b/InvenTree/part/templatetags/report.py new file mode 100644 index 0000000000..32eec76db0 --- /dev/null +++ b/InvenTree/part/templatetags/report.py @@ -0,0 +1,22 @@ +""" +Custom template tags for report generation +""" + +import os + +from django import template +from django.conf import settings + +register = template.Library() + + +@register.simple_tag() +def asset(filename): + """ + Return fully-qualified path for an upload report asset file. + """ + + path = os.path.join(settings.MEDIA_ROOT, 'report', 'assets', filename) + path = os.path.abspath(path) + + return f"file://{path}" From cf0c43d89938df092f3bbb66b13f0aa3000a6a73 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 4 Feb 2021 13:54:26 +1100 Subject: [PATCH 06/17] Add report base template --- .../report/inventree_report_base.html | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 InvenTree/report/templates/report/inventree_report_base.html diff --git a/InvenTree/report/templates/report/inventree_report_base.html b/InvenTree/report/templates/report/inventree_report_base.html new file mode 100644 index 0000000000..936a9758a9 --- /dev/null +++ b/InvenTree/report/templates/report/inventree_report_base.html @@ -0,0 +1,51 @@ +{% load report %} + + + + + + + + + +
+ {% block page_content %} + {% endblock %} +
+ + + + \ No newline at end of file From ddbf2a6313def4f9c43ac894545d4e70f6541214 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 4 Feb 2021 14:49:11 +1100 Subject: [PATCH 07/17] Add margin callouts for report template base --- .../report/inventree_report_base.html | 79 +++++++++++++++---- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/InvenTree/report/templates/report/inventree_report_base.html b/InvenTree/report/templates/report/inventree_report_base.html index 936a9758a9..afcd31f2ed 100644 --- a/InvenTree/report/templates/report/inventree_report_base.html +++ b/InvenTree/report/templates/report/inventree_report_base.html @@ -3,29 +3,76 @@ @@ -33,17 +80,17 @@ -