diff --git a/InvenTree/report/migrations/0017_returnorderreport.py b/InvenTree/report/migrations/0017_returnorderreport.py new file mode 100644 index 0000000000..e908051557 --- /dev/null +++ b/InvenTree/report/migrations/0017_returnorderreport.py @@ -0,0 +1,31 @@ +# Generated by Django 3.2.18 on 2023-03-15 11:17 + +import django.core.validators +from django.db import migrations, models +import report.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0016_auto_20210513_1303'), + ] + + operations = [ + migrations.CreateModel( + name='ReturnOrderReport', + 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')), + ('filename_pattern', models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern')), + ('enabled', models.BooleanField(default=True, help_text='Report template is enabled', verbose_name='Enabled')), + ('filters', models.CharField(blank=True, help_text='Return order query filters', max_length=250, validators=[report.models.validate_return_order_filters], verbose_name='Filters')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index 668fe0509c..ca9e526727 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -67,6 +67,11 @@ def validate_sales_order_filters(filters): return validateFilterString(filters, model=order.models.SalesOrder) +def validate_return_order_filters(filters): + """Validate filter string against ReturnOrder model""" + return validateFilterString(filters, model=order.models.ReturnOrder) + + class WeasyprintReportMixin(WeasyTemplateResponseMixin): """Class for rendering a HTML template to a PDF.""" @@ -467,6 +472,42 @@ class SalesOrderReport(ReportTemplateBase): } +class ReturnOrderReport(ReportTemplateBase): + """Render a custom report against a ReturnOrder object""" + + @staticmethod + def get_api_url(): + """Return the API URL associated with the ReturnOrderReport model""" + return reverse('api-return-order-report-list') + + @classmethod + def getSubdir(cls): + """Return the directory where the ReturnOrderReport templates are stored""" + return 'returnorder' + + filters = models.CharField( + blank=True, + max_length=250, + verbose_name=_('Filters'), + help_text=_('Return order query filters'), + validators=[ + validate_return_order_filters, + ] + ) + + def get_context_data(self, request): + """Return custom context data for the ReturnOrderReport template""" + + order = self.object_to_print + + return { + 'order': order, + 'description': order.description, + 'reference': order.reference, + 'customer': order.customer, + } + + def rename_snippet(instance, filename): """Function to rename a report snippet once uploaded"""