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.
- odoo/addons/base_report_to_printer/README.rst +8 -1
- odoo/addons/base_report_to_printer/__manifest__.py +2 -1
- odoo/addons/base_report_to_printer/i18n/base_report_to_printer.pot +47 -17
- odoo/addons/base_report_to_printer/i18n/sv.po +39 -34
- odoo/addons/base_report_to_printer/i18n/zh_CN.po +161 -155
- odoo/addons/base_report_to_printer/models/ir_actions_report.py +57 -2
- odoo/addons/base_report_to_printer/models/printing_job.py +8 -4
- odoo/addons/base_report_to_printer/models/printing_printer.py +10 -2
- odoo/addons/base_report_to_printer/models/printing_server.py +6 -0
- odoo/addons/base_report_to_printer/readme/ROADMAP.md +3 -0
- odoo/addons/base_report_to_printer/security/ir.model.access.csv +2 -0
- odoo/addons/base_report_to_printer/security/security.xml +4 -3
- odoo/addons/base_report_to_printer/static/description/index.html +33 -21
- odoo/addons/base_report_to_printer/static/src/js/qweb_action_manager.esm.js +64 -10
- odoo/addons/base_report_to_printer/tests/test_ir_actions_report.py +26 -6
- odoo/addons/base_report_to_printer/tests/test_printing_printer_tray.py +4 -3
- odoo/addons/base_report_to_printer/tests/test_report.py +3 -1
- odoo/addons/base_report_to_printer/views/printing_printer.xml +1 -0
- odoo/addons/base_report_to_printer/views/printing_server.xml +1 -0
- {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
- {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
- {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
- {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
|
|
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
|
|
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
|
-
|
|
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)
|
|
@@ -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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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&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="#
|
|
402
|
-
<li><a class="reference internal" href="#
|
|
403
|
-
<li><a class="reference internal" href="#section-
|
|
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-
|
|
407
|
-
<li><a class="reference internal" href="#credits" id="toc-entry-
|
|
408
|
-
<li><a class="reference internal" href="#authors" id="toc-entry-
|
|
409
|
-
<li><a class="reference internal" href="#contributors" id="toc-entry-
|
|
410
|
-
<li><a class="reference internal" href="#maintainers" id="toc-entry-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
501
|
+
<h2><a class="toc-backref" href="#toc-entry-10">Authors</a></h2>
|
|
492
502
|
<ul class="simple">
|
|
493
503
|
<li>Agile Business Group & 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-
|
|
512
|
+
<h2><a class="toc-backref" href="#toc-entry-11">Contributors</a></h2>
|
|
503
513
|
<ul class="simple">
|
|
504
514
|
<li>Ferran Pegueroles <<a class="reference external" href="mailto:ferran@pegueroles.com">ferran@pegueroles.com</a>></li>
|
|
505
515
|
<li>Albert Cervera i Areny <<a class="reference external" href="mailto:albert@nan-tic.com">albert@nan-tic.com</a>></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-
|
|
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"
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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": "
|
|
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",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: odoo-addon-base_report_to_printer
|
|
3
|
-
Version: 17.0.1.
|
|
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:
|
|
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
|
|