From 07fac28b763b3304deadf3f702101036af18764c Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 6 Sep 2024 15:15:16 +1000 Subject: [PATCH] Remove references to old setting (#8018) * Remove references to old setting - Now offloaded to plugins * Remove REPORT_ENABLE_TEST_REPORT setting * Cleanup * Add new boolean setting to control whether reports are attached automatically * Attach generated report to model instance * Update unit testing * Bump API version --- .../InvenTree/InvenTree/api_version.py | 5 +++- src/backend/InvenTree/common/models.py | 14 --------- src/backend/InvenTree/common/tests.py | 7 ----- src/backend/InvenTree/report/api.py | 9 ++++++ ..._labeltemplate_attach_to_model_and_more.py | 23 +++++++++++++++ src/backend/InvenTree/report/models.py | 8 +++++ src/backend/InvenTree/report/serializers.py | 1 + src/backend/InvenTree/report/tests.py | 29 ++++++++++++++++++- .../stock/templates/stock/item_base.html | 6 +--- .../templates/InvenTree/settings/report.html | 2 -- src/backend/InvenTree/templates/base.html | 1 - .../AdminCenter/ReportTemplatePanel.tsx | 6 ++++ .../pages/Index/Settings/SystemSettings.tsx | 4 +-- tasks.py | 7 +++-- 14 files changed, 86 insertions(+), 36 deletions(-) create mode 100644 src/backend/InvenTree/report/migrations/0028_labeltemplate_attach_to_model_and_more.py diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index d278abde37..179bbd692c 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,13 +1,16 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 250 +INVENTREE_API_VERSION = 251 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v251 - 2024-09-06 : https://github.com/inventree/InvenTree/pull/8018 + - Adds "attach_to_model" field to the ReporTemplate model + v250 - 2024-09-04 : https://github.com/inventree/InvenTree/pull/8069 - Fixes 'revision' field definition in Part serializer diff --git a/src/backend/InvenTree/common/models.py b/src/backend/InvenTree/common/models.py index 24e718bd5e..2b8dc5aca3 100644 --- a/src/backend/InvenTree/common/models.py +++ b/src/backend/InvenTree/common/models.py @@ -1704,20 +1704,6 @@ class InvenTreeSetting(BaseInvenTreeSetting): 'default': 'A4', 'choices': report.helpers.report_page_size_options, }, - 'REPORT_ENABLE_TEST_REPORT': { - 'name': _('Enable Test Reports'), - 'description': _('Enable generation of test reports'), - 'default': True, - 'validator': bool, - }, - 'REPORT_ATTACH_TEST_REPORT': { - 'name': _('Attach Test Reports'), - 'description': _( - 'When printing a Test Report, attach a copy of the Test Report to the associated Stock Item' - ), - 'default': False, - 'validator': bool, - }, 'SERIAL_NUMBER_GLOBALLY_UNIQUE': { 'name': _('Globally Unique Serials'), 'description': _('Serial numbers for stock items must be globally unique'), diff --git a/src/backend/InvenTree/common/tests.py b/src/backend/InvenTree/common/tests.py index 7acd3b9c9e..826bce15b7 100644 --- a/src/backend/InvenTree/common/tests.py +++ b/src/backend/InvenTree/common/tests.py @@ -228,9 +228,6 @@ class SettingsTest(InvenTreeTestCase): report_size_obj = InvenTreeSetting.get_setting_object( 'REPORT_DEFAULT_PAGE_SIZE' ) - report_test_obj = InvenTreeSetting.get_setting_object( - 'REPORT_ENABLE_TEST_REPORT' - ) # check settings base fields self.assertEqual(instance_obj.name, 'Server Instance Name') @@ -260,7 +257,6 @@ class SettingsTest(InvenTreeTestCase): # check setting_type self.assertEqual(instance_obj.setting_type(), 'string') - self.assertEqual(report_test_obj.setting_type(), 'boolean') self.assertEqual(stale_days.setting_type(), 'integer') # check as_int @@ -269,9 +265,6 @@ class SettingsTest(InvenTreeTestCase): instance_obj.as_int(), 'InvenTree' ) # not an int -> return default - # check as_bool - self.assertEqual(report_test_obj.as_bool(), True) - # check to_native_value self.assertEqual(stale_days.to_native_value(), 0) diff --git a/src/backend/InvenTree/report/api.py b/src/backend/InvenTree/report/api.py index 75959557f7..f32e7f7d8b 100644 --- a/src/backend/InvenTree/report/api.py +++ b/src/backend/InvenTree/report/api.py @@ -350,6 +350,15 @@ class ReportPrint(GenericAPIView): output = template.render(instance, request) + if template.attach_to_model: + # Attach the generated report to the model instance + data = output.get_document().write_pdf() + instance.create_attachment( + attachment=ContentFile(data, report_name), + comment=_('Report saved at time of printing'), + upload_user=request.user, + ) + # Provide generated report to any interested plugins for plugin in registry.with_mixin('report'): try: diff --git a/src/backend/InvenTree/report/migrations/0028_labeltemplate_attach_to_model_and_more.py b/src/backend/InvenTree/report/migrations/0028_labeltemplate_attach_to_model_and_more.py new file mode 100644 index 0000000000..01fa44c8df --- /dev/null +++ b/src/backend/InvenTree/report/migrations/0028_labeltemplate_attach_to_model_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.15 on 2024-09-05 23:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0027_alter_labeltemplate_model_type_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='labeltemplate', + name='attach_to_model', + field=models.BooleanField(default=False, help_text='Save report output as an attachment against linked model instance when printing', verbose_name='Attach to Model on Print'), + ), + migrations.AddField( + model_name='reporttemplate', + name='attach_to_model', + field=models.BooleanField(default=False, help_text='Save report output as an attachment against linked model instance when printing', verbose_name='Attach to Model on Print'), + ), + ] diff --git a/src/backend/InvenTree/report/models.py b/src/backend/InvenTree/report/models.py index 58cb2a0998..0972eb8703 100644 --- a/src/backend/InvenTree/report/models.py +++ b/src/backend/InvenTree/report/models.py @@ -163,6 +163,14 @@ class ReportTemplateBase(MetadataMixin, InvenTree.models.InvenTreeModel): editable=False, ) + attach_to_model = models.BooleanField( + default=False, + verbose_name=_('Attach to Model on Print'), + help_text=_( + 'Save report output as an attachment against linked model instance when printing' + ), + ) + def generate_filename(self, context, **kwargs): """Generate a filename for this report.""" template_string = Template(self.filename_pattern) diff --git a/src/backend/InvenTree/report/serializers.py b/src/backend/InvenTree/report/serializers.py index 1dadc7114f..1bf2986db6 100644 --- a/src/backend/InvenTree/report/serializers.py +++ b/src/backend/InvenTree/report/serializers.py @@ -42,6 +42,7 @@ class ReportSerializerBase(InvenTreeModelSerializer): 'filename_pattern', 'enabled', 'revision', + 'attach_to_model', ] template = InvenTreeAttachmentSerializerField(required=True) diff --git a/src/backend/InvenTree/report/tests.py b/src/backend/InvenTree/report/tests.py index 429f7a3166..a4036f0551 100644 --- a/src/backend/InvenTree/report/tests.py +++ b/src/backend/InvenTree/report/tests.py @@ -555,8 +555,16 @@ class TestReportTest(PrintTestMixins, ReportTest): template = ReportTemplate.objects.filter( enabled=True, model_type='stockitem' ).first() + self.assertIsNotNone(template) + # Ensure that the 'attach_to_model' attribute is initially False + template.attach_to_model = False + template.save() + template.refresh_from_db() + + self.assertFalse(template.attach_to_model) + url = reverse(self.print_url) # Try to print without providing a valid StockItem @@ -568,18 +576,37 @@ class TestReportTest(PrintTestMixins, ReportTest): # Now print with a valid StockItem item = StockItem.objects.first() + n = item.attachments.count() + response = self.post( url, {'template': template.pk, 'items': [item.pk]}, expected_code=201 ) # There should be a link to the generated PDF - self.assertEqual(response.data['output'].startswith('/media/report/'), True) + self.assertTrue(response.data['output'].startswith('/media/report/')) + self.assertTrue(response.data['output'].endswith('.pdf')) # By default, this should *not* have created an attachment against this stockitem + self.assertEqual(n, item.attachments.count()) self.assertFalse( Attachment.objects.filter(model_id=item.pk, model_type='stockitem').exists() ) + # Now try again, but attach the generated PDF to the StockItem + template.attach_to_model = True + template.save() + + response = self.post( + url, {'template': template.pk, 'items': [item.pk]}, expected_code=201 + ) + + # A new attachment should have been created + self.assertEqual(n + 1, item.attachments.count()) + attachment = item.attachments.order_by('-pk').first() + + # The attachment should be a PDF + self.assertTrue(attachment.attachment.name.endswith('.pdf')) + def test_mdl_build(self): """Test the Build model.""" self.run_print_test(Build, 'build', label=False) diff --git a/src/backend/InvenTree/stock/templates/stock/item_base.html b/src/backend/InvenTree/stock/templates/stock/item_base.html index 8550bc9419..05544a9ebb 100644 --- a/src/backend/InvenTree/stock/templates/stock/item_base.html +++ b/src/backend/InvenTree/stock/templates/stock/item_base.html @@ -54,19 +54,15 @@ {% endif %} -{% if test_report_enabled or labels_enabled %}
-{% endif %} {% if user_owns_item %} diff --git a/src/backend/InvenTree/templates/InvenTree/settings/report.html b/src/backend/InvenTree/templates/InvenTree/settings/report.html index 6622befc36..daaf66bdd0 100644 --- a/src/backend/InvenTree/templates/InvenTree/settings/report.html +++ b/src/backend/InvenTree/templates/InvenTree/settings/report.html @@ -18,8 +18,6 @@ {% include "InvenTree/settings/setting.html" with key="REPORT_DEFAULT_PAGE_SIZE" icon="fa-print" %} {% include "InvenTree/settings/setting.html" with key="REPORT_DEBUG_MODE" icon="fa-laptop-code" %} {% include "InvenTree/settings/setting.html" with key="REPORT_LOG_ERRORS" icon="fa-exclamation-circle" %} - {% include "InvenTree/settings/setting.html" with key="REPORT_ENABLE_TEST_REPORT" icon="fa-vial" %} - {% include "InvenTree/settings/setting.html" with key="REPORT_ATTACH_TEST_REPORT" icon="fa-file-upload" %} diff --git a/src/backend/InvenTree/templates/base.html b/src/backend/InvenTree/templates/base.html index 5cb34fca5f..9d199ae551 100644 --- a/src/backend/InvenTree/templates/base.html +++ b/src/backend/InvenTree/templates/base.html @@ -4,7 +4,6 @@ {% plugins_enabled as plugins_enabled %} {% settings_value 'BARCODE_ENABLE' as barcodes %} -{% settings_value 'REPORT_ENABLE_TEST_REPORT' as test_report_enabled %} {% settings_value 'RETURNORDER_ENABLED' as return_order_enabled %} {% settings_value "REPORT_ENABLE" as report_enabled %} {% settings_value "SERVER_RESTART_REQUIRED" as server_restart_required %} diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx index 66ad35c69c..ee8190af7e 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx @@ -21,6 +21,12 @@ export default function ReportTemplateTable() { modelRenderer: (instance: any) => ( ) + }, + attach_to_model: { + label: t`Attach to Model`, + modelRenderer: (instance: any) => ( + + ) } } }} diff --git a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx index fa42dd2109..15c3122020 100644 --- a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx +++ b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx @@ -161,9 +161,7 @@ export default function SystemSettings() { 'REPORT_ENABLE', 'REPORT_DEFAULT_PAGE_SIZE', 'REPORT_DEBUG_MODE', - 'REPORT_LOG_ERRORS', - 'REPORT_ENABLE_TEST_REPORT', - 'REPORT_ATTACH_TEST_REPORT' + 'REPORT_LOG_ERRORS' ]} /> ) diff --git a/tasks.py b/tasks.py index eb766c8601..0e69b733be 100644 --- a/tasks.py +++ b/tasks.py @@ -1184,7 +1184,7 @@ def frontend_build(c): @task -def frontend_dev(c): +def frontend_server(c): """Start frontend development server. Args: @@ -1447,7 +1447,7 @@ def clear_generated(c): development = Collection( delete_data, docs_server, - frontend_dev, + frontend_server, gunicorn, import_fixtures, schema, @@ -1458,6 +1458,7 @@ development = Collection( test_translations, translate, ) + internal = Collection( clean_settings, clear_generated, @@ -1474,6 +1475,7 @@ internal = Collection( translate_stats, worker, ) + ns = Collection( backup, export_records, @@ -1490,5 +1492,6 @@ ns = Collection( version, wait, ) + ns.add_collection(development, 'dev') ns.add_collection(internal, 'int')