Merge pull request #33 from acsone/7.0-base_report_to_printer_pep8-lga

[PEP8] + latest MQT template
This commit is contained in:
Pedro M. Baeza
2015-09-28 13:09:57 +02:00
20 changed files with 219 additions and 132 deletions

View File

@@ -1,6 +1,10 @@
language: python
sudo: false sudo: false
cache: pip cache: pip
python:
- "2.7"
addons: addons:
apt: apt:
packages: packages:
@@ -9,24 +13,32 @@ addons:
- cups - cups
- libcups2-dev - libcups2-dev
language: python env:
python: global:
- "2.7" - VERSION="7.0" TESTS="0" LINT_CHECK="0" TRANSIFEX="0"
- TRANSIFEX_USER='transbot@odoo-community.org'
- secure: PjP88tPSwimBv4tsgn3UcQAD1heK/wcuSaSfhi2xUt/jSrOaTmWzjaW2gH/eKM1ilxPXwlPGyAIShJ2JJdBiA97hQufOeiqxdkWDctnNVVEDx2Tk0BiG3PPYyhXPgUZ+FNOnjZFF3pNWvzXTQaB0Nvz8plqp93Ov/DEyhrCxHDs=
matrix:
- LINT_CHECK="1"
- TRANSIFEX="1"
- TESTS="1" ODOO_REPO="odoo/odoo"
- TESTS="1" ODOO_REPO="OCA/OCB"
virtualenv: virtualenv:
system_site_packages: true system_site_packages: true
install: install:
- git clone https://github.com/OCA/maintainer-quality-tools.git $HOME/maintainer-quality-tools - git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
- export PATH=$HOME/maintainer-quality-tools/travis:$PATH - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
- travis_install_nightly - travis_install_nightly
- pip install pycups==1.9.66 - pip install pycups==1.9.66
- pip install PyPDF2==1.18 - pip install PyPDF2==1.18
- pip install requests - pip install requests
- git clone https://github.com/OCA/reporting-engine -b ${VERSION} $HOME/reporting-engine - git clone https://github.com/OCA/reporting-engine -b ${VERSION} ${HOME}/reporting-engine
script: script:
- travis_run_tests - travis_run_tests
after_success: after_success:
coveralls - travis_after_tests_success

View File

