odoo-addon-base-report-to-printer 17.0.1.0.1.2__py3-none-any.whl → 17.0.1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of odoo-addon-base-report-to-printer might be problematic. Click here for more details.

Files changed (23) hide show
  1. odoo/addons/base_report_to_printer/README.rst +8 -1
  2. odoo/addons/base_report_to_printer/__manifest__.py +2 -1
  3. odoo/addons/base_report_to_printer/i18n/base_report_to_printer.pot +47 -17
  4. odoo/addons/base_report_to_printer/i18n/sv.po +39 -34
  5. odoo/addons/base_report_to_printer/i18n/zh_CN.po +161 -155
  6. odoo/addons/base_report_to_printer/models/ir_actions_report.py +57 -2
  7. odoo/addons/base_report_to_printer/models/printing_job.py +8 -4
  8. odoo/addons/base_report_to_printer/models/printing_printer.py +10 -2
  9. odoo/addons/base_report_to_printer/models/printing_server.py +6 -0
  10. odoo/addons/base_report_to_printer/readme/ROADMAP.md +3 -0
  11. odoo/addons/base_report_to_printer/security/ir.model.access.csv +2 -0
  12. odoo/addons/base_report_to_printer/security/security.xml +4 -3
  13. odoo/addons/base_report_to_printer/static/description/index.html +33 -21
  14. odoo/addons/base_report_to_printer/static/src/js/qweb_action_manager.esm.js +64 -10
  15. odoo/addons/base_report_to_printer/tests/test_ir_actions_report.py +26 -6
  16. odoo/addons/base_report_to_printer/tests/test_printing_printer_tray.py +4 -3
  17. odoo/addons/base_report_to_printer/tests/test_report.py +3 -1
  18. odoo/addons/base_report_to_printer/views/printing_printer.xml +1 -0
  19. odoo/addons/base_report_to_printer/views/printing_server.xml +1 -0
  20. {odoo_addon_base_report_to_printer-17.0.1.0.1.2.dist-info → odoo_addon_base_report_to_printer-17.0.1.1.0.dist-info}/METADATA +9 -2
  21. {odoo_addon_base_report_to_printer-17.0.1.0.1.2.dist-info → odoo_addon_base_report_to_printer-17.0.1.1.0.dist-info}/RECORD +23 -21
  22. {odoo_addon_base_report_to_printer-17.0.1.0.1.2.dist-info → odoo_addon_base_report_to_printer-17.0.1.1.0.dist-info}/WHEEL +1 -1
  23. {odoo_addon_base_report_to_printer-17.0.1.0.1.2.dist-info → odoo_addon_base_report_to_printer-17.0.1.1.0.dist-info}/top_level.txt +0 -0
@@ -3,9 +3,11 @@
3
3
  # Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>)
4
4
  # Copyright (C) 2011 Domsense srl (<http://www.domsense.com>)
5
5
  # Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
6
+ # Copyright 2024 Tecnativa - Sergio Teruel
6
7
  # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
8
+ import threading
7
9
 
8
- from odoo import _, api, exceptions, fields, models
10
+ from odoo import _, api, exceptions, fields, models, registry
9
11
  from odoo.tools.safe_eval import safe_eval, time
10
12
 
11
13
  REPORT_TYPES = {"qweb-pdf": "pdf", "qweb-text": "text"}
@@ -53,6 +55,12 @@ class IrActionsReport(models.Model):
53
55
  "action": result["action"],
54
56
  "printer_name": result["printer"].name,
55
57
  }
58
+ if result.get("printer_exception") and not self.env.context.get(
59
+ "skip_printer_exception"
60
+ ):
61
+ serializable_result["printer_exception"] = True
62
+ if self.env.context.get("force_print_to_client"):
63
+ serializable_result["action"] = "client"
56
64
  return serializable_result
57
65
 
58
66
  def _get_user_default_print_behaviour(self):
@@ -97,8 +105,49 @@ class IrActionsReport(models.Model):
97
105
  # For some reason design takes report defaults over
98
106
  # False action entries so we must allow for that here
99
107
  result.update({k: v for k, v in print_action.behaviour().items() if v})
