From 5f017682c1efb73a08e4c26f1aaa1b2c17d51e11 Mon Sep 17 00:00:00 2001 From: Laurent Smet Date: Wed, 13 Mar 2024 14:31:15 +0000 Subject: [PATCH] [FIX] base: Allow report with duplicated res_ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In stock, you would print multiple times the same lot label. In this scenario, the rendering method get multiple times the same res_id as parameter. However, the code is loosing track of those duplicated ids before all streams are indexed by res_id. closes odoo/odoo#163362 X-original-commit: fb92e991bb98e5945c57c157754ff0eba306b924 Signed-off-by: Rémy Voet (ryv) Signed-off-by: Laurent Smet (las) --- odoo/addons/base/models/ir_actions_report.py | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/odoo/addons/base/models/ir_actions_report.py b/odoo/addons/base/models/ir_actions_report.py index cd164baf003..4c50aa809da 100644 --- a/odoo/addons/base/models/ir_actions_report.py +++ b/odoo/addons/base/models/ir_actions_report.py @@ -674,6 +674,7 @@ class IrActionsReport(models.Model): # access the report details with sudo() but evaluation context as current user report_sudo = self._get_report(report_ref) + has_duplicated_ids = res_ids and len(res_ids) != len(set(res_ids)) collected_streams = OrderedDict() @@ -682,9 +683,13 @@ class IrActionsReport(models.Model): if res_ids: records = self.env[report_sudo.model].browse(res_ids) for record in records: + res_id = record.id + if res_id in collected_streams: + continue + stream = None attachment = None - if report_sudo.attachment and not self._context.get("report_pdf_no_attachment"): + if not has_duplicated_ids and report_sudo.attachment and not self._context.get("report_pdf_no_attachment"): attachment = report_sudo.retrieve_attachment(record) # Extract the stream from the attachment. @@ -699,13 +704,14 @@ class IrActionsReport(models.Model): stream.close() stream = new_stream - collected_streams[record.id] = { + collected_streams[res_id] = { 'stream': stream, 'attachment': attachment, } # Call 'wkhtmltopdf' to generate the missing streams. res_ids_wo_stream = [res_id for res_id, stream_data in collected_streams.items() if not stream_data['stream']] + all_res_ids_wo_stream = res_ids if has_duplicated_ids else res_ids_wo_stream is_whtmltopdf_needed = not res_ids or res_ids_wo_stream if is_whtmltopdf_needed: @@ -725,16 +731,16 @@ class IrActionsReport(models.Model): # https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2083 additional_context = {'debug': False} - html = self.with_context(**additional_context)._render_qweb_html(report_ref, res_ids_wo_stream, data=data)[0] + html = self.with_context(**additional_context)._render_qweb_html(report_ref, all_res_ids_wo_stream, data=data)[0] bodies, html_ids, header, footer, specific_paperformat_args = self.with_context(**additional_context)._prepare_html(html, report_model=report_sudo.model) - if report_sudo.attachment and set(res_ids_wo_stream) != set(html_ids): + if not has_duplicated_ids and report_sudo.attachment and set(res_ids_wo_stream) != set(html_ids): raise UserError(_( "The report's template %r is wrong, please contact your administrator. \n\n" "Can not separate file to save as attachment because the report's template does not contains the" " attributes 'data-oe-model' and 'data-oe-id' on the div with 'article' classname.", - self.name, + report_sudo.name, )) pdf_content = self._run_wkhtmltopdf( @@ -749,7 +755,7 @@ class IrActionsReport(models.Model): pdf_content_stream = io.BytesIO(pdf_content) # Printing a PDF report without any records. The content could be returned directly. - if not res_ids: + if has_duplicated_ids or not res_ids: return { False: { 'stream': pdf_content_stream, @@ -876,12 +882,13 @@ class IrActionsReport(models.Model): self = self.with_context(webp_as_jpg=True) collected_streams = self._render_qweb_pdf_prepare_streams(report_ref, data, res_ids=res_ids) + has_duplicated_ids = res_ids and len(res_ids) != len(set(res_ids)) # access the report details with sudo() but keep evaluation context as current user report_sudo = self._get_report(report_ref) # Generate the ir.attachment if needed. - if report_sudo.attachment and not self._context.get("report_pdf_no_attachment"): + if not has_duplicated_ids and report_sudo.attachment and not self._context.get("report_pdf_no_attachment"): attachment_vals_list = self._prepare_pdf_report_attachment_vals_list(report_sudo, collected_streams) if attachment_vals_list: attachment_names = ', '.join(x['name'] for x in attachment_vals_list)