Skip to content

Commit

Permalink
[ADD] base_report_to_print_node
Browse files Browse the repository at this point in the history
  • Loading branch information
jjscarafia committed Aug 14, 2020
1 parent 743a1c1 commit 802e89a
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 0 deletions.
49 changes: 49 additions & 0 deletions base_report_to_print_node/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.. |company| replace:: ADHOC SA

.. |company_logo| image:: https://raw.githubusercontent.com/ingadhoc/maintainer-tools/master/resources/adhoc-logo.png
:alt: ADHOC SA
:target: https://www.adhoc.com.ar

.. |icon| image:: https://raw.githubusercontent.com/ingadhoc/maintainer-tools/master/resources/adhoc-icon.png

.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3

===================
Print Node Printing
===================

This module extends the functionality of direct printing. It allows to add your print node printers to odoo

.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: http://runbot.adhoc.com.ar/

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/ingadhoc/reporting-engine/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.

Credits
=======

Images
------

* |company| |icon|

Contributors
------------

Maintainer
----------

|company_logo|

This module is maintained by the |company|.

To contribute to this module, please visit https://www.adhoc.com.ar.
6 changes: 6 additions & 0 deletions base_report_to_print_node/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from . import models
from . import wizards
33 changes: 33 additions & 0 deletions base_report_to_print_node/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
##############################################################################
#
# Copyright (C) 2016 ADHOC SA (http://www.adhoc.com.ar)
# All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': "Print Node Printing",
"version": '11.0.1.0.0',
'category': 'Generic Modules/Base',
'author': 'ADHOC SA',
'license': 'AGPL-3',
"depends": [
'base_report_to_printer',
],
"data": [
'wizards/res_config_settings_view.xml',
],
'installable': True,
}
5 changes: 5 additions & 0 deletions base_report_to_print_node/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from . import printing_printer
209 changes: 209 additions & 0 deletions base_report_to_print_node/models/printing_printer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import fields, models, api, _
from tempfile import mkstemp
from odoo.addons.server_mode.mode import get_mode
from ast import literal_eval
import os
import logging
from odoo.exceptions import UserError, RedirectWarning
from urllib.error import HTTPError
import urllib.request
import requests
import json
import time
import base64
PRINTNODE_URL = 'https://api.printnode.com'
TIMEOUT = 20
_logger = logging.getLogger(__name__)


class PrintingPrinter(models.Model):

_inherit = "printing.printer"

print_node_printer = fields.Boolean(string='Print Node Printer?')
server_id = fields.Many2one(required=False)

@api.model
def _get_print_node_printer(self, print_nodeId):
return self.env['printing.printer'].search([
('print_node_printer', '=', True), ('uri', '=', print_nodeId)], limit=1)

@api.model
def _print_node_status_map(self, state):
return {
'online': 'available',
}.get(state, 'unknown')

@api.model
def update_print_node_printers(self):
_logger.info('Updating Print Node Printers')
pn_printers = self._get_response('printers')
for pn_printer in pn_printers:
printer = self._get_print_node_printer(pn_printer.get('id'))
if not printer:
printer.create({
'name': pn_printer['description'],
'system_name': pn_printer['name'],
'model': pn_printer['name'],
'location': pn_printer.get('computer', {}).get('name'),
'uri': pn_printer['id'],
'print_node_printer': True,
'status': self._print_node_status_map(pn_printer['state']),
'status_message': pn_printer.get('state', False),
})
return True

@api.model
def update_print_node_printers_status(self):
_logger.info('Updating Print Node Printers Status')
pn_printers = self._get_response('printers')
for pn_printer in pn_printers:
printer = self._get_print_node_printer(pn_printer.get('id'))
if printer:
vals = {
'status': self._print_node_status_map(pn_printer['state']),
'status_message': pn_printer.get('state', False),
}
printer.write(vals)

@api.multi
def print_document(self, report, content, **print_opts):
""" Print a file
Format could be pdf, qweb-pdf, raw, ...
"""
if len(self) != 1:
_logger.error(
'Print Node print called with %s but singleton is expeted. Check printers configuration.' % self)
return super().print_document(report, content, **print_opts)

if not self.print_node_printer:
return super().print_document(report, content, **print_opts)

test_enable = literal_eval(
self.env['ir.config_parameter'].sudo().get_param('print_node_enable_print_test', default='False'))
if get_mode() and not test_enable:
_logger.warning(_("Send to printer disable by server mode"))
return True

fd, file_name = mkstemp()
try:
os.write(fd, content)
finally:
os.close(fd)

options = self.print_options(report, **print_opts)

_logger.debug('Sending job to PrintNode printer %s' % (self.system_name))

