Allow offloading of label printing to the configured plugin

This commit is contained in:
Oliver 2022-03-24 14:57:01 +11:00
parent f1f07a1977
commit 6c25a5805d
4 changed files with 111 additions and 28 deletions

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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'>