~opencrea/+junk/aprobio

« back to all changes in this revision

Viewing changes to printer_zpl2/models/printing_label_zpl2.py

  • Committer: joannes
  • Date: 2017-05-17 09:40:42 UTC
  • Revision ID: joannes@debian-20170517094042-47q3j6on72w2h1il
community module

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
# Copyright (C) 2016 SYLEAM (<http://www.syleam.fr>)
 
3
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 
4
 
 
5
import time
 
6
import datetime
 
7
import logging
 
8
from odoo import api, exceptions, fields, models
 
9
from odoo.tools.translate import _
 
10
from odoo.tools.safe_eval import safe_eval
 
11
 
 
12
_logger = logging.getLogger(__name__)
 
13
 
 
14
try:
 
15
    import zpl2
 
16
except ImportError:
 
17
    _logger.debug('Cannot `import zpl2`.')
 
18
 
 
19
 
 
20
class PrintingLabelZpl2(models.Model):
 
21
    _name = 'printing.label.zpl2'
 
22
    _description = 'ZPL II Label'
 
23
 
 
24
    name = fields.Char(required=True, help='Label Name.')
 
25
    description = fields.Char(help='Long description for this label.')
 
26
    model_id = fields.Many2one(
 
27
        comodel_name='ir.model', string='Model', required=True,
 
28
        help='Model used to print this label.')
 
29
    origin_x = fields.Integer(
 
30
        required=True, default=10,
 
31
        help='Origin point of the contents in the label, X coordinate.')
 
32
    origin_y = fields.Integer(
 
33
        required=True, default=10,
 
34
        help='Origin point of the contents in the label, Y coordinate.')
 
35
    width = fields.Integer(
 
36
        required=True, default=480,
 
37
        help='Width of the label, will be set on the printer before printing.')
 
38
    component_ids = fields.One2many(
 
39
        comodel_name='printing.label.zpl2.component', inverse_name='label_id',
 
40
        string='Label Components',
 
41
        help='Components which will be printed on the label.')
 
42
 
 
43
    @api.multi
 
44
    def _generate_zpl2_components_data(
 
45
            self, label_data, record, page_number=1, page_count=1,
 
46
            label_offset_x=0, label_offset_y=0, **extra):
 
47
        self.ensure_one()
 
48
 
 
49
        # Add all elements to print in a list of tuples :
 
50
        #   [(component, data, offset_x, offset_y)]
 
51
        to_print = []
 
52
        for component in self.component_ids:
 
53
            eval_args = extra
 
54
            eval_args.update({
 
55
                'object': record,
 
56
                'page_number': str(page_number + 1),
 
57
                'page_count': str(page_count),
 
58
                'time': time,
 
59
                'datetime': datetime,
 
60
            })
 
61
            data = safe_eval(component.data, eval_args) or ''
 
62
 
 
63
            # Generate a list of elements if the component is repeatable
 
64
            for idx in range(
 
65
                    component.repeat_offset,
 
66
                    component.repeat_offset + component.repeat_count):
 
67
                printed_data = data
 
68
                # Pick the right value if data is a collection
 
69
                if isinstance(data, (list, tuple, set, models.BaseModel)):
 
70
                    # If we reached the end of data, quit the loop
 
71
                    if idx >= len(data):
 
72
                        break
 
73
 
 
74
                    # Set the real data to display
 
75
                    printed_data = data[idx]
 
76
 
 
77
                position = idx - component.repeat_offset
 
78
                to_print.append((
 
79
                    component, printed_data,
 
80
                    label_offset_x + component.repeat_offset_x * position,
 
81
                    label_offset_y + component.repeat_offset_y * position,
 
82
                ))
 
83
 
 
84
        for (component, data, offset_x, offset_y) in to_print:
 
85
            component_offset_x = component.origin_x + offset_x
 
86
            component_offset_y = component.origin_y + offset_y
 
87
            if component.component_type == 'text':
 
88
                barcode_arguments = dict([
 
89
                    (field_name, component[field_name])
 
90
                    for field_name in [
 
91
                        zpl2.ARG_FONT,
 
92
                        zpl2.ARG_ORIENTATION,
 
93
                        zpl2.ARG_HEIGHT,
 
94
                        zpl2.ARG_WIDTH,
 
95
                        zpl2.ARG_REVERSE_PRINT,
 
96
                        zpl2.ARG_IN_BLOCK,
 
97
                        zpl2.ARG_BLOCK_WIDTH,
 
98
                        zpl2.ARG_BLOCK_LINES,
 
99
                        zpl2.ARG_BLOCK_SPACES,
 
100
                        zpl2.ARG_BLOCK_JUSTIFY,
 
101
                        zpl2.ARG_BLOCK_LEFT_MARGIN,
 
102
                    ]
 
103
                ])
 