108
+ printer = result.get("printer")
109
+ if printer:
110
+ # When no printer is available we can fallback to the default behavior
111
+ # letting the user to manually print the reports.
112
+ try:
113
+ printer.server_id._open_connection(raise_on_error=True)
114
+ printer_exception = printer.status in [
115
+ "error",
116
+ "server-error",
117
+ "unavailable",
118
+ ]
119
+ except Exception:
120
+ printer_exception = True
121
+ if printer_exception and not self.env.context.get("skip_printer_exception"):
122
+ result["printer_exception"] = True
100
123
  return result
101
124
 
125
+ def print_document_client_action(self, record_ids, data=None):
126
+ behaviour = self.behaviour()
127
+ printer = behaviour.pop("printer", None)
128
+ if printer.multi_thread:
129
+
130
+ @self.env.cr.postcommit.add
131
+ def _launch_print_thread():
132
+ threaded_calculation = threading.Thread(
133
+ target=self.print_document_threaded,
134
+ args=(self.id, record_ids, data),
135
+ )
136
+ threaded_calculation.start()
137
+
138
+ return True
139
+ else:
140
+ try:
141
+ return self.print_document(record_ids, data=data)
142
+ except Exception:
143
+ return
144
+
145
+ def print_document_threaded(self, report_id, record_ids, data):
146
+ with registry(self._cr.dbname).cursor() as cr:
147
+ self = self.with_env(self.env(cr=cr))
148
+ report = self.env["ir.actions.report"].browse(report_id)
149
+ report.print_document(record_ids, data)
150
+
102
151
  def print_document(self, record_ids, data=None):
103
152
  """Print a document, do not return the document file"""
104
153
  report_type = REPORT_TYPES.get(self.report_type)
@@ -127,6 +176,7 @@ class IrActionsReport(models.Model):
127
176
  else:
128
177
  title = self.report_name
129
178
  behaviour["title"] = title
179
+ behaviour["res_ids"] = record_ids
130
180
  # TODO should we use doc_format instead of report_type
