Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
=====================
Report QWeb PDF Cover
=====================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:a8281cb16bf42a1a55f7a1e0ee12c955d423b27fb9ded1f215f7033e67721644
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
:target: https://github.com/OCA/reporting-engine/tree/18.0/report_qweb_pdf_cover
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-report_qweb_pdf_cover
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows for front and back covers to be added to the
generated PDF reports. They can be added as a separate page, at the
beginning or the end of the report, but they can also overlap the first
and last page of the actual report, respectively.
**Table of contents**
.. contents::
:local:
Usage
=====
To add a cover to a report, you need to access to the report's
configuration, more specifically to the Advanced Properties tab. There,
you will find two checkboxes, one for the front cover and another for
the back cover. They both work the same, so let's focus on the front
cover with an example.
- You must check the Use Front Cover checkbox to enable the front cover.
You will see that a new checkbox and a PDF file widget appear.
- If you want the front cover to overlap with the first page of the PDF
report, you should also check the Overlap Front Cover checkbox. Leave
it unchecked if you don't want the front cover to overlap with the
first page.
- The last step would be to upload the PDF file that will be used as the
front cover. You can do this by clicking on the PDF file widget and
selecting the file.
- Important! The file must be a PDF file, and it should have only one
page. If it has more pages, only the first one will be used.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/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
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_qweb_pdf_cover%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* ForgeFlow
Contributors
------------
- Laura Cazorla <laura.cazorla@forgeflow.com>
Maintainers
-----------
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/18.0/report_qweb_pdf_cover>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,4 @@
# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com)
# Part of ForgeFlow. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -0,0 +1,16 @@
# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com)
# Part of ForgeFlow. See LICENSE file for full copyright and licensing details.
{
"name": "Report QWeb PDF Cover",
"summary": "Add front and back covers to your QWeb PDF reports",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
"category": "Reporting",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"depends": ["web"],
"data": ["views/ir_actions_views.xml"],
"installable": True,
"application": False,
}

View File

@@ -0,0 +1,158 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * report_qweb_pdf_cover
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-27 08:09+0000\n"
"PO-Revision-Date: 2024-08-27 08:09+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__back_cover_pdf
msgid "Back Cover PDF"
msgstr "Contraportada PDF"
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Failed to load back cover: %s"
msgstr "Error al cargar la contraportada: %s"
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Failed to load front cover: %s"
msgstr "Error al cargar la portada: %s"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__front_cover_pdf
msgid "Front Cover PDF"
msgstr "Portada PDF"
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "No usable back cover found."
msgstr "No se encontró ninguna contraportada usable."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "No usable front cover found."
msgstr "No se encontró ninguna portada usable."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__back_cover_overlap
msgid "Overlap Back Cover"
msgstr "Superponer Contraportada"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__front_cover_overlap
msgid "Overlap Front Cover"
msgstr "Superponer Portada"
#. module: report_qweb_pdf_cover
#: model:ir.model,name:report_qweb_pdf_cover.model_ir_actions_report
msgid "Report Action"
msgstr "Acción de Informe"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__back_cover_pdf
msgid "Upload an PDF file to use as a back cover on this report."
msgstr "Suba un archivo PDF para usar como contraportada en este informe."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__front_cover_pdf
msgid "Upload an PDF file to use as a front cover on this report."
msgstr "Suba un archivo PDF para usar como portada en este informe."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__use_back_cover
msgid "Use Back Cover"
msgstr "Usar Contraportada"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__use_front_cover
msgid "Use Front Cover"
msgstr "Usar Portada"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__use_back_cover
msgid "Use a back cover when rendering the PDF report."
msgstr "Usar una contraportada al renderizar el informe PDF."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__use_front_cover
msgid "Use a front cover when rendering the PDF report."
msgstr "Usar una portada al renderizar el informe PDF."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__back_cover_overlap
msgid ""
"When set, the back cover of the report will overlap with the contents of the "
"last page of the report. This is useful to include some information of the "
"report in the back cover."
msgstr ""
"Cuando se establece, la contraportada del informe se superpondrá con el "
"contenido de la última página del informe. Esto es útil para incluir alguna "
"información del informe en la contraportada."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__front_cover_overlap
msgid ""
"When set, the front cover of the report will overlap with the contents of "
"the first page of the report. This is useful to include some information of "
"the report in the front cover."
msgstr ""
"Cuando se establece, la portada del informe se superpondrá con el contenido "
"de la primera página del informe. Esto es útil para incluir alguna "
"información del informe en la portada."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid ""
"Your back cover PDF contains more than one page, all but the first one will "
"be ignored."
msgstr ""
"Su contraportada PDF contiene más de una página, todas menos la primera se "
"ignorarán."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Your back cover PDF does not contain any pages."
msgstr "Su contraportada PDF no contiene ninguna página."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid ""
"Your front cover PDF contains more than one page, all but the first one will "
"be ignored."
msgstr ""
"Su portada PDF contiene más de una página, todas menos la primera se "
"ignorarán."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Your front cover PDF does not contain any pages."
msgstr "Su portada PDF no contiene ninguna página"

