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 @@ + + + +