diff --git a/report_fillpdf/README.rst b/report_fillpdf/README.rst
new file mode 100644
index 000000000..f3249a6d4
--- /dev/null
+++ b/report_fillpdf/README.rst
@@ -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 ::
+
+
+
+.. 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
+`_. 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
+
+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.
diff --git a/report_fillpdf/__init__.py b/report_fillpdf/__init__.py
new file mode 100644
index 000000000..2a4823f86
--- /dev/null
+++ b/report_fillpdf/__init__.py
@@ -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
diff --git a/report_fillpdf/__manifest__.py b/report_fillpdf/__manifest__.py
new file mode 100644
index 000000000..5871aa9af
--- /dev/null
+++ b/report_fillpdf/__manifest__.py
@@ -0,0 +1,31 @@
+# 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)",
+ "website": "https://github.com/OCA/reporting-engine",
+ "category": "Reporting",
+ "version": "14.0.1.0.1",
+ "license": "AGPL-3",
+ "external_dependencies": {
+ "python": [
+ "fdfgen",
+ ],
+ "deb": [
+ "pdftk",
+ ],
+ },
+ "depends": [
+ "base",
+ "web",
+ ],
+ "data": [
+ "views/webclient_templates.xml",
+ ],
+ "demo": [
+ "demo/report.xml",
+ ],
+ "installable": True,
+}
diff --git a/report_fillpdf/controllers/__init__.py b/report_fillpdf/controllers/__init__.py
new file mode 100644
index 000000000..12a7e529b
--- /dev/null
+++ b/report_fillpdf/controllers/__init__.py
@@ -0,0 +1 @@
+from . import main
diff --git a/report_fillpdf/controllers/main.py b/report_fillpdf/controllers/main.py
new file mode 100644
index 000000000..0f7b50012
--- /dev/null
+++ b/report_fillpdf/controllers/main.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2017 Creu Blanca
+# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
+
+import json
+
+from odoo.http import content_disposition, request, route
+
+from odoo.addons.web.controllers import main as report
+
+
+class ReportController(report.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)
+ if docids:
+ docids = [int(i) for i in docids.split(",")]
+ if data.get("options"):
+ data.update(json.loads(data.pop("options")))
+ if data.get("context"):
+ # Ignore 'lang' here, because the context in data is the one
+ # from the webclient *but* if the user explicitely wants to
+ # change the lang, this mechanism overwrites it.
+ data["context"] = json.loads(data["context"])
+ if data["context"].get("lang"):
+ del data["context"]["lang"]
+ context.update(data["context"])
+ pdf = report.with_context(context).render_fillpdf(docids, data=data)[0]
+ pdfhttpheaders = [
+ ("Content-Type", "application/pdf"),
+ ("Content-Length", len(pdf)),
+ (
+ "Content-Disposition",
+ content_disposition(report.report_file + ".pdf"),
+ ),
+ ]
+ return request.make_response(pdf, headers=pdfhttpheaders)
+ return super(ReportController, self).report_routes(
+ reportname, docids, converter, **data
+ )
diff --git a/report_fillpdf/demo/report.xml b/report_fillpdf/demo/report.xml
new file mode 100644
index 000000000..4ba31d9fa
--- /dev/null
+++ b/report_fillpdf/demo/report.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/report_fillpdf/i18n/de.po b/report_fillpdf/i18n/de.po
new file mode 100644
index 000000000..98ece8524
--- /dev/null
+++ b/report_fillpdf/i18n/de.po
@@ -0,0 +1,63 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * report_fillpdf
+#
+# Translators:
+# Ricardo Gross , 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 , 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 ""
diff --git a/report_fillpdf/i18n/fr.po b/report_fillpdf/i18n/fr.po
new file mode 100644
index 000000000..9c00bf30c
--- /dev/null
+++ b/report_fillpdf/i18n/fr.po
@@ -0,0 +1,63 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * report_fillpdf
+#
+# Translators:
+# Nicolas JEUDY , 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-05 17:53+0000\n"
+"PO-Revision-Date: 2018-01-05 17:53+0000\n"
+"Last-Translator: Nicolas JEUDY , 2018\n"
+"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n"
+"Language: fr\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 model n'a pas été trouvé"
+
+#. 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 "Nom"
+
+#. module: report_fillpdf
+#: model:ir.actions.report,name:report_fillpdf.partner_fillpdf
+msgid "Fill PDF"
+msgstr "Remplir le PDF"
+
+#. 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 "Dernière modification le"
+
+#. module: report_fillpdf
+#: model:ir.model,name:report_fillpdf.model_ir_actions_report
+msgid "ir.actions.report"
+msgstr "ir.actions.report"
+
+#. module: report_fillpdf
+#: model:ir.model,name:report_fillpdf.model_report_report_fillpdf_abstract
+msgid "report.report_fillpdf.abstract"
+msgstr "report.report_fillpdf.abstract"
+
+#. module: report_fillpdf
+#: model:ir.model,name:report_fillpdf.model_report_report_fillpdf_partner_fillpdf
+msgid "report.report_fillpdf.partner_fillpdf"
+msgstr "report.report_fillpdf.partner_fillpdf"
diff --git a/report_fillpdf/i18n/report_fillpdf.pot b/report_fillpdf/i18n/report_fillpdf.pot
new file mode 100644
index 000000000..fcc41526d
--- /dev/null
+++ b/report_fillpdf/i18n/report_fillpdf.pot
@@ -0,0 +1,59 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * report_fillpdf
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.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_fillpdf
+#: code:addons/report_fillpdf/models/ir_report.py:18
+#, python-format
+msgid "%s model was not found"
+msgstr ""
+
+#. 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 ""
+
+#. module: report_fillpdf
+#: model:ir.actions.report,name:report_fillpdf.partner_fillpdf
+msgid "Fill PDF"
+msgstr ""
+
+#. 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 ""
+
+#. 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 ""
+
+#. 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 ""
+
diff --git a/report_fillpdf/models/__init__.py b/report_fillpdf/models/__init__.py
new file mode 100644
index 000000000..54dbf3df6
--- /dev/null
+++ b/report_fillpdf/models/__init__.py
@@ -0,0 +1 @@
+from . import ir_report
diff --git a/report_fillpdf/models/ir_report.py b/report_fillpdf/models/ir_report.py
new file mode 100644
index 000000000..6849151f5
--- /dev/null
+++ b/report_fillpdf/models/ir_report.py
@@ -0,0 +1,89 @@
+# Copyright 2017 Creu Blanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
+
+import logging
+from collections import OrderedDict
+
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError
+
+_logger = logging.getLogger(__name__)
+
+
+class ReportAction(models.Model):
+ _inherit = "ir.actions.report"
+
+ report_type = fields.Selection(
+ selection_add=[("fillpdf", "PDF Filler")], ondelete={"fillpdf": "set default"}
+ )
+
+ @api.model
+ def render_fillpdf(self, docids, data):
+ # Here we add pdf attachment support
+ self_sudo = self.sudo()
+ save_in_attachment = OrderedDict()
+ # Maps the streams in `save_in_attachment` back to the records they came from
+ stream_record = dict()
+ if docids:
+ # Dispatch the records by ones having an attachment and ones requesting a call to
+ # fillpdf.
+ Model = self.env[self_sudo.model]
+ record_ids = Model.browse(docids)
+ fp_record_ids = Model
+ if self_sudo.attachment:
+ for record_id in record_ids:
+ attachment = self_sudo.retrieve_attachment(record_id)
+ if attachment:
+ stream = self_sudo._retrieve_stream_from_attachment(attachment)
+ save_in_attachment[record_id.id] = stream
+ stream_record[stream] = record_id
+ if not self_sudo.attachment_use or not attachment:
+ fp_record_ids += record_id
+
+ else:
+ fp_record_ids = record_ids
+ docids = fp_record_ids.ids
+
+ if save_in_attachment and not docids:
+ _logger.info("The PDF report has been generated from attachments.")
+ self._raise_on_unreadable_pdfs(save_in_attachment.values(), stream_record)
+ return self_sudo._post_pdf(save_in_attachment), "pdf"
+
+ # We generate pdf with fillpdf
+ report_model_name = "report.%s" % self.report_name
+ report_model = self.env.get(report_model_name)
+ if report_model is None:
+ raise UserError(_("%s model was not found" % report_model_name))
+
+ pdf_content = report_model.with_context(
+ {"active_model": self.model}
+ ).fill_report(docids, data)
+
+ if docids:
+ self._raise_on_unreadable_pdfs(save_in_attachment.values(), stream_record)
+ _logger.info(
+ "The PDF report has been generated for model: %s, records %s."
+ % (self_sudo.model, str(docids))
+ )
+ return (
+ self_sudo._post_pdf(
+ save_in_attachment, pdf_content=pdf_content, res_ids=docids
+ ),
+ "pdf",
+ )
+
+ return pdf_content, "pdf"
+
+ @api.model
+ def _get_report_from_name(self, report_name):
+ res = super(ReportAction, self)._get_report_from_name(report_name)
+ if res:
+ return res
+ report_obj = self.env["ir.actions.report"]
+ qwebtypes = ["fillpdf"]
+ conditions = [
+ ("report_type", "in", qwebtypes),
+ ("report_name", "=", report_name),
+ ]
+ context = self.env["res.users"].context_get()
+ return report_obj.with_context(context).search(conditions, limit=1)
diff --git a/report_fillpdf/report/__init__.py b/report_fillpdf/report/__init__.py
new file mode 100644
index 000000000..9ba94517f
--- /dev/null
+++ b/report_fillpdf/report/__init__.py
@@ -0,0 +1,2 @@
+from . import report_fill_pdf
+from . import report_partner_pdf
diff --git a/report_fillpdf/report/report_fill_pdf.py b/report_fillpdf/report/report_fill_pdf.py
new file mode 100644
index 000000000..09f200c81
--- /dev/null
+++ b/report_fillpdf/report/report_fill_pdf.py
@@ -0,0 +1,68 @@
+# Copyright 2017 Creu Blanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
+
+
+import logging
+import os
+import tempfile
+from contextlib import closing
+from io import BytesIO
+from subprocess import PIPE, Popen
+
+from odoo import api, models, tools
+
+_logger = logging.getLogger(__name__)
+try:
+ from fdfgen import forge_fdf
+
+ EXTERNAL_DEPENDENCY_BINARY_PDFTK = tools.find_in_path("pdftk")
+except (ImportError, IOError) as err:
+ _logger.debug("Error while importing: %s." % err)
+ EXTERNAL_DEPENDENCY_BINARY_PDFTK = ""
+
+
+class ReportFillPDFAbstract(models.AbstractModel):
+ _name = "report.report_fillpdf.abstract"
+
+ def fill_report(self, docids, data):
+ objs = self.env[self.env.context.get("active_model")].browse(docids)
+ return self.fill_pdf_form(
+ self.get_form(data, objs), self.get_document_values(data, objs)
+ )
+
+ @api.model
+ def get_original_document_path(self, data, objs):
+ raise NotImplementedError()
+
+ @api.model
+ def get_form(self, data, objs):
+ with open(self.get_original_document_path(data, objs), "rb") as file:
+ result = file.read()
+ return result
+
+ @api.model
+ def get_document_values(self, data, objs):
+ return {}
+
+ @api.model
+ def fill_pdf_form(self, form, vals):
+ fdf = forge_fdf("", vals.items(), [], [], [])
+ document_fd, document_path = tempfile.mkstemp(suffix=".pdf", prefix="")
+ with closing(os.fdopen(document_fd, "wb")) as body_file:
+ body_file.write(form)
+ args = [
+ EXTERNAL_DEPENDENCY_BINARY_PDFTK,
+ document_path,
+ "fill_form",
+ "-",
+ "output",
+ "-",
+ "dont_ask",
+ "flatten",
+ ]
+ p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = p.communicate(fdf)
+ os.unlink(document_path)
+ if stderr.strip():
+ raise IOError(stderr)
+ return BytesIO(stdout).getvalue()
diff --git a/report_fillpdf/report/report_partner_pdf.py b/report_fillpdf/report/report_partner_pdf.py
new file mode 100644
index 000000000..5b13ae88b
--- /dev/null
+++ b/report_fillpdf/report/report_partner_pdf.py
@@ -0,0 +1,19 @@
+# Copyright 2017 Creu Blanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
+
+from odoo import api, models
+from odoo.modules import get_resource_path
+
+
+class PartnerPDF(models.AbstractModel):
+ _name = "report.report_fillpdf.partner_fillpdf"
+ _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}
diff --git a/report_fillpdf/static/description/icon.png b/report_fillpdf/static/description/icon.png
new file mode 100644
index 000000000..3a0328b51
Binary files /dev/null and b/report_fillpdf/static/description/icon.png differ
diff --git a/report_fillpdf/static/src/js/report/action_manager_report.js b/report_fillpdf/static/src/js/report/action_manager_report.js
new file mode 100644
index 000000000..efbc5f891
--- /dev/null
+++ b/report_fillpdf/static/src/js/report/action_manager_report.js
@@ -0,0 +1,98 @@
+// © 2017 Creu Blanca
+// License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
+odoo.define("report_fillpdf.report", function (require) {
+ "use strict";
+
+ var core = require("web.core");
+ var ActionManager = require("web.ActionManager");
+ var framework = require("web.framework");
+ var session = require("web.session");
+ var _t = core._t;
+
+ ActionManager.include({
+ _downloadReportfillpdf: function (url, actions) {
+ var self = this;
+ framework.blockUI();
+ var type = "fillpdf";
+ var cloned_action = _.clone(actions);
+ var new_url = url;
+
+ if (
+ _.isUndefined(cloned_action.data) ||
+ _.isNull(cloned_action.data) ||
+ (_.isObject(cloned_action.data) && _.isEmpty(cloned_action.data))
+ ) {
+ if (cloned_action.context.active_ids) {
+ new_url += "/" + cloned_action.context.active_ids.join(",");
+ }
+ } else {
+ new_url +=
+ "?options=" +
+ encodeURIComponent(JSON.stringify(cloned_action.data));
+ new_url +=
+ "&context=" +
+ encodeURIComponent(JSON.stringify(cloned_action.context));
+ }
+
+ return new Promise(function (resolve, reject) {
+ var blocked = !session.get_file({
+ url: new_url,
+ data: {
+ data: JSON.stringify([new_url, type]),
+ },
+ success: resolve,
+ error: (error) => {
+ self.call("crash_manager", "rpc_error", error);
+ reject();
+ },
+ complete: framework.unblockUI,
+ });
+ if (blocked) {
+ // AAB: this check should be done in get_file service directly,
+ // should not be the concern of the caller (and that way, get_file
+ // could return a deferred)
+ var message = _t(
+ "A popup window with your report was blocked. You " +
+ "may need to change your browser settings to allow " +
+ "popup windows for this page."
+ );
+ this.do_warn(_t("Warning"), message, true);
+ }
+ });
+ },
+
+ _triggerDownload: function (action, options, type) {
+ var self = this;
+ var reportUrls = this._makeReportUrls(action);
+ if (type === "fillpdf") {
+ return this._downloadReportfillpdf(reportUrls[type], action).then(
+ function () {
+ if (action.close_on_report_download) {
+ var closeAction = {type: "ir.actions.act_window_close"};
+ return self.doAction(
+ closeAction,
+ _.pick(options, "on_close")
+ );
+ }
+ return options.on_close();
+ }
+ );
+ }
+ return this._super.apply(this, arguments);
+ },
+
+ _makeReportUrls: function (action) {
+ var reportUrls = this._super.apply(this, arguments);
+ reportUrls.fillpdf = "/report/fillpdf/" + action.report_name;
+ return reportUrls;
+ },
+
+ _executeReportAction: function (action, options) {
+ var self = this;
+ if (action.report_type === "fillpdf") {
+ return self._triggerDownload(action, options, "fillpdf");
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+});
diff --git a/report_fillpdf/static/src/pdf/partner_pdf.pdf b/report_fillpdf/static/src/pdf/partner_pdf.pdf
new file mode 100644
index 000000000..29b4e67b7
Binary files /dev/null and b/report_fillpdf/static/src/pdf/partner_pdf.pdf differ
diff --git a/report_fillpdf/tests/__init__.py b/report_fillpdf/tests/__init__.py
new file mode 100644
index 000000000..32ae3c2c3
--- /dev/null
+++ b/report_fillpdf/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_report
diff --git a/report_fillpdf/tests/test_report.py b/report_fillpdf/tests/test_report.py
new file mode 100644
index 000000000..5ff16c55b
--- /dev/null
+++ b/report_fillpdf/tests/test_report.py
@@ -0,0 +1,14 @@
+# Copyright 2017 Creu Blanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
+
+from odoo.tests import common
+
+
+class TestReport(common.TransactionCase):
+ def test_report(self):
+ report_object = self.env["ir.actions.report"]
+ report_name = "report_fillpdf.partner_fillpdf"
+ report = report_object._get_report_from_name(report_name)
+ docs = self.env["res.company"].search([], limit=1).partner_id
+ self.assertEqual(report.report_type, "fillpdf")
+ report._render(docs.ids, {})
diff --git a/report_fillpdf/views/webclient_templates.xml b/report_fillpdf/views/webclient_templates.xml
new file mode 100644
index 000000000..2fd7f1324
--- /dev/null
+++ b/report_fillpdf/views/webclient_templates.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/requirements.txt b/requirements.txt
index 603fb74cb..ef13711b1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
# generated from manifests external_dependencies
cryptography
endesive
+fdfgen
py3o.formats
py3o.template
diff --git a/setup/report_fillpdf/odoo/addons/report_fillpdf b/setup/report_fillpdf/odoo/addons/report_fillpdf
new file mode 120000
index 000000000..7bc57984e
--- /dev/null
+++ b/setup/report_fillpdf/odoo/addons/report_fillpdf
@@ -0,0 +1 @@
+../../../../report_fillpdf
\ No newline at end of file
diff --git a/setup/report_fillpdf/setup.py b/setup/report_fillpdf/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/report_fillpdf/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)