View File

@@ -0,0 +1,157 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * report_qweb_pdf_cover
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-10-23 09:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.6.2\n"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__back_cover_pdf
msgid "Back Cover PDF"
msgstr "Retrocopertina PDF"
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Failed to load back cover: %s"
msgstr "Caricamento retrocopertina fallito: %s"
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Failed to load front cover: %s"
msgstr "Caricamento copertina fallito: %s"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__front_cover_pdf
msgid "Front Cover PDF"
msgstr "Copertina PDF"
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "No usable back cover found."
msgstr "Trovata retrocopertina non utilizzabile."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "No usable front cover found."
msgstr "Trovata copertina non usabile."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__back_cover_overlap
msgid "Overlap Back Cover"
msgstr "Sovrapponi retrocopertina"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__front_cover_overlap
msgid "Overlap Front Cover"
msgstr "Sovrapponi copertina"
#. module: report_qweb_pdf_cover
#: model:ir.model,name:report_qweb_pdf_cover.model_ir_actions_report
msgid "Report Action"
msgstr "Azione resoconto"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__back_cover_pdf
msgid "Upload an PDF file to use as a back cover on this report."
msgstr "Carica un file PDF da usare come retrocopertina in questo resoconto."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__front_cover_pdf
msgid "Upload an PDF file to use as a front cover on this report."
msgstr "Carica un file PDF da usare come copertina in questo resoconto."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__use_back_cover
msgid "Use Back Cover"
msgstr "Utilizza retrocopertina"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__use_front_cover
msgid "Use Front Cover"
msgstr "Utilizza copertina"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__use_back_cover
msgid "Use a back cover when rendering the PDF report."
msgstr "Utilizza retrocopertina nella produzione del resoconto PDF."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__use_front_cover
msgid "Use a front cover when rendering the PDF report."
msgstr "Utilizza copertina nella produzione del resoconto PDF."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__back_cover_overlap
msgid ""
"When set, the back cover of the report will overlap with the contents of the"
" last page of the report. This is useful to include some information of the "
"report in the back cover."
msgstr ""
"Se impostato, la retrocopertina del resoconto si sovrapporrà al contenuto "
"dell'ultima pagina del resoconto. Ciò è utile per includere alcune "
"informazioni del resoconto nella retrocopertina."
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__front_cover_overlap
msgid ""
"When set, the front cover of the report will overlap with the contents of "
"the first page of the report. This is useful to include some information of "
"the report in the front cover."
msgstr ""
"Se impostato, la copertina del resoconto si sovrapporrà al contenuto della "
"prima pagina del resoconto. Ciò è utile per includere alcune informazioni "
"del resoconto nella copertina."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid ""
"Your back cover PDF contains more than one page, all but the first one will "
"be ignored."
msgstr ""
"La retrocopertina PDF contiene più di una pagina, verrà considerata solo la "
"prima."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Your back cover PDF does not contain any pages."
msgstr "La retrocopertina PDF non contiene alcuna pagina."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid ""
"Your front cover PDF contains more than one page, all but the first one will"
" be ignored."
msgstr ""
"La copertina PDF contiene più di una pagina, verrà considerata solo la prima."
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
#, python-format
msgid "Your front cover PDF does not contain any pages."
msgstr "La copertina PDF non contiene alcuna pagina."

