From e733e9f89a104a9929448b4916fb9ffe9d083fe7 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 3 Nov 2023 20:11:24 +0100 Subject: [PATCH 1/7] base_report_to_printer: fix string --- base_report_to_printer/models/printing_job.py | 12 ++++++++---- .../static/src/js/qweb_action_manager.esm.js | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/base_report_to_printer/models/printing_job.py b/base_report_to_printer/models/printing_job.py index 6d9a347..d38fc2c 100644 --- a/base_report_to_printer/models/printing_job.py +++ b/base_report_to_printer/models/printing_job.py @@ -15,7 +15,7 @@ class PrintingJob(models.Model): name = fields.Char(help="Job name.") active = fields.Boolean( - default=True, help="Unchecked if the job is purged from cups." + default=True, help="Unchecked if the job is purged from CUPS." ) job_id_cups = fields.Integer( string="Job ID", required=True, help="CUPS id for this job." @@ -40,11 +40,15 @@ class PrintingJob(models.Model): help="Percentage of progress for this job.", ) time_at_creation = fields.Datetime( - required=True, help="Date and time of creation for this job." + string="Creation Date", + required=True, + help="Date and time of creation of this job.", + ) + time_at_processing = fields.Datetime( + string="Processing Date", help="Date and time of process for this job." ) - time_at_processing = fields.Datetime(help="Date and time of process for this job.") time_at_completed = fields.Datetime( - help="Date and time of completion for this job." + string="Completion Date", help="Date and time of completion for this job." ) job_state = fields.Selection( selection=[ 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 d9f9769..f9cfd9c 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 @@ -20,7 +20,7 @@ async function cupsReportActionHandler(action, options, env) { if (result) { env.services.notification.add(_t("Successfully sent to printer!")); } else { - env.services.notification.add(_t("Could not sent to printer!")); + env.services.notification.add(_t("Could not send to printer!")); } return true; } From 540e5269d2a4bc99569abbf7ec278eb6fb840ffa Mon Sep 17 00:00:00 2001 From: dtec-landoo Date: Wed, 27 Mar 2024 14:20:53 +0100 Subject: [PATCH 2/7] [16.0][FIX] base_report_to_printer: Allow create option --- base_report_to_printer/security/security.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base_report_to_printer/security/security.xml b/base_report_to_printer/security/security.xml index 8f68e12..e0c9e22 100644 --- a/base_report_to_printer/security/security.xml +++ b/base_report_to_printer/security/security.xml @@ -125,9 +125,10 @@ Update printer wizard - - - + + + + Print Attachment User From 41847575ec22254c50228607db12af92d284a620 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 31 Jan 2024 13:02:02 +0100 Subject: [PATCH 3/7] [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 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", From 6f027e2f8cae361beb2299f4d7ffe748d4b2b0a4 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 20 Sep 2023 11:19:15 +0200 Subject: [PATCH 4/7] [FIX] base_report_to_printer: update printers wizard - Add access rules to the wizard - Set a fallback name for the printers and respect the user custom ones TT45159 --- base_report_to_printer/__manifest__.py | 1 + base_report_to_printer/models/printing_printer.py | 2 +- base_report_to_printer/models/printing_server.py | 5 +++++ base_report_to_printer/security/ir.model.access.csv | 2 ++ base_report_to_printer/tests/test_printing_printer_tray.py | 7 ++++--- 5 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 base_report_to_printer/security/ir.model.access.csv diff --git a/base_report_to_printer/__manifest__.py b/base_report_to_printer/__manifest__.py index 2105161..8ba8600 100644 --- a/base_report_to_printer/__manifest__.py +++ b/base_report_to_printer/__manifest__.py @@ -18,6 +18,7 @@ "data": [ "data/printing_data.xml", "security/security.xml", + "security/ir.model.access.csv", "views/printing_printer.xml", "views/printing_server.xml", "views/printing_job.xml", diff --git a/base_report_to_printer/models/printing_printer.py b/base_report_to_printer/models/printing_printer.py index 8d2811e..67fc590 100644 --- a/base_report_to_printer/models/printing_printer.py +++ b/base_report_to_printer/models/printing_printer.py @@ -71,7 +71,7 @@ class PrintingPrinter(models.Model): def _prepare_update_from_cups(self, cups_connection, cups_printer): mapping = {3: "available", 4: "printing", 5: "error"} cups_vals = { - "name": cups_printer["printer-info"], + "name": self.name or cups_printer["printer-info"], "model": cups_printer.get("printer-make-and-model", False), "location": cups_printer.get("printer-location", False), "uri": cups_printer.get("device-uri", False), diff --git a/base_report_to_printer/models/printing_server.py b/base_report_to_printer/models/printing_server.py index d5958f7..a072567 100644 --- a/base_report_to_printer/models/printing_server.py +++ b/base_report_to_printer/models/printing_server.py @@ -121,6 +121,11 @@ class PrintingServer(models.Model): printer_values["server_id"] = server.id updated_printers.append(name) + # We want to keep any existing customized name over existing printer + # We want also to rely in the system name as a fallback to avoid + # empty names. + if not printer_values.get("name") and not printer.name: + printer_values["name"] = name if not printer: printer_values["system_name"] = name printer.create(printer_values) diff --git a/base_report_to_printer/security/ir.model.access.csv b/base_report_to_printer/security/ir.model.access.csv new file mode 100644 index 0000000..b97fc91 --- /dev/null +++ b/base_report_to_printer/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_printing_printer_update_wizard,printers update,model_printing_printer_update_wizard,base.group_system,1,1,1,1 diff --git a/base_report_to_printer/tests/test_printing_printer_tray.py b/base_report_to_printer/tests/test_printing_printer_tray.py index 1588643..c0168ff 100644 --- a/base_report_to_printer/tests/test_printing_printer_tray.py +++ b/base_report_to_printer/tests/test_printing_printer_tray.py @@ -40,7 +40,7 @@ class TestPrintingPrinter(TransactionCase): self.server = self.env["printing.server"].create({}) self.printer = self.env["printing.printer"].create( { - "name": "Printer", + "name": "", "server_id": self.server.id, "system_name": "Sys Name", "default": True, @@ -105,10 +105,11 @@ class TestPrintingPrinter(TransactionCase): 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") + self.printer.name = "My custom name" + self.ServerModel.update_printers() + self.assertEqual(self.printer.name, "My custom name") @mock.patch("%s.cups" % server_model) def test_prepare_update_from_cups_no_ppd(self, cups): From f097b37767f333d4a98729a1b91bf67102d5e820 Mon Sep 17 00:00:00 2001 From: sergio-teruel Date: Sat, 26 Oct 2024 23:32:27 +0200 Subject: [PATCH 5/7] [IMP] base_report_to_printer: Add printer option to launch reports in new thread --- base_report_to_printer/README.rst | 5 ++-- .../models/ir_actions_report.py | 27 ++++++++++++++++++- .../models/printing_printer.py | 10 ++++++- .../models/printing_server.py | 1 + .../static/description/index.html | 16 ++++++----- .../static/src/js/qweb_action_manager.esm.js | 10 +++---- .../tests/test_ir_actions_report.py | 18 +++++++++++++ .../views/printing_printer.xml | 1 + .../views/printing_server.xml | 1 + 9 files changed, 72 insertions(+), 17 deletions(-) diff --git a/base_report_to_printer/README.rst b/base_report_to_printer/README.rst index 009291b..1613e83 100644 --- a/base_report_to_printer/README.rst +++ b/base_report_to_printer/README.rst @@ -89,9 +89,8 @@ this will not be displayed by CUPS web interface or in Odoo. To see this information, you need to change the configuration of your CUPS server and set the JobPrivateValue directive to "none" (or some other list of values which does not include "job-name") , and reload the server. See -cupsd.conf(5) -<`https://www.cups.org/doc/man-cupsd.conf.html\\> >`__ -for details. +cupsd.conf(5) for +details. Usage ===== diff --git a/base_report_to_printer/models/ir_actions_report.py b/base_report_to_printer/models/ir_actions_report.py index 0547709..395837f 100644 --- a/base_report_to_printer/models/ir_actions_report.py +++ b/base_report_to_printer/models/ir_actions_report.py @@ -3,9 +3,11 @@ # Copyright (C) 2011 Agile Business Group sagl () # Copyright (C) 2011 Domsense srl () # Copyright (C) 2013-2014 Camptocamp () +# Copyright 2024 Tecnativa - Sergio Teruel # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import threading -from odoo import _, api, exceptions, fields, models +from odoo import _, api, exceptions, fields, models, registry from odoo.tools.safe_eval import safe_eval, time REPORT_TYPES = {"qweb-pdf": "pdf", "qweb-text": "text"} @@ -118,6 +120,29 @@ class IrActionsReport(models.Model): result["printer_exception"] = True return result + def print_document_client_action(self, record_ids, data=None): + behaviour = self.behaviour() + printer = behaviour.pop("printer", None) + if printer.multi_thread: + + @self.env.cr.postcommit.add + def _launch_print_thread(): + threaded_calculation = threading.Thread( + target=self.print_document_threaded, + args=(self.id, record_ids, data), + ) + threaded_calculation.start() + + return True + else: + return self.print_document(record_ids, data=data) + + def print_document_threaded(self, report_id, record_ids, data): + with registry(self._cr.dbname).cursor() as cr: + self = self.with_env(self.env(cr=cr)) + report = self.env["ir.actions.report"].browse(report_id) + report.print_document(record_ids, data) + def print_document(self, record_ids, data=None): """Print a document, do not return the document file""" report_type = REPORT_TYPES.get(self.report_type) diff --git a/base_report_to_printer/models/printing_printer.py b/base_report_to_printer/models/printing_printer.py index 67fc590..a7e2587 100644 --- a/base_report_to_printer/models/printing_printer.py +++ b/base_report_to_printer/models/printing_printer.py @@ -12,7 +12,7 @@ import logging import os from tempfile import mkstemp -from odoo import fields, models +from odoo import api, fields, models _logger = logging.getLogger(__name__) @@ -67,6 +67,14 @@ class PrintingPrinter(models.Model): tray_ids = fields.One2many( comodel_name="printing.tray", inverse_name="printer_id", string="Paper Sources" ) + multi_thread = fields.Boolean( + compute="_compute_multi_thread", readonly=False, store=True + ) + + @api.depends("server_id.multi_thread") + def _compute_multi_thread(self): + for printer in self: + printer.multi_thread = printer.server_id.multi_thread def _prepare_update_from_cups(self, cups_connection, cups_printer): mapping = {3: "available", 4: "printing", 5: "error"} diff --git a/base_report_to_printer/models/printing_server.py b/base_report_to_printer/models/printing_server.py index a072567..6d64088 100644 --- a/base_report_to_printer/models/printing_server.py +++ b/base_report_to_printer/models/printing_server.py @@ -41,6 +41,7 @@ class PrintingServer(models.Model): string="Printers List", help="List of printers available on this server.", ) + multi_thread = fields.Boolean() def _open_connection(self, raise_on_error=False): self.ensure_one() diff --git a/base_report_to_printer/static/description/index.html b/base_report_to_printer/static/description/index.html index 6aec188..5b5360f 100644 --- a/base_report_to_printer/static/description/index.html +++ b/base_report_to_printer/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code { margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.option { span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -438,9 +439,8 @@ this will not be displayed by CUPS web interface or in Odoo. To see this information, you need to change the configuration of your CUPS server and set the JobPrivateValue directive to “none” (or some other list of values which does not include “job-name”) , and reload the server. See -cupsd.conf(5) -<https://www.cups.org/doc/man-cupsd.conf.html\> -for details.

+cupsd.conf(5) <https://www.cups.org/doc/man-cupsd.conf.html> for +details.

Usage

@@ -523,7 +523,9 @@ If you spotted it first, help us to smash it by providing a detailed and welcome

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

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.

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 7b95ed0..3c3a90f 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 @@ -16,11 +16,11 @@ async function cupsReportActionHandler(action, options, env) { 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, - ]); + const result = await orm.call( + "ir.actions.report", + "print_document_client_action", + [action.id, action.context.active_ids, action.data] + ); if (result) { env.services.notification.add(_t("Successfully sent to printer!"), { type: "success", 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 5b5578b..4e1e77d 100644 --- a/base_report_to_printer/tests/test_ir_actions_report.py +++ b/base_report_to_printer/tests/test_ir_actions_report.py @@ -295,3 +295,21 @@ class TestIrActionsReportXml(TransactionCase): self.assertEqual(action.printer_tray_id, tray) action.onchange_printing_printer_id() self.assertFalse(action.printer_tray_id) + + def test_print_in_new_thread(self): + """It should return the action and printer from printing action in other + thread""" + report = self.Model.search([], limit=1) + self.env.user.printing_action = "server" + printing_action = self.new_printing_action() + printing_action.user_id = self.env.user + printing_action.printer_id = self.new_printer() + printing_action.printer_id.multi_thread = True + self.assertEqual( + report.behaviour(), + { + "action": printing_action.action, + "printer": printing_action.printer_id, + "tray": False, + }, + ) diff --git a/base_report_to_printer/views/printing_printer.xml b/base_report_to_printer/views/printing_printer.xml index 4424c84..0c7f0f4 100644 --- a/base_report_to_printer/views/printing_printer.xml +++ b/base_report_to_printer/views/printing_printer.xml @@ -78,6 +78,7 @@ + diff --git a/base_report_to_printer/views/printing_server.xml b/base_report_to_printer/views/printing_server.xml index de9a04b..259ec1a 100644 --- a/base_report_to_printer/views/printing_server.xml +++ b/base_report_to_printer/views/printing_server.xml @@ -32,6 +32,7 @@ + From b9e968510c25a23070bf290c166f1bef3491784d Mon Sep 17 00:00:00 2001 From: David Date: Mon, 11 Nov 2024 13:31:15 +0100 Subject: [PATCH 6/7] [IMP] base_report_to_printer: exceptions notifications Better handling of exceptions feedback. A notification will show up with the issued printer and report and a button for the user to download the report as a fallback to the failure. TT51628 --- base_report_to_printer/README.rst | 7 ++ .../models/ir_actions_report.py | 8 ++- base_report_to_printer/readme/ROADMAP.md | 3 + .../static/description/index.html | 41 +++++++----- .../static/src/js/qweb_action_manager.esm.js | 66 +++++++++++++++---- 5 files changed, 94 insertions(+), 31 deletions(-) create mode 100644 base_report_to_printer/readme/ROADMAP.md diff --git a/base_report_to_printer/README.rst b/base_report_to_printer/README.rst index 1613e83..526f4d4 100644 --- a/base_report_to_printer/README.rst +++ b/base_report_to_printer/README.rst @@ -111,6 +111,13 @@ Guidelines for use: When no tray is configured for a report and a user, the default tray setup on the CUPS server is used. +Known issues / Roadmap +====================== + +- With threaded printing there's no download fallback when the issue + isn't detected by the CUPS Odoo backend. To able to do it, we would + need to notify the bus or use web_notify for it. + Changelog ========= diff --git a/base_report_to_printer/models/ir_actions_report.py b/base_report_to_printer/models/ir_actions_report.py index 395837f..8af5143 100644 --- a/base_report_to_printer/models/ir_actions_report.py +++ b/base_report_to_printer/models/ir_actions_report.py @@ -59,6 +59,8 @@ class IrActionsReport(models.Model): "skip_printer_exception" ): serializable_result["printer_exception"] = True + if self.env.context.get("force_print_to_client"): + serializable_result["action"] = "client" return serializable_result def _get_user_default_print_behaviour(self): @@ -135,7 +137,10 @@ class IrActionsReport(models.Model): return True else: - return self.print_document(record_ids, data=data) + try: + return self.print_document(record_ids, data=data) + except Exception: + return def print_document_threaded(self, report_id, record_ids, data): with registry(self._cr.dbname).cursor() as cr: @@ -171,6 +176,7 @@ class IrActionsReport(models.Model): else: title = self.report_name behaviour["title"] = title + behaviour["res_ids"] = record_ids # TODO should we use doc_format instead of report_type return printer.print_document( self, document, doc_format=self.report_type, **behaviour diff --git a/base_report_to_printer/readme/ROADMAP.md b/base_report_to_printer/readme/ROADMAP.md new file mode 100644 index 0000000..f35d11c --- /dev/null +++ b/base_report_to_printer/readme/ROADMAP.md @@ -0,0 +1,3 @@ +- With threaded printing there's no download fallback when the issue + isn't detected by the CUPS Odoo backend. To able to do it, we would + need to notify the bus or use web_notify for it. diff --git a/base_report_to_printer/static/description/index.html b/base_report_to_printer/static/description/index.html index 5b5360f..7732f22 100644 --- a/base_report_to_printer/static/description/index.html +++ b/base_report_to_printer/static/description/index.html @@ -399,16 +399,17 @@ preprinted paper such as payment slip.

  • Installation
  • Configuration
  • Usage
  • -
  • Changelog
  • +
    +

    Known issues / Roadmap

    +
      +
    • With threaded printing there’s no download fallback when the issue +isn’t detected by the CUPS Odoo backend. To able to do it, we would +need to notify the bus or use web_notify for it.
    • +
    +
    -

    Bug Tracker

    +

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -486,9 +495,9 @@ If you spotted it first, help us to smash it by providing a detailed and welcome

    Do not contact contributors directly about support or help with technical issues.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • Agile Business Group & Domsense
    • Pegueroles SCP
    • @@ -499,7 +508,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
    -

    Contributors

    +

    Contributors

    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association 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 3c3a90f..2d110dc 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 @@ -1,4 +1,5 @@ /** @odoo-module */ +import {Markup} from "web.utils"; import {_t} from "@web/core/l10n/translation"; import {registry} from "@web/core/registry"; @@ -9,13 +10,12 @@ async function cupsReportActionHandler(action, options, env) { const print_action = await orm.call( "ir.actions.report", "print_action_for_report_name", - [action.report_name] + [action.report_name], + {context: {force_print_to_client: action.context.force_print_to_client}} ); - if ( - print_action && - print_action.action === "server" && - !print_action.printer_exception - ) { + var printer_exception = print_action.printer_exception; + if (print_action && print_action.action === "server" && !printer_exception) { + // The Odoo CUPS backend is ok. We try to print into the printer const result = await orm.call( "ir.actions.report", "print_document_client_action", @@ -25,20 +25,58 @@ async function cupsReportActionHandler(action, options, env) { env.services.notification.add(_t("Successfully sent to printer!"), { type: "success", }); - } else { - env.services.notification.add(_t("Could not send to printer!"), { - type: "danger", - }); + return true; + // In case of exception during the job, we won't get any response. So we + // should flag the exception and notify the user } - return true; + env.services.notification.add(_t("Could not sent to printer!"), { + type: "danger", + }); + printer_exception = true; } - if (print_action.printer_exception) { - env.services.notification.add( - env._t("The printer couldn't be reached. Downloading document instead"), + if (print_action && print_action.action === "server" && printer_exception) { + // Just so the translation engine detects them as it doesn't do it inside + // template strings + const terms = { + the_report: env._t("The report"), + couldnt_be_printed: env._t( + "couldn't be printed. Click on the button below to download it" + ), + issue_on: env._t("Issue on"), + }; + const notificationRemove = env.services.notification.add( + Markup( + `

    ${terms.the_report} ${action.name} ${terms.couldnt_be_printed}

    ` + ), { + title: `${terms.issue_on} ${print_action.printer_name}`, type: "warning", + sticky: true, + messageIsHtml: true, + buttons: [ + { + name: env._t("Print"), + primary: true, + icon: "fa-print", + onClick: async () => { + const context = { + force_print_to_client: true, + must_skip_send_to_printer: true, + }; + env.services.user.updateContext(context); + await env.services.action.doAction( + {type: "ir.actions.report", ...action}, + { + additionalContext: context, + } + ); + notificationRemove(); + }, + }, + ], } ); + return true; } } } From 5b5444fd7e66c1238b1b7b7f1fefbbcedfd60498 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 15 Nov 2024 17:20:54 +0100 Subject: [PATCH 7/7] [FIX] base_report_to_printer: wrong translation --- base_report_to_printer/i18n/sv.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base_report_to_printer/i18n/sv.po b/base_report_to_printer/i18n/sv.po index 6c84e31..3f0f419 100644 --- a/base_report_to_printer/i18n/sv.po +++ b/base_report_to_printer/i18n/sv.po @@ -921,7 +921,7 @@ msgstr "Guide" #: code:addons/base_report_to_printer/wizards/print_attachment_report.py:0 #, python-format msgid "{name} ({copies} copies)" -msgstr "{namn} ({kopior} kopior)" +msgstr "{name} ({copies} kopior)" #~ msgid "Job" #~ msgstr "Jobb"