Skip to content

[16.0][MIG] report fillpdf #1013

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions report_fillpdf/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

====================
Base report fill PDF
====================

This module provides a basic report class that fills pdfs.

Installation
============

Make sure you have ``fdfgen`` Python module installed::

$ pip install fdfgen

For testing it is also necessary ``pdftk`` app installed:

Ubuntu ::

apt-get install pdftk

OSX ::

* Install pdftk (https://www.pdflabs.com/tools/pdftk-server/).

Windows ::

* Install pdftk (https://www.pdflabs.com/tools/pdftk-server/).

Usage
=====

An example of Fill PDF report for partners on a module called `module_name`:

A python class ::

from odoo import models

class PartnerFillPDF(models.AbstractModel):
_name = 'report.module_name.report_name'
_inherit = 'report.report_fillpdf.abstract'

@api.model
def get_original_document_path(self, data, objs):
return get_resource_path(
'report_fillpdf', 'static/src/pdf', 'partner_pdf.pdf')

@api.model
def get_document_values(self, data, objs):
objs.ensure_one()
return {'name': objs.name}

A computed form can be executed modifying the computing function ::

from odoo import models

class PartnerFillPDF(models.AbstractModel):
_name = 'report.module_name.report_name'
_inherit = 'report.report_fillpdf.abstract'

@api.model
def get_form(self, data, objs):
return self.env['ir.attachment'].search([], limit=1)

@api.model
def get_document_values(self, data, objs):
objs.ensure_one()
return {'name': objs.name}


A report XML record ::

<report
id="partner_fillpdf"
model="res.partner"
string="Fill PDF"
report_type="fillpdf"
name="report_fillpdf.partner_fillpdf"
file="res_partner"
attachment_use="False"
/>

.. 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/11.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
=======

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

* Enric Tobella <[email protected]>

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.
5 changes: 5 additions & 0 deletions report_fillpdf/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from . import controllers
from . import models
from . import report
34 changes: 34 additions & 0 deletions report_fillpdf/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2017 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Base report PDF Filler",
"summary": """
Base module that fills PDFs""",
"author": "Creu Blanca," "Odoo Community Association (OCA)",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Creu Blanca, Odoo Community Association (OCA)"

"website": "https://github.com/OCA/reporting-engine",
"category": "Reporting",
"version": "16.0.1.0.1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to 16.0.1.0.0

"license": "AGPL-3",
"external_dependencies": {
"python": [
"fdfgen",
],
"deb": [
"pdftk",
],
},
"depends": [
"base",
"web",
],
"data": [],
"demo": [
"demo/report.xml",
],
"installable": True,
"assets": {
"web.assets_backend": [
"report_fillpdf/static/src/js/report/action_manager_report.esm.js",
],
},
}
1 change: 1 addition & 0 deletions report_fillpdf/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import main
99 changes: 99 additions & 0 deletions report_fillpdf/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright (C) 2017 Creu Blanca
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).

import json
import logging

from werkzeug.urls import url_decode

from odoo.http import (
content_disposition,
request,
route,
serialize_exception as _serialize_exception,
)
from odoo.tools import html_escape
from odoo.tools.safe_eval import safe_eval, time

from odoo.addons.web.controllers.report import ReportController

_logger = logging.getLogger(__name__)


class ReportController(ReportController):
@route()
def report_routes(self, reportname, docids=None, converter=None, **data):
if converter == "fillpdf":
report = request.env["ir.actions.report"]._get_report_from_name(reportname)
context = dict(request.env.context)

Check warning on line 28 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L27-L28

Added lines #L27 - L28 were not covered by tests
if docids:
docids = [int(i) for i in docids.split(",")]

Check warning on line 30 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L30

Added line #L30 was not covered by tests
if data.get("options"):
data.update(json.loads(data.pop("options")))

Check warning on line 32 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L32

Added line #L32 was not covered by tests
if data.get("context"):
data["context"] = json.loads(data["context"])
context.update(data["context"])
pdf = report.with_context(**context).render_fillpdf(

Check warning on line 36 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L34-L36

Added lines #L34 - L36 were not covered by tests
reportname, docids, data=data
)[0]
pdfhttpheaders = [

Check warning on line 39 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L39

Added line #L39 was not covered by tests
("Content-Type", "application/pdf"),
("Content-Length", len(pdf)),
]
return request.make_response(pdf, headers=pdfhttpheaders)
return super().report_routes(reportname, docids, converter, **data)

Check warning on line 44 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L43-L44

Added lines #L43 - L44 were not covered by tests

@route()
def report_download(self, data, context=None, token=None):
requestcontent = json.loads(data)
url, report_type = requestcontent[0], requestcontent[1]

Check warning on line 49 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L48-L49

Added lines #L48 - L49 were not covered by tests
if report_type == "fillpdf":
try:
reportname = url.split("/report/fillpdf/")[1].split("?")[0]
docids = None

Check warning on line 53 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L51-L53

Added lines #L51 - L53 were not covered by tests
if "/" in reportname:
reportname, docids = reportname.split("/")

Check warning on line 55 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L55