@@ -1,5 +1,8 @@
[![Runbot Status](https://runbot.odoo-community.org/runbot/badge/flat/144/7.0.svg)](https://runbot.odoo-community.org/runbot/repo/github-com-oca-report-print-send-144)
[![Build Status](https://travis-ci.org/OCA/report-print-send.svg?branch=7.0)](https://travis-ci.org/OCA/report-print-send) [![Build Status](https://travis-ci.org/OCA/report-print-send.svg?branch=7.0)](https://travis-ci.org/OCA/report-print-send)
[![Coverage Status](https://coveralls.io/repos/OCA/report-print-send/badge.png?branch=7.0)](https://coveralls.io/r/OCA/report-print-send?branch=7.0) [![Coverage Status](https://coveralls.io/repos/OCA/report-print-send/badge.png?branch=7.0)](https://coveralls.io/r/OCA/report-print-send?branch=7.0)
[![Code Climate](https://codeclimate.com/github/OCA/report-print-send/badges/gpa.svg)](https://codeclimate.com/github/OCA/report-pint-send)
Report - Printing and Sending Report - Printing and Sending
============================= =============================
@@ -10,3 +13,15 @@ This project aim to deal with modules related to manage document printing and se
- Add an printing queue - Add an printing queue
- Allow to choose printer - Allow to choose printer
- ... - ...
Translation Status
------------------
[![Transifex Status](https://www.transifex.com/projects/p/OCA-report-print-send-7-0/chart/image_png)](https://www.transifex.com/projects/p/OCA-report-print-send-7-0)
----
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
http://odoo-community.org/

View File

@@ -78,7 +78,8 @@ Contributors
* Lionel Sausin <ls@numerigraphe.com> * Lionel Sausin <ls@numerigraphe.com>
""", """,
'author': "Agile Business Group & Domsense, Pegueroles SCP, NaN,Odoo Community Association (OCA)", 'author': "Agile Business Group & Domsense, Pegueroles SCP, NaN,"
"Odoo Community Association (OCA)",
'website': 'http://www.agilebg.com', 'website': 'http://www.agilebg.com',
'license': 'AGPL-3', 'license': 'AGPL-3',
"depends": ['base', 'base_calendar'], "depends": ['base', 'base_calendar'],
@@ -93,5 +94,5 @@ Contributors
'application': True, 'application': True,
'external_dependencies': { 'external_dependencies': {
'python': ['cups'] 'python': ['cups']
} }
} }

View File

@@ -32,6 +32,7 @@ from openerp.osv import orm, fields
class report_xml(orm.Model): class report_xml(orm.Model):
""" """
Reports Reports
""" """
@@ -45,7 +46,8 @@ class report_xml(orm.Model):
options['raw'] = True options['raw'] = True
return options return options
def print_direct(self, cr, uid, report_id, result, format, printer, context=None): def print_direct(self, cr, uid, report_id, result, format, printer,
context=None):
fd, file_name = mkstemp() fd, file_name = mkstemp()
try: try:
os.write(fd, base64.decodestring(result)) os.write(fd, base64.decodestring(result))
@@ -59,9 +61,11 @@ class report_xml(orm.Model):
printer_system_name = printer.system_name printer_system_name = printer.system_name
connection = cups.Connection() connection = cups.Connection()
options = self.set_print_options(cr, uid, report_id, format, context=context) options = self.set_print_options(cr, uid, report_id, format,
context=context)
connection.printFile(printer_system_name, file_name, file_name, options=options) connection.printFile(printer_system_name, file_name, file_name,
options=options)
logger = logging.getLogger('base_report_to_printer') logger = logging.getLogger('base_report_to_printer')
logger.info("Printing job : '%s'" % file_name) logger.info("Printing job : '%s'" % file_name)
return True return True
@@ -69,20 +73,20 @@ class report_xml(orm.Model):
_inherit = 'ir.actions.report.xml' _inherit = 'ir.actions.report.xml'
_columns = { _columns = {
'property_printing_action': fields.property( 'property_printing_action': fields.property(
#'ir.actions.report.xml', # 'ir.actions.report.xml',
'printing.action', 'printing.action',
type='many2one', type='many2one',
relation='printing.action', relation='printing.action',
string='Action', string='Action',
view_load=True, view_load=True,
method=True, method=True,
), ),
'printing_printer_id': fields.many2one('printing.printer', 'Printer'), 'printing_printer_id': fields.many2one('printing.printer', 'Printer'),
'printing_action_ids': fields.one2many( 'printing_action_ids': fields.one2many(
'printing.report.xml.action', 'report_id', 'Actions', 'printing.report.xml.action', 'report_id', 'Actions',
help='This field allows configuring action and printer on a per ' help='This field allows configuring action and printer on a per '
'user basis'), 'user basis'),
} }
def behaviour(self, cr, uid, ids, context=None): def behaviour(self, cr, uid, ids, context=None):
result = {} result = {}
@@ -93,7 +97,8 @@ class report_xml(orm.Model):
# Retrieve system wide printer # Retrieve system wide printer
default_printer = printer_obj.get_default(cr, uid, context=context) default_printer = printer_obj.get_default(cr, uid, context=context)
if default_printer: if default_printer:
default_printer = printer_obj.browse(cr, uid, default_printer, context=context) default_printer = printer_obj.browse(cr, uid, default_printer,
context=context)
# Retrieve user default values # Retrieve user default values
user = self.pool['res.users'].browse(cr, uid, uid, context=context) user = self.pool['res.users'].browse(cr, uid, uid, context=context)
@@ -107,8 +112,8 @@ class report_xml(orm.Model):
printer = default_printer printer = default_printer
# Retrieve report default values # Retrieve report default values
if (report.property_printing_action if (report.property_printing_action and
and report.property_printing_action.type != 'user_default'): report.property_printing_action.type != 'user_default'):
action = report.property_printing_action.type action = report.property_printing_action.type
if report.printing_printer_id: if report.printing_printer_id:
printer = report.printing_printer_id printer = report.printing_printer_id
@@ -120,7 +125,8 @@ class report_xml(orm.Model):
('user_id', '=', uid), ('user_id', '=', uid),
('action', '!=', 'user_default')], context=context) ('action', '!=', 'user_default')], context=context)
if act_ids: if act_ids:
user_action = printing_act_obj.behaviour(cr, uid, act_ids[0], context) user_action = printing_act_obj.behaviour(cr, uid, act_ids[0],
context)
action = user_action['action'] action = user_action['action']
if user_action['printer']: if user_action['printer']:
printer = user_action['printer'] printer = user_action['printer']
@@ -128,5 +134,5 @@ class report_xml(orm.Model):
result[report.id] = { result[report.id] = {
'action': action, 'action': action,
'printer': printer, 'printer': printer,
} }
return result return result

View File

@@ -34,6 +34,7 @@ from openerp.tools.translate import _
class printing_printer(orm.Model): class printing_printer(orm.Model):
""" """
Printers Printers
""" """
@@ -78,14 +79,14 @@ class printing_printer(orm.Model):
'URI', 'URI',
size=500, size=500,
readonly=True), readonly=True),
} }
_order = "name" _order = "name"
_defaults = { _defaults = {
'default': lambda *a: False, 'default': lambda *a: False,
'status': lambda *a: 'unknown', 'status': lambda *a: 'unknown',
} }
def __init__(self, pool, cr): def __init__(self, pool, cr):
super(printing_printer, self).__init__(pool, cr) super(printing_printer, self).__init__(pool, cr)
@@ -113,7 +114,7 @@ class printing_printer(orm.Model):
if context is None: if context is None:
context = {} context = {}
try: try:
# Skip update to avoid the thread being created again # Skip update to avoid the thread being created again
ctx = context.copy() ctx = context.copy()
ctx['skip_update'] = True ctx['skip_update'] = True
ids = self.search(cr, uid, [], context=ctx) ids = self.search(cr, uid, [], context=ctx)
@@ -151,7 +152,8 @@ class printing_printer(orm.Model):
return return
self.updating = True self.updating = True
self.lock.release() self.lock.release()
thread = Thread(target=self.update_printers_status, args=(cr.dbname, uid, context.copy())) thread = Thread(target=self.update_printers_status,
args=(cr.dbname, uid, context.copy()))
thread.start() thread.start()
def update(self, cr, uid, context=None): def update(self, cr, uid, context=None):
@@ -161,7 +163,8 @@ class printing_printer(orm.Model):
return True return True
last_update = self.last_update last_update = self.last_update
now = time.time() now = time.time()
# Only update printer status if current status is more than 10 seconds old. # Only update printer status if current status is more than
# 10 seconds old.
if not last_update or now - last_update > 10: if not last_update or now - last_update > 10:
self.start_printer_update(cr, uid, context) self.start_printer_update(cr, uid, context)
# Wait up to five seconds for printer status update # Wait up to five seconds for printer status update
@@ -178,7 +181,8 @@ class printing_printer(orm.Model):
).search(cr, uid, args, offset, ).search(cr, uid, args, offset,
limit, order, context, count) limit, order, context, count)
def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): def read(self, cr, uid, ids, fields=None, context=None,
load='_classic_read'):
self.update(cr, uid, context) self.update(cr, uid, context)
return super(printing_printer, self return super(printing_printer, self
).read(cr, uid, ids, fields, context, load) ).read(cr, uid, ids, fields, context, load)
@@ -211,7 +215,7 @@ def _available_action_types(self, cr, uid, context=None):
('server', _('Send to Printer')), ('server', _('Send to Printer')),
('client', _('Send to Client')), ('client', _('Send to Client')),
('user_default', _("Use user's defaults")), ('user_default', _("Use user's defaults")),
] ]
class printing_action(orm.Model): class printing_action(orm.Model):
@@ -220,5 +224,6 @@ class printing_action(orm.Model):
_columns = { _columns = {
'name': fields.char('Name', size=256, required=True), 'name': fields.char('Name', size=256, required=True),
'type': fields.selection(_available_action_types, 'Type', required=True), 'type': fields.selection(_available_action_types, 'Type',
} required=True),
}

