[IMP] product_print_zpl_barcode: remove dep on base_report_to_printer. Use direct print.
This commit is contained in:
@@ -39,12 +39,12 @@ This module has been written by Alexis de Lattre from Akretion
|
|||||||
'depends': [
|
'depends': [
|
||||||
'point_of_sale',
|
'point_of_sale',
|
||||||
'barcodes',
|
'barcodes',
|
||||||
'base_report_to_printer',
|
|
||||||
],
|
],
|
||||||
'external_dependencies': {'python': ['python-barcode>=0.14.0']},
|
'external_dependencies': {'python': ['python-barcode>=0.14.0']},
|
||||||
'data': [
|
'data': [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'wizard/product_print_zpl_barcode_view.xml',
|
'wizard/product_print_zpl_barcode_view.xml',
|
||||||
|
'wizard/res_config_settings_view.xml',
|
||||||
'views/product.xml',
|
'views/product.xml',
|
||||||
'views/stock_picking.xml',
|
'views/stock_picking.xml',
|
||||||
'data/barcode_sequence.xml',
|
'data/barcode_sequence.xml',
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
from . import product_print_zpl_barcode
|
from . import product_print_zpl_barcode
|
||||||
|
from . import res_config_settings
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ from odoo.tools import float_compare, float_is_zero
|
|||||||
from stdnum.ean import is_valid, calc_check_digit
|
from stdnum.ean import is_valid, calc_check_digit
|
||||||
import base64
|
import base64
|
||||||
import re
|
import re
|
||||||
|
import socket
|
||||||
|
import ipaddress
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
PRINTER_PORT = 9100
|
||||||
|
PRINTER_TIMEOUT = 10
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +40,8 @@ class ProductPrintZplBarcode(models.TransientModel):
|
|||||||
raise UserError(_(
|
raise UserError(_(
|
||||||
"There are no pricelist in company '%s'.") % company.name)
|
"There are no pricelist in company '%s'.") % company.name)
|
||||||
|
|
||||||
printer = self.env['printing.printer'].get_default()
|
printer_ip = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'product_print_zpl_barcode.printer_ip')
|
||||||
|
|
||||||
line_ids = []
|
line_ids = []
|
||||||
if self._context.get('active_model') == 'product.product':
|
if self._context.get('active_model') == 'product.product':
|
||||||
@@ -71,7 +76,7 @@ class ProductPrintZplBarcode(models.TransientModel):
|
|||||||
'company_id': company.id,
|
'company_id': company.id,
|
||||||
'nomenclature_id': nomenclature.id,
|
'nomenclature_id': nomenclature.id,
|
||||||
'pricelist_id': pricelist.id,
|
'pricelist_id': pricelist.id,
|
||||||
'zpl_printer_id': printer and printer.id or False,
|
'zpl_printer_ip': printer_ip,
|
||||||
'line_ids': line_ids,
|
'line_ids': line_ids,
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
@@ -108,8 +113,7 @@ class ProductPrintZplBarcode(models.TransientModel):
|
|||||||
], default='step1', readonly=True)
|
], default='step1', readonly=True)
|
||||||
zpl_file = fields.Binary(string='ZPL File', readonly=True)
|
zpl_file = fields.Binary(string='ZPL File', readonly=True)
|
||||||
zpl_filename = fields.Char('ZPL Filename')
|
zpl_filename = fields.Char('ZPL Filename')
|
||||||
zpl_printer_id = fields.Many2one(
|
zpl_printer_ip = fields.Char(string='ZPL Printer IP Address')
|
||||||
'printing.printer', string='ZPL Printer')
|
|
||||||
line_ids = fields.One2many(
|
line_ids = fields.One2many(
|
||||||
'product.print.zpl.barcode.line', 'parent_id',
|
'product.print.zpl.barcode.line', 'parent_id',
|
||||||
string='Lines', states={'step2': [('readonly', True)]})
|
string='Lines', states={'step2': [('readonly', True)]})
|
||||||
@@ -168,11 +172,21 @@ class ProductPrintZplBarcode(models.TransientModel):
|
|||||||
return action
|
return action
|
||||||
|
|
||||||
def print_zpl(self):
|
def print_zpl(self):
|
||||||
if not self.zpl_printer_id:
|
if not self.zpl_printer_ip:
|
||||||
raise UserError(_(
|
raise UserError(_(
|
||||||
"You must select a ZPL Printer."))
|
"You must configure the IP address of the ZPL Printer."))
|
||||||
self.zpl_printer_id.print_document(
|
zpl_file_bytes = base64.decodebytes(self.zpl_file)
|
||||||
self.zpl_filename, base64.decodebytes(self.zpl_file), format='raw')
|
try:
|
||||||
|
with socket.create_connection((self.zpl_printer_ip, PRINTER_PORT), timeout=PRINTER_TIMEOUT) as sock:
|
||||||
|
sock.send(zpl_file_bytes)
|
||||||
|
except Exception as e:
|
||||||
|
raise UserError(_(
|
||||||
|
"Failure in the connection to the ZPL printer "
|
||||||
|
"on %(ip_addr)s port %(port)s: %(error)s.",
|
||||||
|
ip_addr=self.zpl_printer_ip,
|
||||||
|
port=PRINTER_PORT,
|
||||||
|
error=e,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
class ProductPrintZplBarcodeLine(models.TransientModel):
|
class ProductPrintZplBarcodeLine(models.TransientModel):
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<group name="step2" states="step2">
|
<group name="step2" states="step2">
|
||||||
<field name="zpl_file" filename="zpl_filename" />
|
<field name="zpl_file" filename="zpl_filename" />
|
||||||
<field name="zpl_filename" invisible="1"/>
|
<field name="zpl_filename" invisible="1"/>
|
||||||
<field name="zpl_printer_id" attrs="{'required': [('state', '=', 'step2')]}"/>
|
<field name="zpl_printer_ip" attrs="{'required': [('state', '=', 'step2')]}"/>
|
||||||
</group>
|
</group>
|
||||||
<group name="lines">
|
<group name="lines">
|
||||||
<field name="line_ids" colspan="2" nolabel="1">
|
<field name="line_ids" colspan="2" nolabel="1">
|
||||||
|
|||||||
24
product_print_zpl_barcode/wizard/res_config_settings.py
Normal file
24
product_print_zpl_barcode/wizard/res_config_settings.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Copyright 2023 Akretion France (http://www.akretion.com/)
|
||||||
|
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
|
class ResConfigSettings(models.TransientModel):
|
||||||
|
_inherit = "res.config.settings"
|
||||||
|
|
||||||
|
zpl_printer_ip = fields.Char(
|
||||||
|
config_parameter="product_print_zpl_barcode.printer_ip",
|
||||||
|
string="ZPL Printer IP Address")
|
||||||
|
|
||||||
|
@api.constrains('zpl_printer_ip')
|
||||||
|
def _check_zpl_printer_ip(self):
|
||||||
|
for wiz in self:
|
||||||
|
if wiz.zpl_printer_ip:
|
||||||
|
try:
|
||||||
|
ipaddress.ip_address(wiz.zpl_printer_ip)
|
||||||
|
except Exception as e:
|
||||||
|
raise ValidationError(str(e))
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2024 Akretion France (http://www.akretion.com/)
|
||||||
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||||
|
<field name="model">res.config.settings</field>
|
||||||
|
<field name="inherit_id" ref="base_setup.res_config_settings_view_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//div[@id='companies']" position='after'>
|
||||||
|
<h2>Barcode printing</h2>
|
||||||
|
<div class="row mt16 o_settings_container" name="zpl_printer">
|
||||||
|
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||||
|
<div class="o_setting_right_pane" id="zpl_printer_ip">
|
||||||
|
<div class="row">
|
||||||
|
<label for="zpl_printer_ip" class="col-md-5" />
|
||||||
|
<field name="zpl_printer_ip" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user