mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	Add new global setting to control auto-upload of test reports (#3137)
* Add new global setting to control auto-upload of test reports * Adds callback to attach a copy of the test report when printing * Fix for all attachment API endpoints - The AttachmentMixin must come first! - User was not being set, as the custom 'perform_create' function was never called * Remove duplicated UserSerializer * display uploading user in attachment table * Add unit test to check the test report is automatically uploaded
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| """API functionality for the 'report' app""" | ||||
|  | ||||
| from django.core.exceptions import FieldError, ValidationError | ||||
| from django.core.files.base import ContentFile | ||||
| from django.http import HttpResponse | ||||
| from django.template.exceptions import TemplateDoesNotExist | ||||
| from django.urls import include, path, re_path | ||||
| @@ -15,7 +16,7 @@ import common.models | ||||
| import InvenTree.helpers | ||||
| import order.models | ||||
| import part.models | ||||
| from stock.models import StockItem | ||||
| from stock.models import StockItem, StockItemAttachment | ||||
|  | ||||
| from .models import (BillOfMaterialsReport, BuildReport, PurchaseOrderReport, | ||||
|                      SalesOrderReport, TestReport) | ||||
| @@ -158,6 +159,18 @@ class PartReportMixin: | ||||
| class ReportPrintMixin: | ||||
|     """Mixin for printing reports.""" | ||||
|  | ||||
|     def report_callback(self, object, report, request): | ||||
|         """Callback function for each object/report combination. | ||||
|  | ||||
|         Allows functionality to be performed before returning the consolidated PDF | ||||
|  | ||||
|         Arguments: | ||||
|             object: The model instance to be printed | ||||
|             report: The individual PDF file object | ||||
|             request: The request instance associated with this print call | ||||
|         """ | ||||
|         ... | ||||
|  | ||||
|     def print(self, request, items_to_print): | ||||
|         """Print this report template against a number of pre-validated items.""" | ||||
|         if len(items_to_print) == 0: | ||||
| @@ -182,12 +195,16 @@ class ReportPrintMixin: | ||||
|             report.object_to_print = item | ||||
|  | ||||
|             report_name = report.generate_filename(request) | ||||
|             output = report.render(request) | ||||
|  | ||||
|             # Run report callback for each generated report | ||||
|             self.report_callback(item, output, request) | ||||
|  | ||||
|             try: | ||||
|                 if debug_mode: | ||||
|                     outputs.append(report.render_as_string(request)) | ||||
|                 else: | ||||
|                     outputs.append(report.render(request)) | ||||
|                     outputs.append(output) | ||||
|             except TemplateDoesNotExist as e: | ||||
|                 template = str(e) | ||||
|                 if not template: | ||||
| @@ -326,6 +343,22 @@ class StockItemTestReportPrint(generics.RetrieveAPIView, StockItemReportMixin, R | ||||
|     queryset = TestReport.objects.all() | ||||
|     serializer_class = TestReportSerializer | ||||
|  | ||||
|     def report_callback(self, item, report, request): | ||||
|         """Callback to (optionally) save a copy of the generated report""" | ||||
|  | ||||
|         if common.models.InvenTreeSetting.get_setting('REPORT_ATTACH_TEST_REPORT'): | ||||
|  | ||||
|             # Construct a PDF file object | ||||
|             pdf = report.get_document().write_pdf() | ||||
|             pdf_content = ContentFile(pdf, "test_report.pdf") | ||||
|  | ||||
|             StockItemAttachment.objects.create( | ||||
|                 attachment=pdf_content, | ||||
|                 stock_item=item, | ||||
|                 user=request.user, | ||||
|                 comment=_("Test report") | ||||
|             ) | ||||
|  | ||||
|     def get(self, request, *args, **kwargs): | ||||
|         """Check if valid stock item(s) have been provided.""" | ||||
|         items = self.get_items() | ||||
|   | ||||
| @@ -9,9 +9,9 @@ from django.urls import reverse | ||||
|  | ||||
| import report.models as report_models | ||||
| from build.models import Build | ||||
| from common.models import InvenTreeUserSetting | ||||
| from common.models import InvenTreeSetting, InvenTreeUserSetting | ||||
| from InvenTree.api_tester import InvenTreeAPITestCase | ||||
| from stock.models import StockItem | ||||
| from stock.models import StockItem, StockItemAttachment | ||||
|  | ||||
|  | ||||
| class ReportTest(InvenTreeAPITestCase): | ||||
| @@ -141,15 +141,28 @@ class TestReportTest(ReportTest): | ||||
|         # Now print with a valid StockItem | ||||
|         item = StockItem.objects.first() | ||||
|  | ||||
|         response = self.get(url, {'item': item.pk}) | ||||
|         response = self.get(url, {'item': item.pk}, expected_code=200) | ||||
|  | ||||
|         # Response should be a StreamingHttpResponse (PDF file) | ||||
|         self.assertEqual(type(response), StreamingHttpResponse) | ||||
|  | ||||
|         headers = response.headers | ||||
|  | ||||
|         self.assertEqual(headers['Content-Type'], 'application/pdf') | ||||
|  | ||||
|         # By default, this should *not* have created an attachment against this stockitem | ||||
|         self.assertFalse(StockItemAttachment.objects.filter(stock_item=item).exists()) | ||||
|  | ||||
|         # Change the setting, now the test report should be attached automatically | ||||
|         InvenTreeSetting.set_setting('REPORT_ATTACH_TEST_REPORT', True, None) | ||||
|  | ||||
|         response = self.get(url, {'item': item.pk}, expected_code=200) | ||||
|         headers = response.headers | ||||
|         self.assertEqual(headers['Content-Type'], 'application/pdf') | ||||
|  | ||||
|         # Check that a report has been uploaded | ||||
|         attachment = StockItemAttachment.objects.filter(stock_item=item).first() | ||||
|         self.assertIsNotNone(attachment) | ||||
|  | ||||
|  | ||||
| class BuildReportTest(ReportTest): | ||||
|     """Unit test class for the BuildReport model""" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user