View File

@@ -31,7 +31,8 @@ from openerp.addons.base_calendar import base_calendar
class virtual_report_spool(base_calendar.virtual_report_spool): class virtual_report_spool(base_calendar.virtual_report_spool):
def exp_report(self, db, uid, object, ids, datas=None, context=None): def exp_report(self, db, uid, object, ids, datas=None, context=None):
res = super(virtual_report_spool, self).exp_report(db, uid, object, ids, datas, context) res = super(virtual_report_spool, self).exp_report(
db, uid, object, ids, datas, context)
self._reports[res]['report_name'] = object self._reports[res]['report_name'] = object
return res return res
@@ -43,22 +44,27 @@ class virtual_report_spool(base_calendar.virtual_report_spool):
# First of all load report defaults: name, action and printer # First of all load report defaults: name, action and printer
report_obj = pool.get('ir.actions.report.xml') report_obj = pool.get('ir.actions.report.xml')
report = report_obj.search( report = report_obj.search(
cr, uid, [('report_name', '=', self._reports[report_id]['report_name'])]) cr, uid, [('report_name', '=',
self._reports[report_id]['report_name'])])
if report: if report:
report = report_obj.browse(cr, uid, report[0]) report = report_obj.browse(cr, uid, report[0])
data = report.behaviour()[report.id] data = report.behaviour()[report.id]
action = data['action'] action = data['action']
printer = data['printer'] printer = data['printer']
if action != 'client': if action != 'client':
if (self._reports and self._reports.get(report_id, False) if (self._reports and
and self._reports[report_id].get('result', False) self._reports.get(report_id, False) and
and self._reports[report_id].get('format', False)): self._reports[report_id].get('result', False) and
self._reports[report_id].get('format', False)):
report_obj.print_direct( report_obj.print_direct(
cr, uid, report.id, base64.encodestring(self._reports[report_id]['result']), cr, uid, report.id, base64.encodestring(
self._reports[report_id]['result']),
self._reports[report_id]['format'], printer) self._reports[report_id]['format'], printer)
# FIXME "Warning" removed as it breaks the workflow # FIXME "Warning" removed as it breaks the workflow
# it would be interesting to have a dialog box to confirm if we really want to print # it would be interesting to have a dialog box to
# in this case it must be with a by pass parameter to allow massive impression # confirm if we really want to print
# in this case it must be with a by pass parameter to
# allow massive impression
# raise osv.except_osv( # raise osv.except_osv(
# _('Printing...'), # _('Printing...'),
# _('Document sent to printer %s') % (printer,)) # _('Document sent to printer %s') % (printer,))
@@ -69,9 +75,8 @@ class virtual_report_spool(base_calendar.virtual_report_spool):
finally: finally:
cr.close() cr.close()
res = super(virtual_report_spool, self).exp_report_get(db, uid, report_id) res = super(virtual_report_spool, self).exp_report_get(db, uid,
report_id)
return res return res
virtual_report_spool() virtual_report_spool()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -24,27 +24,28 @@
############################################################################## ##############################################################################
from openerp.osv import orm, fields from openerp.osv import orm, fields
from printing import _available_action_types from openerp.addons.base_report_to_printer.printing import \
_available_action_types
class report_xml_action(orm.Model): class report_xml_action(orm.Model):
_name = 'printing.report.xml.action' _name = 'printing.report.xml.action'
_description = 'Report Printing Actions' _description = 'Report Printing Actions'
_columns = { _columns = {
'report_id': fields.many2one('ir.actions.report.xml', 'Report', required=True, ondelete='cascade'), 'report_id': fields.many2one('ir.actions.report.xml', 'Report',
'user_id': fields.many2one('res.users', 'User', required=True, ondelete='cascade'), required=True, ondelete='cascade'),
'action': fields.selection(_available_action_types, 'Action', required=True), 'user_id': fields.many2one('res.users', 'User', required=True,
ondelete='cascade'),
'action': fields.selection(_available_action_types, 'Action',
required=True),
'printer_id': fields.many2one('printing.printer', 'Printer'), 'printer_id': fields.many2one('printing.printer', 'Printer'),
} }
def behaviour(self, cr, uid, act_id, context=None): def behaviour(self, cr, uid, act_id, context=None):
result = {}
if not act_id: if not act_id:
return False return False
action = self.browse(cr, uid, act_id, context=context) action = self.browse(cr, uid, act_id, context=context)
return { return {
'action': action.action, 'action': action.action,
'printer': action.printer_id, 'printer': action.printer_id,
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -24,10 +24,12 @@
############################################################################## ##############################################################################
from openerp.osv import orm, fields from openerp.osv import orm, fields
from printing import _available_action_types from openerp.addons.base_report_to_printer.printing import \
_available_action_types
class res_users(orm.Model): class res_users(orm.Model):
""" """
Users Users
""" """
@@ -41,8 +43,8 @@ class res_users(orm.Model):
if x[0] != 'user_default'] if x[0] != 'user_default']
_columns = { _columns = {
'printing_action': fields.selection(_user_available_action_types, 'Printing Action'), 'printing_action': fields.selection(_user_available_action_types,
'printing_printer_id': fields.many2one('printing.printer', 'Default Printer'), 'Printing Action'),
} 'printing_printer_id': fields.many2one('printing.printer',
'Default Printer'),
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: }

