Skip to content

Commit

Permalink
report_qweb_pdf_watermark (OCA#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
hbrunn authored and Kay Häusler committed Dec 19, 2018
1 parent 51d6556 commit eb1da5b
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 0 deletions.
62 changes: 62 additions & 0 deletions report_qweb_pdf_watermark/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

=============
Pdf watermark
=============

This module was written to add watermarks (backgrounds) to PDF reports.

This is necessary because of the way wkhtmltopdf handles headers and footers, in the current versions if quite impossible to have a background for the complete page.

Usage
=====

To use this module, you need to:

#. go to your report
#. select a PDF or image to use as watermark. Note that resolutions and size must match, otherwise you'll have funny results
#. advanced users (members of group technical settings) can also fill in an expression that returns the data (base64 encoded) to be used as watermark

.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/143/8.0

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 smashing it by providing a detailed and welcomed feedback.

Credits
=======

Images
------

* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.

Contributors
------------

* Holger Brunn <[email protected]>

Do not contact contributors directly about help with questions or problems concerning this addon, but use the `community mailing list <mailto:[email protected]>`_ or the `appropriate specialized mailinglist <https://odoo-community.org/groups>`_ for help, and the bug tracker linked in `Bug Tracker`_ above for technical issues.

Maintainer
----------

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

This module is maintained by the OCA.

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.

To contribute to this module, please visit https://odoo-community.org.
4 changes: 4 additions & 0 deletions report_qweb_pdf_watermark/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models
18 changes: 18 additions & 0 deletions report_qweb_pdf_watermark/__openerp__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Pdf watermark",
"version": "9.0.1.0.0",
"author": "Therp BV,Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "Reporting",
"summary": "Add watermarks to your QWEB PDF reports",
"depends": [
'report',
],
"data": [
"demo/report.xml",
"views/ir_actions_report_xml.xml",
],
}
30 changes: 30 additions & 0 deletions report_qweb_pdf_watermark/demo/report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<report
id="demo_report"
string="Demo report"
model="res.users"
report_type="qweb-pdf"
name="report_qweb_pdf_watermark.demo_report_view"
file="report_qweb_pdf_watermark.demo_report_view"
paperformat="report.paperformat_euro"
/>
<record id="demo_report" model="ir.actions.report.xml">
<field name="pdf_watermark_expression">docs[:1].company_id.logo</field>
</record>
<template id="demo_report_view">
<t t-call="report.html_container">
<t t-call="report.external_layout">
<div class="page">
<ul>
<li t-foreach="docs" t-as="doc">
<t t-esc="doc.name" />
</li>
</ul>
</div>
</t>
</t>
</template>
</data>
</openerp>
5 changes: 5 additions & 0 deletions report_qweb_pdf_watermark/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import ir_actions_report_xml
from . import report
14 changes: 14 additions & 0 deletions report_qweb_pdf_watermark/models/ir_actions_report_xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import fields, models


class IrActionsReportXml(models.Model):
_inherit = 'ir.actions.report.xml'

pdf_watermark = fields.Binary('Watermark')
pdf_watermark_expression = fields.Char(
'Watermark expression', help='An expression yielding the base64 '
'encoded data to be used as watermark. \n'
'You have access to variables `env` and `docs`')
87 changes: 87 additions & 0 deletions report_qweb_pdf_watermark/models/report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from base64 import b64decode
from logging import getLogger
from pyPdf import PdfFileWriter, PdfFileReader
from pyPdf.utils import PdfReadError
from PIL import Image
from StringIO import StringIO
from openerp import api, models, tools
logger = getLogger(__name__)


class Report(models.Model):
_inherit = 'report'

@api.v7
def get_pdf(
self, cr, uid, ids, report_name, html=None, data=None, context=None
):
# pylint: disable=R8110
# this override cannot be done in v8 api
result = super(Report, self).get_pdf(
cr, uid, ids, report_name, html=html, data=data,
context=context
)
report = self._get_report_from_name(cr, uid, report_name)
watermark = None
if report.pdf_watermark:
watermark = b64decode(report.pdf_watermark)
else:
env = api.Environment(cr, uid, context)
watermark = tools.safe_eval(
report.pdf_watermark_expression or 'None',
dict(env=env, docs=env[report.model].browse(ids)),
)
if watermark:
watermark = b64decode(watermark)

if not watermark:
return result

pdf = PdfFileWriter()
pdf_watermark = None
try:
pdf_watermark = PdfFileReader(StringIO(watermark))
except PdfReadError:
# let's see if we can convert this with pillow
try:
image = Image.open(StringIO(watermark))
pdf_buffer = StringIO()
if image.mode != 'RGB':
image = image.convert('RGB')
resolution = image.info.get(
'dpi', report.paperformat_id.dpi or 90
)
if isinstance(resolution, tuple):
resolution = resolution[0]
image.save(pdf_buffer, 'pdf', resolution=resolution)
pdf_watermark = PdfFileReader(pdf_buffer)
except:
logger.exception('Failed to load watermark')

if not pdf_watermark:
logger.error(
'No usable watermark found, got %s...', watermark[:100]
)
return result

if pdf_watermark.numPages < 1:
logger.error('Your watermark pdf does not contain any pages')
return result
if pdf_watermark.numPages > 1:
logger.debug('Your watermark pdf contains more than one page, '
'all but the first one will be ignored')

for page in PdfFileReader(StringIO(result)).pages:
watermark_page = pdf.addBlankPage(
page.mediaBox.getWidth(), page.mediaBox.getHeight()
)
watermark_page.mergePage(pdf_watermark.getPage(0))
watermark_page.mergePage(page)

pdf_content = StringIO()
pdf.write(pdf_content)

return pdf_content.getvalue()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions report_qweb_pdf_watermark/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_report_qweb_pdf_watermark
32 changes: 32 additions & 0 deletions report_qweb_pdf_watermark/tests/test_report_qweb_pdf_watermark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.tests.common import TransactionCase


class TestReportQwebPdfWatermark(TransactionCase):
def test_report_qweb_pdf_watermark(self):
# with our image, we have three
self._test_report_images(3)

self.env.ref('report_qweb_pdf_watermark.demo_report').write({
'pdf_watermark_expression': False,
})
# without, we have two
self._test_report_images(2)

self.env.ref('report_qweb_pdf_watermark.demo_report').write({
'pdf_watermark': self.env.user.company_id.logo,
})
# and now we should have three again
self._test_report_images(3)

def _test_report_images(self, number):
pdf = self.registry['report'].get_pdf(
self.cr,
self.uid,
self.env['res.users'].search([]).ids,
'report_qweb_pdf_watermark.demo_report_view',
context={}
)
self.assertEqual(pdf.count('/Subtype /Image'), number)
15 changes: 15 additions & 0 deletions report_qweb_pdf_watermark/views/ir_actions_report_xml.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="act_report_xml_view" model="ir.ui.view">
<field name="model">ir.actions.report.xml</field>
<field name="inherit_id" ref="base.act_report_xml_view" />
<field name="arch" type="xml">
<field name="attachment" position="after">
<field 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>
</record>
</data>
</openerp>

0 comments on commit eb1da5b

Please sign in to comment.