Added line #L55 was not covered by tests
if docids:
# Generic report:
response = self.report_routes(

Check warning on line 58 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L58

Added line #L58 was not covered by tests
reportname, docids=docids, converter="fillpdf", context=context
)
else:
# Particular report:
data = dict(

Check warning on line 63 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L63

Added line #L63 was not covered by tests
url_decode(url.split("?")[1]).items()
) # decoding the args represented in JSON
if "context" in data:
context, data_context = json.loads(context or "{}"), json.loads(

Check warning on line 67 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L67

Added line #L67 was not covered by tests
data.pop("context")
)
context = json.dumps({**context, **data_context})
response = self.report_routes(

Check warning on line 71 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L70-L71

Added lines #L70 - L71 were not covered by tests
reportname, converter="fillpdf", context=context, **data
)

report = request.env["ir.actions.report"]._get_report_from_name(

Check warning on line 75 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L75

Added line #L75 was not covered by tests
reportname
)
filename = "%s.%s" % (report.name, "pdf")

Check warning on line 78 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L78

Added line #L78 was not covered by tests

if docids:
ids = [int(x) for x in docids.split(",")]
obj = request.env[report.model].browse(ids)

Check warning on line 82 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L81-L82

Added lines #L81 - L82 were not covered by tests
if report.print_report_name and not len(obj) > 1:
report_name = safe_eval(

Check warning on line 84 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L84

Added line #L84 was not covered by tests
report.print_report_name, {"object": obj, "time": time}
)
filename = "%s.%s" % (report_name, "pdf")

Check warning on line 87 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L87

Added line #L87 was not covered by tests
if not response.headers.get("Content-Disposition"):
response.headers.add(

Check warning on line 89 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L89

Added line #L89 was not covered by tests
"Content-Disposition", content_disposition(filename)
)
return response
except Exception as e:
_logger.exception("Error while generating report %s", reportname)
se = _serialize_exception(e)
error = {"code": 200, "message": "Odoo Server Error", "data": se}
return request.make_response(html_escape(json.dumps(error)))

Check warning on line 97 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L92-L97

Added lines #L92 - L97 were not covered by tests
else:
return super().report_download(data, context=context, token=token)

Check warning on line 99 in report_fillpdf/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

report_fillpdf/controllers/main.py#L99

Added line #L99 was not covered by tests
14 changes: 14 additions & 0 deletions report_fillpdf/demo/report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--
© 2017 Creu Blanca
License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
-->
<record model="ir.actions.report" id="partner_fillpdf">
<field name="name">report_fillpdf.partner_fillpdf</field>
<field name="model">res.partner</field>
<field name="report_type">fillpdf</field>
<field name="report_name">report_fillpdf.partner_fillpdf</field>
<field name="report_file">res_partner</field>
</record>
</odoo>
63 changes: 63 additions & 0 deletions report_fillpdf/i18n/de.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * report_fillpdf
#
# Translators:
# Ricardo Gross <[email protected]>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-12-23 03:49+0000\n"
"PO-Revision-Date: 2017-12-23 03:49+0000\n"
"Last-Translator: Ricardo Gross <[email protected]>, 2017\n"
"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n"
"Language: de\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"

#. module: report_fillpdf
#: code:addons/report_fillpdf/models/ir_report.py:18
#, python-format
msgid "%s model was not found"
msgstr "%s Modell wurde nicht gefunden"

#. module: report_fillpdf
#: model:ir.model.fields,field_description:report_fillpdf.field_report_report_fillpdf_abstract_display_name
#: model:ir.model.fields,field_description:report_fillpdf.field_report_report_fillpdf_partner_fillpdf_display_name
msgid "Display Name"
msgstr "Name anzeigen"

#. module: report_fillpdf
#: model:ir.actions.report,name:report_fillpdf.partner_fillpdf
msgid "Fill PDF"
msgstr "PDF ausfüllen"

#. module: report_fillpdf
#: model:ir.model.fields,field_description:report_fillpdf.field_report_report_fillpdf_abstract_id
#: model:ir.model.fields,field_description:report_fillpdf.field_report_report_fillpdf_partner_fillpdf_id
msgid "ID"
msgstr "ID"

#. module: report_fillpdf
#: model:ir.model.fields,field_description:report_fillpdf.field_report_report_fillpdf_abstract___last_update
#: model:ir.model.fields,field_description:report_fillpdf.field_report_report_fillpdf_partner_fillpdf___last_update
msgid "Last Modified on"
msgstr "Zuletzt geändert am"

#. module: report_fillpdf
#: model:ir.model,name:report_fillpdf.model_ir_actions_report
msgid "ir.actions.report"
msgstr ""

#. module: report_fillpdf
#: model:ir.model,name:report_fillpdf.model_report_report_fillpdf_abstract
msgid "report.report_fillpdf.abstract"
msgstr ""

#. module: report_fillpdf
#: model:ir.model,name:report_fillpdf.model_report_report_fillpdf_partner_fillpdf
msgid "report.report_fillpdf.partner_fillpdf"
msgstr ""
Loading