# Copyright 2017 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) import json import mimetypes from werkzeug import exceptions, url_decode from odoo.http import route, request from odoo.addons.web.controllers import main from odoo.addons.web.controllers.main import ( _serialize_exception, content_disposition ) from odoo.tools import html_escape class ReportController(main.ReportController): @route() def report_routes(self, reportname, docids=None, converter=None, **data): if converter != 'py3o': return super(ReportController, self).report_routes( reportname=reportname, docids=docids, converter=converter, **data) 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']) ir_action = request.env['ir.actions.report'] action_py3o_report = ir_action.get_from_report_name( reportname, "py3o").with_context(context) if not action_py3o_report: raise exceptions.HTTPException( description='Py3o action report not found for report_name ' '%s' % reportname) res, filetype = action_py3o_report.render(docids, data) filename = action_py3o_report.gen_report_download_filename( docids, data) if not filename.endswith(filetype): filename = "{}.{}".format(filename, filetype) content_type = mimetypes.guess_type("x." + filetype)[0] http_headers = [('Content-Type', content_type), ('Content-Length', len(res)), ('Content-Disposition', content_disposition(filename)) ] return request.make_response(res, headers=http_headers) @route() def report_download(self, data, token): """This function is used by 'qwebactionmanager.js' in order to trigger the download of a py3o/controller report. :param data: a javascript array JSON.stringified containg report internal url ([0]) and type [1] :returns: Response with a filetoken cookie and an attachment header """ requestcontent = json.loads(data) url, report_type = requestcontent[0], requestcontent[1] if 'py3o' not in report_type: return super(ReportController, self).report_download(data, token) try: reportname = url.split('/report/py3o/')[1].split('?')[0] docids = None if '/' in reportname: reportname, docids = reportname.split('/') if docids: # Generic report: response = self.report_routes( reportname, docids=docids, converter='py3o') else: # Particular report: # decoding the args represented in JSON data = list(url_decode(url.split('?')[1]).items()) response = self.report_routes( reportname, converter='py3o', **dict(data)) response.set_cookie('fileToken', token) return response except Exception as e: se = _serialize_exception(e) error = { 'code': 200, 'message': "Odoo Server Error", 'data': se } return request.make_response(html_escape(json.dumps(error)))