View File

@@ -29,9 +29,6 @@ from openerp.osv import orm
class printing_printer_update_wizard(orm.TransientModel): class printing_printer_update_wizard(orm.TransientModel):
_name = "printing.printer.update.wizard" _name = "printing.printer.update.wizard"
_columns = {
}
def action_cancel(self, cr, uid, ids, context=None): def action_cancel(self, cr, uid, ids, context=None):
return {} return {}
@@ -57,7 +54,7 @@ class printing_printer_update_wizard(orm.TransientModel):
'model': printer.get('printer-make-and-model', False), 'model': printer.get('printer-make-and-model', False),
'location': printer.get('printer-location', False), 'location': printer.get('printer-location', False),
'uri': printer.get('device-uri', False), 'uri': printer.get('device-uri', False),
}, context) }, context)
return { return {
'name': 'Printers', 'name': 'Printers',
@@ -66,7 +63,4 @@ class printing_printer_update_wizard(orm.TransientModel):
'res_model': 'printing.printer', 'res_model': 'printing.printer',
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'target': 'current', 'target': 'current',
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -19,7 +19,7 @@
# #
############################################################################## ##############################################################################
import ir_attachment from . import ir_attachment
import pingen from . import pingen
import pingen_document from . import pingen_document
import res_company from . import res_company

View File

@@ -30,7 +30,7 @@
'depends': [], 'depends': [],
'external_dependencies': { 'external_dependencies': {
'python': ['requests'], 'python': ['requests'],
}, },
'description': """ 'description': """
Integration with pingen.com Integration with pingen.com
=========================== ===========================
@@ -91,8 +91,8 @@ you will need to manually handle the case, either from the pingen.com backend,
or by changing the document on OpenERP and resolving the error on the Pingen or by changing the document on OpenERP and resolving the error on the Pingen
Document. Document.
When a connection error occurs, the action will be retried on the next scheduler When a connection error occurs, the action will be retried on the next
run. scheduler run.
Dependencies Dependencies
------------ ------------
@@ -111,7 +111,7 @@ Dependencies
'pingen_data.xml', 'pingen_data.xml',
'res_company_view.xml', 'res_company_view.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
], ],
'tests': [], 'tests': [],
'installable': False, 'installable': False,
'auto_install': False, 'auto_install': False,

View File