View File

@@ -0,0 +1,137 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * report_qweb_pdf_cover
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__back_cover_pdf
msgid "Back Cover PDF"
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid "Failed to load back cover: %s"
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid "Failed to load front cover: %s"
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__front_cover_pdf
msgid "Front Cover PDF"
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid "No usable back cover found."
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid "No usable front cover found."
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__back_cover_overlap
msgid "Overlap Back Cover"
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__front_cover_overlap
msgid "Overlap Front Cover"
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model,name:report_qweb_pdf_cover.model_ir_actions_report
msgid "Report Action"
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__back_cover_pdf
msgid "Upload an PDF file to use as a back cover on this report."
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__front_cover_pdf
msgid "Upload an PDF file to use as a front cover on this report."
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__use_back_cover
msgid "Use Back Cover"
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,field_description:report_qweb_pdf_cover.field_ir_actions_report__use_front_cover
msgid "Use Front Cover"
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__use_back_cover
msgid "Use a back cover when rendering the PDF report."
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__use_front_cover
msgid "Use a front cover when rendering the PDF report."
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__back_cover_overlap
msgid ""
"When set, the back cover of the report will overlap with the contents of the"
" last page of the report. This is useful to include some information of the "
"report in the back cover."
msgstr ""
#. module: report_qweb_pdf_cover
#: model:ir.model.fields,help:report_qweb_pdf_cover.field_ir_actions_report__front_cover_overlap
msgid ""
"When set, the front cover of the report will overlap with the contents of "
"the first page of the report. This is useful to include some information of "
"the report in the front cover."
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid ""
"Your back cover PDF contains more than one page, all but the first one will "
"be ignored."
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid "Your back cover PDF does not contain any pages."
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid ""
"Your front cover PDF contains more than one page, all but the first one will"
" be ignored."
msgstr ""
#. module: report_qweb_pdf_cover
#. odoo-python
#: code:addons/report_qweb_pdf_cover/models/ir_actions_report.py:0
msgid "Your front cover PDF does not contain any pages."
msgstr ""

View File

@@ -0,0 +1,4 @@
# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com)
# Part of ForgeFlow. See LICENSE file for full copyright and licensing details.
from . import ir_actions_report

View File

