From fd764968b8db493bf5533788bd92bfdec212a21b Mon Sep 17 00:00:00 2001 From: Laurent Smet Date: Thu, 28 Jul 2022 14:32:09 +0000 Subject: [PATCH] [FIX] base: Fix pdf generation for l10n_ch QR-bill When printing the qr-bill for multiple records, we are no longer passing the code spliting the pdf for each record since 'attachment' is not checked on the qr-bill action report. Bug introduced by: https://github.com/odoo/odoo/commit/38e4a5fbc35b6089ec70b27e5ae74cc83c981a17 closes odoo/odoo#97050 X-original-commit: afaf7c1db4500c6115f119ff3592027e7b3b550d Signed-off-by: Florian Gilbert (flg) Signed-off-by: Laurent Smet --- odoo/addons/base/models/ir_actions_report.py | 53 ++++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/odoo/addons/base/models/ir_actions_report.py b/odoo/addons/base/models/ir_actions_report.py index 934a229cb13..594af972ff0 100644 --- a/odoo/addons/base/models/ir_actions_report.py +++ b/odoo/addons/base/models/ir_actions_report.py @@ -717,18 +717,18 @@ class IrActionsReport(models.Model): # Split the pdf for each record using the PDF outlines. - if not self.attachment: - # Splitting the pdf is not needed since we don't have any attachment to generate. - collected_streams[False] = {'stream': pdf_content_stream} - elif len(res_ids_wo_stream) == 1: - # Only one record: append the whole PDF. + # Only one record: append the whole PDF. + if len(res_ids_wo_stream) == 1: collected_streams[res_ids_wo_stream[0]]['stream'] = pdf_content_stream - else: - # In case of multiple docs, we need to split the pdf according the records. - # To do so, we split the pdf based on top outlines computed by wkhtmltopdf. - # An outline is a html tag found on the document. To retrieve this table, - # we look on the pdf structure using pypdf to compute the outlines_pages from - # the top level heading in /Outlines. + return collected_streams + + # In case of multiple docs, we need to split the pdf according the records. + # To do so, we split the pdf based on top outlines computed by wkhtmltopdf. + # An outline is a html tag found on the document. To retrieve this table, + # we look on the pdf structure using pypdf to compute the outlines_pages from + # the top level heading in /Outlines. + html_ids_wo_none = [x for x in html_ids if x] + if len(res_ids_wo_stream) > 1 and set(res_ids_wo_stream) == set(html_ids_wo_none): reader = PdfFileReader(pdf_content_stream) root = reader.trailer['/Root'] has_valid_outlines = '/Outlines' in root and '/First' in root['/Outlines'] @@ -747,18 +747,27 @@ class IrActionsReport(models.Model): break node = node['/Next'] outlines_pages = sorted(set(outlines_pages)) - # There should be only one top-level heading by document - assert len(outlines_pages) == len(res_ids) + + # The number of outlines must be equal to the number of records to be able to split the document. + has_same_number_of_outlines = len(outlines_pages) == len(res_ids) + # There should be a top-level heading on first page - assert outlines_pages[0] == 0 - for i, num in enumerate(outlines_pages): - to = outlines_pages[i + 1] if i + 1 < len(outlines_pages) else reader.numPages - attachment_writer = PdfFileWriter() - for j in range(num, to): - attachment_writer.addPage(reader.getPage(j)) - stream = io.BytesIO() - attachment_writer.write(stream) - collected_streams[res_ids[i]]['stream'] = stream + has_top_level_heading = outlines_pages[0] == 0 + + if has_same_number_of_outlines and has_top_level_heading: + # Split the PDF according to outlines. + for i, num in enumerate(outlines_pages): + to = outlines_pages[i + 1] if i + 1 < len(outlines_pages) else reader.numPages + attachment_writer = PdfFileWriter() + for j in range(num, to): + attachment_writer.addPage(reader.getPage(j)) + stream = io.BytesIO() + attachment_writer.write(stream) + collected_streams[res_ids[i]]['stream'] = stream + + return collected_streams + + collected_streams[False] = {'stream': pdf_content_stream} return collected_streams