2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00

Merge pull request #1579 from SchrodingersGat/report-naming

Adds a "filename_template" field to reports
This commit is contained in:
Oliver 2021-05-13 14:03:30 +10:00 committed by GitHub
commit a1fa3315b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 3 deletions

View File

@ -63,16 +63,23 @@ class LabelPrintMixin:
# In debug mode, generate single HTML output, rather than PDF # In debug mode, generate single HTML output, rather than PDF
debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE') debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE')
label_name = "label.pdf"
# Merge one or more PDF files into a single download # Merge one or more PDF files into a single download
for item in items_to_print: for item in items_to_print:
label = self.get_object() label = self.get_object()
label.object_to_print = item label.object_to_print = item
label_name = label.generate_filename(request)
if debug_mode: if debug_mode:
outputs.append(label.render_as_string(request)) outputs.append(label.render_as_string(request))
else: else:
outputs.append(label.render(request)) outputs.append(label.render(request))
if not label_name.endswith(".pdf"):
label_name += ".pdf"
if debug_mode: if debug_mode:
""" """
Contatenate all rendered templates into a single HTML string, Contatenate all rendered templates into a single HTML string,
@ -103,7 +110,7 @@ class LabelPrintMixin:
return InvenTree.helpers.DownloadFile( return InvenTree.helpers.DownloadFile(
pdf, pdf,
'inventree_label.pdf', label_name,
content_type='application/pdf' content_type='application/pdf'
) )

View File

@ -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'),
),
]

View File

@ -15,6 +15,7 @@ from django.db import models
from django.core.validators import FileExtensionValidator, MinValueValidator from django.core.validators import FileExtensionValidator, MinValueValidator
from django.core.exceptions import ValidationError, FieldError from django.core.exceptions import ValidationError, FieldError
from django.template import Template, Context
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -138,6 +139,13 @@ class LabelTemplate(models.Model):
validators=[MinValueValidator(2)] 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 @property
def template_name(self): def template_name(self):
""" """
@ -162,6 +170,19 @@ class LabelTemplate(models.Model):
return {} 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): def context(self, request):
""" """
Provides context data to the template. Provides context data to the template.
@ -201,6 +222,7 @@ class LabelTemplate(models.Model):
self.template_name, self.template_name,
base_url=request.build_absolute_uri("/"), base_url=request.build_absolute_uri("/"),
presentational_hints=True, presentational_hints=True,
filename=self.generate_filename(request),
**kwargs **kwargs
) )

View File

@ -208,16 +208,24 @@ class ReportPrintMixin:
# In debug mode, generate single HTML output, rather than PDF # In debug mode, generate single HTML output, rather than PDF
debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE') 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 # Merge one or more PDF files into a single download
for item in items_to_print: for item in items_to_print:
report = self.get_object() report = self.get_object()
report.object_to_print = item report.object_to_print = item
report_name = report.generate_filename(request)
if debug_mode: if debug_mode:
outputs.append(report.render_as_string(request)) outputs.append(report.render_as_string(request))
else: else:
outputs.append(report.render(request)) outputs.append(report.render(request))
if not report_name.endswith('.pdf'):
report_name += '.pdf'
if debug_mode: if debug_mode:
""" """
Contatenate all rendered templates into a single HTML string, Contatenate all rendered templates into a single HTML string,
@ -248,7 +256,7 @@ class ReportPrintMixin:
return InvenTree.helpers.DownloadFile( return InvenTree.helpers.DownloadFile(
pdf, pdf,
'inventree_report.pdf', report_name,
content_type='application/pdf' content_type='application/pdf'
) )

View File

@ -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'),
),
]

View File

@ -16,6 +16,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError, FieldError from django.core.exceptions import ValidationError, FieldError
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.template import Template, Context
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.core.validators import FileExtensionValidator from django.core.validators import FileExtensionValidator
@ -224,6 +225,7 @@ class ReportTemplateBase(ReportBase):
All context to be passed to the renderer. 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 = self.get_context_data(request)
context['base_url'] = common.models.InvenTreeSetting.get_setting('INVENTREE_BASE_URL') context['base_url'] = common.models.InvenTreeSetting.get_setting('INVENTREE_BASE_URL')
@ -238,9 +240,22 @@ class ReportTemplateBase(ReportBase):
return context 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): 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) Useful for debug mode (viewing generated code)
""" """
@ -263,12 +278,20 @@ class ReportTemplateBase(ReportBase):
self.template_name, self.template_name,
base_url=request.build_absolute_uri("/"), base_url=request.build_absolute_uri("/"),
presentational_hints=True, presentational_hints=True,
filename=self.generate_filename(request),
**kwargs) **kwargs)
return wp.render_to_response( return wp.render_to_response(
self.context(request), self.context(request),
**kwargs) **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( enabled = models.BooleanField(
default=True, default=True,
verbose_name=_('Enabled'), verbose_name=_('Enabled'),
@ -326,6 +349,7 @@ class TestReport(ReportTemplateBase):
return { return {
'stock_item': stock_item, 'stock_item': stock_item,
'serial': stock_item.serial,
'part': stock_item.part, 'part': stock_item.part,
'results': stock_item.testResultMap(include_installed=self.include_installed), 'results': stock_item.testResultMap(include_installed=self.include_installed),
'result_list': stock_item.testResultList(include_installed=self.include_installed) 'result_list': stock_item.testResultList(include_installed=self.include_installed)
@ -367,6 +391,7 @@ class BuildReport(ReportTemplateBase):
'bom_items': my_build.part.get_bom_items(), 'bom_items': my_build.part.get_bom_items(),
'reference': my_build.reference, 'reference': my_build.reference,
'quantity': my_build.quantity, 'quantity': my_build.quantity,
'title': str(my_build),
} }