[MIG] printer_zpl2: Migration to 13.0

This commit is contained in:
Rod Schouteden
2019-09-30 15:35:28 +02:00
committed by mreficent
parent fe3208cd64
commit 4291cca6ca
23 changed files with 2074 additions and 1345 deletions

View File

@@ -1,42 +1,42 @@
# Copyright (C) 2018 Florent de Labarre (<https://github.com/fmdl>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import re
import base64
import binascii
import io
import logging
import re
from PIL import Image, ImageOps
from odoo import fields, models, _
from odoo import _ as translate, fields, models
_logger = logging.getLogger(__name__)
try:
import zpl2
except ImportError:
_logger.debug('Cannot `import zpl2`.')
_logger.debug("Cannot `import zpl2`.")
def _compute_arg(data, arg):
vals = {}
for i, d in enumerate(data.split(',')):
for i, d in enumerate(data.split(",")):
vals[arg[i]] = d
return vals
def _field_origin(data):
if data[:2] == 'FO':
if data[:2] == "FO":
position = data[2:]
vals = _compute_arg(position, ['origin_x', 'origin_y'])
vals = _compute_arg(position, ["origin_x", "origin_y"])
return vals
return {}
def _font_format(data):
if data[:1] == 'A':
data = data.split(',')
if data[:1] == "A":
data = data.split(",")
vals = {}
if len(data[0]) > 1:
vals[zpl2.ARG_FONT] = data[0][1]
@@ -52,15 +52,10 @@ def _font_format(data):
def _default_font_format(data):
if data[:2] == 'CF':
args = [
zpl2.ARG_FONT,
zpl2.ARG_HEIGHT,
zpl2.ARG_WIDTH,
]
if data[:2] == "CF":
args = [zpl2.ARG_FONT, zpl2.ARG_HEIGHT, zpl2.ARG_WIDTH]
vals = _compute_arg(data[2:], args)
if vals.get(zpl2.ARG_HEIGHT, False) \
and not vals.get(zpl2.ARG_WIDTH, False):
if vals.get(zpl2.ARG_HEIGHT, False) and not vals.get(zpl2.ARG_WIDTH, False):
vals.update({zpl2.ARG_WIDTH: vals.get(zpl2.ARG_HEIGHT)})
else:
vals.update({zpl2.ARG_HEIGHT: 10, zpl2.ARG_HEIGHT: 10})
@@ -69,7 +64,7 @@ def _default_font_format(data):
def _field_block(data):
if data[:2] == 'FB':
if data[:2] == "FB":
vals = {zpl2.ARG_IN_BLOCK: True}
args = [
zpl2.ARG_BLOCK_WIDTH,
@@ -84,8 +79,8 @@ def _field_block(data):
def _code11(data):
if data[:2] == 'B1':
vals = {'component_type': zpl2.BARCODE_CODE_11}
if data[:2] == "B1":
vals = {"component_type": zpl2.BARCODE_CODE_11}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_CHECK_DIGITS,
@@ -99,8 +94,8 @@ def _code11(data):
def _interleaved2of5(data):
if data[:2] == 'B2':
vals = {'component_type': zpl2.BARCODE_INTERLEAVED_2_OF_5}
if data[:2] == "B2":
vals = {"component_type": zpl2.BARCODE_INTERLEAVED_2_OF_5}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -114,8 +109,8 @@ def _interleaved2of5(data):
def _code39(data):
if data[:2] == 'B3':
vals = {'component_type': zpl2.BARCODE_CODE_39}
if data[:2] == "B3":
vals = {"component_type": zpl2.BARCODE_CODE_39}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_CHECK_DIGITS,
@@ -129,8 +124,8 @@ def _code39(data):
def _code49(data):
if data[:2] == 'B4':
vals = {'component_type': zpl2.BARCODE_CODE_49}
if data[:2] == "B4":
vals = {"component_type": zpl2.BARCODE_CODE_49}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -143,8 +138,8 @@ def _code49(data):
def _pdf417(data):
if data[:2] == 'B7':
vals = {'component_type': zpl2.BARCODE_PDF417}
if data[:2] == "B7":
vals = {"component_type": zpl2.BARCODE_PDF417}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -159,8 +154,8 @@ def _pdf417(data):
def _ean8(data):
if data[:2] == 'B8':
vals = {'component_type': zpl2.BARCODE_EAN_8}
if data[:2] == "B8":
vals = {"component_type": zpl2.BARCODE_EAN_8}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -173,8 +168,8 @@ def _ean8(data):
def _upce(data):
if data[:2] == 'B9':
vals = {'component_type': zpl2.BARCODE_UPC_E}
if data[:2] == "B9":
vals = {"component_type": zpl2.BARCODE_UPC_E}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -188,8 +183,8 @@ def _upce(data):
def _code128(data):
if data[:2] == 'BC':
vals = {'component_type': zpl2.BARCODE_CODE_128}
if data[:2] == "BC":
vals = {"component_type": zpl2.BARCODE_CODE_128}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -204,8 +199,8 @@ def _code128(data):
def _ean13(data):
if data[:2] == 'BE':
vals = {'component_type': zpl2.BARCODE_EAN_13}
if data[:2] == "BE":
vals = {"component_type": zpl2.BARCODE_EAN_13}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_HEIGHT,
@@ -218,8 +213,8 @@ def _ean13(data):
def _qrcode(data):
if data[:2] == 'BQ':
vals = {'component_type': zpl2.BARCODE_QR_CODE}
if data[:2] == "BQ":
vals = {"component_type": zpl2.BARCODE_QR_CODE}
args = [
zpl2.ARG_ORIENTATION,
zpl2.ARG_MODEL,
@@ -233,25 +228,21 @@ def _qrcode(data):
def _default_barcode_field(data):
if data[:2] == 'BY':
args = [
zpl2.ARG_MODULE_WIDTH,
zpl2.ARG_BAR_WIDTH_RATIO,
zpl2.ARG_HEIGHT,
]
if data[:2] == "BY":
args = [zpl2.ARG_MODULE_WIDTH, zpl2.ARG_BAR_WIDTH_RATIO, zpl2.ARG_HEIGHT]
return _compute_arg(data[2:], args)
return {}
def _field_reverse_print(data):
if data[:2] == 'FR':
if data[:2] == "FR":
return {zpl2.ARG_REVERSE_PRINT: True}
return {}
def _graphic_box(data):
if data[:2] == 'GB':
vals = {'component_type': 'rectangle'}
if data[:2] == "GB":
vals = {"component_type": "rectangle"}
args = [
zpl2.ARG_WIDTH,
zpl2.ARG_HEIGHT,
@@ -265,48 +256,43 @@ def _graphic_box(data):
def _graphic_circle(data):
if data[:2] == 'GC':
vals = {'component_type': 'circle'}
args = [
zpl2.ARG_WIDTH,
zpl2.ARG_THICKNESS,
zpl2.ARG_COLOR,
]
if data[:2] == "GC":
vals = {"component_type": "circle"}
args = [zpl2.ARG_WIDTH, zpl2.ARG_THICKNESS, zpl2.ARG_COLOR]
vals.update(_compute_arg(data[2:], args))
return vals
return {}
def _graphic_field(data):
if data[:3] == 'GFA':
if data[:3] == "GFA":
vals = {}
args = [
'compression',
'total_bytes',
'total_bytes',
'bytes_per_row',
'ascii_data',
"compression",
"total_bytes",
"total_bytes",
"bytes_per_row",
"ascii_data",
]
vals.update(_compute_arg(data[3:], args))
# Image
rawData = re.sub('[^A-F0-9]+', '', vals['ascii_data'])
rawData = re.sub("[^A-F0-9]+", "", vals["ascii_data"])
rawData = binascii.unhexlify(rawData)
width = int(float(vals['bytes_per_row']) * 8)
height = int(float(vals['total_bytes']) / width) * 8
width = int(float(vals["bytes_per_row"]) * 8)
height = int(float(vals["total_bytes"]) / width) * 8
img = Image.frombytes(
'1', (width, height), rawData, 'raw').convert('L')
img = Image.frombytes("1", (width, height), rawData, "raw").convert("L")
img = ImageOps.invert(img)
imgByteArr = io.BytesIO()
img.save(imgByteArr, format='PNG')
img.save(imgByteArr, format="PNG")
image = base64.b64encode(imgByteArr.getvalue())
return {
'component_type': 'graphic',
'graphic_image': image,
"component_type": "graphic",
"graphic_image": image,
zpl2.ARG_WIDTH: width,
zpl2.ARG_HEIGHT: height,
}
@@ -314,29 +300,29 @@ def _graphic_field(data):
def _get_data(data):
if data[:2] == 'FD':
return {'data': '"%s"' % data[2:]}
if data[:2] == "FD":
return {"data": '"%s"' % data[2:]}
return {}
SUPPORTED_CODE = {
'FO': {'method': _field_origin},
'FD': {'method': _get_data},
'A': {'method': _font_format},
'FB': {'method': _field_block},
'B1': {'method': _code11},
'B2': {'method': _interleaved2of5},
'B3': {'method': _code39},
'B4': {'method': _code49},
'B7': {'method': _pdf417},
'B8': {'method': _ean8},
'B9': {'method': _upce},
'BC': {'method': _code128},
'BE': {'method': _ean13},
'BQ': {'method': _qrcode},
'BY': {
'method': _default_barcode_field,
'default': [
"FO": {"method": _field_origin},
"FD": {"method": _get_data},
"A": {"method": _font_format},
"FB": {"method": _field_block},
"B1": {"method": _code11},
"B2": {"method": _interleaved2of5},
"B3": {"method": _code39},
"B4": {"method": _code49},
"B7": {"method": _pdf417},
"B8": {"method": _ean8},
"B9": {"method": _upce},
"BC": {"method": _code128},
"BE": {"method": _ean13},
"BQ": {"method": _qrcode},
"BY": {
"method": _default_barcode_field,
"default": [
zpl2.BARCODE_CODE_11,
zpl2.BARCODE_INTERLEAVED_2_OF_5,
zpl2.BARCODE_CODE_39,
@@ -349,93 +335,93 @@ SUPPORTED_CODE = {
zpl2.BARCODE_QR_CODE,
],
},
'CF': {'method': _default_font_format, 'default': ['text']},
'FR': {'method': _field_reverse_print},
'GB': {'method': _graphic_box},
'GC': {'method': _graphic_circle},
'GFA': {'method': _graphic_field},
"CF": {"method": _default_font_format, "default": ["text"]},
"FR": {"method": _field_reverse_print},
"GB": {"method": _graphic_box},
"GC": {"method": _graphic_circle},
"GFA": {"method": _graphic_field},
}
class WizardImportZPl2(models.TransientModel):
_name = 'wizard.import.zpl2'
_description = 'Import ZPL2'
_name = "wizard.import.zpl2"
_description = "Import ZPL2"
label_id = fields.Many2one(
comodel_name='printing.label.zpl2', string='Label',
required=True, readonly=True,)
data = fields.Text(
required=True, help='Printer used to print the labels.')
comodel_name="printing.label.zpl2", string="Label", required=True, readonly=True
)
data = fields.Text(required=True, help="Printer used to print the labels.")
delete_component = fields.Boolean(
string='Delete existing components', default=False)
string="Delete existing components", default=False
)
def _start_sequence(self):
sequences = self.mapped('label_id.component_ids.sequence')
sequences = self.mapped("label_id.component_ids.sequence")
if sequences:
return max(sequences) + 1
return 0
def import_zpl2(self):
self.ensure_one()
Zpl2Component = self.env['printing.label.zpl2.component']
Zpl2Component = self.env["printing.label.zpl2.component"]
if self.delete_component:
self.mapped('label_id.component_ids').unlink()
self.mapped("label_id.component_ids").unlink()
sequence = self._start_sequence()
default = {}
for i, line in enumerate(self.data.split('\n')):
for i, line in enumerate(self.data.split("\n")):
vals = {}
args = line.split('^')
args = line.split("^")
for arg in args:
for key, code in SUPPORTED_CODE.items():
component_arg = code['method'](arg)
for _, code in SUPPORTED_CODE.items():
component_arg = code["method"](arg)
if component_arg:
if code.get('default', False):
for deft in code.get('default'):
if code.get("default", False):
for deft in code.get("default"):
default.update({deft: component_arg})
else:
vals.update(component_arg)
break
if vals:
if 'component_type' not in vals.keys():
vals.update({'component_type': 'text'})
if "component_type" not in vals.keys():
vals.update({"component_type": "text"})
if vals['component_type'] in default.keys():
vals.update(default[vals['component_type']])
if vals["component_type"] in default.keys():
vals.update(default[vals["component_type"]])
vals = self._update_vals(vals)
seq = sequence + i * 10
vals.update({
'name': _('Import %s') % seq,
'sequence': seq,
'label_id': self.label_id.id,
})
vals.update(
{
"name": translate("Import %s") % seq,
"sequence": seq,
"label_id": self.label_id.id,
}
)
Zpl2Component.create(vals)
def _update_vals(self, vals):
if 'orientation' in vals.keys() and vals['orientation'] == '':
vals['orientation'] = 'N'
if "orientation" in vals.keys() and vals["orientation"] == "":
vals["orientation"] = "N"
# Field
Zpl2Component = self.env['printing.label.zpl2.component']
Zpl2Component = self.env["printing.label.zpl2.component"]
model_fields = Zpl2Component.fields_get()
component = {}
for field, value in vals.items():
if field in model_fields.keys():
field_type = model_fields[field].get('type', False)
if field_type == 'boolean':
field_type = model_fields[field].get("type", False)
if field_type == "boolean":
if not value or value == zpl2.BOOL_NO:
value = False
else:
value = True
if field_type in ('integer', 'float'):
if field_type in ("integer", "float"):
value = float(value)
if field == 'model':
value = int(float(value))
component.update({field: value})
return component