mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 21:25:42 +00:00 
			
		
		
		
	Allow offloading of label printing to the configured plugin
This commit is contained in:
		| @@ -1,12 +1,15 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from io import BytesIO | ||||
| from PIL import Image | ||||
|  | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
|  | ||||
| from django.conf import settings | ||||
| from django.conf.urls import url, include | ||||
| from django.core.exceptions import ValidationError, FieldError | ||||
| from django.http import HttpResponse | ||||
| from django.http import HttpResponse, JsonResponse | ||||
|  | ||||
| from django_filters.rest_framework import DjangoFilterBackend | ||||
|  | ||||
| @@ -14,6 +17,7 @@ from rest_framework import generics, filters | ||||
| from rest_framework.response import Response | ||||
|  | ||||
| import InvenTree.helpers | ||||
| from InvenTree.tasks import offload_task | ||||
| import common.models | ||||
|  | ||||
| from plugin.registry import registry | ||||
| @@ -102,6 +106,8 @@ class LabelPrintMixin: | ||||
|  | ||||
|         label_name = "label.pdf" | ||||
|  | ||||
|         label_names = [] | ||||
|  | ||||
|         # Merge one or more PDF files into a single download | ||||
|         for item in items_to_print: | ||||
|             label = self.get_object() | ||||
| @@ -109,6 +115,8 @@ class LabelPrintMixin: | ||||
|  | ||||
|             label_name = label.generate_filename(request) | ||||
|  | ||||
|             label_names.append(label_name) | ||||
|  | ||||
|             if debug_mode: | ||||
|                 outputs.append(label.render_as_string(request)) | ||||
|             else: | ||||
| @@ -117,7 +125,46 @@ class LabelPrintMixin: | ||||
|         if not label_name.endswith(".pdf"): | ||||
|             label_name += ".pdf" | ||||
|  | ||||
|         if debug_mode: | ||||
|         if plugin is not None: | ||||
|             """ | ||||
|             Label printing is to be handled by a plugin, | ||||
|             rather than being exported to PDF. | ||||
|  | ||||
|             In this case, we do the following: | ||||
|              | ||||
|             - Individually generate each label, exporting as an image file | ||||
|             - Pass all the images through to the label printing plugin | ||||
|             - Return a JSON response indicating that the printing has been offloaded | ||||
|              | ||||
|             """ | ||||
|  | ||||
|             for output in outputs: | ||||
|                 """ | ||||
|                 For each output, we generate a temporary image file, | ||||
|                 which will then get sent to the printer | ||||
|                 """ | ||||
|  | ||||
|                 # Generate a png image at 300dpi | ||||
|                 (img_data, w, h) = output.get_document().write_png(resolution=300) | ||||
|  | ||||
|                 # Construct a BytesIO object, which can be read by pillow | ||||
|                 img_bytes = BytesIO(img_data) | ||||
|  | ||||
|                 image = Image.open(img_bytes) | ||||
|  | ||||
|                 # Offload a background task to print the provided label | ||||
|                 offload_task( | ||||
|                     'plugin.events.print_label', | ||||
|                     plugin.plugin_slug(), | ||||
|                     image | ||||
|                 ) | ||||
|  | ||||
|             return JsonResponse({ | ||||
|                 'plugin': plugin.plugin_slug(), | ||||
|                 'labels': label_names, | ||||
|             }) | ||||
|  | ||||
|         elif debug_mode: | ||||
|             """ | ||||
|             Contatenate all rendered templates into a single HTML string, | ||||
|             and return the string as a HTML response. | ||||
| @@ -126,6 +173,7 @@ class LabelPrintMixin: | ||||
|             html = "\n".join(outputs) | ||||
|  | ||||
|             return HttpResponse(html) | ||||
|  | ||||
|         else: | ||||
|             """ | ||||
|             Concatenate all rendered pages into a single PDF object, | ||||
|   | ||||
| @@ -415,15 +415,6 @@ class LabelPrintingMixin: | ||||
|     def get_printer_name(self): | ||||
|         return self.PRINTER_NAME | ||||
|  | ||||
|     def print_labels(self, labels, **kwargs): | ||||
|         """ | ||||
|         Print multiple labels. | ||||
|         Default implementation is to call print_label() for each label, | ||||
|         but it can be overridden if desired. | ||||
|         """ | ||||
|         for label in labels: | ||||
|             self.print_label(label, **kwargs) | ||||
|  | ||||
|     def print_label(self, label, **kwargs): | ||||
|         """ | ||||
|         Callback to print a single label | ||||
|   | ||||
| @@ -95,7 +95,11 @@ def process_event(plugin_slug, event, *args, **kwargs): | ||||
|  | ||||
|     logger.info(f"Plugin '{plugin_slug}' is processing triggered event '{event}'") | ||||
|  | ||||
|     plugin = registry.plugins[plugin_slug] | ||||
|     plugin = registry.plugins.get(plugin_slug, None) | ||||
|      | ||||
|     if plugin is None: | ||||
|         logger.error(f"Could not find matching plugin for '{plugin_slug}'") | ||||
|         return | ||||
|  | ||||
|     plugin.process_event(event, *args, **kwargs) | ||||
|  | ||||
| @@ -186,3 +190,25 @@ def after_delete(sender, instance, **kwargs): | ||||
|         model=sender.__name__, | ||||
|         table=table, | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def print_label(plugin_slug, label_image, **kwargs): | ||||
|     """ | ||||
|     Print label with the provided plugin. | ||||
|  | ||||
|     This task is nominally handled by the background worker. | ||||
|  | ||||
|     Arguments: | ||||
|         plugin_slug: The unique slug (key) of the plugin | ||||
|         label_image: A PIL.Image image object to be printed | ||||
|     """ | ||||
|  | ||||
|     logger.info(f"Plugin '{plugin_slug}' is printing a label") | ||||
|  | ||||
|     plugin = registry.plugins.get(plugin_slug, None) | ||||
|      | ||||
|     if plugin is None: | ||||
|         logger.error(f"Could not find matching plugin for '{plugin_slug}'") | ||||
|         return | ||||
|  | ||||
|     plugin.print_label(label_image) | ||||
|   | ||||
| @@ -14,11 +14,41 @@ | ||||
| */ | ||||
|  | ||||
| /* exported | ||||
|     printLabels, | ||||
|     printPartLabels, | ||||
|     printStockItemLabels, | ||||
|     printStockLocationLabels, | ||||
| */ | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Perform the "print" action. | ||||
|  */ | ||||
| function printLabels(url, plugin=null) { | ||||
|  | ||||
|     if (plugin) { | ||||
|         // If a plugin is provided, do not redirect the browser. | ||||
|         // Instead, perform an API request and display a message | ||||
|  | ||||
|         url = url + `plugin=${plugin}`; | ||||
|  | ||||
|         inventreeGet(url, {}, { | ||||
|             success: function(response) { | ||||
|                 showMessage( | ||||
|                     '{% trans "Labels sent to printer" %}', | ||||
|                     { | ||||
|                         style: 'success', | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         }); | ||||
|     } else { | ||||
|         window.location.href = url; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| function printStockItemLabels(items) { | ||||
|     /** | ||||
|      * Print stock item labels for the given stock items | ||||
| @@ -67,11 +97,7 @@ function printStockItemLabels(items) { | ||||
|                                 href += `items[]=${item}&`; | ||||
|                             }); | ||||
|  | ||||
|                             if (data.plugin) { | ||||
|                                 href += `plugin=${data.plugin}`; | ||||
|                             } | ||||
|  | ||||
|                             window.location.href = href; | ||||
|                             printLabels(href, data.plugin); | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
| @@ -80,6 +106,7 @@ function printStockItemLabels(items) { | ||||
|     ); | ||||
| } | ||||
|  | ||||
|  | ||||
| function printStockLocationLabels(locations) { | ||||
|  | ||||
|     if (locations.length == 0) { | ||||
| @@ -124,11 +151,7 @@ function printStockLocationLabels(locations) { | ||||
|                                 href += `locations[]=${location}&`; | ||||
|                             }); | ||||
|  | ||||
|                             if (data.plugin) { | ||||
|                                 href += `plugin=${data.plugin}`; | ||||
|                             } | ||||
|  | ||||
|                             window.location.href = href; | ||||
|                             printLabels(href, data.plugin); | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
| @@ -186,11 +209,7 @@ function printPartLabels(parts) { | ||||
|                                 url += `parts[]=${part}&`; | ||||
|                             }); | ||||
|  | ||||
|                             if (data.plugin) { | ||||
|                                 href += `plugin=${data.plugin}`; | ||||
|                             } | ||||
|  | ||||
|                             window.location.href = url; | ||||
|                             printLabels(href, data.plugin); | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
| @@ -234,7 +253,6 @@ function selectLabel(labels, items, options={}) { | ||||
|  | ||||
|     var plugin_selection = ''; | ||||
|      | ||||
|      | ||||
|     if (plugins.length > 0) { | ||||
|         plugin_selection =` | ||||
|         <div class='form-group'> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user