131
181
  return printer.print_document(
132
182
  self, document, doc_format=self.report_type, **behaviour
@@ -140,7 +190,12 @@ class IrActionsReport(models.Model):
140
190
  """
141
191
  if self.env.context.get("must_skip_send_to_printer"):
142
192
  return False
143
- if behaviour["action"] == "server" and printer and document:
193
+ if (
194
+ behaviour["action"] == "server"
195
+ and printer
196
+ and document
197
+ and not behaviour.get("printer_exception")
198
+ ):
144
199
  return True
145
200
  return False
146
201
 
@@ -15,7 +15,7 @@ class PrintingJob(models.Model):
15
15
 
16
16
  name = fields.Char(help="Job name.")
17
17
  active = fields.Boolean(
18
- default=True, help="Unchecked if the job is purged from cups."
18
+ default=True, help="Unchecked if the job is purged from CUPS."
19
19
  )
20
20
  job_id_cups = fields.Integer(
21
21
  string="Job ID", required=True, help="CUPS id for this job."
@@ -40,11 +40,15 @@ class PrintingJob(models.Model):
40
40
  help="Percentage of progress for this job.",
41
41
  )
42
42
  time_at_creation = fields.Datetime(
43
- required=True, help="Date and time of creation for this job."
43
+ string="Creation Date",
44
+ required=True,
45
+ help="Date and time of creation of this job.",
46
+ )
47
+ time_at_processing = fields.Datetime(
48
+ string="Processing Date", help="Date and time of process for this job."
44
49
  )
45
- time_at_processing = fields.Datetime(help="Date and time of process for this job.")
46
50
  time_at_completed = fields.Datetime(
47
- help="Date and time of completion for this job."
51
+ string="Completion Date", help="Date and time of completion for this job."
48
52
  )
49
53
  job_state = fields.Selection(
50
54
  selection=[
@@ -12,7 +12,7 @@ import logging
12
12
  import os
13
13
  from tempfile import mkstemp
14
14
 
15
- from odoo import fields, models
15
+ from odoo import api, fields, models
16
16
 
17
17
  _logger = logging.getLogger(__name__)
18
18
 
@@ -67,11 +67,19 @@ class PrintingPrinter(models.Model):
67
67
  tray_ids = fields.One2many(
68
68
  comodel_name="printing.tray", inverse_name="printer_id", string="Paper Sources"
69
69
  )
70
+ multi_thread = fields.Boolean(
71
+ compute="_compute_multi_thread", readonly=False, store=True
72
+ )
73
+
74
+ @api.depends("server_id.multi_thread")
75
+ def _compute_multi_thread(self):
76
+ for printer in self:
77
+ printer.multi_thread = printer.server_id.multi_thread
70
78
 
71
79
  def _prepare_update_from_cups(self, cups_connection, cups_printer):
72
80
  mapping = {3: "available", 4: "printing", 5: "error"}
73
81
  cups_vals = {
74
- "name": cups_printer["printer-info"],
82
+ "name": self.name or cups_printer["printer-info"],
75
83
  "model": cups_printer.get("printer-make-and-model", False),
76
84
  "location": cups_printer.get("printer-location", False),
77
85
  "uri": cups_printer.get("device-uri", False),
@@ -41,6 +41,7 @@ class PrintingServer(models.Model):
41
41
  string="Printers List",
42
42
  help="List of printers available on this server.",
43
43
  )
44
+ multi_thread = fields.Boolean()
44
45
 
45
46
  def _open_connection(self, raise_on_error=False):
46
47
  self.ensure_one()
@@ -121,6 +122,11 @@ class PrintingServer(models.Model):
121
122
  printer_values["server_id"] = server.id
122
123
 
123
124
  updated_printers.append(name)
125
+ # We want to keep any existing customized name over existing printer
126
+ # We want also to rely in the system name as a fallback to avoid
127
+ # empty names.
128
+ if not printer_values.get("name") and not printer.name:
129
+ printer_values["name"] = name
124
130
  if not printer:
125
131
  printer_values["system_name"] = name
126
132
  printer.create(printer_values)
@@ -0,0 +1,3 @@
1
+ - With threaded printing there's no download fallback when the issue
2
+ isn't detected by the CUPS Odoo backend. To able to do it, we would
3
+ need to notify the bus or use web_notify for it.
@@ -0,0 +1,2 @@
1
+ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
2
+ access_printing_printer_update_wizard,printers update,model_printing_printer_update_wizard,base.group_system,1,1,1,1
@@ -125,9 +125,10 @@
125
125
  <field name="name">Update printer wizard</field>
126
126
  <field name="model_id" ref="model_printing_printer_update_wizard" />
127
127
  <field name="group_id" ref="printing_group_manager" />
128
- <field eval="1" name="perm_read" />
129
- <field eval="1" name="perm_unlink" />
130
- <field eval="1" name="perm_write" />
128
+ <field eval="1" name="perm_read" />
129
+ <field eval="1" name="perm_unlink" />
130
+ <field eval="1" name="perm_write" />
131
+ <field eval="1" name="perm_create" />
131
132
  </record>
132
133
  <record id="access_wizard_print_attachment_user" model="ir.model.access">
133
134
  <field name="name">Print Attachment User</field>
@@ -8,10 +8,11 @@
8
8
 
9
9
  /*
10
10
  :Author: David Goodger (goodger@python.org)
11
- :Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
11
+ :Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
12
12
  :Copyright: This stylesheet has been placed in the public domain.
13
13
 
14
14
  Default cascading style sheet for the HTML output of Docutils.
15
+ Despite the name, some widely supported CSS2 features are used.
15
16
 
16
17
  See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
17
18
  customize this style sheet.
@@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
274
275
  margin-left: 2em ;
275
276
  margin-right: 2em }
276
277
 
277
- pre.code .ln { color: grey; } /* line numbers */
278
+ pre.code .ln { color: gray; } /* line numbers */
278
279
  pre.code, code { background-color: #eeeeee }
279
280
  pre.code .comment, code .comment { color: #5C6576 }
280
281
  pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +301,7 @@ span.option {
300
301
  span.pre {
301
302
  white-space: pre }
302
303
 
303
- span.problematic {
304
+ span.problematic, pre.problematic {
304
305
  color: red }
305
306
 
306
307
  span.section-subtitle {
@@ -366,7 +367,7 @@ ul.auto-toc {
366
367
  !! This file is generated by oca-gen-addon-readme !!
367
368
  !! changes will be overwritten. !!
368
369
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
369
- !! source digest: sha256:3d37f5e02c22560d293e60d6fb565eea3a6657926defd87d4a6ca71cc229ab60
370
+ !! source digest: sha256:3a4df341af99afdc1534aaa8ddac591846be1e2a917780dedce0900b4e425434
370
371
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
371
372
  <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/report-print-send/tree/17.0/base_report_to_printer"><img alt="OCA/report-print-send" src="https://img.shields.io/badge/github-OCA%2Freport--print--send-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/report-print-send-17-0/report-print-send-17-0-base_report_to_printer"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/report-print-send&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372
373
  <p>This module allows users to send reports to a printer attached to the
@@ -398,16 +399,17 @@ preprinted paper such as payment slip.</p>
398
399
  <li><a class="reference internal" href="#installation" id="toc-entry-1">Installation</a></li>
399
400
  <li><a class="reference internal" href="#configuration" id="toc-entry-2">Configuration</a></li>
400
401
  <li><a class="reference internal" href="#usage" id="toc-entry-3">Usage</a></li>
401
- <li><a class="reference internal" href="#changelog" id="toc-entry-4">Changelog</a><ul>
402
- <li><a class="reference internal" href="#section-1" id="toc-entry-5">13.0.1.0.0 (2019-09-30)</a></li>
403
- <li><a class="reference internal" href="#section-2" id="toc-entry-6">12.0.1.0.0 (2018-02-04)</a></li>
402
+ <li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-4">Known issues / Roadmap</a></li>
403
+ <li><a class="reference internal" href="#changelog" id="toc-entry-5">Changelog</a><ul>
404
+ <li><a class="reference internal" href="#section-1" id="toc-entry-6">13.0.1.0.0 (2019-09-30)</a></li>
405
+ <li><a class="reference internal" href="#section-2" id="toc-entry-7">12.0.1.0.0 (2018-02-04)</a></li>
404
406
  </ul>
405
407
  </li>
406
- <li><a class="reference internal" href="#bug-tracker" id="toc-entry-7">Bug Tracker</a></li>
407
- <li><a class="reference internal" href="#credits" id="toc-entry-8">Credits</a><ul>
408
- <li><a class="reference internal" href="#authors" id="toc-entry-9">Authors</a></li>
409
- <li><a class="reference internal" href="#contributors" id="toc-entry-10">Contributors</a></li>
410
- <li><a class="reference internal" href="#maintainers" id="toc-entry-11">Maintainers</a></li>
408
+ <li><a class="reference internal" href="#bug-tracker" id="toc-entry-8">Bug Tracker</a></li>
409
+ <li><a class="reference internal" href="#credits" id="toc-entry-9">Credits</a><ul>
410
+ <li><a class="reference internal" href="#authors" id="toc-entry-10">Authors</a></li>
411
+ <li><a class="reference internal" href="#contributors" id="toc-entry-11">Contributors</a></li>
412
+ <li><a class="reference internal" href="#maintainers" id="toc-entry-12">Maintainers</a></li>
411
413
  </ul>
412
414
  </li>
413
415
  </ul>
@@ -462,23 +464,31 @@ preferences.</li>
462
464
  <p>When no tray is configured for a report and a user, the default tray
463
465
  setup on the CUPS server is used.</p>
464
466
  </div>
467
+ <div class="section" id="known-issues-roadmap">
468
+ <h1><a class="toc-backref" href="#toc-entry-4">Known issues / Roadmap</a></h1>
469
+ <ul class="simple">
470
+ <li>With threaded printing there’s no download fallback when the issue
471
+ isn’t detected by the CUPS Odoo backend. To able to do it, we would
472
+ need to notify the bus or use web_notify for it.</li>
473
+ </ul>
474
+ </div>
465
475
  <div class="section" id="changelog">
466
- <h1><a class="toc-backref" href="#toc-entry-4">Changelog</a></h1>
476
+ <h1><a class="toc-backref" href="#toc-entry-5">Changelog</a></h1>
467
477
  <div class="section" id="section-1">
468
- <h2><a class="toc-backref" href="#toc-entry-5">13.0.1.0.0 (2019-09-30)</a></h2>
478
+ <h2><a class="toc-backref" href="#toc-entry-6">13.0.1.0.0 (2019-09-30)</a></h2>
469
479
  <ul class="simple">
470
480
  <li>[RELEASE] Port from V12.</li>
471
481
  </ul>
472
482
  </div>
473
483
  <div class="section" id="section-2">
474
- <h2><a class="toc-backref" href="#toc-entry-6">12.0.1.0.0 (2018-02-04)</a></h2>
484
+ <h2><a class="toc-backref" href="#toc-entry-7">12.0.1.0.0 (2018-02-04)</a></h2>
475
485
  <ul class="simple">
476
486
  <li>[RELEASE] Port from V11.</li>
477
487
  </ul>
478
488
  </div>
479
489
  </div>
480
490
  <div class="section" id="bug-tracker">
481
- <h1><a class="toc-backref" href="#toc-entry-7">Bug Tracker</a></h1>
491
+ <h1><a class="toc-backref" href="#toc-entry-8">Bug Tracker</a></h1>
482
492
  <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/report-print-send/issues">GitHub Issues</a>.
483
493
  In case of trouble, please check there if your issue has already been reported.
484
494
  If you spotted it first, help us to smash it by providing a detailed and welcomed
@@ -486,9 +496,9 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
486
496
  <p>Do not contact contributors directly about support or help with technical issues.</p>
487
497
  </div>
488
498
  <div class="section" id="credits">
489
- <h1><a class="toc-backref" href="#toc-entry-8">Credits</a></h1>
499
+ <h1><a class="toc-backref" href="#toc-entry-9">Credits</a></h1>
490
500
  <div class="section" id="authors">
491
- <h2><a class="toc-backref" href="#toc-entry-9">Authors</a></h2>
501
+ <h2><a class="toc-backref" href="#toc-entry-10">Authors</a></h2>
492
502
  <ul class="simple">
493
503
  <li>Agile Business Group &amp; Domsense</li>
494
504
  <li>Pegueroles SCP</li>
@@ -499,7 +509,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
499
509
  </ul>
500
510
  </div>
501
511
  <div class="section" id="contributors">
502
- <h2><a class="toc-backref" href="#toc-entry-10">Contributors</a></h2>
512
+ <h2><a class="toc-backref" href="#toc-entry-11">Contributors</a></h2>
503
513
  <ul class="simple">
504
514
  <li>Ferran Pegueroles &lt;<a class="reference external" href="mailto:ferran&#64;pegueroles.com">ferran&#64;pegueroles.com</a>&gt;</li>
505
515
  <li>Albert Cervera i Areny &lt;<a class="reference external" href="mailto:albert&#64;nan-tic.com">albert&#64;nan-tic.com</a>&gt;</li>
@@ -521,9 +531,11 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
521
531
  </ul>
522
532
  </div>
523
533
  <div class="section" id="maintainers">
524
- <h2><a class="toc-backref" href="#toc-entry-11">Maintainers</a></h2>
534
+ <h2><a class="toc-backref" href="#toc-entry-12">Maintainers</a></h2>
525
535
  <p>This module is maintained by the OCA.</p>
526
- <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
536
+ <a class="reference external image-reference" href="https://odoo-community.org">
537
+ <img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
538
+ </a>
527
539
  <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
528
540
  mission is to support the collaborative development of Odoo features and
529
541
  promote its widespread use.</p>
@@ -1,4 +1,5 @@
1
1
  /** @odoo-module */
2
+ import {Markup} from "web.utils";
2
3
  import {_t} from "@web/core/l10n/translation";
3
4
  import {registry} from "@web/core/registry";
4
5
 
@@ -9,19 +10,72 @@ async function cupsReportActionHandler(action, options, env) {
9
10
  const print_action = await orm.call(
10
11
  "ir.actions.report",
11
12
  "print_action_for_report_name",
12
- [action.report_name]
13
+ [action.report_name],
14
+ {context: {force_print_to_client: action.context.force_print_to_client}}
13
15
  );
14
- if (print_action && print_action.action === "server") {
15
- const result = await orm.call("ir.actions.report", "print_document", [
16
- action.id,
17
- action.context.active_ids,
18
- action.data,
19
- ]);
16
+ var printer_exception = print_action.printer_exception;
17
+ if (print_action && print_action.action === "server" && !printer_exception) {
18
+ // The Odoo CUPS backend is ok. We try to print into the printer
19
+ const result = await orm.call(
20
+ "ir.actions.report",
21
+ "print_document_client_action",
22
+ [action.id, action.context.active_ids, action.data]
23
+ );
20
24
  if (result) {
21
- env.services.notification.add(_t("Successfully sent to printer!"));
22
- } else {
23
- env.services.notification.add(_t("Could not sent to printer!"));
25
+ env.services.notification.add(_t("Successfully sent to printer!"), {
26
+ type: "success",
27
+ });
28
+ return true;
29
+ // In case of exception during the job, we won't get any response. So we
30
+ // should flag the exception and notify the user
24
31
  }
32
+ env.services.notification.add(_t("Could not sent to printer!"), {
33
+ type: "danger",
34
+ });
35
+ printer_exception = true;
36
+ }
37
+ if (print_action && print_action.action === "server" && printer_exception) {
38
+ // Just so the translation engine detects them as it doesn't do it inside
39
+ // template strings
40
+ const terms = {
41
+ the_report: env._t("The report"),
42
+ couldnt_be_printed: env._t(
43
+ "couldn't be printed. Click on the button below to download it"
44
+ ),
45
+ issue_on: env._t("Issue on"),
46
+ };
47
+ const notificationRemove = env.services.notification.add(
48
+ Markup(
49
+ `<p>${terms.the_report} <strong>${action.name}</strong> ${terms.couldnt_be_printed}</p>`
50
+ ),
51
+ {
52
+ title: `${terms.issue_on} ${print_action.printer_name}`,
53
+ type: "warning",
54
+ sticky: true,
55
+ messageIsHtml: true,
56
+ buttons: [
57
+ {
58
+ name: env._t("Print"),
59
+ primary: true,
60
+ icon: "fa-print",
61
+ onClick: async () => {
62
+ const context = {
63
+ force_print_to_client: true,
64
+ must_skip_send_to_printer: true,
65
+ };
66
+ env.services.user.updateContext(context);
67
+ await env.services.action.doAction(
68
+ {type: "ir.actions.report", ...action},
69
+ {
70
+ additionalContext: context,
71
+ }
72
+ );
73
+ notificationRemove();
74
+ },
75
+ },
76
+ ],
77
+ }
78
+ );
25
79
  return true;
26
80
  }
27
81
  }
@@ -12,10 +12,12 @@ model = "odoo.addons.base.models.ir_actions_report.IrActionsReport"
12
12
  class TestIrActionsReportXml(TransactionCase):
13
13
  def setUp(self):
14
14
  super().setUp()
15
- self.Model = self.env["ir.actions.report"]
15
+ self.Model = self.env["ir.actions.report"].with_context(
16
+ skip_printer_exception=True
17
+ )
16
18
  self.vals = {}
17
19
 
18
- self.report = self.env["ir.actions.report"].search([], limit=1)
20
+ self.report = self.Model.search([], limit=1)
19
21
  self.server = self.env["printing.server"].create({})
20
22
 
21
23
  def new_action(self):
@@ -153,7 +155,7 @@ class TestIrActionsReportXml(TransactionCase):
153
155
  self.env.user.printing_action = "client"
154
156
  printing_action = self.new_printing_action()
155
157
  printing_action.user_id = self.env.user
156
- printing_action.report_id = self.env["ir.actions.report"].search(
158
+ printing_action.report_id = self.Model.search(
157
159
  [("id", "!=", report.id)], limit=1
158
160
  )
159
161
  self.assertEqual(
@@ -213,7 +215,7 @@ class TestIrActionsReportXml(TransactionCase):
213
215
  """
214
216
  It should return the correct tray
215
217
  """
216
- report = self.env["ir.actions.report"].search([], limit=1)
218
+ report = self.Model.search([], limit=1)
217
219
  action = self.env["printing.report.xml.action"].create(
218
220
  {"user_id": self.env.user.id, "report_id": report.id, "action": "server"}
219
221
  )
@@ -266,7 +268,7 @@ class TestIrActionsReportXml(TransactionCase):
266
268
  self.assertEqual("Action tray", report.behaviour()["tray"])
267
269
 
268
270
  def test_onchange_printer_tray_id_empty(self):
269
- action = self.env["ir.actions.report"].new({"printer_tray_id": False})
271
+ action = self.Model.new({"printer_tray_id": False})
270
272
  action.onchange_printing_printer_id()
271
273
  self.assertFalse(action.printer_tray_id)
272
274
 
@@ -289,7 +291,25 @@ class TestIrActionsReportXml(TransactionCase):
289
291
  {"name": "Tray", "system_name": "TrayName", "printer_id": printer.id}
290
292
  )
291
293
 
292
- action = self.env["ir.actions.report"].new({"printer_tray_id": tray.id})
294
+ action = self.Model.new({"printer_tray_id": tray.id})
293
295
  self.assertEqual(action.printer_tray_id, tray)
294
296
  action.onchange_printing_printer_id()
295
297
  self.assertFalse(action.printer_tray_id)
298
+
299
+ def test_print_in_new_thread(self):
300
+ """It should return the action and printer from printing action in other
301
+ thread"""
302
+ report = self.Model.search([], limit=1)
303
+ self.env.user.printing_action = "server"
304
+ printing_action = self.new_printing_action()
305
+ printing_action.user_id = self.env.user
306
+ printing_action.printer_id = self.new_printer()
307
+ printing_action.printer_id.multi_thread = True
308
+ self.assertEqual(
309
+ report.behaviour(),
310
+ {
311
+ "action": printing_action.action,
312
+ "printer": printing_action.printer_id,
313
+ "tray": False,
314
+ },
315
+ )
@@ -40,7 +40,7 @@ class TestPrintingPrinter(TransactionCase):
40
40
  self.server = self.env["printing.server"].create({})
41
41
  self.printer = self.env["printing.printer"].create(
42
42
  {
43
- "name": "Printer",
43
+ "name": "",
44
44
  "server_id": self.server.id,
45
45
  "system_name": "Sys Name",
46
46
  "default": True,
@@ -105,10 +105,11 @@ class TestPrintingPrinter(TransactionCase):
105
105
  Check that the update_printers method calls _prepare_update_from_cups
106
106
  """
107
107
  self.mock_cups_ppd(cups, file_name=False)
108
-
109
- self.assertEqual(self.printer.name, "Printer")
110
108
  self.ServerModel.update_printers()
111
109
  self.assertEqual(self.printer.name, "info")
110
+ self.printer.name = "My custom name"
111
+ self.ServerModel.update_printers()
112
+ self.assertEqual(self.printer.name, "My custom name")
112
113
 
113
114
  @mock.patch("%s.cups" % server_model)
114
115
  def test_prepare_update_from_cups_no_ppd(self, cups):
@@ -11,7 +11,9 @@ from odoo.tests import common
11
11
  class TestReport(common.HttpCase):
12
12
  def setUp(self):
13
13
  super().setUp()
14
- self.Model = self.env["ir.actions.report"]
14
+ self.Model = self.env["ir.actions.report"].with_context(
15
+ skip_printer_exception=True
16
+ )
15
17
  self.server = self.env["printing.server"].create({})
16
18
  self.report_vals = {
17
19
  "name": "Test Report",
@@ -78,6 +78,7 @@
78
78
  <field name="location" />
79
79
  <field name="status" />
80
80
  <field name="status_message" />
81
+ <field name="multi_thread" />
81
82
  </group>
82
83
  <group string="Trays" name="trays">
83
84
  <field name="tray_ids" nolabel="1" colspan="2">
@@ -32,6 +32,7 @@
32
32
  <field name="user" />
33
33
  <field name="password" />
34
34
  <field name="encryption_policy" />
35
+ <field name="multi_thread" />
35
36
  </group>
36
37
  </group>
37
38
  <separator name="printers" string="Printers" />
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: odoo-addon-base_report_to_printer
3
- Version: 17.0.1.0.1.2
3
+ Version: 17.0.1.1.0
4
4
  Requires-Python: >=3.10
5
5
  Requires-Dist: odoo>=17.0a,<17.1dev
6
6
  Requires-Dist: pycups
@@ -23,7 +23,7 @@ Report to printer
23
23
  !! This file is generated by oca-gen-addon-readme !!
24
24
  !! changes will be overwritten. !!
25
25
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
26
- !! source digest: sha256:3d37f5e02c22560d293e60d6fb565eea3a6657926defd87d4a6ca71cc229ab60
26
+ !! source digest: sha256:3a4df341af99afdc1534aaa8ddac591846be1e2a917780dedce0900b4e425434
27
27
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28
28
 
29
29
  .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -128,6 +128,13 @@ Guidelines for use:
128
128
  When no tray is configured for a report and a user, the default tray
129
129
  setup on the CUPS server is used.
130
130
 
131
+ Known issues / Roadmap
132
+ ======================
133
+
134
+ - With threaded printing there's no download fallback when the issue
135
+ isn't detected by the CUPS Odoo backend. To able to do it, we would
136
+ need to notify the bus or use web_notify for it.
137
+
131
138
  Changelog
132
139
  =========
133
140