@@ -0,0 +1,220 @@
# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com)
# Part of ForgeFlow. See LICENSE file for full copyright and licensing details.
from base64 import b64decode
from io import BytesIO
from logging import getLogger
from PyPDF2 import PdfFileReader, PdfFileWriter
from odoo import api, fields, models
logger = getLogger(__name__)
class Report(models.Model):
_inherit = "ir.actions.report"
use_front_cover = fields.Boolean(
default=False, help="Use a front cover when rendering the PDF report."
)
use_back_cover = fields.Boolean(
default=False, help="Use a back cover when rendering the PDF report."
)
front_cover_overlap = fields.Boolean(
default=False,
string="Overlap Front Cover",
help="When set, the front cover of the report will overlap with the "
"contents of the first page of the report. This is useful to include "
"some information of the report in the front cover.",
)
back_cover_overlap = fields.Boolean(
default=False,
string="Overlap Back Cover",
help="When set, the back cover of the report will overlap with the "
"contents of the last page of the report. This is useful to include "
"some information of the report in the back cover.",
)
front_cover_pdf = fields.Binary(
string="Front Cover PDF",
help="Upload an PDF file to use as a front cover on this report.",
)
back_cover_pdf = fields.Binary(
string="Back Cover PDF",
help="Upload an PDF file to use as a back cover on this report.",
)
@api.model
def pdf_check_pages(self, num_pages, front=True):
if num_pages < 1:
if front:
logger.error(
self.env._("Your front cover PDF does not contain any pages.")
)
else:
logger.error(
self.env._("Your back cover PDF does not contain any pages.")
)
return False
elif num_pages > 1:
if front:
logger.info(
self.env._(
"Your front cover PDF contains more than one page, "
"all but the first one will be ignored."
)
)
else:
logger.info(
self.env._(
"Your back cover PDF contains more than one page, "
"all but the first one will be ignored."
)
)
return True
def load_covers(
self, report_sudo, front_cover, back_cover, use_front_cover, use_back_cover
):
if use_front_cover:
front_cover_pdf = self.front_cover_pdf or report_sudo.front_cover_pdf
if front_cover_pdf:
front_cover = b64decode(front_cover_pdf)
if use_back_cover:
back_cover_pdf = self.back_cover_pdf or report_sudo.back_cover_pdf
if back_cover_pdf:
back_cover = b64decode(back_cover_pdf)
return front_cover, back_cover
@api.model
def load_cover_pdfs(self, front_cover, back_cover, use_front_cover, use_back_cover):
pdf_front_cover = False
pdf_back_cover = False
if use_front_cover:
try:
pdf_front_cover = PdfFileReader(BytesIO(front_cover))
if not pdf_front_cover:
use_front_cover = False
logger.error(self.env._("No usable front cover found."))
except Exception as e:
use_front_cover = False
logger.exception(self.env._("Failed to load front cover: %s", e))
if use_back_cover:
try:
pdf_back_cover = PdfFileReader(BytesIO(back_cover))
if not pdf_back_cover:
use_back_cover = False
logger.error(self.env._("No usable back cover found."))
except Exception as e:
use_back_cover = False
logger.exception(self.env._("Failed to load back cover: %s", e))
return use_front_cover, pdf_front_cover, use_back_cover, pdf_back_cover
@api.model
def insert_cover_pages(
self,
pdf,
pages,
pdf_front_cover,
pdf_back_cover,
use_front_cover,
use_back_cover,
front_cover_overlap,
back_cover_overlap,
):
for index, page in enumerate(pages):
report_page = pdf.addBlankPage(
page.mediaBox.getWidth(), page.mediaBox.getHeight()
)
if index == 0 and use_front_cover:
if not front_cover_overlap:
front_cover_page = report_page
front_cover_page.mergePage(pdf_front_cover.getPage(0))
report_page = pdf.addBlankPage(
page.mediaBox.getWidth(), page.mediaBox.getHeight()
)
else:
report_page.mergePage(pdf_front_cover.getPage(0))
if index == len(pages) - 1 and use_back_cover:
if not back_cover_overlap:
back_cover_page = pdf.addBlankPage(
page.mediaBox.getWidth(), page.mediaBox.getHeight()
)
back_cover_page.mergePage(pdf_back_cover.getPage(0))
else:
report_page.mergePage(pdf_back_cover.getPage(0))
report_page.mergePage(page)
@api.model
def _run_wkhtmltopdf(
self,
bodies,
report_ref=False,
header=None,
footer=None,
landscape=False,
specific_paperformat_args=None,
set_viewport_size=False,
):
result = super()._run_wkhtmltopdf(
bodies,
report_ref=report_ref,
header=header,
footer=footer,
landscape=landscape,
specific_paperformat_args=specific_paperformat_args,
set_viewport_size=set_viewport_size,
)
report_sudo = self._get_report(report_ref)
front_cover = False
back_cover = False
use_front_cover = self.use_front_cover or report_sudo.use_front_cover
use_back_cover = self.use_back_cover or report_sudo.use_back_cover
front_cover_overlap = (
self.front_cover_overlap or report_sudo.front_cover_overlap
)
back_cover_overlap = self.back_cover_overlap or report_sudo.back_cover_overlap
if not use_front_cover and not use_back_cover:
return result
front_cover, back_cover = self.load_covers(
report_sudo, front_cover, back_cover, use_front_cover, use_back_cover
)
if not front_cover and not back_cover:
return result
pdf = PdfFileWriter()
(
use_front_cover,
pdf_front_cover,
use_back_cover,
pdf_back_cover,
) = self.load_cover_pdfs(
front_cover, back_cover, use_front_cover, use_back_cover
)
if use_front_cover and not self.pdf_check_pages(
pdf_front_cover.numPages, front=True
):
use_front_cover = False
if use_back_cover and not self.pdf_check_pages(
pdf_back_cover.numPages, front=False
):
use_back_cover = False
pages = PdfFileReader(BytesIO(result)).pages
self.insert_cover_pages(
pdf,
pages,
pdf_front_cover,
pdf_back_cover,
use_front_cover,
use_back_cover,
front_cover_overlap,
back_cover_overlap,
)
pdf_content = BytesIO()
pdf.write(pdf_content)
return pdf_content.getvalue()

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1 @@
- Laura Cazorla \<<laura.cazorla@forgeflow.com>\>

