3 Commits

Author SHA1 Message Date
Christian Anetzberger
baceb8fb66 Changed default label printer 2023-08-07 10:40:12 +02:00
Christian Anetzberger
86ec8cf99d Fixes 2022-11-17 07:34:21 +01:00
Christian Anetzberger
415f0f5d84 Updated for version-14 2022-11-10 14:46:27 +01:00
16 changed files with 149 additions and 88 deletions

4
.gitignore vendored
View File

@@ -7,7 +7,8 @@ latest_updates.json
.wnf-lang-status .wnf-lang-status
*.egg-info *.egg-info
dist/ dist/
erpnext/docs/current label_printing/public/dist
label_printing/docs/current
*.swp *.swp
*.swo *.swo
__pycache__ __pycache__
@@ -15,3 +16,4 @@ __pycache__
.idea/ .idea/
.vscode/ .vscode/
node_modules/ node_modules/
.backportrc.json

View File

@@ -5,20 +5,15 @@ import os
import json import json
from frappe import _ from frappe import _
from PyPDF2 import PdfWriter
from frappe.utils.pdf import get_pdf, cleanup
from frappe.core.doctype.access_log.access_log import make_access_log
from PyPDF2 import PdfFileWriter
from frappe.utils.jinja import render_template
@frappe.whitelist() @frappe.whitelist()
def print_label(values): def print_label(values):
values = json.loads(values) values = json.loads(values)
printer_setting = frappe.db.get_single_value(
'Label Printer Settings', 'label_printer'), print_format = frappe.get_value(
print_format = frappe.db.get_single_value( "Label Printer", values["printer_select"], "label_print_format")
'Label Printer Settings', 'label_print_format')
for label in values["labels"]: for label in values["labels"]:
doc = frappe.new_doc('Label') doc = frappe.new_doc('Label')
@@ -40,19 +35,20 @@ def print_label(values):
newdoc = doc.insert() newdoc = doc.insert()
print_label_by_server( print_label_by_server(
"Label", newdoc.name, label["label_qty"], printer_setting[0], print_format, doc=None, no_letterhead=0, file_path=None) "Label", newdoc.name, label["label_qty"], values["printer_select"], print_format, doc=None, no_letterhead=0, file_path=None)
return 200 return 200
def print_label_by_server(doctype, name, qty, printer_setting, print_format=None, doc=None, no_letterhead=0, file_path=None): def print_label_by_server(doctype, name, qty, printer_setting, print_format=None, doc=None, no_letterhead=0, file_path=None):
pdf_options = { pdf_options = {
'page-width': '{0}mm'.format(frappe.db.get_single_value('Label Printer Settings', 'label_width')), 'page-width': '{0}mm'.format(frappe.get_value("Label Printer", printer_setting, "label_width")),
'page-height': '{0}mm'.format(frappe.db.get_single_value('Label Printer Settings', 'label_height')), 'page-height': '{0}mm'.format(frappe.get_value("Label Printer", printer_setting, "label_height")),
} }
print_settings = frappe.get_doc( print_settings = frappe.get_doc(
"Network Printer Settings", printer_setting) "Network Printer Settings", printer_setting)
try: try:
import cups import cups
except ImportError: except ImportError:
@@ -62,27 +58,39 @@ def print_label_by_server(doctype, name, qty, printer_setting, print_format=None
cups.setServer(print_settings.server_ip) cups.setServer(print_settings.server_ip)
cups.setPort(print_settings.port) cups.setPort(print_settings.port)
conn = cups.Connection() conn = cups.Connection()
output = PdfFileWriter() output = PdfWriter()
output = frappe.get_print(doctype, name, print_format, doc=doc, output = frappe.get_print(doctype, name, print_format, doc=doc,
no_letterhead=no_letterhead, as_pdf=True, output=output, pdf_options=pdf_options) no_letterhead=no_letterhead, as_pdf=True, output=output, pdf_options=pdf_options)
if not file_path: if not file_path:
file_path = os.path.join( file_path = os.path.join(
"/", "tmp", "frappe-pdf-{0}.pdf".format(frappe.generate_hash())) "/", "tmp", f"frappe-pdf-{frappe.generate_hash()}.pdf")
output.write(open(file_path, "wb")) output.write(open(file_path, "wb"))
for _ in range(qty): for _ in range(qty):
conn.printFile(print_settings.printer_name, file_path, name, {}) conn.printFile(print_settings.printer_name,
except IOError as e: file_path, name, {})
if ("ContentNotFoundError" in e.message
except OSError as e:
if (
"ContentNotFoundError" in e.message
or "ContentOperationNotPermittedError" in e.message or "ContentOperationNotPermittedError" in e.message
or "UnknownContentError" in e.message or "UnknownContentError" in e.message
or "RemoteHostClosedError" in e.message): or "RemoteHostClosedError" in e.message
):
frappe.throw(_("PDF generation failed")) frappe.throw(_("PDF generation failed"))
except cups.IPPError: except cups.IPPError:
frappe.throw(_("Printing failed")) frappe.throw(_("Printing failed"))
finally:
return
@frappe.whitelist() @frappe.whitelist()
def get_associated_stockentry(workorder): def get_associated_stockentry(workorder):
return frappe.get_last_doc('Stock Entry', filters={"work_order": workorder}) return frappe.get_last_doc('Stock Entry', filters={"work_order": workorder})
# @frappe.whitelist()
# def get_label_printers():
# label_printing_settings = frappe.get_doc('Label Printing Settings')
# label_printer_names = []
#
# for x in label_printing_settings.label_printers:
# label_printer_names.append(x.label_printer)
#
# return(label_printer_names)

View File

@@ -1,4 +1,4 @@
from . import __version__ as app_version from frappe import _
app_name = "label_printing" app_name = "label_printing"
app_title = "Label Printing" app_title = "Label Printing"
@@ -8,13 +8,14 @@ app_icon = "octicon octicon-file-directory"
app_color = "grey" app_color = "grey"
app_email = "admin@canetzberger.design" app_email = "admin@canetzberger.design"
app_license = "MIT" app_license = "MIT"
required_apps = ["erpnext"]
# Includes in <head> # Includes in <head>
# ------------------ # ------------------
# include js, css files in header of desk.html # include js, css files in header of desk.html
# app_include_css = "/assets/label_printing/css/label_printing.css" # app_include_css = "/assets/label_printing/css/label_printing.css"
app_include_js = "/assets/js/label_printing.min.js" app_include_js = "label_printing.bundle.js"
# include js, css files in header of web template # include js, css files in header of web template
# web_include_css = "/assets/label_printing/css/label_printing.css" # web_include_css = "/assets/label_printing/css/label_printing.css"
@@ -148,30 +149,6 @@ app_include_js = "/assets/js/label_printing.min.js"
# auto_cancel_exempted_doctypes = ["Auto Repeat"] # auto_cancel_exempted_doctypes = ["Auto Repeat"]
# User Data Protection
# --------------------
user_data_fields = [
{
"doctype": "{doctype_1}",
"filter_by": "{filter_by}",
"redact_fields": ["{field_1}", "{field_2}"],
"partial": 1,
},
{
"doctype": "{doctype_2}",
"filter_by": "{filter_by}",
"partial": 1,
},
{
"doctype": "{doctype_3}",
"strict": False,
},
{
"doctype": "{doctype_4}"
}
]
# Authentication and authorization # Authentication and authorization
# -------------------------------- # --------------------------------
@@ -179,9 +156,9 @@ user_data_fields = [
# "label_printing.auth.validate" # "label_printing.auth.validate"
# ] # ]
jenv = { jinja = {
"methods": [ "methods": [
"generateBarcode:label_printing.utils.barcode.generateBarcode", "label_printing.utils.barcode.generateBarcode",
"get_code128_glyphs:label_printing.utils.barcode.generateBarcodeGlyphs" "label_printing.utils.barcode.generateBarcodeGlyphs"
] ]
} }

View File

@@ -1,7 +1,7 @@
{ {
"actions": [], "actions": [],
"allow_rename": 1, "autoname": "field:label_printer",
"creation": "2022-02-09 11:54:25.055075", "creation": "2022-11-09 10:36:02.195555",
"doctype": "DocType", "doctype": "DocType",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
@@ -15,48 +15,47 @@
{ {
"fieldname": "label_printer", "fieldname": "label_printer",
"fieldtype": "Link", "fieldtype": "Link",
"in_list_view": 1,
"label": "Label Printer", "label": "Label Printer",
"options": "Network Printer Settings" "options": "Network Printer Settings",
"reqd": 1,
"unique": 1
}, },
{ {
"description": "in mm",
"fieldname": "label_height", "fieldname": "label_height",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Label Height" "in_list_view": 1,
"label": "Label Height",
"reqd": 1
}, },
{ {
"description": "in mm",
"fieldname": "label_width", "fieldname": "label_width",
"fieldtype": "Int", "fieldtype": "Int",
"label": "Label Width" "in_list_view": 1,
"label": "Label Width",
"reqd": 1
}, },
{ {
"fieldname": "label_print_format", "fieldname": "label_print_format",
"fieldtype": "Link", "fieldtype": "Link",
"in_list_view": 1,
"label": "Label Print Format", "label": "Label Print Format",
"options": "Print Format" "options": "Print Format",
"reqd": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"issingle": 1, "istable": 1,
"links": [], "links": [],
"modified": "2022-04-03 14:50:49.776678", "modified": "2022-11-09 12:27:38.327808",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Label Printing", "module": "Label Printing",
"name": "Label Printer Settings", "name": "Label Printer",
"name_case": "Title Case",
"naming_rule": "By fieldname",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [],
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC" "sort_order": "DESC",
"states": []
} }

View File

@@ -4,5 +4,5 @@
# import frappe # import frappe
from frappe.model.document import Document from frappe.model.document import Document
class LabelPrinterSettings(Document): class LabelPrinter(Document):
pass pass

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2022, CAnetzberger Design and contributors // Copyright (c) 2022, CAnetzberger Design and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Label Printer Settings', { frappe.ui.form.on('Label Printing Settings', {
// refresh: function(frm) { // refresh: function(frm) {
// } // }

View File

@@ -0,0 +1,50 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2022-02-09 11:54:25.055075",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"enable_label_printing",
"label_printers"
],
"fields": [
{
"default": "0",
"fieldname": "enable_label_printing",
"fieldtype": "Check",
"label": "Enable Label Printing"
},
{
"depends_on": "enable_label_printing",
"fieldname": "label_printers",
"fieldtype": "Table",
"label": "Label Printers",
"options": "Label Printer"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2022-11-09 10:42:37.066676",
"modified_by": "Administrator",
"module": "Label Printing",
"name": "Label Printing Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2022, CAnetzberger Design and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LabelPrintingSettings(Document):
pass

View File

@@ -4,5 +4,5 @@
# import frappe # import frappe
import unittest import unittest
class TestLabelPrinterSettings(unittest.TestCase): class TestLabelPrintingSettings(unittest.TestCase):
pass pass

View File

@@ -2,22 +2,28 @@
"absolute_value": 0, "absolute_value": 0,
"align_labels_right": 0, "align_labels_right": 0,
"creation": "2022-03-01 09:42:22.551134", "creation": "2022-03-01 09:42:22.551134",
"css": ".print-format {\n\tmargin: 0;\n\tpadding: 0;\n margin-left: 1mm;\n margin-right: 1mm;\n margin-top: 1mm;\n margin-bottom: 1mm;\n\twidth: 100mm;\n\tmax-height: 39mm;\n}\n\n.page-size {\n\twidth: 104mm;\n\theight: 40mm;\n}\n\n.label-wrapper {\n\twidth: 100mm;\n\ttext-align: center;\n\tdisplay: -webkit-box;\n\t/* wkhtmltopdf uses this one */\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n\t-webkit-box-pack: center;\n\t/* wkhtmltopdf uses this one */\n\t-webkit-justify-content: center;\n\tjustify-content: center;\n\tfont-size: 15px;\n}\n\n.left-wrapper {\n\twidth: 80mm;\n}\n\n.left-wrapper div {\n\twhite-space: nowrap;\n\tfont-size: 12px;\n}\n\n.right-wrapper {\n\twidth: 20mm;\n\ttext-align: right;\n}\n\n.label-wrapper h4 {\n\tmargin: 0;\n\tword-break: break-all;\n\tfont-size: 23px;\n}\n\n.label-wrapper h4 small {\n\tcolor: black;\n}\n\n", "css": ".print-format {\n\tmargin: 0;\n\tpadding: 0;\n margin-left: 1mm;\n margin-right: 1mm;\n margin-top: 1mm;\n margin-bottom: 1mm;\n\twidth: 100mm;\n\tmax-height: 39mm;\n}\n\n.page-size {\n\twidth: 104mm;\n\theight: 40mm;\n}\n\n.label-wrapper {\n\twidth: 100mm;\n\ttext-align: center;\n\tdisplay: -webkit-box;\n\t/* wkhtmltopdf uses this one */\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n\t-webkit-box-pack: center;\n\t/* wkhtmltopdf uses this one */\n\t-webkit-justify-content: center;\n\tjustify-content: center;\n\tfont-size: 15px;\n}\n\n.left-wrapper {\n\twidth: 80mm;\n}\n\n.left-wrapper div {\n\twhite-space: nowrap;\n\tfont-size: 12px;\n}\n\n.right-wrapper {\n\twidth: 20mm;\n\ttext-align: right;\n}\n\n.label-wrapper h4 {\n\tmargin: 0;\n\twhite-space: nowrap;\n\tfont-size: 23px;\n}\n\n.label-wrapper h4 small {\n\tcolor: black;\n}\n\n",
"custom_format": 1, "custom_format": 1,
"disabled": 0, "disabled": 0,
"doc_type": "Label", "doc_type": "Label",
"docstatus": 0, "docstatus": 0,
"doctype": "Print Format", "doctype": "Print Format",
"font": "Default", "font": "Default",
"font_size": 0,
"html": "{% if doc.customer %}\n<div class=\"label-wrapper\">\n\n <div class=\"left-wrapper\">\n {% if doc.item_code %}\n <h4>\n <strong>{{doc.item_code}}</strong>\n </h4>\n {% endif %}\n\n {% if doc.item_name%}\n <h4>\n <small> {{doc.item_name}}</small>\n </h4>\n {% endif %}\n\n\n {% if doc.customer %}\n <div>{{doc.customer}}</div>\n {% endif %}\n\n {% if doc.delivery_date %}\n <div>\n <strong> {{_(\"Delivery Date\")}} </strong> {{frappe.utils.formatdate(doc.delivery_date, \"dd.MM.YYYY\")}}\n </div>\n {% endif %}\n\n {% if doc.batch %}\n <div>\n <strong>{{_(\"Batch\")}} </strong> {{doc.batch}}\n </div>\n {% endif %}\n\n {% if doc.qty %}\n <div>\n <strong>{{_(\"Qty\")}} </strong> {{ doc.qty }}\n </div>\n {% endif %}\n\n {% if doc.information%}\n <div>\n {{doc.information}}\n </div>\n {% endif %}\n\n\n </div>\n \n <div class=\"right-wrapper\">\n <img src=\"/files/hp_logo_black.jpg\" style=\"width: 30px;\">\n </div>\n</div>\n\n{% else %}\n\n<div class=\"label-wrapper\">\n\n <div class=\"left-wrapper\">\n {% if doc.item_code %}\n <h4 style=\"font-size: 30px; white-space: normal; padding: 2mm;\">\n <strong>{{doc.item_code}}</strong>\n </h4>\n {% endif %}\n\n\n {% if doc.batch %}\n <div style=\"font-size: 15px;\">\n <strong>{{_(\"Batch\")}} </strong> {{doc.batch}}\n </div>\n {% endif %}\n\n\n {% if doc.information%}\n <div>\n {{doc.information}}\n </div>\n {% endif %}\n\n\n </div>\n</div>\n\n{% endif %}", "html": "{% if doc.customer %}\n<div class=\"label-wrapper\">\n\n <div class=\"left-wrapper\">\n {% if doc.item_code %}\n <h4>\n <strong>{{doc.item_code}}</strong>\n </h4>\n {% endif %}\n\n {% if doc.item_name%}\n <h4>\n <small> {{doc.item_name}}</small>\n </h4>\n {% endif %}\n\n\n {% if doc.customer %}\n <div>{{doc.customer}}</div>\n {% endif %}\n\n {% if doc.delivery_date %}\n <div>\n <strong> {{_(\"Delivery Date\")}} </strong> {{frappe.utils.formatdate(doc.delivery_date, \"dd.MM.YYYY\")}}\n </div>\n {% endif %}\n\n {% if doc.batch %}\n <div>\n <strong>{{_(\"Batch\")}} </strong> {{doc.batch}}\n </div>\n {% endif %}\n\n {% if doc.qty %}\n <div>\n <strong>{{_(\"Qty\")}} </strong> {{ doc.qty }}\n </div>\n {% endif %}\n\n {% if doc.information%}\n <div>\n {{doc.information}}\n </div>\n {% endif %}\n\n\n </div>\n \n <div class=\"right-wrapper\">\n <img src=\"/files/hp_logo_black.jpg\" style=\"width: 30px;\">\n </div>\n</div>\n\n{% else %}\n\n<div class=\"label-wrapper\">\n\n <div class=\"left-wrapper\">\n {% if doc.item_code %}\n <h4 style=\"font-size: 30px; white-space: normal; padding: 2mm;\">\n <strong>{{doc.item_code}}</strong>\n </h4>\n {% endif %}\n\n\n {% if doc.batch %}\n <div style=\"font-size: 15px;\">\n <strong>{{_(\"Batch\")}} </strong> {{doc.batch}}\n </div>\n {% endif %}\n\n\n {% if doc.information%}\n <div>\n {{doc.information}}\n </div>\n {% endif %}\n\n\n </div>\n</div>\n\n{% endif %}",
"idx": 0, "idx": 0,
"line_breaks": 0, "line_breaks": 0,
"modified": "2022-04-03 14:52:16.543089", "margin_bottom": 0.0,
"margin_left": 0.0,
"margin_right": 0.0,
"margin_top": 0.0,
"modified": "2022-11-10 12:13:59.766486",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Label Printing", "module": "Label Printing",
"name": "Label", "name": "Label",
"owner": "christian@prothmann.com", "owner": "christian@prothmann.com",
"print_format_builder": 1, "print_format_builder": 1,
"print_format_builder_beta": 0,
"print_format_type": "Jinja", "print_format_type": "Jinja",
"raw_printing": 0, "raw_printing": 0,
"show_section_headings": 0, "show_section_headings": 0,

View File

@@ -1,5 +0,0 @@
{
"js/label_printing.min.js": [
"public/js/label_printing_desk.js"
]
}

View File

@@ -0,0 +1 @@
import './label_printing_desk';

View File

@@ -28,6 +28,8 @@ function setupLabelsDialog(page) {
} }
} }
let label_printer_names
let d = new frappe.ui.Dialog({ let d = new frappe.ui.Dialog({
title: __("Print Labels"), title: __("Print Labels"),
fields: [{ fields: [{
@@ -87,6 +89,17 @@ function setupLabelsDialog(page) {
fieldname: 'batch', fieldname: 'batch',
fieldtype: 'Data' fieldtype: 'Data'
}, },
{
fieldtype: 'Section Break',
label: __('Printer')
},
{
label: __("Printer Select"),
options: ['Labeldrucker Werk 1 (Ind. 6)', 'Labeldrucker Werk 2 (Bre. 19)'],
fieldname: 'printer_select',
fieldtype: 'Select',
default: 'Labeldrucker Werk 2 (Bre. 19)'
},
{ {
fieldtype: 'Section Break', fieldtype: 'Section Break',
label: __('Labels') label: __('Labels')
@@ -134,7 +147,9 @@ function setupLabelsDialog(page) {
} }
}, },
}); });
d.hide(); d.hide();
} }
}); });
handleDataFetch(); handleDataFetch();

View File

@@ -1 +1 @@
/Volumes/development/frappe/frappe-bench/apps/label_printing/node_modules /home/frappe/frappe-bench/apps/label_printing/node_modules