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.

99 lines
3.6 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2013 XCG Consulting <http://odoo.consulting>
  3. # © 2016 ACSONE SA/NV
  4. # © 2017 Therp BV <http://therp.nl>
  5. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  6. import json
  7. import logging
  8. import os
  9. import requests
  10. import tempfile
  11. from contextlib import closing
  12. from openerp import _, api, models
  13. from openerp.exceptions import UserError
  14. from StringIO import StringIO
  15. logger = logging.getLogger(__name__)
  16. try:
  17. from py3o.template import Template
  18. from py3o.template.helpers import Py3oConvertor
  19. except ImportError:
  20. logger.debug('Cannot import py3o.template')
  21. class Py3oReport(models.TransientModel):
  22. _inherit = 'py3o.report'
  23. @api.multi
  24. def _create_single_report(self, model_instance, data, save_in_attachment):
  25. """ This function to generate our py3o report
  26. """
  27. self.ensure_one()
  28. report_xml = self.ir_actions_report_xml_id
  29. filetype = report_xml.py3o_filetype
  30. if not report_xml.py3o_server_id:
  31. return super(Py3oReport, self)._create_single_report(
  32. model_instance, data, save_in_attachment,
  33. )
  34. elif report_xml.py3o_is_local_fusion:
  35. result_path = super(
  36. Py3oReport, self.with_context(
  37. report_py3o_skip_conversion=True,
  38. )
  39. )._create_single_report(
  40. model_instance, data, save_in_attachment,
  41. )
  42. with closing(open(result_path, 'r')) as out_stream:
  43. tmpl_data = out_stream.read()
  44. datadict = {}
  45. else:
  46. result_fd, result_path = tempfile.mkstemp(
  47. suffix='.' + filetype, prefix='p3o.report.tmp.')
  48. tmpl_data = self.get_template(model_instance)
  49. in_stream = StringIO(tmpl_data)
  50. with closing(os.fdopen(result_fd, 'w+')) as out_stream:
  51. template = Template(in_stream, out_stream, escape_false=True)
  52. localcontext = self._get_parser_context(model_instance, data)
  53. expressions = template.get_all_user_python_expression()
  54. py_expression = template.convert_py3o_to_python_ast(
  55. expressions)
  56. convertor = Py3oConvertor()
  57. data_struct = convertor(py_expression)
  58. datadict = data_struct.render(localcontext)
  59. # Call py3o.server to render the template in the desired format
  60. files = {
  61. 'tmpl_file': tmpl_data,
  62. }
  63. fields = {
  64. "targetformat": filetype,
  65. "datadict": json.dumps(datadict),
  66. "image_mapping": "{}",
  67. "escape_false": "on",
  68. }
  69. if report_xml.py3o_is_local_fusion:
  70. fields['skipfusion'] = '1'
  71. if filetype == 'pdf':
  72. options = report_xml.pdf_options_id or\
  73. report_xml.py3o_server_id.pdf_options_id
  74. if options:
  75. pdf_options_dict = options.odoo2libreoffice_options()
  76. fields['pdf_options'] = json.dumps(pdf_options_dict)
  77. r = requests.post(
  78. report_xml.py3o_server_id.url, data=fields, files=files)
  79. if r.status_code != 200:
  80. # server says we have an issue... let's tell that to enduser
  81. raise UserError(
  82. _('Fusion server error %s') % r.text,
  83. )
  84. chunk_size = 1024
  85. with open(result_path, 'w+') as fd:
  86. for chunk in r.iter_content(chunk_size):
  87. fd.write(chunk)
  88. if len(model_instance) == 1:
  89. self._postprocess_report(
  90. result_path, model_instance.id, save_in_attachment)
  91. return result_path