View File

@@ -0,0 +1,4 @@
This module allows for front and back covers to be added to the
generated PDF reports. They can be added as a separate page, at the
beginning or the end of the report, but they can also overlap the first
and last page of the actual report, respectively.

View File

@@ -0,0 +1,17 @@
To add a cover to a report, you need to access to the report's
configuration, more specifically to the Advanced Properties tab. There,
you will find two checkboxes, one for the front cover and another for
the back cover. They both work the same, so let's focus on the front
cover with an example.
- You must check the Use Front Cover checkbox to enable the front cover.
You will see that a new checkbox and a PDF file widget appear.
- If you want the front cover to overlap with the first page of the PDF
report, you should also check the Overlap Front Cover checkbox. Leave
it unchecked if you don't want the front cover to overlap with the
first page.
- The last step would be to upload the PDF file that will be used as the
front cover. You can do this by clicking on the PDF file widget and
selecting the file.
- Important! The file must be a PDF file, and it should have only one
page. If it has more pages, only the first one will be used.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,448 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Report QWeb PDF Cover</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
: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.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
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 }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="report-qweb-pdf-cover">
<h1 class="title">Report QWeb PDF Cover</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:a8281cb16bf42a1a55f7a1e0ee12c955d423b27fb9ded1f215f7033e67721644
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/reporting-engine/tree/18.0/report_qweb_pdf_cover"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-report_qweb_pdf_cover"><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/reporting-engine&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows for front and back covers to be added to the
generated PDF reports. They can be added as a separate page, at the
beginning or the end of the report, but they can also overlap the first
and last page of the actual report, respectively.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>To add a cover to a report, you need to access to the reports
configuration, more specifically to the Advanced Properties tab. There,
you will find two checkboxes, one for the front cover and another for
the back cover. They both work the same, so lets focus on the front
cover with an example.</p>
<ul class="simple">
<li>You must check the Use Front Cover checkbox to enable the front cover.
You will see that a new checkbox and a PDF file widget appear.</li>
<li>If you want the front cover to overlap with the first page of the PDF
report, you should also check the Overlap Front Cover checkbox. Leave
it unchecked if you dont want the front cover to overlap with the
first page.</li>
<li>The last step would be to upload the PDF file that will be used as the
front cover. You can do this by clicking on the PDF file widget and
selecting the file.</li>
<li>Important! The file must be a PDF file, and it should have only one
page. If it has more pages, only the first one will be used.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_qweb_pdf_cover%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>ForgeFlow</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<ul class="simple">
<li>Laura Cazorla &lt;<a class="reference external" href="mailto:laura.cazorla&#64;forgeflow.com">laura.cazorla&#64;forgeflow.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/18.0/report_qweb_pdf_cover">OCA/reporting-engine</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,32 @@
<?xml version='1.0' encoding='utf-8' ?>
<odoo>
<record id="act_report_xml_view" model="ir.ui.view">
<field name="model">ir.actions.report</field>
<field name="inherit_id" ref="base.act_report_xml_view" />
<field name="arch" type="xml">
<field name="attachment" position="after">
<field name="use_front_cover" invisible="report_type != 'qweb-pdf'" />
<field
name="front_cover_overlap"
invisible="report_type != 'qweb-pdf' or not use_front_cover"
/>
<field
name="front_cover_pdf"
invisible="report_type != 'qweb-pdf' or not use_front_cover"
widget="pdf_viewer"
/>
<field name="use_back_cover" invisible="report_type != 'qweb-pdf'" />
<field
name="back_cover_overlap"
invisible="report_type != 'qweb-pdf' or not use_back_cover"
/>
<field
name="back_cover_pdf"
invisible="report_type != 'qweb-pdf' or not use_back_cover"
widget="pdf_viewer"
/>
</field>
</field>
</record>
</odoo>