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.

110 lines
4.1 KiB

  1. # © 2013 XCG Consulting <http://odoo.consulting>
  2. # © 2016 ACSONE SA/NV
  3. # © 2017 Therp BV <http://therp.nl>
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  5. import json
  6. import logging
  7. import os
  8. import requests
  9. import tempfile
  10. from datetime import datetime
  11. from contextlib import closing
  12. from openerp import _, api, models
  13. from openerp.exceptions import UserError
  14. from io import BytesIO
  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):
  25. """ This function to generate our py3o report
  26. """
  27. self.ensure_one()
  28. report_xml = self.ir_actions_report_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,
  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
  41. )
  42. with closing(open(result_path, 'rb')) 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 = BytesIO(tmpl_data)
  50. with closing(os.fdopen(result_fd, 'wb+')) 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. url = report_xml.py3o_server_id.url
  72. logger.info(
  73. 'Connecting to %s to convert report %s to %s',
  74. url, report_xml.report_name, filetype)
  75. if filetype == 'pdf':
  76. options = report_xml.pdf_options_id or\
  77. report_xml.py3o_server_id.pdf_options_id
  78. if options:
  79. pdf_options_dict = options.odoo2libreoffice_options()
  80. fields['pdf_options'] = json.dumps(pdf_options_dict)
  81. logger.debug('PDF Export options: %s', pdf_options_dict)
  82. start_chrono = datetime.now()
  83. r = requests.post(url, data=fields, files=files)
  84. if r.status_code != 200:
  85. # server says we have an issue... let's tell that to enduser
  86. logger.error('Py3o fusion server error: %s', r.text)
  87. raise UserError(
  88. _('Fusion server error %s') % r.text,
  89. )
  90. chunk_size = 1024
  91. with open(result_path, 'w+b') as fd:
  92. for chunk in r.iter_content(chunk_size):
  93. fd.write(chunk)
  94. end_chrono = datetime.now()
  95. convert_seconds = (end_chrono - start_chrono).total_seconds()
  96. logger.info(
  97. 'Report %s converted to %s in %s seconds',
  98. report_xml.report_name, filetype, convert_seconds)
  99. if len(model_instance) == 1:
  100. self._postprocess_report(
  101. model_instance, result_path)
  102. return result_path