@@ -41,8 +41,10 @@ class ir_attachment(orm.Model):
'pingen_speed': fields.selection( 'pingen_speed': fields.selection(
[('1', 'Priority'), ('2', 'Economy')], [('1', 'Priority'), ('2', 'Economy')],
'Speed', 'Speed',
help="Defines the sending speed if the document is automatically sent"), help="Defines the sending speed if the document is "
'pingen_color': fields.selection([('0', 'B/W'), ('1', 'Color')], 'Type of print'), "automatically sent"),
'pingen_color': fields.selection([('0', 'B/W'), ('1', 'Color')],
'Type of print'),
} }
_defaults = { _defaults = {
@@ -56,14 +58,15 @@ class ir_attachment(orm.Model):
'config': 'created from attachment'} 'config': 'created from attachment'}
def _handle_pingen_document(self, cr, uid, attachment_id, context=None): def _handle_pingen_document(self, cr, uid, attachment_id, context=None):
""" Reponsible of the related ``pingen.document`` when the ``send_to_pingen`` """ Reponsible of the related ``pingen.document``
field is modified. when the ``send_to_pingen`` field is modified.
Only one pingen document can be created per attachment. Only one pingen document can be created per attachment.
When ``send_to_pingen`` is activated: When ``send_to_pingen`` is activated:
* Create a ``pingen.document`` if it does not already exist * Create a ``pingen.document`` if it does not already exist
* Put the related ``pingen.document`` to ``pending`` if it already exist * Put the related ``pingen.document`` to ``pending`` if
it already exist
When it is deactivated: When it is deactivated:
* Do nothing if no related ``pingen.document`` exists * Do nothing if no related ``pingen.document`` exists
* Or cancel it * Or cancel it
@@ -72,7 +75,8 @@ class ir_attachment(orm.Model):
""" """
pingen_document_obj = self.pool.get('pingen.document') pingen_document_obj = self.pool.get('pingen.document')
attachment = self.browse(cr, uid, attachment_id, context=context) attachment = self.browse(cr, uid, attachment_id, context=context)
document = attachment.pingen_document_ids[0] if attachment.pingen_document_ids else None document = attachment.pingen_document_ids[
0] if attachment.pingen_document_ids else None
if attachment.send_to_pingen: if attachment.send_to_pingen:
if document: if document:
document.write({'state': 'pending'}, context=context) document.write({'state': 'pending'}, context=context)
@@ -87,22 +91,26 @@ class ir_attachment(orm.Model):
if document.state == 'pushed': if document.state == 'pushed':
raise osv.except_osv( raise osv.except_osv(
_('Error'), _('Error'),
_('The attachment %s is already pushed to pingen.com.') % _('The attachment %s is already pushed to '
attachment.name) 'pingen.com.') % attachment.name)
document.write({'state': 'canceled'}, context=context) document.write({'state': 'canceled'}, context=context)
return return
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
attachment_id = super(ir_attachment, self).create(cr, uid, vals, context=context) attachment_id = super(ir_attachment, self).create(
cr, uid, vals, context=context)
if 'send_to_pingen' in vals: if 'send_to_pingen' in vals:
self._handle_pingen_document(cr, uid, attachment_id, context=context) self._handle_pingen_document(
cr, uid, attachment_id, context=context)
return attachment_id return attachment_id
def write(self, cr, uid, ids, vals, context=None): def write(self, cr, uid, ids, vals, context=None):
res = super(ir_attachment, self).write(cr, uid, ids, vals, context=context) res = super(ir_attachment, self).write(
cr, uid, ids, vals, context=context)
if 'send_to_pingen' in vals: if 'send_to_pingen' in vals:
for attachment_id in ids: for attachment_id in ids:
self._handle_pingen_document(cr, uid, attachment_id, context=context) self._handle_pingen_document(
cr, uid, attachment_id, context=context)
return res return res
def _decoded_content(self, cr, uid, attachment, context=None): def _decoded_content(self, cr, uid, attachment, context=None):

View File

