[MIG] base_report_to_printer: Upgrade to v9

This commit is contained in:
Dave Lasley
2016-07-04 14:36:57 -07:00
committed by trisdoan
parent 39783eee72
commit 49fdb7f19a
37 changed files with 955 additions and 674 deletions

View File

@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from . import ir_actions_report_xml
from . import printing_action
from . import printing_printer
from . import printing_report_xml_action
from . import report
from . import res_users

View File

@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2007 Ferran Pegueroles <ferran@pegueroles.com>
# Copyright (c) 2009 Albert Cervera i Areny <albert@nan-tic.com>
# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>)
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
class IrActionsReportXml(models.Model):
"""
Reports
"""
_inherit = 'ir.actions.report.xml'
property_printing_action_id = fields.Many2one(
comodel_name='printing.action',
string='Action',
company_dependent=True,
)
printing_printer_id = fields.Many2one(
comodel_name='printing.printer',
string='Printer'
)
printing_action_ids = fields.One2many(
comodel_name='printing.report.xml.action',
inverse_name='report_id',
string='Actions',
help='This field allows configuring action and printer on a per '
'user basis'
)
@api.model
def print_action_for_report_name(self, report_name):
""" Returns if the action is a direct print or pdf
Called from js
"""
report_obj = self.env['report']
report = report_obj._get_report_from_name(report_name)
if not report:
return {}
result = report.behaviour()[report.id]
serializable_result = {
'action': result['action'],
'printer_name': result['printer'].name,
}
return serializable_result
@api.multi
def behaviour(self):
result = {}
printer_obj = self.env['printing.printer']
printing_act_obj = self.env['printing.report.xml.action']
# Set hardcoded default action
default_action = 'client'
# Retrieve system wide printer
default_printer = printer_obj.get_default()
# Retrieve user default values
user = self.env.user
if user.printing_action:
default_action = user.printing_action
if user.printing_printer_id:
default_printer = user.printing_printer_id
for report in self:
action = default_action
printer = default_printer
# Retrieve report default values
report_action = report.property_printing_action_id
if report_action and report_action.type != 'user_default':
action = report_action.type
if report.printing_printer_id:
printer = report.printing_printer_id
# Retrieve report-user specific values
print_action = printing_act_obj.search(
[('report_id', '=', report.id),
('user_id', '=', self.env.uid),
('action', '!=', 'user_default')],
limit=1)
if print_action:
user_action = print_action.behaviour()
action = user_action['action']
if user_action['printer']:
printer = user_action['printer']
result[report.id] = {'action': action,
'printer': printer,
}
return result

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2007 Ferran Pegueroles <ferran@pegueroles.com>
# Copyright (c) 2009 Albert Cervera i Areny <albert@nan-tic.com>
# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>)
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
@api.model
def _available_action_types(self):
return [('server', 'Send to Printer'),
('client', 'Send to Client'),
('user_default', "Use user's defaults"),
]
class PrintingAction(models.Model):
_name = 'printing.action'
_description = 'Print Job Action'
name = fields.Char(required=True)
type = fields.Selection(
lambda s: _available_action_types(s),
required=True,
)

View File

