diff --git a/report_xlsx/__manifest__.py b/report_xlsx/__manifest__.py index 9687c218..d5b03397 100644 --- a/report_xlsx/__manifest__.py +++ b/report_xlsx/__manifest__.py @@ -1,30 +1,16 @@ # Copyright 2015 ACSONE SA/NV () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). { - 'name': "Base report xlsx", - - 'summary': "Base module to create xlsx report", - 'author': 'ACSONE SA/NV,' - 'Creu Blanca,' - 'Odoo Community Association (OCA)', - 'website': "https://github.com/oca/reporting-engine", - 'category': 'Reporting', - 'version': '13.0.1.0.0', - 'license': 'AGPL-3', - 'external_dependencies': { - 'python': [ - 'xlsxwriter', - 'xlrd', - ], - }, - 'depends': [ - 'base', 'web', - ], - 'data': [ - 'views/webclient_templates.xml', - ], - 'demo': [ - 'demo/report.xml', - ], - 'installable': True, + "name": "Base report xlsx", + "summary": "Base module to create xlsx report", + "author": "ACSONE SA/NV," "Creu Blanca," "Odoo Community Association (OCA)", + "website": "https://github.com/oca/reporting-engine", + "category": "Reporting", + "version": "13.0.1.0.0", + "license": "AGPL-3", + "external_dependencies": {"python": ["xlsxwriter", "xlrd"]}, + "depends": ["base", "web"], + "data": ["views/webclient_templates.xml"], + "demo": ["demo/report.xml"], + "installable": True, } diff --git a/report_xlsx/controllers/main.py b/report_xlsx/controllers/main.py index b3f0ecbd..9436da37 100644 --- a/report_xlsx/controllers/main.py +++ b/report_xlsx/controllers/main.py @@ -1,49 +1,48 @@ # Copyright (C) 2017 Creu Blanca # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). -from odoo.addons.web.controllers import main as report -from odoo.http import content_disposition, route, request -from odoo.tools.safe_eval import safe_eval - import json import time +from odoo.http import content_disposition, request, route +from odoo.tools.safe_eval import safe_eval + +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 == 'xlsx': - report = request.env['ir.actions.report']._get_report_from_name( - reportname) + if converter == "xlsx": + 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'): + 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']) - xlsx = report.with_context(context).render_xlsx( - docids, data=data - )[0] + data["context"] = json.loads(data["context"]) + if data["context"].get("lang"): + del data["context"]["lang"] + context.update(data["context"]) + xlsx = report.with_context(context).render_xlsx(docids, data=data)[0] report_name = report.report_file if report.print_report_name and not len(docids) > 1: obj = request.env[report.model].browse(docids[0]) - report_name = safe_eval(report.print_report_name, - {'object': obj, 'time': time}) + report_name = safe_eval( + report.print_report_name, {"object": obj, "time": time} + ) xlsxhttpheaders = [ - ('Content-Type', 'application/vnd.openxmlformats-' - 'officedocument.spreadsheetml.sheet'), - ('Content-Length', len(xlsx)), ( - 'Content-Disposition', - content_disposition(report_name + '.xlsx') - ) + "Content-Type", + "application/vnd.openxmlformats-" + "officedocument.spreadsheetml.sheet", + ), + ("Content-Length", len(xlsx)), + ("Content-Disposition", content_disposition(report_name + ".xlsx")), ] return request.make_response(xlsx, headers=xlsxhttpheaders) return super(ReportController, self).report_routes( diff --git a/report_xlsx/models/ir_report.py b/report_xlsx/models/ir_report.py index 4e1edff6..3f5db2fb 100644 --- a/report_xlsx/models/ir_report.py +++ b/report_xlsx/models/ir_report.py @@ -1,7 +1,7 @@ # Copyright 2015 ACSONE SA/NV () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import UserError @@ -15,8 +15,10 @@ class ReportAction(models.Model): 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) - return report_model.with_context(active_model=self.model).create_xlsx_report( # noqa + raise UserError(_("%s model was not found") % report_model_name) + return report_model.with_context( + active_model=self.model + ).create_xlsx_report( # noqa docids, data ) diff --git a/report_xlsx/report/report_partner_xlsx.py b/report_xlsx/report/report_partner_xlsx.py index ca259fd5..14022f35 100644 --- a/report_xlsx/report/report_partner_xlsx.py +++ b/report_xlsx/report/report_partner_xlsx.py @@ -5,12 +5,12 @@ from odoo import models class PartnerXlsx(models.AbstractModel): - _name = 'report.report_xlsx.partner_xlsx' - _inherit = 'report.report_xlsx.abstract' - _description = 'Partner XLSX Report' + _name = "report.report_xlsx.partner_xlsx" + _inherit = "report.report_xlsx.abstract" + _description = "Partner XLSX Report" def generate_xlsx_report(self, workbook, data, partners): for obj in partners: - sheet = workbook.add_worksheet('Report') - bold = workbook.add_format({'bold': True}) + sheet = workbook.add_worksheet("Report") + bold = workbook.add_format({"bold": True}) sheet.write(0, 0, obj.name, bold) diff --git a/report_xlsx/report/report_xlsx.py b/report_xlsx/report/report_xlsx.py index 7a25cd37..244d88dc 100644 --- a/report_xlsx/report/report_xlsx.py +++ b/report_xlsx/report/report_xlsx.py @@ -1,22 +1,22 @@ # Copyright 2015 ACSONE SA/NV () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +import logging from io import BytesIO from odoo import models -import logging _logger = logging.getLogger(__name__) try: import xlsxwriter except ImportError: - _logger.debug('Can not import xlsxwriter`.') + _logger.debug("Can not import xlsxwriter`.") class ReportXlsxAbstract(models.AbstractModel): - _name = 'report.report_xlsx.abstract' - _description = 'Abstract XLSX Report' + _name = "report.report_xlsx.abstract" + _description = "Abstract XLSX Report" def _get_objs_for_report(self, docids, data): """ @@ -34,11 +34,11 @@ class ReportXlsxAbstract(models.AbstractModel): """ if docids: ids = docids - elif data and 'context' in data: - ids = data["context"].get('active_ids', []) + elif data and "context" in data: + ids = data["context"].get("active_ids", []) else: - ids = self.env.context.get('active_ids', []) - return self.env[self.env.context.get('active_model')].browse(ids) + ids = self.env.context.get("active_ids", []) + return self.env[self.env.context.get("active_model")].browse(ids) def create_xlsx_report(self, docids, data): objs = self._get_objs_for_report(docids, data) @@ -47,7 +47,7 @@ class ReportXlsxAbstract(models.AbstractModel): self.generate_xlsx_report(workbook, data, objs) workbook.close() file_data.seek(0) - return file_data.read(), 'xlsx' + return file_data.read(), "xlsx" def get_workbook_options(self): """ diff --git a/report_xlsx/static/src/js/report/action_manager_report.js b/report_xlsx/static/src/js/report/action_manager_report.js index 4949ad51..a028aa68 100644 --- a/report_xlsx/static/src/js/report/action_manager_report.js +++ b/report_xlsx/static/src/js/report/action_manager_report.js @@ -17,23 +17,25 @@ odoo.define("report_xlsx.report", function (require) { var def = $.Deferred(); var type = "xlsx"; 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))) - { + (_.isObject(cloned_action.data) && _.isEmpty(cloned_action.data))) { if (cloned_action.context.active_ids) { - url += "/" + cloned_action.context.active_ids.join(','); + new_url += "/" + cloned_action.context.active_ids.join(','); } } else { - url += "?options=" + encodeURIComponent(JSON.stringify(cloned_action.data)); - url += "&context=" + encodeURIComponent(JSON.stringify(cloned_action.context)); + new_url += "?options=" + encodeURIComponent( + JSON.stringify(cloned_action.data)); + new_url += "&context=" + encodeURIComponent( + JSON.stringify(cloned_action.context)); } var blocked = !session.get_file({ - url: url, + url: new_url, data: { - data: JSON.stringify([url, type]), + data: JSON.stringify([new_url, type]), }, success: def.resolve.bind(def), error: function () { @@ -58,14 +60,15 @@ odoo.define("report_xlsx.report", function (require) { var self = this; var reportUrls = this._makeReportUrls(action); if (type === "xlsx") { - return this._downloadReportXLSX(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')); - } else { + return this._downloadReportXLSX(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); }, @@ -82,7 +85,7 @@ odoo.define("report_xlsx.report", function (require) { return self._triggerDownload(action, options, 'xlsx'); } return this._super.apply(this, arguments); - } + }, }); }); diff --git a/report_xlsx/tests/test_report.py b/report_xlsx/tests/test_report.py index 02550952..74e7db95 100644 --- a/report_xlsx/tests/test_report.py +++ b/report_xlsx/tests/test_report.py @@ -1,31 +1,32 @@ # Copyright 2017 Creu Blanca # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo.tests import common import logging + +from odoo.tests import common + _logger = logging.getLogger(__name__) try: from xlrd import open_workbook except ImportError: - _logger.debug('Can not import xlrd`.') + _logger.debug("Can not import xlrd`.") class TestReport(common.TransactionCase): def setUp(self): super(TestReport, self).setUp() - report_object = self.env['ir.actions.report'] - self.xlsx_report = ( - self.env['report.report_xlsx.abstract'] - .with_context(active_model='res.partner') + report_object = self.env["ir.actions.report"] + self.xlsx_report = self.env["report.report_xlsx.abstract"].with_context( + active_model="res.partner" ) - self.report_name = 'report_xlsx.partner_xlsx' + self.report_name = "report_xlsx.partner_xlsx" self.report = report_object._get_report_from_name(self.report_name) - self.docs = self.env['res.company'].search([], limit=1).partner_id + self.docs = self.env["res.company"].search([], limit=1).partner_id def test_report(self): report = self.report - self.assertEqual(report.report_type, 'xlsx') + self.assertEqual(report.report_type, "xlsx") rep = report.render(self.docs.ids, {}) wb = open_workbook(file_contents=rep[0]) sheet = wb.sheet_by_index(0) @@ -35,18 +36,19 @@ class TestReport(common.TransactionCase): # Typical call from WebUI with wizard objs = self.xlsx_report._get_objs_for_report( - False, {"context": {"active_ids": self.docs.ids}}) + False, {"context": {"active_ids": self.docs.ids}} + ) self.assertEquals(objs, self.docs) # Typical call from within code not to report_action objs = self.xlsx_report.with_context( - active_ids=self.docs.ids)._get_objs_for_report(False, False) + active_ids=self.docs.ids + )._get_objs_for_report(False, False) self.assertEquals(objs, self.docs) # Typical call from WebUI objs = self.xlsx_report._get_objs_for_report( - self.docs.ids, - {"data": [self.report_name, self.report.report_type]} + self.docs.ids, {"data": [self.report_name, self.report.report_type]} ) self.assertEquals(objs, self.docs)