@@ -58,19 +58,23 @@ def pingen_datetime_to_utc(dt):
class PingenException(RuntimeError): class PingenException(RuntimeError):
"""There was an ambiguous exception that occurred while handling your """There was an ambiguous exception that occurred while handling your
request.""" request."""
class ConnectionError(PingenException): class ConnectionError(PingenException):
"""An Error occured with the pingen API""" """An Error occured with the pingen API"""
class APIError(PingenException): class APIError(PingenException):
"""An Error occured with the pingen API""" """An Error occured with the pingen API"""
class Pingen(object): class Pingen(object):
""" Interface to the pingen.com API """ """ Interface to the pingen.com API """
def __init__(self, token, staging=True): def __init__(self, token, staging=True):
@@ -132,11 +136,13 @@ class Pingen(object):
if response.json['error']: if response.json['error']:
raise APIError( raise APIError(
"%s: %s" % (response.json['errorcode'], response.json['errormessage'])) "%s: %s" % (response.json['errorcode'],
response.json['errormessage']))
return response return response
def push_document(self, filename, filestream, send=None, speed=None, color=None): def push_document(self, filename, filestream, send=None, speed=None,
color=None):
""" Upload a document to pingen.com and eventually ask to send it """ Upload a document to pingen.com and eventually ask to send it
:param str filename: name of the file to push :param str filename: name of the file to push
@@ -154,7 +160,7 @@ class Pingen(object):
'send': send, 'send': send,
'speed': speed, 'speed': speed,
'color': color, 'color': color,
} }
# we cannot use the `files` param alongside # we cannot use the `files` param alongside
# with the `datas`param when data is a # with the `datas`param when data is a
@@ -164,7 +170,7 @@ class Pingen(object):
formdata = { formdata = {
'file': (filename, filestream.read()), 'file': (filename, filestream.read()),
'data': json.dumps(data), 'data': json.dumps(data),
} }
multipart, content_type = encode_multipart_formdata(formdata) multipart, content_type = encode_multipart_formdata(formdata)
@@ -196,7 +202,7 @@ class Pingen(object):
data = { data = {
'speed': speed, 'speed': speed,
'color': color, 'color': color,
} }
response = self._send( response = self._send(
self.session.post, self.session.post,
'document/send', 'document/send',

View File

@@ -34,6 +34,7 @@ _logger = logging.getLogger(__name__)
class pingen_document(orm.Model): class pingen_document(orm.Model):
""" A pingen document is the state of the synchronization of """ A pingen document is the state of the synchronization of
an attachment with pingen.com an attachment with pingen.com
@@ -75,7 +76,8 @@ class pingen_document(orm.Model):
'post_status': fields.char('Post Status', size=128, readonly=True), 'post_status': fields.char('Post Status', size=128, readonly=True),
'parsed_address': fields.text('Parsed Address', readonly=True), 'parsed_address': fields.text('Parsed Address', readonly=True),
'cost': fields.float('Cost', readonly=True), 'cost': fields.float('Cost', readonly=True),
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True), 'currency_id': fields.many2one('res.currency', 'Currency',
readonly=True),
'country_id': fields.many2one('res.country', 'Country', readonly=True), 'country_id': fields.many2one('res.country', 'Country', readonly=True),
'send_date': fields.datetime('Date of sending', readonly=True), 'send_date': fields.datetime('Date of sending', readonly=True),
'pages': fields.integer('Pages', readonly=True), 'pages': fields.integer('Pages', readonly=True),
@@ -95,7 +97,8 @@ class pingen_document(orm.Model):
""" Returns a pingen session for a user """ """ Returns a pingen session for a user """
company = self.pool.get('res.users').browse( company = self.pool.get('res.users').browse(
cr, uid, uid, context=context).company_id cr, uid, uid, context=context).company_id
return self.pool.get('res.company')._pingen(cr, uid, company, context=context) return self.pool.get('res.company')._pingen(cr, uid, company,
context=context)
def _push_to_pingen(self, cr, uid, document, pingen=None, context=None): def _push_to_pingen(self, cr, uid, document, pingen=None, context=None):
""" Push a document to pingen.com """ Push a document to pingen.com
@@ -141,11 +144,13 @@ class pingen_document(orm.Model):
document.write( document.write(
{'last_error_message': error, {'last_error_message': error,
'state': state, 'state': state,
'push_date': push_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT), 'push_date': push_date.strftime(
tools.DEFAULT_SERVER_DATETIME_FORMAT),
'pingen_id': doc_id, 'pingen_id': doc_id,
'post_id': post_id}, 'post_id': post_id},
context=context) context=context)
_logger.info('Pingen Document %s: pushed to %s' % (document.id, pingen.url)) _logger.info('Pingen Document %s: pushed to %s' % (document.id,
pingen.url))
def push_to_pingen(self, cr, uid, ids, context=None): def push_to_pingen(self, cr, uid, ids, context=None):
""" Push a document to pingen.com """ Push a document to pingen.com
@@ -164,7 +169,8 @@ class pingen_document(orm.Model):
except ConnectionError as e: except ConnectionError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Connection Error'), _('Pingen Connection Error'),
_('Connection Error when asking for sending the document %s to Pingen') % document.name) _('Connection Error when asking for sending the '
'document %s to Pingen') % document.name)
except APIError as e: except APIError as e:
raise osv.except_osv( raise osv.except_osv(
@@ -174,11 +180,13 @@ class pingen_document(orm.Model):
except: except:
_logger.exception( _logger.exception(
'Unexcepted Error when updating the status of pingen.document %s: ' % 'Unexcepted Error when updating the status of '
'pingen.document %s: ' %
document.id) document.id)
raise osv.except_osv( raise osv.except_osv(
_('Error'), _('Error'),
_('Unexcepted Error when updating the status of Document %s') % document.name) _('Unexcepted Error when updating the status '
'of Document %s') % document.name)
return True return True
def _push_and_send_to_pingen_cron(self, cr, uid, ids, context=None): def _push_and_send_to_pingen_cron(self, cr, uid, ids, context=None):
@@ -209,11 +217,13 @@ class pingen_document(orm.Model):
try: try:
if document.state == 'pending': if document.state == 'pending':
self._push_to_pingen( self._push_to_pingen(
loc_cr, uid, document, pingen=session, context=context) loc_cr, uid, document, pingen=session,
context=context)
elif document.state == 'pushed': elif document.state == 'pushed':
self._ask_pingen_send( self._ask_pingen_send(
loc_cr, uid, document, pingen=session, context=context) loc_cr, uid, document, pingen=session,
context=context)
except ConnectionError as e: except ConnectionError as e:
document.write({'last_error_message': e, document.write({'last_error_message': e,
'state': 'error'}, 'state': 'error'},
@@ -264,11 +274,13 @@ class pingen_document(orm.Model):
document.pingen_speed, document.pingen_speed,
document.pingen_color) document.pingen_color)
except ConnectionError: except ConnectionError:
_logger.exception('Connection Error when asking for sending Pingen Document %s to %s.' % _logger.exception('Connection Error when asking for sending '
'Pingen Document %s to %s.' %
(document.id, pingen.url)) (document.id, pingen.url))
raise raise
except APIError: except APIError:
_logger.exception('API Error when asking for sending Pingen Document %s to %s.' % _logger.exception('API Error when asking for sending '
'Pingen Document %s to %s.' %
(document.id, pingen.url)) (document.id, pingen.url))
raise raise
@@ -277,7 +289,8 @@ class pingen_document(orm.Model):
'state': 'sendcenter', 'state': 'sendcenter',
'post_id': post_id}, 'post_id': post_id},
context=context) context=context)
_logger.info('Pingen Document %s: asked for sending to %s' % (document.id, pingen.url)) _logger.info('Pingen Document %s: asked for sending to %s' %
(document.id, pingen.url))
return True return True
@@ -291,7 +304,8 @@ class pingen_document(orm.Model):
with self._get_pingen_session(cr, uid, context=context) as session: with self._get_pingen_session(cr, uid, context=context) as session:
for document in self.browse(cr, uid, ids, context=context): for document in self.browse(cr, uid, ids, context=context):
try: try:
self._ask_pingen_send(cr, uid, document, pingen=session, context=context) self._ask_pingen_send(
cr, uid, document, pingen=session, context=context)
except ConnectionError as e: except ConnectionError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Connection Error'), _('Pingen Connection Error'),
@@ -306,11 +320,13 @@ class pingen_document(orm.Model):
except: except:
_logger.exception( _logger.exception(
'Unexcepted Error when updating the status of pingen.document %s: ' % 'Unexcepted Error when updating the status of '
'pingen.document %s: ' %
document.id) document.id)
raise osv.except_osv( raise osv.except_osv(
_('Error'), _('Error'),
_('Unexcepted Error when updating the status of Document %s') % document.name) _('Unexcepted Error when updating the status '
'of Document %s') % document.name)
return True return True
def _update_post_infos(self, cr, uid, document, pingen, context=None): def _update_post_infos(self, cr, uid, document, pingen, context=None):
@@ -348,10 +364,11 @@ class pingen_document(orm.Model):
'currency_id': currency_ids[0] if currency_ids else False, 'currency_id': currency_ids[0] if currency_ids else False,
'parsed_address': post_infos['address'], 'parsed_address': post_infos['address'],
'country_id': country_ids[0] if country_ids else False, 'country_id': country_ids[0] if country_ids else False,
'send_date': send_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT), 'send_date': send_date.strftime(
tools.DEFAULT_SERVER_DATETIME_FORMAT),
'pages': post_infos['pages'], 'pages': post_infos['pages'],
'last_error_message': False, 'last_error_message': False,
} }
if pingen.is_posted(post_infos): if pingen.is_posted(post_infos):
vals['state'] = 'sent' vals['state'] = 'sent'
@@ -381,7 +398,8 @@ class pingen_document(orm.Model):
loc_cr, uid, document, pingen=session, context=context) loc_cr, uid, document, pingen=session, context=context)
except (ConnectionError, APIError): except (ConnectionError, APIError):
# will be retried the next time # will be retried the next time
# In any case, the error has been logged by _update_post_infos # In any case, the error has been logged by
# _update_post_infos
loc_cr.rollback() loc_cr.rollback()
except: except:
_logger.error('Unexcepted error in pingen cron') _logger.error('Unexcepted error in pingen cron')
@@ -406,20 +424,24 @@ class pingen_document(orm.Model):
except ConnectionError as e: except ConnectionError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Connection Error'), _('Pingen Connection Error'),
_('Connection Error when updating the status of Document %s' _('Connection Error when updating the status of '
'Document %s'
' from Pingen') % document.name) ' from Pingen') % document.name)
except APIError as e: except APIError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Error'), _('Pingen Error'),
_('Error when updating the status of Document %s from Pingen: ' _('Error when updating the status of Document %s '
'from Pingen: '
'\n%s') % (document.name, e)) '\n%s') % (document.name, e))
except: except:
_logger.exception( _logger.exception(
'Unexcepted Error when updating the status of pingen.document %s: ' % 'Unexcepted Error when updating the status of '
'pingen.document %s: ' %
document.id) document.id)
raise osv.except_osv( raise osv.except_osv(
_('Error'), _('Error'),
_('Unexcepted Error when updating the status of Document %s') % document.name) _('Unexcepted Error when updating the status of '
'Document %s') % document.name)
return True return True