@@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2007 Ferran Pegueroles <ferran@pegueroles.com>
# Copyright (c) 2009 Albert Cervera i Areny <albert@nan-tic.com>
# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>)
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import os
from tempfile import mkstemp
from openerp import models, fields, api, _
from openerp.exceptions import UserError
from openerp.tools.config import config
_logger = logging.getLogger(__name__)
try:
import cups
except ImportError:
_logger.debug('Cannot `import cups`.')
CUPS_HOST = config.get('cups_host', 'localhost')
CUPS_PORT = int(config.get('cups_port', 631)) # config.get returns a string
class PrintingPrinter(models.Model):
"""
Printers
"""
_name = 'printing.printer'
_description = 'Printer'
_order = 'name'
name = fields.Char(required=True, select=True)
system_name = fields.Char(required=True, select=True)
default = fields.Boolean(readonly=True)
status = fields.Selection([('unavailable', 'Unavailable'),
('printing', 'Printing'),
('unknown', 'Unknown'),
('available', 'Available'),
('error', 'Error'),
('server-error', 'Server Error')],
required=True,
readonly=True,
default='unknown')
status_message = fields.Char(readonly=True)
model = fields.Char(readonly=True)
location = fields.Char(readonly=True)
uri = fields.Char(string='URI', readonly=True)
@api.model
def update_printers_status(self, domain=None):
if domain is None:
domain = []
printer_recs = self.search(domain)
try:
connection = cups.Connection(CUPS_HOST, CUPS_PORT)
printers = connection.getPrinters()
except:
printer_recs.write({'status': 'server-error'})
else:
for printer in printer_recs:
cups_printer = printers.get(printer.system_name)
if cups_printer:
printer.update_from_cups(connection, cups_printer)
else:
# not in cups list
printer.status = 'unavailable'
return True
@api.multi
def _prepare_update_from_cups(self, cups_connection, cups_printer):
mapping = {
3: 'available',
4: 'printing',
5: 'error'
}
vals = {
'model': cups_printer.get('printer-make-and-model', False),
'location': cups_printer.get('printer-location', False),
'uri': cups_printer.get('device-uri', False),
'status': mapping.get(cups_printer['printer-state'], 'unknown'),
}
return vals
@api.multi
def update_from_cups(self, cups_connection, cups_printer):
""" Update a printer from the information returned by cups.
:param cups_connection: connection to CUPS, may be used when the
method is overriden (e.g. in printer_tray)
:param cups_printer: dict of information returned by CUPS for the
current printer
"""
self.ensure_one()
vals = self._prepare_update_from_cups(cups_connection, cups_printer)
if any(self[name] != value for name, value in vals.iteritems()):
self.write(vals)
@api.multi
def print_options(self, report, format, copies=1):
""" Hook to set print options """
options = {}
if format == 'raw':
options['raw'] = 'True'
if copies > 1:
options['copies'] = str(copies)
return options
@api.multi
def print_document(self, report, content, format, copies=1):
""" Print a file
Format could be pdf, qweb-pdf, raw, ...
"""
self.ensure_one()
fd, file_name = mkstemp()
try:
os.write(fd, content)
finally:
os.close(fd)
try:
_logger.debug(
'Starting to connect to CUPS on %s:%s'
% (CUPS_HOST, CUPS_PORT))
connection = cups.Connection(CUPS_HOST, CUPS_PORT)
_logger.debug('Connection to CUPS successfull')
except:
raise UserError(
_("Failed to connect to the CUPS server on %s:%s. "
"Check that the CUPS server is running and that "
"you can reach it from the Odoo server.")
% (CUPS_HOST, CUPS_PORT))
options = self.print_options(report, format, copies)
_logger.debug(
'Sending job to CUPS printer %s on %s'
% (self.system_name, CUPS_HOST))
connection.printFile(self.system_name,
file_name,
file_name,
options=options)
_logger.info("Printing job: '%s' on %s" % (file_name, CUPS_HOST))
return True
@api.multi
def set_default(self):
if not self:
return
self.ensure_one()
default_printers = self.search([('default', '=', True)])
default_printers.write({'default': False})
self.write({'default': True})
return True
@api.multi
def get_default(self):
return self.search([('default', '=', True)], limit=1)

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2007 Ferran Pegueroles <ferran@pegueroles.com>
# Copyright (c) 2009 Albert Cervera i Areny <albert@nan-tic.com>
# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>)
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
from .printing_action import _available_action_types
class PrintingReportXmlAction(models.Model):
_name = 'printing.report.xml.action'
_description = 'Printing Report Printing Actions'
report_id = fields.Many2one(comodel_name='ir.actions.report.xml',
string='Report',
required=True,
ondelete='cascade')
user_id = fields.Many2one(comodel_name='res.users',
string='User',
required=True,
ondelete='cascade')
action = fields.Selection(
lambda s: _available_action_types(s),
required=True,
)
printer_id = fields.Many2one(comodel_name='printing.printer',
string='Printer')
@api.multi
def behaviour(self):
if not self:
return {}
return {'action': self.action,
'printer': self.printer_id,
}

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2014 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, exceptions, _, api
class Report(models.Model):
_inherit = 'report'
@api.multi
def print_document(self, report_name, html=None, data=None):
""" Print a document, do not return the document file """
res = []
context = self.env.context
if context is None:
context = self.env['res.users'].context_get()
local_context = context.copy()
local_context['must_skip_send_to_printer'] = True
for rec_id in self.with_context(local_context):
document = rec_id.get_pdf(report_name, html=html, data=data)
report = self._get_report_from_name(report_name)
behaviour = report.behaviour()[report.id]
printer = behaviour['printer']
if not printer:
raise exceptions.Warning(
_('No printer configured to print this report.')
)
res.append(
printer.print_document(report, document, report.report_type)
)
return all(res)
@api.multi
def _can_print_report(self, behaviour, printer, document):
"""Predicate that decide if report can be sent to printer
If you want to prevent `get_pdf` to send report you can set
the `must_skip_send_to_printer` key to True in the context
"""
if self.env.context.get('must_skip_send_to_printer'):
return False
if behaviour['action'] == 'server' and printer and document:
return True
return False
@api.v7
def get_pdf(self, cr, uid, ids, report_name, html=None,
data=None, context=None):
""" Generate a PDF and returns it.
If the action configured on the report is server, it prints the
generated document as well.
"""
document = super(Report, self).get_pdf(cr, uid, ids, report_name,
html=html, data=data,
context=context)
report = self._get_report_from_name(cr, uid, report_name)
behaviour = report.behaviour()[report.id]
printer = behaviour['printer']
can_print_report = self._can_print_report(cr, uid, ids,
behaviour, printer, document,
context=context)
if can_print_report:
printer.print_document(report, document, report.report_type)
return document
@api.v8
def get_pdf(self, records, report_name, html=None, data=None):
return self._model.get_pdf(self._cr, self._uid,
records.ids, report_name,
html=html, data=data, context=self._context)

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2007 Ferran Pegueroles <ferran@pegueroles.com>
# Copyright (c) 2009 Albert Cervera i Areny <albert@nan-tic.com>
# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>)
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
from .printing_action import _available_action_types
class ResUsers(models.Model):
_inherit = 'res.users'
printing_action = fields.Selection(
lambda s: s._user_available_action_types(),
)
printing_printer_id = fields.Many2one(comodel_name='printing.printer',
string='Default Printer')
@api.model
def _available_action_types(self):
return _available_action_types(self)
@api.model
def _user_available_action_types(self):
return [(code, string) for code, string
in self._available_action_types()
if code != 'user_default']