104
                label_data.font_data(
 
105
                    component_offset_x, component_offset_y,
 
106
                    barcode_arguments, data)
 
107
            elif component.component_type == 'rectangle':
 
108
                label_data.graphic_box(
 
109
                    component_offset_x, component_offset_y, {
 
110
                        zpl2.ARG_WIDTH: component.width,
 
111
                        zpl2.ARG_HEIGHT: component.height,
 
112
                        zpl2.ARG_THICKNESS: component.thickness,
 
113
                        zpl2.ARG_COLOR: component.color,
 
114
                        zpl2.ARG_ROUNDING: component.rounding,
 
115
                    })
 
116
            elif component.component_type == 'circle':
 
117
                label_data.graphic_circle(
 
118
                    component_offset_x, component_offset_y, {
 
119
                        zpl2.ARG_DIAMETER: component.width,
 
120
                        zpl2.ARG_THICKNESS: component.thickness,
 
121
                        zpl2.ARG_COLOR: component.color,
 
122
                    })
 
123
            elif component.component_type == 'sublabel':
 
124
                component_offset_x += component.sublabel_id.origin_x
 
125
                component_offset_y += component.sublabel_id.origin_y
 
126
                component.sublabel_id._generate_zpl2_components_data(
 
127
                    label_data, data,
 
128
                    label_offset_x=component_offset_x,
 
129
                    label_offset_y=component_offset_y)
 
130
            else:
 
131
                barcode_arguments = dict([
 
132
                    (field_name, component[field_name])
 
133
                    for field_name in [
 
134
                        zpl2.ARG_ORIENTATION,
 
135
                        zpl2.ARG_CHECK_DIGITS,
 
136
                        zpl2.ARG_HEIGHT,
 
137
                        zpl2.ARG_INTERPRETATION_LINE,
 
138
                        zpl2.ARG_INTERPRETATION_LINE_ABOVE,
 
139
                        zpl2.ARG_SECURITY_LEVEL,
 
140
                        zpl2.ARG_COLUMNS_COUNT,
 
141
                        zpl2.ARG_ROWS_COUNT,
 
142
                        zpl2.ARG_TRUNCATE,
 
143
                        zpl2.ARG_MODULE_WIDTH,
 
144
                        zpl2.ARG_BAR_WIDTH_RATIO,
 
145
                    ]
 
146
                ])
 
147
                label_data.barcode_data(
 
148
                    component.origin_x + offset_x,
 
149
                    component.origin_y + offset_y,
 
150
                    component.component_type, barcode_arguments, data)
 
151
 
 
152
    @api.multi
 
153
    def _generate_zpl2_data(self, record, page_count=1, **extra):
 
154
        self.ensure_one()
 
155
        label_data = zpl2.Zpl2()
 
156
 
 
157
        for page_number in range(page_count):
 
158
            # Initialize printer's configuration
 
159
            label_data.label_start()
 
160
            label_data.print_width(self.width)
 
161
            label_data.label_encoding()
 
162
 
 
163
            label_data.label_home(self.origin_x, self.origin_y)
 
164
 
 
165
            self._generate_zpl2_components_data(
 
166
                label_data, record, page_number=page_number,
 
167
                page_count=page_count)
 
168
 
 
169
            # Restore printer's configuration and end the label
 
170
            label_data.configuration_update(zpl2.CONF_RECALL_LAST_SAVED)
 
171
            label_data.label_end()
 
172
 
 
173
        return label_data.output()
 
174
 
 
175
    @api.multi
 
176
    def print_label(self, printer, record, page_count=1, **extra):
 
177
        for label in self:
 
178
            if record._name != label.model_id.model:
 
179
                raise exceptions.UserError(
 
180
                    _('This label cannot be used on {model}').format(
 
181
                        model=record._name))
 
182
 
 
183
            # Send the label to printer
 
184
            label_contents = label._generate_zpl2_data(
 
185
                record, page_count=page_count, **extra)
 
186
            printer.print_document(None, label_contents, 'raw')
 
187
 
 
188
        return True