From 4d8657315e587825c6fca007a66517bacaa3e57e Mon Sep 17 00:00:00 2001 From: Graeme Gellatly Date: Fri, 6 Oct 2017 01:16:33 +1300 Subject: [PATCH] [WIP] Commit before rebase on latest #109 for user and view updates Migration of printer_tray to v11 and integration with base_report_to_printer --- base_report_to_printer/README.rst | 28 +- base_report_to_printer/__manifest__.py | 4 +- base_report_to_printer/models/__init__.py | 1 + .../models/ir_actions_report.py | 10 + .../models/printing_printer.py | 75 +++- .../models/printing_report_xml_action.py | 12 + .../models/printing_tray.py | 22 ++ base_report_to_printer/models/res_users.py | 12 + base_report_to_printer/security/security.xml | 203 ++++++----- base_report_to_printer/tests/__init__.py | 2 + .../tests/test_ir_actions_report.py | 31 ++ .../tests/test_printing_printer_tray.py | 330 ++++++++++++++++++ .../tests/test_printing_report_xml_action.py | 31 ++ .../tests/test_printing_tray.py | 52 +++ .../tests/test_res_users.py | 31 ++ .../views/ir_actions_report.xml | 1 + .../views/printing_printer.xml | 18 +- .../views/printing_report.xml | 61 ++-- 18 files changed, 788 insertions(+), 136 deletions(-) create mode 100644 base_report_to_printer/models/printing_tray.py create mode 100644 base_report_to_printer/tests/test_printing_printer_tray.py create mode 100644 base_report_to_printer/tests/test_printing_tray.py diff --git a/base_report_to_printer/README.rst b/base_report_to_printer/README.rst index 976216d36bf..ecce690c164 100644 --- a/base_report_to_printer/README.rst +++ b/base_report_to_printer/README.rst @@ -8,18 +8,25 @@ Report To Printer This module allows users to send reports to a printer attached to the server. - It adds an optional behaviour on reports to send it directly to a printer. * `Send to Client` is the default behaviour providing you a downloadable PDF * `Send to Printer` prints the report on selected printer +It detects trays on printers installation plus permits to select the +paper source on which you want to print directly. + Report behaviour is defined by settings. +You will find this option on default user config, on default report +config and on specific config per user per report. + +This allows you to dedicate a specific paper source for example for +preprinted paper such as payment slip. Settings can be configured: -* globaly +* globally * per user * per report * per user and report @@ -47,12 +54,17 @@ rights to give users the ability to view the print menu. Usage ===== -To show all available printers for your server, use the -`Settings/Configuration/Printing/Update Printers from CUPS` wizard. - + * To update the CUPS printers in *Settings > Printing > Update Printers + from CUPS* + * If you want to print a report on a specific printer or tray, you can change + these in *Settings > Printing > Reports* to define default behaviour. + * If you want to print a report on a specific printer and/or tray for a user, you can + change these in *Settings > Printing > Reports* in + *Specific actions per user* + * Users may also select a default action, printer or tray in their preferences -Then go to the user profile and set the users printing action and default -printer. +When no tray is configured for a report and a user, the +default tray setup on the CUPS server is used. Caveat ------ @@ -62,7 +74,7 @@ displayed for the deprecated report types (RML, Webkit, ...). .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/144/9.0 + :target: https://runbot.odoo-community.org/runbot/144/11.0 Known issues / Roadmap diff --git a/base_report_to_printer/__manifest__.py b/base_report_to_printer/__manifest__.py index 313e91a0676..a3775b5a718 100644 --- a/base_report_to_printer/__manifest__.py +++ b/base_report_to_printer/__manifest__.py @@ -8,10 +8,10 @@ { 'name': "Report to printer", - 'version': '11.0.1.0.1', + 'version': '11.0.2.0.0', 'category': 'Generic Modules/Base', 'author': "Agile Business Group & Domsense, Pegueroles SCP, NaN," - " LasLabs, Odoo Community Association (OCA)", + " LasLabs, Camptocamp, Odoo Community Association (OCA)", 'website': 'http://www.agilebg.com', 'license': 'AGPL-3', "depends": ['web'], diff --git a/base_report_to_printer/models/__init__.py b/base_report_to_printer/models/__init__.py index 2d903d12bd2..ea1b173bf2e 100644 --- a/base_report_to_printer/models/__init__.py +++ b/base_report_to_printer/models/__init__.py @@ -6,4 +6,5 @@ from . import printing_printer from . import printing_server from . import printing_report_xml_action +from . import printing_tray from . import res_users diff --git a/base_report_to_printer/models/ir_actions_report.py b/base_report_to_printer/models/ir_actions_report.py index d6202284686..e9108ebfffe 100644 --- a/base_report_to_printer/models/ir_actions_report.py +++ b/base_report_to_printer/models/ir_actions_report.py @@ -21,6 +21,11 @@ class IrActionsReport(models.Model): comodel_name='printing.printer', string='Default Printer' ) + printer_tray_id = fields.Many2one( + comodel_name='printing.tray', + string='Paper Source', + domain="[('printer_id', '=', printing_printer_id)]", + ) printing_action_ids = fields.One2many( comodel_name='printing.report.xml.action', inverse_name='report_id', @@ -29,6 +34,11 @@ class IrActionsReport(models.Model): 'user basis' ) + @api.onchange('printing_printer_id') + def onchange_printing_printer_id(self): + """ Reset the tray when the printer is changed """ + self.printer_tray_id = False + @api.model def print_action_for_report_name(self, report_name): """ Returns if the action is a direct print or pdf diff --git a/base_report_to_printer/models/printing_printer.py b/base_report_to_printer/models/printing_printer.py index 51880ffc108..44a454f6f48 100644 --- a/base_report_to_printer/models/printing_printer.py +++ b/base_report_to_printer/models/printing_printer.py @@ -7,8 +7,8 @@ # Copyright (C) 2016 SYLEAM () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import errno import logging - import os from tempfile import mkstemp @@ -17,6 +17,11 @@ _logger = logging.getLogger(__name__) +try: + import cups +except ImportError: + _logger.debug('Cannot `import cups`.') + class PrintingPrinter(models.Model): """ @@ -52,6 +57,55 @@ class PrintingPrinter(models.Model): model = fields.Char(readonly=True) location = fields.Char(readonly=True) uri = fields.Char(string='URI', readonly=True) + tray_ids = fields.One2many(comodel_name='printing.tray', + inverse_name='printer_id', + string='Paper Sources') + + @api.multi + def _prepare_update_from_cups(self, cups_connection, cups_printer): + vals = super(PrintingPrinter, self)._prepare_update_from_cups( + cups_connection, cups_printer) + + printer_uri = cups_printer['printer-uri-supported'] + printer_system_name = printer_uri[printer_uri.rfind('/') + 1:] + ppd_info = cups_connection.getPPD3(printer_system_name) + ppd_path = ppd_info[2] + if not ppd_path: + return vals + + ppd = cups.PPD(ppd_path) + option = ppd.findOption('InputSlot') + try: + os.unlink(ppd_path) + except OSError as err: + # ENOENT means No such file or directory + # The file has already been deleted, we can continue the update + if err.errno != errno.ENOENT: + raise + if not option: + return vals + + vals['tray_ids'] = [] + cups_trays = { + tray_option['choice']: tray_option['text'] + for tray_option in option.choices + } + + # Add new trays + vals['tray_ids'].extend([ + (0, 0, {'name': text, 'system_name': choice}) + for choice, text in cups_trays.items() + if choice not in self.tray_ids.mapped('system_name') + ]) + + # Remove deleted trays + vals['tray_ids'].extend([ + (2, tray.id) + for tray in self.tray_ids.filtered( + lambda record: record.system_name not in cups_trays.keys()) + ]) + + return vals @api.multi def _prepare_update_from_cups(self, cups_connection, cups_printer): @@ -79,6 +133,25 @@ def print_options(self, report=None, format=None, copies=1): options['raw'] = 'True' if copies > 1: options['copies'] = str(copies) + if report is not None: + printing_act_obj = self.env['printing.report.xml.action'] + if report.printer_tray_id: + tray = report.printer_tray_id + else: + # Retrieve user default values + tray = self.env.user.printer_tray_id + + # Retrieve report-user specific values + action = printing_act_obj.search([ + ('report_id', '=', report.id), + ('user_id', '=', self.env.uid), + ('action', '!=', 'user_default'), + ], limit=1) + if action.printer_tray_id: + tray = action.printer_tray_id + + if tray: + options['InputSlot'] = str(tray.system_name) return options @api.multi diff --git a/base_report_to_printer/models/printing_report_xml_action.py b/base_report_to_printer/models/printing_report_xml_action.py index ccc27b4e549..018c07942b1 100644 --- a/base_report_to_printer/models/printing_report_xml_action.py +++ b/base_report_to_printer/models/printing_report_xml_action.py @@ -28,6 +28,17 @@ class PrintingReportXmlAction(models.Model): printer_id = fields.Many2one(comodel_name='printing.printer', string='Printer') + printer_tray_id = fields.Many2one( + comodel_name='printing.tray', + string='Paper Source', + domain="[('printer_id', '=', printer_id)]", + ) + + @api.onchange('printer_id') + def onchange_printer_id(self): + """ Reset the tray when the printer is changed """ + self.printer_tray_id = False + @api.multi def behaviour(self): if not self: @@ -35,4 +46,5 @@ def behaviour(self): return { 'action': self.action, 'printer': self.printer_id, + 'tray': self.printer_tray_id.system_name } diff --git a/base_report_to_printer/models/printing_tray.py b/base_report_to_printer/models/printing_tray.py new file mode 100644 index 00000000000..da12e703e30 --- /dev/null +++ b/base_report_to_printer/models/printing_tray.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2013-2014 Camptocamp () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class PrinterTray(models.Model): + _name = 'printing.tray' + _description = 'Printer Tray' + + _order = 'name asc' + + name = fields.Char(required=True) + system_name = fields.Char(required=True, readonly=True) + printer_id = fields.Many2one( + comodel_name='printing.printer', + string='Printer', + required=True, + readonly=True, + ondelete='cascade', + ) diff --git a/base_report_to_printer/models/res_users.py b/base_report_to_printer/models/res_users.py index 092a00bd9e6..7fa6b7dca41 100644 --- a/base_report_to_printer/models/res_users.py +++ b/base_report_to_printer/models/res_users.py @@ -37,3 +37,15 @@ def _register_hook(self): 'printing_action', 'printing_printer_id', ]) + + printer_tray_id = fields.Many2one( + comodel_name='printing.tray', + string='Default Printer Paper Source', + domain="[('printer_id', '=', printing_printer_id)]", + ) + + @api.onchange('printing_printer_id') + def onchange_printing_printer_id(self): + """ Reset the tray when the printer is changed """ + self.printer_tray_id = False + diff --git a/base_report_to_printer/security/security.xml b/base_report_to_printer/security/security.xml index 5bf2761b7ce..83eac3ff064 100644 --- a/base_report_to_printer/security/security.xml +++ b/base_report_to_printer/security/security.xml @@ -1,96 +1,115 @@ - - - Printing / Print Manager - - - - Printing / Print User - - - Printing Server Manager - - - - - - - - - Printing Printer Manager - - - - - - - - - Printing Action Manager - - - - - - - - - Printing Report Xml Action Manager - - - - - - - + + + Printing / Print Manager + + + + Printing / Print User + + + Printing Server Manager + + + + + + + + + Printing Printer Manager + + + + + + + + + Printing Action Manager + + + + + + + + + Printing Report Xml Action Manager + + + + + + + - - - - Printing Server User - - - - - - - - - Printing Printer User - - - - - - - - - Printing Job User - - - - - - - - - Printing Action User - - - - - - - - - Printing Report Xml Action User - - - - - - - - + + + + Printing Server User + + + + + + + + + Printing Printer User + + + + + + + + + Printing Job User + + + + + + + + + Printing Action User + + + + + + + + + Printing Report Xml Action User + + + + + + + + + + Printing Tray User + + + + + + + + + Printing Tray User + + + + + + + + diff --git a/base_report_to_printer/tests/__init__.py b/base_report_to_printer/tests/__init__.py index 49a8da58161..0f52428ee54 100644 --- a/base_report_to_printer/tests/__init__.py +++ b/base_report_to_printer/tests/__init__.py @@ -4,7 +4,9 @@ from . import test_printing_job from . import test_printing_printer +from . import test_printing_printer_tray from . import test_printing_server +from . import test_printing_tray from . import test_report from . import test_res_users from . import test_ir_actions_report diff --git a/base_report_to_printer/tests/test_ir_actions_report.py b/base_report_to_printer/tests/test_ir_actions_report.py index 25f6e16617e..172b80410f8 100644 --- a/base_report_to_printer/tests/test_ir_actions_report.py +++ b/base_report_to_printer/tests/test_ir_actions_report.py @@ -204,3 +204,34 @@ def test_behaviour_printing_action_user_defaults(self): 'printer': report.printing_printer_id, }, }) + + def test_onchange_printer_tray_id_empty(self): + action = self.env['ir.actions.report'].new( + {'printer_tray_id': False}) + action.onchange_printing_printer_id() + self.assertFalse(action.printer_tray_id) + + def test_onchange_printer_tray_id_not_empty(self): + server = self.env['printing.server'].create({}) + printer = self.env['printing.printer'].create({ + 'name': 'Printer', + 'server_id': server.id, + 'system_name': 'Sys Name', + 'default': True, + 'status': 'unknown', + 'status_message': 'Msg', + 'model': 'res.users', + 'location': 'Location', + 'uri': 'URI', + }) + tray = self.env['printing.tray'].create({ + 'name': 'Tray', + 'system_name': 'TrayName', + 'printer_id': printer.id, + }) + + action = self.env['ir.actions.report'].new( + {'printer_tray_id': tray.id}) + self.assertEqual(action.printer_tray_id, tray) + action.onchange_printing_printer_id() + self.assertFalse(action.printer_tray_id) diff --git a/base_report_to_printer/tests/test_printing_printer_tray.py b/base_report_to_printer/tests/test_printing_printer_tray.py new file mode 100644 index 00000000000..7fe7dcb7b1c --- /dev/null +++ b/base_report_to_printer/tests/test_printing_printer_tray.py @@ -0,0 +1,330 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import errno +import mock +import tempfile +from odoo.tests.common import TransactionCase + + +model = 'odoo.addons.base_report_to_printer.models.printing_printer' +server_model = 'odoo.addons.base_report_to_printer.models.printing_server' + +ppd_header = '*PPD-Adobe: "4.3"' +ppd_input_slot_header = """ +*OpenUI *InputSlot: PickOne +*DefaultInputSlot: Auto +*InputSlot Auto/Auto (Default): " + << /DeferredMediaSelection true /ManualFeed false + /MediaPosition null /MediaType null >> setpagedevice + userdict /TSBMediaType 0 put" +*End +""" +ppd_input_slot_body = """ +*InputSlot {name}/{text}: " + << /DeferredMediaSelection true /ManualFeed false + /MediaPosition null /MediaType null >> setpagedevice + userdict /TSBMediaType 0 put" +*End +""" +ppd_input_slot_footer = """ +*CloseUI: *InputSlot +""" + + +class TestPrintingPrinter(TransactionCase): + + def setUp(self): + super(TestPrintingPrinter, self).setUp() + self.Model = self.env['printing.printer'] + self.ServerModel = self.env['printing.server'] + self.server = self.env['printing.server'].create({}) + self.printer = self.env['printing.printer'].create({ + 'name': 'Printer', + 'server_id': self.server.id, + 'system_name': 'Sys Name', + 'default': True, + 'status': 'unknown', + 'status_message': 'Msg', + 'model': 'res.users', + 'location': 'Location', + 'uri': 'URI', + }) + self.tray_vals = { + 'name': 'Tray', + 'system_name': 'TrayName', + 'printer_id': self.printer.id, + } + + def new_tray(self, vals=None): + values = self.tray_vals + if vals is not None: + values.update(vals) + return self.env['printing.tray'].create(values) + + def build_ppd(self, input_slots=None): + """ + Builds a fake PPD file declaring defined input slots + """ + ppd_contents = ppd_header + ppd_contents += ppd_input_slot_header + if input_slots is not None: + for input_slot in input_slots: + ppd_contents += ppd_input_slot_body.format( + name=input_slot['name'], + text=input_slot['text'], + ) + ppd_contents += ppd_input_slot_footer + + return ppd_contents + + def mock_cups_ppd(self, cups, file_name=None, input_slots=None): + """ + Create a fake PPD file (if needed), then mock the getPPD3 method + return value to give that file + """ + if file_name is None: + fd, file_name = tempfile.mkstemp() + + if file_name: + ppd_contents = self.build_ppd(input_slots=input_slots) + with open(file_name, 'w') as fp: + fp.write(ppd_contents) + + cups.Connection().getPPD3.return_value = (200, 0, file_name) + cups.Connection().getPrinters.return_value = { + self.printer.system_name: { + 'printer-info': 'info', + 'printer-uri-supported': 'uri', + }, + } + + def test_print_options(self): + """ + It should generate the right options dictionnary + """ + report = self.env['ir.actions.report'].search([], limit=1) + action = self.env['printing.report.xml.action'].create({ + 'user_id': self.env.user.id, + 'report_id': report.id, + 'action': 'server', + }) + user_tray = self.new_tray({ + 'system_name': 'User tray', + }) + report_tray = self.new_tray({ + 'system_name': 'Report tray', + }) + action_tray = self.new_tray({ + 'system_name': 'Action tray', + }) + + # No report passed + self.env.user.printer_tray_id = False + options = self.Model.print_options() + self.assertFalse('InputSlot' in options) + + # No tray defined + self.env.user.printer_tray_id = False + report.printer_tray_id = False + action.printer_tray_id = False + options = self.Model.print_options(report, 'pdf') + self.assertFalse('InputSlot' in options) + + # Only user tray is defined + self.env.user.printer_tray_id = user_tray + report.printer_tray_id = False + action.printer_tray_id = False + options = self.Model.print_options(report, 'pdf') + self.assertEquals(options, { + 'InputSlot': 'User tray', + }) + + # Only report tray is defined + self.env.user.printer_tray_id = False + report.printer_tray_id = report_tray + action.printer_tray_id = False + options = self.Model.print_options(report, 'pdf') + self.assertEquals(options, { + 'InputSlot': 'Report tray', + }) + + # Only action tray is defined + self.env.user.printer_tray_id = False + report.printer_tray_id = False + action.printer_tray_id = action_tray + options = self.Model.print_options(report, 'pdf') + self.assertEquals(options, { + 'InputSlot': 'Action tray', + }) + + # All trays are defined + self.env.user.printer_tray_id = user_tray + report.printer_tray_id = report_tray + action.printer_tray_id = action_tray + options = self.Model.print_options(report, 'pdf') + self.assertEquals(options, { + 'InputSlot': 'Action tray', + }) + + @mock.patch('%s.cups' % server_model) + def test_update_printers(self, cups): + """ + Check that the update_printers method calls _prepare_update_from_cups + """ + self.mock_cups_ppd(cups, file_name=False) + + self.assertEqual(self.printer.name, 'Printer') + self.ServerModel.update_printers() + self.assertEqual(self.printer.name, 'info') + + @mock.patch('%s.cups' % server_model) + def test_prepare_update_from_cups_no_ppd(self, cups): + """ + Check that the tray_ids field has no value when no PPD is available + """ + self.mock_cups_ppd(cups, file_name=False) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertFalse('tray_ids' in vals) + + @mock.patch('%s.cups' % server_model) + def test_prepare_update_from_cups_empty_ppd(self, cups): + """ + Check that the tray_ids field has no value when the PPD file has + no input slot declared + """ + fd, file_name = tempfile.mkstemp() + self.mock_cups_ppd(cups, file_name=file_name) + # Replace the ppd file's contents by an empty file + with open(file_name, 'w') as fp: + fp.write(ppd_header) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertFalse('tray_ids' in vals) + + @mock.patch('%s.cups' % server_model) + @mock.patch('os.unlink') + def test_prepare_update_from_cups_unlink_error(self, os_unlink, cups): + """ + When OSError other than ENOENT is encountered, the exception is raised + """ + # Break os.unlink + os_unlink.side_effect = OSError(errno.EIO, 'Error') + + self.mock_cups_ppd(cups) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + with self.assertRaises(OSError): + self.printer._prepare_update_from_cups(connection, cups_printer) + + @mock.patch('%s.cups' % server_model) + @mock.patch('os.unlink') + def test_prepare_update_from_cups_unlink_error_enoent( + self, os_unlink, cups): + """ + When a ENOENT error is encountered, the file has already been unlinked + + This is not an issue, as we were trying to delete the file. + The update can continue. + """ + # Break os.unlink + os_unlink.side_effect = OSError(errno.ENOENT, 'Error') + + self.mock_cups_ppd(cups) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertEqual(vals['tray_ids'], [(0, 0, { + 'name': 'Auto (Default)', + 'system_name': 'Auto', + })]) + + @mock.patch('%s.cups' % server_model) + def test_prepare_update_from_cups(self, cups): + """ + Check the return value when adding a single tray + """ + self.mock_cups_ppd(cups) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertEqual(vals['tray_ids'], [(0, 0, { + 'name': 'Auto (Default)', + 'system_name': 'Auto', + })]) + + @mock.patch('%s.cups' % server_model) + def test_prepare_update_from_cups_with_multiple_trays(self, cups): + """ + Check the return value when adding multiple trays at once + """ + self.mock_cups_ppd(cups, input_slots=[ + {'name': 'Tray1', 'text': 'Tray 1'}, + ]) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertItemsEqual(vals['tray_ids'], [(0, 0, { + 'name': 'Auto (Default)', + 'system_name': 'Auto', + }), (0, 0, { + 'name': 'Tray 1', + 'system_name': 'Tray1', + })]) + + @mock.patch('%s.cups' % server_model) + def test_prepare_update_from_cups_already_known_trays(self, cups): + """ + Check that calling the method twice doesn't create the trays multiple + times + """ + self.mock_cups_ppd(cups, input_slots=[ + {'name': 'Tray1', 'text': 'Tray 1'}, + ]) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + # Create a tray which is in the PPD file + self.new_tray({'system_name': 'Tray1'}) + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertEqual(vals['tray_ids'], [(0, 0, { + 'name': 'Auto (Default)', + 'system_name': 'Auto', + })]) + + @mock.patch('%s.cups' % server_model) + def test_prepare_update_from_cups_unknown_trays(self, cups): + """ + Check that trays which are not in the PPD file are removed from Odoo + """ + self.mock_cups_ppd(cups) + + connection = cups.Connection() + cups_printer = connection.getPrinters()[self.printer.system_name] + + # Create a tray which is absent from the PPD file + tray = self.new_tray() + + vals = self.printer._prepare_update_from_cups(connection, cups_printer) + self.assertEqual(vals['tray_ids'], [(0, 0, { + 'name': 'Auto (Default)', + 'system_name': 'Auto', + }), (2, tray.id)]) diff --git a/base_report_to_printer/tests/test_printing_report_xml_action.py b/base_report_to_printer/tests/test_printing_report_xml_action.py index 4020dbd7bc3..ce81f1fe0d8 100644 --- a/base_report_to_printer/tests/test_printing_report_xml_action.py +++ b/base_report_to_printer/tests/test_printing_report_xml_action.py @@ -56,3 +56,34 @@ def test_behaviour(self): }) self.assertEqual(self.Model.behaviour(), {}) + + def test_onchange_printer_tray_id_empty(self): + action = self.env['printing.report.xml.action'].new( + {'printer_tray_id': False}) + action.onchange_printer_id() + self.assertFalse(action.printer_tray_id) + + def test_onchange_printer_tray_id_not_empty(self): + server = self.env['printing.server'].create({}) + printer = self.env['printing.printer'].create({ + 'name': 'Printer', + 'server_id': server.id, + 'system_name': 'Sys Name', + 'default': True, + 'status': 'unknown', + 'status_message': 'Msg', + 'model': 'res.users', + 'location': 'Location', + 'uri': 'URI', + }) + tray = self.env['printing.tray'].create({ + 'name': 'Tray', + 'system_name': 'TrayName', + 'printer_id': printer.id, + }) + + action = self.env['printing.report.xml.action'].new( + {'printer_tray_id': tray.id}) + self.assertEqual(action.printer_tray_id, tray) + action.onchange_printer_id() + self.assertFalse(action.printer_tray_id) diff --git a/base_report_to_printer/tests/test_printing_tray.py b/base_report_to_printer/tests/test_printing_tray.py new file mode 100644 index 00000000000..ca82837576f --- /dev/null +++ b/base_report_to_printer/tests/test_printing_tray.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.tests.common import TransactionCase + + +model = 'odoo.addons.base_report_to_printer.models.printing_server' + + +class TestPrintingTray(TransactionCase): + + def setUp(self): + super(TestPrintingTray, self).setUp() + self.Model = self.env['printing.tray'] + self.server = self.env['printing.server'].create({}) + self.printer = self.env['printing.printer'].create({ + 'name': 'Printer', + 'server_id': self.server.id, + 'system_name': 'Sys Name', + 'default': True, + 'status': 'unknown', + 'status_message': 'Msg', + 'model': 'res.users', + 'location': 'Location', + 'uri': 'URI', + }) + self.tray_vals = { + 'name': 'Tray', + 'system_name': 'TrayName', + 'printer_id': self.printer.id, + } + + def new_tray(self): + return self.env['printing.tray'].create(self.tray_vals) + + def test_report_behaviour(self): + """ It should add the selected tray in the report data """ + ir_report = self.env['ir.actions.report'].search([], limit=1) + report = self.env['printing.report.xml.action'].create({ + 'user_id': self.env.user.id, + 'report_id': ir_report.id, + 'action': 'server', + }) + report.printer_tray_id = False + behaviour = report.behaviour() + self.assertEqual(behaviour['tray'], False) + + # Check that we have te right value + report.printer_tray_id = self.new_tray() + behaviour = report.behaviour() + self.assertEqual(behaviour['tray'], report.printer_tray_id.system_name) diff --git a/base_report_to_printer/tests/test_res_users.py b/base_report_to_printer/tests/test_res_users.py index f02a4c89de9..a357c78f818 100644 --- a/base_report_to_printer/tests/test_res_users.py +++ b/base_report_to_printer/tests/test_res_users.py @@ -26,3 +26,34 @@ def test_available_action_types_includes_something_else(self): """ It should still contain other valid keys """ self.user_vals['printing_action'] = 'server' self.assertTrue(self.new_record()) + + def test_onchange_printer_tray_id_empty(self): + user = self.env['res.users'].new( + {'printer_tray_id': False}) + user.onchange_printing_printer_id() + self.assertFalse(user.printer_tray_id) + + def test_onchange_printer_tray_id_not_empty(self): + server = self.env['printing.server'].create({}) + printer = self.env['printing.printer'].create({ + 'name': 'Printer', + 'server_id': server.id, + 'system_name': 'Sys Name', + 'default': True, + 'status': 'unknown', + 'status_message': 'Msg', + 'model': 'res.users', + 'location': 'Location', + 'uri': 'URI', + }) + tray = self.env['printing.tray'].create({ + 'name': 'Tray', + 'system_name': 'TrayName', + 'printer_id': printer.id, + }) + + user = self.env['res.users'].new( + {'printer_tray_id': tray.id}) + self.assertEqual(user.printer_tray_id, tray) + user.onchange_printing_printer_id() + self.assertFalse(user.printer_tray_id) diff --git a/base_report_to_printer/views/ir_actions_report.xml b/base_report_to_printer/views/ir_actions_report.xml index 33757ae8c34..91b49569add 100644 --- a/base_report_to_printer/views/ir_actions_report.xml +++ b/base_report_to_printer/views/ir_actions_report.xml @@ -11,6 +11,7 @@ + diff --git a/base_report_to_printer/views/printing_printer.xml b/base_report_to_printer/views/printing_printer.xml index acb2494eb86..bb612db8412 100644 --- a/base_report_to_printer/views/printing_printer.xml +++ b/base_report_to_printer/views/printing_printer.xml @@ -23,22 +23,32 @@ - + - +