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.

111 lines
4.2 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 datetime import datetime
  12. from contextlib import closing
  13. from openerp import _, api, models
  14. from openerp.exceptions import UserError
  15. from StringIO import StringIO
  16. logger = logging.getLogger(__name__)
  17. try:
  18. from py3o.template import Template
  19. from py3o.template.helpers import Py3oConvertor
  20. except ImportError:
  21. logger.debug('Cannot import py3o.template')
  22. class Py3oReport(models.TransientModel):
  23. _inherit = 'py3o.report'
  24. @api.multi
  25. def _create_single_report(self, model_instance, data, save_in_attachment):
  26. """ This function to generate our py3o report
  27. """
  28. self.ensure_one()
  29. report_xml = self.ir_actions_report_xml_id
  30. filetype = report_xml.py3o_filetype
  31. if not report_xml.py3o_server_id:
  32. return super(Py3oReport, self)._create_single_report(
  33. model_instance, data, save_in_attachment,
  34. )
  35. elif report_xml.py3o_is_local_fusion:
  36. result_path = super(
  37. Py3oReport, self.with_context(
  38. report_py3o_skip_conversion=True,
  39. )
  40. )._create_single_report(
  41. model_instance, data, save_in_attachment,
  42. )
  43. with closing(open(result_path, 'r')) as out_stream:
  44. tmpl_data = out_stream.read()
  45. datadict = {}
  46. else:
  47. result_fd, result_path = tempfile.mkstemp(
  48. suffix='.' + filetype, prefix='p3o.report.tmp.')
  49. tmpl_data = self.get_template(model_instance)
  50. in_stream = StringIO(tmpl_data)
  51. with closing(os.fdopen(result_fd, 'w+')) as out_stream:
  52. template = Template(in_stream, out_stream, escape_false=True)
  53. localcontext = self._get_parser_context(model_instance, data)
  54. expressions = template.get_all_user_python_expression()
  55. py_expression = template.convert_py3o_to_python_ast(
  56. expressions)
  57. convertor = Py3oConvertor()
  58. data_struct = convertor(py_expression)
  59. datadict = data_struct.render(localcontext)
  60. # Call py3o.server to render the template in the desired format
  61. files = {
  62. 'tmpl_file': tmpl_data,
  63. }
  64. fields = {
  65. "targetformat": filetype,
  66. "datadict": json.dumps(datadict),
  67. "image_mapping": "{}",
  68. "escape_false": "on",
  69. }
  70. if report_xml.py3o_is_local_fusion:
  71. fields['skipfusion'] = '1'
  72. url = report_xml.py3o_server_id.url
  73. logger.info(
  74. 'Connecting to %s to convert report %s to %s',
  75. url, report_xml.report_name, filetype)
  76. if filetype == 'pdf':
  77. options = report_xml.pdf_options_id or\
  78. report_xml.py3o_server_id.pdf_options_id
  79. if options:
  80. pdf_options_dict = options.odoo2libreoffice_options()
  81. fields['pdf_options'] = json.dumps(pdf_options_dict)
  82. logger.debug('PDF Export options: %s', pdf_options_dict)
  83. start_chrono = datetime.now()
  84. r = requests.post(url, data=fields, files=files)
  85. if r.status_code != 200:
  86. # server says we have an issue... let's tell that to enduser
  87. logger.error('Py3o fusion server error: %s', r.text)
  88. raise UserError(
  89. _('Fusion server error %s') % r.text,
  90. )
  91. chunk_size = 1024
  92. with open(result_path, 'w+') as fd:
  93. for chunk in r.iter_content(chunk_size):
  94. fd.write(chunk)
  95. end_chrono = datetime.now()
  96. convert_seconds = (end_chrono - start_chrono).total_seconds()
  97. logger.info(
  98. 'Report %s converted to %s in %s seconds',
  99. report_xml.report_name, filetype, convert_seconds)
  100. if len(model_instance) == 1:
  101. self._postprocess_report(
  102. result_path, model_instance.id, save_in_attachment)
  103. return result_path