[ADD] report_qweb_pdf_watermark (#86)
parent
fa0c51dc23
commit
ab1b1aa062
|
@ -2,10 +2,13 @@ sudo: false
|
|||
cache: pip
|
||||
|
||||
addons:
|
||||
sources:
|
||||
- pov-wkhtmltopdf
|
||||
apt:
|
||||
packages:
|
||||
- expect-dev # provides unbuffer utility
|
||||
- python-lxml # because pip installation is slow
|
||||
- wkhtmltopdf # report tests
|
||||
|
||||
language: python
|
||||
|
||||
|
@ -26,6 +29,10 @@ env:
|
|||
virtualenv:
|
||||
system_site_packages: true
|
||||
|
||||
before_install:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
|
||||
install:
|
||||
- git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
|
||||
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
|
||||
|
|
|
@ -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 <hbrunn@therp.nl>
|
||||
|
||||
Do not contact contributors directly about help with questions or problems concerning this addon, but use the `community mailing list <mailto:community@mail.odoo.com>`_ 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.
|
|
@ -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
|
|
@ -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",
|
||||
],
|
||||
}
|
|
@ -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>
|
|
@ -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
|
|
@ -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`')
|
|
@ -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()
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -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
|
|
@ -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)
|
|
@ -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>
|
Loading…
Reference in New Issue