# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import json import time from werkzeug import exceptions, url_decode from werkzeug.datastructures import Headers from werkzeug.test import Client from werkzeug.wrappers import BaseResponse from odoo.http import Controller, route, request from odoo.tools import html_escape from odoo.addons.web.controllers.main import _serialize_exception, content_disposition from odoo.tools.safe_eval import safe_eval class ReportController(Controller): #------------------------------------------------------ # Report controllers #------------------------------------------------------ @route([ '/report//', '/report///', ], type='http', auth='user', website=True) def report_routes(self, reportname, docids=None, converter=None, **data): report_obj = request.env['report'] 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']) if converter == 'html': html = report_obj.with_context(context).get_html(docids, reportname, data=data) return request.make_response(html) elif converter == 'pdf': pdf = report_obj.with_context(context).get_pdf(docids, reportname, data=data) pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] return request.make_response(pdf, headers=pdfhttpheaders) else: raise exceptions.HTTPException(description='Converter %s not implemented.' % converter) #------------------------------------------------------ # Misc. route utils #------------------------------------------------------ @route(['/report/barcode', '/report/barcode//'], type='http', auth="public") def report_barcode(self, type, value, width=600, height=100, humanreadable=0): """Contoller able to render barcode images thanks to reportlab. Samples: :param type: Accepted types: 'Codabar', 'Code11', 'Code128', 'EAN13', 'EAN8', 'Extended39', 'Extended93', 'FIM', 'I2of5', 'MSI', 'POSTNET', 'QR', 'Standard39', 'Standard93', 'UPCA', 'USPS_4State' :param humanreadable: Accepted values: 0 (default) or 1. 1 will insert the readable value at the bottom of the output image """ try: barcode = request.env['report'].barcode(type, value, width=width, height=height, humanreadable=humanreadable) except (ValueError, AttributeError): raise exceptions.HTTPException(description='Cannot convert into barcode.') return request.make_response(barcode, headers=[('Content-Type', 'image/png')]) @route(['/report/download'], type='http', auth="user") def report_download(self, data, token): """This function is used by 'qwebactionmanager.js' in order to trigger the download of a pdf/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, type = requestcontent[0], requestcontent[1] try: if type == 'qweb-pdf': reportname = url.split('/report/pdf/')[1].split('?')[0] docids = None if '/' in reportname: reportname, docids = reportname.split('/') if docids: # Generic report: response = self.report_routes(reportname, docids=docids, converter='pdf') else: # Particular report: data = url_decode(url.split('?')[1]).items() # decoding the args represented in JSON response = self.report_routes(reportname, converter='pdf', **dict(data)) report = request.env['report']._get_report_from_name(reportname) filename = "%s.%s" % (report.name, "pdf") if docids: ids = [int(x) for x in docids.split(",")] obj = request.env[report.model].browse(ids) if report.print_report_name and not len(obj) > 1: filename = safe_eval(report.print_report_name, {'object': obj, 'time': time}) response.headers.add('Content-Disposition', content_disposition(filename)) response.set_cookie('fileToken', token) return response elif type == 'controller': reqheaders = Headers(request.httprequest.headers) response = Client(request.httprequest.app, BaseResponse).get(url, headers=reqheaders, follow_redirects=True) response.set_cookie('fileToken', token) return response else: return except Exception, e: se = _serialize_exception(e) error = { 'code': 200, 'message': "Odoo Server Error", 'data': se } return request.make_response(html_escape(json.dumps(error))) @route(['/report/check_wkhtmltopdf'], type='json', auth="user") def check_wkhtmltopdf(self): return request.env['report']._check_wkhtmltopdf()