From 43eab67b601b07b8374a8574ac32f0c37c811e12 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 31 Jan 2024 13:02:02 +0100 Subject: [PATCH] [IMP] base_report_to_printer: out of connection fallback to client If the CUPS server isn't available the user won't be able to do anything to print the report they need. At last we can give them the chance to have a fallback behavior downloading the document. TT47134 --- .../models/ir_actions_report.py | 26 ++++++++++++++++++- .../static/src/js/qweb_action_manager.esm.js | 22 +++++++++++++--- .../tests/test_ir_actions_report.py | 14 +++++----- base_report_to_printer/tests/test_report.py | 4 ++- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/base_report_to_printer/models/ir_actions_report.py b/base_report_to_printer/models/ir_actions_report.py index b7d05a5..4d8dd8c 100644 --- a/base_report_to_printer/models/ir_actions_report.py +++ b/base_report_to_printer/models/ir_actions_report.py @@ -54,6 +54,10 @@ class IrActionsReport(models.Model): "action": result["action"], "printer_name": result["printer"].name, } + if result.get("printer_exception") and not self.env.context.get( + "skip_printer_exception" + ): + serializable_result["printer_exception"] = True return serializable_result def _get_user_default_print_behaviour(self): @@ -98,6 +102,21 @@ class IrActionsReport(models.Model): # For some reason design takes report defaults over # False action entries so we must allow for that here result.update({k: v for k, v in print_action.behaviour().items() if v}) + printer = result.get("printer") + if printer: + # When no printer is available we can fallback to the default behavior + # letting the user to manually print the reports. + try: + printer.server_id._open_connection(raise_on_error=True) + printer_exception = printer.status in [ + "error", + "server-error", + "unavailable", + ] + except Exception: + printer_exception = True + if printer_exception and not self.env.context.get("skip_printer_exception"): + result["printer_exception"] = True return result def print_document(self, record_ids, data=None): @@ -141,7 +160,12 @@ class IrActionsReport(models.Model): """ if self.env.context.get("must_skip_send_to_printer"): return False - if behaviour["action"] == "server" and printer and document: + if ( + behaviour["action"] == "server" + and printer + and document + and not behaviour.get("printer_exception") + ): return True return False diff --git a/base_report_to_printer/static/src/js/qweb_action_manager.esm.js b/base_report_to_printer/static/src/js/qweb_action_manager.esm.js index f9cfd9c..7b95ed0 100644 --- a/base_report_to_printer/static/src/js/qweb_action_manager.esm.js +++ b/base_report_to_printer/static/src/js/qweb_action_manager.esm.js @@ -11,19 +11,35 @@ async function cupsReportActionHandler(action, options, env) { "print_action_for_report_name", [action.report_name] ); - if (print_action && print_action.action === "server") { + if ( + print_action && + print_action.action === "server" && + !print_action.printer_exception + ) { const result = await orm.call("ir.actions.report", "print_document", [ action.id, action.context.active_ids, action.data, ]); if (result) { - env.services.notification.add(_t("Successfully sent to printer!")); + env.services.notification.add(_t("Successfully sent to printer!"), { + type: "success", + }); } else { - env.services.notification.add(_t("Could not send to printer!")); + env.services.notification.add(_t("Could not send to printer!"), { + type: "danger", + }); } return true; } + if (print_action.printer_exception) { + env.services.notification.add( + env._t("The printer couldn't be reached. Downloading document instead"), + { + type: "warning", + } + ); + } } } 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 0ba5a87..5b5578b 100644 --- a/base_report_to_printer/tests/test_ir_actions_report.py +++ b/base_report_to_printer/tests/test_ir_actions_report.py @@ -12,10 +12,12 @@ model = "odoo.addons.base.models.ir_actions_report.IrActionsReport" class TestIrActionsReportXml(TransactionCase): def setUp(self): super().setUp() - self.Model = self.env["ir.actions.report"] + self.Model = self.env["ir.actions.report"].with_context( + skip_printer_exception=True + ) self.vals = {} - self.report = self.env["ir.actions.report"].search([], limit=1) + self.report = self.Model.search([], limit=1) self.server = self.env["printing.server"].create({}) def new_action(self): @@ -153,7 +155,7 @@ class TestIrActionsReportXml(TransactionCase): self.env.user.printing_action = "client" printing_action = self.new_printing_action() printing_action.user_id = self.env.user - printing_action.report_id = self.env["ir.actions.report"].search( + printing_action.report_id = self.Model.search( [("id", "!=", report.id)], limit=1 ) self.assertEqual( @@ -213,7 +215,7 @@ class TestIrActionsReportXml(TransactionCase): """ It should return the correct tray """ - report = self.env["ir.actions.report"].search([], limit=1) + report = self.Model.search([], limit=1) action = self.env["printing.report.xml.action"].create( {"user_id": self.env.user.id, "report_id": report.id, "action": "server"} ) @@ -266,7 +268,7 @@ class TestIrActionsReportXml(TransactionCase): self.assertEqual("Action tray", report.behaviour()["tray"]) def test_onchange_printer_tray_id_empty(self): - action = self.env["ir.actions.report"].new({"printer_tray_id": False}) + action = self.Model.new({"printer_tray_id": False}) action.onchange_printing_printer_id() self.assertFalse(action.printer_tray_id) @@ -289,7 +291,7 @@ class TestIrActionsReportXml(TransactionCase): {"name": "Tray", "system_name": "TrayName", "printer_id": printer.id} ) - action = self.env["ir.actions.report"].new({"printer_tray_id": tray.id}) + action = self.Model.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_report.py b/base_report_to_printer/tests/test_report.py index e93d0a0..e821962 100644 --- a/base_report_to_printer/tests/test_report.py +++ b/base_report_to_printer/tests/test_report.py @@ -11,7 +11,9 @@ from odoo.tests import common class TestReport(common.HttpCase): def setUp(self): super().setUp() - self.Model = self.env["ir.actions.report"] + self.Model = self.env["ir.actions.report"].with_context( + skip_printer_exception=True + ) self.server = self.env["printing.server"].create({}) self.report_vals = { "name": "Test Report",