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.

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