[13.0][MIG] report_qweb_pdf_watermark

pull/478/head
fshah 2021-01-28 11:15:00 +05:30
parent 5554601d7e
commit 929e2309a4
10 changed files with 78 additions and 58 deletions

View File

@ -62,6 +62,11 @@ Changelog
* [MIG] Migration to V12. * [MIG] Migration to V12.
13.0.1.0.0 (2021-01-27)
~~~~~~~~~~~~~~~~~~~~~~~
* [MIG] Migration to V13.
Bug Tracker Bug Tracker
=========== ===========
@ -87,6 +92,7 @@ Contributors
* Stefan Rijnhart <stefan@opener.am> * Stefan Rijnhart <stefan@opener.am>
* Rod Schouteden <rod.schouteden@dynapps.be> * Rod Schouteden <rod.schouteden@dynapps.be>
* Robin Goots <robin.goots@dynapps.be> * Robin Goots <robin.goots@dynapps.be>
* Foram Shah <foram.shah@initos.com>
Maintainers Maintainers
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@ -1,4 +1,4 @@
# © 2016 Therp BV <http://therp.nl> # © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models from . import models # pyflakes.ignore

View File

@ -2,28 +2,19 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{ {
"name": "Pdf watermark", "name": "Pdf watermark",
"version": "12.0.1.0.1", "version": "13.0.1.0.0",
"author": "Therp BV, " "author": "Therp BV, " "Odoo Community Association (OCA)",
"Odoo Community Association (OCA)",
"license": "AGPL-3", "license": "AGPL-3",
"category": "Technical Settings", "category": "Technical Settings",
"summary": "Add watermarks to your QWEB PDF reports", "summary": "Add watermarks to your QWEB PDF reports",
"website": "https://github.com/oca/reporting-engine", "website": "https://github.com/oca/reporting-engine",
"depends": [ "depends": ["web"],
'web',
],
"data": [ "data": [
"demo/report.xml", "demo/report.xml",
"views/ir_actions_report_xml.xml", "views/ir_actions_report_xml.xml",
"views/layout_templates.xml", "views/layout_templates.xml",
], ],
"demo": [ "demo": ["demo/report.xml"],
"demo/report.xml"
],
"installable": True, "installable": True,
'external_dependencies': { "external_dependencies": {"python": ["PyPDF2"]},
'python': [
'PyPDF2',
],
},
} }

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<report <report
id="demo_report" id="demo_report"
@ -8,7 +8,7 @@
name="report_qweb_pdf_watermark.demo_report_view" name="report_qweb_pdf_watermark.demo_report_view"
file="report_qweb_pdf_watermark.demo_report_view" file="report_qweb_pdf_watermark.demo_report_view"
paperformat="base.paperformat_euro" paperformat="base.paperformat_euro"
/> />
<record id="demo_report" model="ir.actions.report"> <record id="demo_report" model="ir.actions.report">
<field name="pdf_watermark_expression">docs[:1].company_id.logo</field> <field name="pdf_watermark_expression">docs[:1].company_id.logo</field>
</record> </record>

View File

@ -1,3 +1,4 @@
# © 2016 Therp BV <http://therp.nl> # © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import report from . import report

View File