View File

@@ -47,7 +47,7 @@ Report to printer - Paper tray selection
'data': [ 'data': [
'users_view.xml', 'users_view.xml',
'ir_report_view.xml', 'ir_report_view.xml',
], ],
'test': [], 'test': [],
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': False,

View File

@@ -29,14 +29,15 @@ class ReportXML(orm.Model):
'printer_tray_id': fields.many2one( 'printer_tray_id': fields.many2one(
'printing.tray', 'Paper Source', 'printing.tray', 'Paper Source',
domain="[('printer_id', '=', printing_printer_id)]"), domain="[('printer_id', '=', printing_printer_id)]"),
} }
def set_print_options(self, cr, uid, report_id, format, context=None): def set_print_options(self, cr, uid, report_id, format, context=None):
""" """
Hook to define Tray Hook to define Tray
""" """
printing_act_obj = self.pool.get('printing.report.xml.action') printing_act_obj = self.pool.get('printing.report.xml.action')
options = super(ReportXML, self).set_print_options(cr, uid, report_id, format, context=context) options = super(ReportXML, self).set_print_options(
cr, uid, report_id, format, context=context)
# Retrieve user default values # Retrieve user default values
user = self.pool.get('res.users').browse(cr, uid, context) user = self.pool.get('res.users').browse(cr, uid, context)
@@ -54,7 +55,8 @@ class ReportXML(orm.Model):
('user_id', '=', uid), ('user_id', '=', uid),
('action', '!=', 'user_default')], context=context) ('action', '!=', 'user_default')], context=context)
if act_ids: if act_ids:
user_action = printing_act_obj.browse(cr, uid, act_ids[0], context=context) user_action = printing_act_obj.browse(
cr, uid, act_ids[0], context=context)
if user_action.tray_id: if user_action.tray_id:
tray = user_action.tray_id tray = user_action.tray_id

