OCA reporting engine fork for dev and update.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.9 KiB

  1. # Copyright 2017 ACSONE SA/NV
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
  3. import json
  4. import mimetypes
  5. from werkzeug import exceptions, url_decode
  6. from odoo.http import route, request
  7. from odoo.addons.web.controllers import main
  8. from odoo.addons.web.controllers.main import (
  9. _serialize_exception,
  10. content_disposition
  11. )
  12. from odoo.tools import html_escape
  13. class ReportController(main.ReportController):
  14. @route()
  15. def report_routes(self, reportname, docids=None, converter=None, **data):
  16. if converter != 'py3o':
  17. return super(ReportController, self).report_routes(
  18. reportname=reportname, docids=docids, converter=converter,
  19. **data)
  20. context = dict(request.env.context)
  21. if docids:
  22. docids = [int(i) for i in docids.split(',')]
  23. if data.get('options'):
  24. data.update(json.loads(data.pop('options')))
  25. if data.get('context'):
  26. # Ignore 'lang' here, because the context in data is the
  27. # one from the webclient *but* if the user explicitely wants to
  28. # change the lang, this mechanism overwrites it.
  29. data['context'] = json.loads(data['context'])
  30. if data['context'].get('lang'):
  31. del data['context']['lang']
  32. context.update(data['context'])
  33. ir_action = request.env['ir.actions.report']
  34. action_py3o_report = ir_action.get_from_report_name(
  35. reportname, "py3o").with_context(context)
  36. if not action_py3o_report:
  37. raise exceptions.HTTPException(
  38. description='Py3o action report not found for report_name '
  39. '%s' % reportname)
  40. res, filetype = action_py3o_report.render(docids, data)
  41. filename = action_py3o_report.gen_report_download_filename(
  42. docids, data)
  43. if not filename.endswith(filetype):
  44. filename = "{}.{}".format(filename, filetype)
  45. content_type = mimetypes.guess_type("x." + filetype)[0]
  46. http_headers = [('Content-Type', content_type),
  47. ('Content-Length', len(res)),
  48. ('Content-Disposition', content_disposition(filename))
  49. ]
  50. return request.make_response(res, headers=http_headers)
  51. @route()
  52. def report_download(self, data, token):
  53. """This function is used by 'qwebactionmanager.js' in order to trigger
  54. the download of a py3o/controller report.
  55. :param data: a javascript array JSON.stringified containg report
  56. internal url ([0]) and type [1]
  57. :returns: Response with a filetoken cookie and an attachment header
  58. """
  59. requestcontent = json.loads(data)
  60. url, report_type = requestcontent[0], requestcontent[1]
  61. if 'py3o' not in report_type:
  62. return super(ReportController, self).report_download(data, token)
  63. try:
  64. reportname = url.split('/report/py3o/')[1].split('?')[0]
  65. docids = None
  66. if '/' in reportname:
  67. reportname, docids = reportname.split('/')
  68. if docids:
  69. # Generic report:
  70. response = self.report_routes(
  71. reportname, docids=docids, converter='py3o')
  72. else:
  73. # Particular report:
  74. # decoding the args represented in JSON
  75. data = list(url_decode(url.split('?')[1]).items())
  76. response = self.report_routes(
  77. reportname, converter='py3o', **dict(data))
  78. response.set_cookie('fileToken', token)
  79. return response
  80. except Exception as e:
  81. se = _serialize_exception(e)
  82. error = {
  83. 'code': 200,
  84. 'message': "Odoo Server Error",
  85. 'data': se
  86. }
  87. return request.make_response(html_escape(json.dumps(error)))