@ -1,16 +1,18 @@
# © 2016 Therp BV <http://therp.nl> # © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from base64 import b64decode from base64 import b64decode
from logging import getLogger
from PIL import Image
from io import BytesIO from io import BytesIO
from logging import getLogger
from PIL import Image
from odoo import api, fields, models, tools
try: try:
# we need this to be sure PIL has loaded PDF support # we need this to be sure PIL has loaded PDF support
from PIL import PdfImagePlugin # noqa: F401 from PIL import PdfImagePlugin # noqa: F401
except ImportError: except ImportError:
pass pass
from odoo import api, models, fields, tools
logger = getLogger(__name__) logger = getLogger(__name__)
@ -18,42 +20,53 @@ try:
from PyPDF2 import PdfFileWriter, PdfFileReader # pylint: disable=W0404 from PyPDF2 import PdfFileWriter, PdfFileReader # pylint: disable=W0404
from PyPDF2.utils import PdfReadError # pylint: disable=W0404 from PyPDF2.utils import PdfReadError # pylint: disable=W0404
except ImportError: except ImportError:
logger.debug('Can not import PyPDF2') logger.debug("Can not import PyPDF2")
class Report(models.Model): class Report(models.Model):
_inherit = 'ir.actions.report' _inherit = "ir.actions.report"
pdf_watermark = fields.Binary('Watermark') pdf_watermark = fields.Binary("Watermark")
pdf_watermark_expression = fields.Char( pdf_watermark_expression = fields.Char(
'Watermark expression', help='An expression yielding the base64 ' "Watermark expression",
'encoded data to be used as watermark. \n' help="An expression yielding the base64 "
'You have access to variables `env` and `docs`') "encoded data to be used as watermark. \n"
"You have access to variables `env` and `docs`",
)
@api.multi
def render_qweb_pdf(self, res_ids=None, data=None): def render_qweb_pdf(self, res_ids=None, data=None):
if not self.env.context.get('res_ids'): if not self.env.context.get("res_ids"):
return super( return super(Report, self.with_context(res_ids=res_ids)).render_qweb_pdf(
Report, self.with_context(res_ids=res_ids) res_ids=res_ids, data=data
).render_qweb_pdf(res_ids=res_ids, data=data) )
return super(Report, self).render_qweb_pdf(res_ids=res_ids, data=data) return super(Report, self).render_qweb_pdf(res_ids=res_ids, data=data)
@api.model @api.model
def _run_wkhtmltopdf(self, bodies, header=None, footer=None, def _run_wkhtmltopdf(
landscape=False, specific_paperformat_args=None, self,
set_viewport_size=False): bodies,
header=None,
footer=None,
landscape=False,
specific_paperformat_args=None,
set_viewport_size=False,
):
result = super(Report, self)._run_wkhtmltopdf( result = super(Report, self)._run_wkhtmltopdf(
bodies, header=header, footer=footer, landscape=landscape, bodies,
header=header,
footer=footer,
landscape=landscape,
specific_paperformat_args=specific_paperformat_args, specific_paperformat_args=specific_paperformat_args,
set_viewport_size=set_viewport_size) set_viewport_size=set_viewport_size,
)
docids = self.env.context.get('res_ids', False) docids = self.env.context.get("res_ids", False)
watermark = None watermark = None
if self.pdf_watermark: if self.pdf_watermark:
watermark = b64decode(self.pdf_watermark) watermark = b64decode(self.pdf_watermark)
elif docids: elif docids:
watermark = tools.safe_eval( watermark = tools.safe_eval(
self.pdf_watermark_expression or 'None', self.pdf_watermark_expression or "None",
dict(env=self.env, docs=self.env[self.model].browse(docids)), dict(env=self.env, docs=self.env[self.model].browse(docids)),
) )
if watermark: if watermark:
@ -72,30 +85,28 @@ class Report(models.Model):
Image.init() Image.init()
image = Image.open(BytesIO(watermark)) image = Image.open(BytesIO(watermark))
pdf_buffer = BytesIO() pdf_buffer = BytesIO()
if image.mode != 'RGB': if image.mode != "RGB":
image = image.convert('RGB') image = image.convert("RGB")
resolution = image.info.get( resolution = image.info.get("dpi", self.paperformat_id.dpi or 90)
'dpi', self.paperformat_id.dpi or 90
)
if isinstance(resolution, tuple): if isinstance(resolution, tuple):
resolution = resolution[0] resolution = resolution[0]
image.save(pdf_buffer, 'pdf', resolution=resolution) image.save(pdf_buffer, "pdf", resolution=resolution)
pdf_watermark = PdfFileReader(pdf_buffer) pdf_watermark = PdfFileReader(pdf_buffer)
except: except Exception as e:
logger.exception('Failed to load watermark') logger.exception("Failed to load watermark", e)
if not pdf_watermark: if not pdf_watermark:
logger.error( logger.error("No usable watermark found, got %s...", watermark[:100])
'No usable watermark found, got %s...', watermark[:100]
)
return result return result
if pdf_watermark.numPages < 1: if pdf_watermark.numPages < 1:
logger.error('Your watermark pdf does not contain any pages') logger.error("Your watermark pdf does not contain any pages")
return result return result
if pdf_watermark.numPages > 1: if pdf_watermark.numPages > 1:
logger.debug('Your watermark pdf contains more than one page, ' logger.debug(
'all but the first one will be ignored') "Your watermark pdf contains more than one page, "
"all but the first one will be ignored"
)
for page in PdfFileReader(BytesIO(result)).pages: for page in PdfFileReader(BytesIO(result)).pages:
watermark_page = pdf.addBlankPage( watermark_page = pdf.addBlankPage(

View File

@ -1,3 +1,4 @@
# © 2016 Therp BV <http://therp.nl> # © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_report_qweb_pdf_watermark from . import test_report_qweb_pdf_watermark

View File

@ -1,6 +1,7 @@
# © 2016 Therp BV <http://therp.nl> # © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from PIL import Image from PIL import Image
from odoo.tests.common import HttpCase from odoo.tests.common import HttpCase

View File

@ -1,12 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="act_report_xml_view" model="ir.ui.view"> <record id="act_report_xml_view" model="ir.ui.view">
<field name="model">ir.actions.report</field> <field name="model">ir.actions.report</field>
<field name="inherit_id" ref="base.act_report_xml_view" /> <field name="inherit_id" ref="base.act_report_xml_view" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="attachment" position="after"> <field name="attachment" position="after">
<field name="pdf_watermark" attrs="{'invisible': [('report_type', '!=', 'qweb-pdf')]}" /> <field
<field name="pdf_watermark_expression" attrs="{'invisible': [('report_type', '!=', 'qweb-pdf')]}" groups="base.group_no_one" /> name="pdf_watermark"
attrs="{'invisible': [('report_type', '!=', 'qweb-pdf')]}"
/>
<field
name="pdf_watermark_expression"
attrs="{'invisible': [('report_type', '!=', 'qweb-pdf')]}"
groups="base.group_no_one"
/>
</field> </field>
</field> </field>
</record> </record>

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Include fix for https://github.com/odoo/odoo/issues/16610 --> <!-- Include fix for https://github.com/odoo/odoo/issues/16610 -->
<template id="assets_pdf" inherit_id="web.report_assets_pdf"> <template id="assets_pdf" inherit_id="web.report_assets_pdf">
<link position="after"> <link position="after">
<link href="/report_qweb_pdf_watermark/static/src/css/report_qweb_pdf_watermark.css" <link
rel="stylesheet"/> href="/report_qweb_pdf_watermark/static/src/css/report_qweb_pdf_watermark.css"
rel="stylesheet"
/>
</link> </link>
</template> </template>
</odoo> </odoo>