View File

@@ -30,8 +30,9 @@ class Printer(orm.Model):
_inherit = 'printing.printer' _inherit = 'printing.printer'
_columns = { _columns = {
'tray_ids': fields.one2many('printing.tray', 'printer_id', 'Paper Sources'), 'tray_ids': fields.one2many('printing.tray', 'printer_id',
} 'Paper Sources'),
}
def _update_tray_option(self, db_name, uid, printer, context=None): def _update_tray_option(self, db_name, uid, printer, context=None):
""" """
@@ -54,12 +55,13 @@ class Printer(orm.Model):
return return
try: try:
for tray_opt in option.choices: for tray_opt in option.choices:
if tray_opt['choice'] not in [t.system_name for t in printer.tray_ids]: if tray_opt['choice'] not in [
t.system_name for t in printer.tray_ids]:
tray_vals = { tray_vals = {
'name': tray_opt['text'], 'name': tray_opt['text'],
'system_name': tray_opt['choice'], 'system_name': tray_opt['choice'],
'printer_id': printer.id, 'printer_id': printer.id,
} }
tray_obj.create(cr, uid, tray_vals, context=context) tray_obj.create(cr, uid, tray_vals, context=context)
cr.commit() cr.commit()
@@ -76,7 +78,8 @@ class Printer(orm.Model):
""" """
db, pool = pooler.get_db_and_pool(db_name) db, pool = pooler.get_db_and_pool(db_name)
cr = db.cursor() cr = db.cursor()
res = super(Printer, self).update_printers_status(db_name, uid, context=context) res = super(Printer, self).update_printers_status(db_name, uid,
context=context)
try: try:
connection = cups.Connection() connection = cups.Connection()
printers = connection.getPrinters() printers = connection.getPrinters()
@@ -84,7 +87,9 @@ class Printer(orm.Model):
except: except:
server_error = True server_error = True
printer_ids = self.search(cr, uid, [('system_name', 'in', printers.keys())], context=context) printer_ids = self.search(cr, uid,
[('system_name', 'in', printers.keys())],
context=context)
if server_error: if server_error:
vals = {'status': 'server_error'} vals = {'status': 'server_error'}
self.write(cr, uid, printer_ids, vals, context=context) self.write(cr, uid, printer_ids, vals, context=context)
@@ -95,5 +100,6 @@ class Printer(orm.Model):
for printer in printer_list: for printer in printer_list:
# XXX we consider config of printer won't change # XXX we consider config of printer won't change
if not printer.tray_ids: if not printer.tray_ids:
self._update_tray_option(db_name, uid, printer, context=context) self._update_tray_option(db_name, uid, printer,
context=context)
return res return res

View File

@@ -29,5 +29,6 @@ class PrinterTray(orm.Model):
_columns = { _columns = {
'name': fields.char('Name', size=64, required=True), 'name': fields.char('Name', size=64, required=True),
'system_name': fields.char('System Name', size=64, required=True), 'system_name': fields.char('System Name', size=64, required=True),
'printer_id': fields.many2one('printing.printer', 'Printer', required=True), 'printer_id': fields.many2one('printing.printer', 'Printer',
} required=True),
}

View File

@@ -29,10 +29,11 @@ class ReportXMLAction(orm.Model):
'printer_tray_id': fields.many2one( 'printer_tray_id': fields.many2one(
'printing.tray', 'Paper Source', 'printing.tray', 'Paper Source',
domain="[('printer_id', '=', printer_id)]"), domain="[('printer_id', '=', printer_id)]"),
} }
def behaviour(self, cr, uid, act_id, context=None): def behaviour(self, cr, uid, act_id, context=None):
res = super(ReportXMLAction, self).behaviour(cr, uid, act_id, context=context) res = super(ReportXMLAction, self).behaviour(cr, uid, act_id,
context=context)
action = self.browse(cr, uid, act_id, context=context) action = self.browse(cr, uid, act_id, context=context)
res['tray'] = action.printer_tray_id.system_name res['tray'] = action.printer_tray_id.system_name
return res return res

View File

@@ -29,4 +29,4 @@ class ResUsers(orm.Model):
'printer_tray_id': fields.many2one( 'printer_tray_id': fields.many2one(
'printing.tray', 'Default Printer Paper Source', 'printing.tray', 'Default Printer Paper Source',
domain="[('printer_id', '=', printing_printer_id)]"), domain="[('printer_id', '=', printing_printer_id)]"),
} }