From d71446f7d19867ebb1010a91323548b66ce7513f Mon Sep 17 00:00:00 2001 From: David Date: Wed, 31 Jan 2024 13:02:02 +0100 Subject: [PATCH 1/2] [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 bff6897..0547709 100644 --- a/base_report_to_printer/models/ir_actions_report.py +++ b/base_report_to_printer/models/ir_actions_report.py @@ -53,6 +53,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): @@ -97,6 +101,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): @@ -140,7 +159,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 0a7c369..370fd94 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 @@ -10,19 +10,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(env._t("Successfully sent to printer!")); + env.services.notification.add(env._t("Successfully sent to printer!"), { + type: "success", + }); } else { - env.services.notification.add(env._t("Could not send to printer!")); + env.services.notification.add(env._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 64332f9..e010dd8 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(TestIrActionsReportXml, self).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 7821510..d101c18 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(TestReport, self).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", From a514f470c5518faad7f859c8fae92496c714cd1a Mon Sep 17 00:00:00 2001 From: David Date: Wed, 9 Oct 2024 12:14:39 +0200 Subject: [PATCH 2/2] [FIX] base_report_to_label_printer: adapt to printer exceptions handling --- base_report_to_label_printer/tests/test_ir_actions_report.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base_report_to_label_printer/tests/test_ir_actions_report.py b/base_report_to_label_printer/tests/test_ir_actions_report.py index 25bab84..aafefe8 100644 --- a/base_report_to_label_printer/tests/test_ir_actions_report.py +++ b/base_report_to_label_printer/tests/test_ir_actions_report.py @@ -10,7 +10,9 @@ class TestIrActionsReport(TransactionCase): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - cls.Model = cls.env["ir.actions.report"] + cls.Model = cls.env["ir.actions.report"].with_context( + skip_printer_exception=True + ) cls.server = cls.env["printing.server"].create({}) def new_printer(self):