mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Allow offloading of label printing to the configured plugin
This commit is contained in:
parent
f1f07a1977
commit
6c25a5805d
@ -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'>
|
||||
|
Loading…
Reference in New Issue
Block a user