# atrapamos el error y lo mandamos por el log para que no de piedrazo
# y posiblemente rompa interfaz
try:
res = self._submit_job(
self.uri,
options.get('format', 'pdf'),
file_name,
options,
)
_logger.info("Printing job '%s' for document %s" % (res, file_name))
except Exception as e:
_logger.error('Could not submit job to print node. This is what we get:\n%s' % e)
return True

@api.multi
def enable(self):
print_node_printers = self.filtered('print_node_printer')
print_node_printers.update_print_node_printers_status()
return super(PrintingPrinter, self - print_node_printers).enable()

@api.multi
def disable(self):
print_node_printers = self.filtered('print_node_printer')
print_node_printers.write({'status': 'unavailable', 'status_message': 'disabled by user'})
return super(PrintingPrinter, self - print_node_printers).disable()

# API interaction

@api.model
def ReadFile(self, pathname):
"""Read contents of a file and return content.
Args:
pathname: string, (path)name of file.
Returns:
string: contents of file.
"""
try:
f = open(pathname, 'rb')
try:
s = f.read()
except IOError as error:
_logger.info('Error reading %s\n%s', pathname, error)
finally:
f.close()
return s
except IOError as error:
_logger.error('Error opening %s\n%s', pathname, error)
return None

@api.model
def _submit_job(self, printerid, jobtype, jobsrc, options):
"""Submit a job to printerid with content of dataUrl.
Args:
printerid: string, the printer id to submit the job to.
jobtype: string, must match the dictionary keys in content and
content_type.
jobsrc: string, points to source for job. Could be a pathname or
id string.
Returns:
boolean: True = submitted, False = errors.
"""
# TODO implementar options
if jobtype in ['qweb-pdf', 'pdf', 'aeroo']:
jobtype = 'pdf'
else:
raise UserError(_('Jobtype %s not implemented for Print Node') % (jobtype))

content = self.ReadFile(jobsrc)
content = base64.b64encode(content).decode("utf-8")

# Make the title unique for each job, since the printer by default will
# name the print job file the same as the title.
datehour = time.strftime('%b%d%H%M', time.localtime())
title = '%s%s' % (datehour, jobsrc)

data = {
"printerId": printerid,
"title": title,
"contentType": "pdf_base64",
"content": content,
"source": "created by odoo db: %s" % self.env.cr.dbname,
}
return self._get_response('printjobs', data)

@api.model
def _get_response(self, service, data=None):
api_key = self.env['ir.config_parameter'].sudo().get_param('base_report_to_print_node.api_key')
if not api_key:
dummy, action_id = self.env[
'ir.model.data'].get_object_reference('base_setup', 'action_general_configuration')
msg = _(
"You haven't configured your 'Print Node Api Key'.")
raise RedirectWarning(
msg, action_id, _('Go to the configuration panel'))
request_url = "%s/%s" % (PRINTNODE_URL, service)
headers = {
'authorization': 'Basic ' + base64.b64encode(api_key.encode('UTF-8')).decode('UTF-8'),
}
if data:
headers["Content-Type"] = "application/json"
data_json = data and json.dumps(data).encode('utf-8') or None
try:
req = urllib.request.Request(request_url, data_json, headers)
response = urllib.request.urlopen(req, timeout=TIMEOUT).read()
except HTTPError:
raise UserError(_("Could not connect to print node. Check your configuration"))
return json.loads(response.decode('utf-8'))
6 changes: 6 additions & 0 deletions base_report_to_print_node/wizards/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from . import printing_printer_update_wizard
from . import res_config_settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import models, api, fields


class PrintingPrinterUpdateWizard(models.TransientModel):
_inherit = 'printing.printer.update.wizard'

@api.multi
def action_ok(self):
self.ensure_one()
self.env['printing.printer'].update_print_node_printers()
return super(PrintingPrinterUpdateWizard, self).action_ok()
15 changes: 15 additions & 0 deletions base_report_to_print_node/wizards/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import models, fields, api


class ResConfigSettings(models.TransientModel):

_inherit = 'res.config.settings'

print_node_api_key = fields.Char(
string='Print Node Api Key',
config_parameter='base_report_to_print_node.api_key'
)
22 changes: 22 additions & 0 deletions base_report_to_print_node/wizards/res_config_settings_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">General Settings</field>
<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="//label[@for='module_google_drive']/../.." position="after">
<div class="col-xs-12 col-md-6 o_setting_box" modifiers="{}">
<div class="o_setting_right_pane" modifiers="{}">
<label string="Print Node Api Key"/>
<div lass="content-group" name="print_node">
<div>
<field name="print_node_api_key" class="oe_inline"/>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

0 comments on commit 802e89a

Please sign in to comment.