示例#1
0
    def _create_single_report(self, model_instance, data, save_in_attachment):
        """ This function to generate our py3o report
        """
        self.ensure_one()
        report_xml = self.ir_actions_report_xml_id
        filetype = report_xml.py3o_filetype

        result_fd, result_path = tempfile.mkstemp(
            suffix='.' + filetype, prefix='p3o.report.tmp.')
        tmpl_data = self.get_template(model_instance)

        in_stream = StringIO(tmpl_data)
        with closing(os.fdopen(result_fd, 'w+')) as out_stream:
            template = Template(in_stream, out_stream, escape_false=True)
            localcontext = self._get_parser_context(model_instance, data)
            is_native = Formats().get_format(filetype).native
            if report_xml.py3o_is_local_fusion:
                template.render(localcontext)
                out_stream.seek(0)
                tmpl_data = out_stream.read()
                datadict = {}
            else:
                expressions = template.get_all_user_python_expression()
                py_expression = template.convert_py3o_to_python_ast(
                    expressions)
                convertor = Py3oConvertor()
                data_struct = convertor(py_expression)
                datadict = data_struct.render(localcontext)

        # if not is_native or not report_xml.py3o_is_local_fusion:
        #     # Call py3o.server to render the template in the desired format
        #     files = {
        #         'tmpl_file': tmpl_data,
        #     }
        #     fields = {
        #         "targetformat": filetype,
        #         "datadict": json.dumps(datadict),
        #         "image_mapping": "{}",
        #         "escape_false": "on",
        #     }
        #     if report_xml.py3o_is_local_fusion:
        #         fields['skipfusion'] = '1'
        #     r = requests.post(
        #         report_xml.py3o_server_id.url, data=fields, files=files)
        #     if r.status_code != 200:
        #         # server says we have an issue... let's tell that to enduser
        #         raise UserError(
        #             _('Fusion server error %s') % r.text,
        #         )

        #     chunk_size = 1024
        #     with open(result_path, 'w+') as fd:
        #         for chunk in r.iter_content(chunk_size):
        #             fd.write(chunk)
        if len(model_instance) == 1:
            self._postprocess_report(
                result_path, model_instance.id, save_in_attachment)
        return result_path
示例#2
0
    def _create_single_report(self, model_instance, data, save_in_attachment):
        """ This function to generate our py3o report
        """
        self.ensure_one()
        report_xml = self.ir_actions_report_xml_id
        filetype = report_xml.py3o_filetype
        if not report_xml.py3o_server_id:
            return super(Py3oReport, self)._create_single_report(
                model_instance,
                data,
                save_in_attachment,
            )
        elif report_xml.py3o_is_local_fusion:
            result_path = super(
                Py3oReport,
                self.with_context(
                    report_py3o_skip_conversion=True, ))._create_single_report(
                        model_instance,
                        data,
                        save_in_attachment,
                    )
            with closing(open(result_path, 'r')) as out_stream:
                tmpl_data = out_stream.read()
            datadict = {}
        else:
            result_fd, result_path = tempfile.mkstemp(suffix='.' + filetype,
                                                      prefix='p3o.report.tmp.')
            tmpl_data = self.get_template(model_instance)

            in_stream = StringIO(tmpl_data)
            with closing(os.fdopen(result_fd, 'w+')) as out_stream:
                template = Template(in_stream, out_stream, escape_false=True)
                localcontext = self._get_parser_context(model_instance, data)
                expressions = template.get_all_user_python_expression()
                py_expression = template.convert_py3o_to_python_ast(
                    expressions)
                convertor = Py3oConvertor()
                data_struct = convertor(py_expression)
                datadict = data_struct.render(localcontext)

        # Call py3o.server to render the template in the desired format
        files = {
            'tmpl_file': tmpl_data,
        }
        fields = {
            "targetformat": filetype,
            "datadict": json.dumps(datadict),
            "image_mapping": "{}",
            "escape_false": "on",
        }
        if report_xml.py3o_is_local_fusion:
            fields['skipfusion'] = '1'
        url = report_xml.py3o_server_id.url
        logger.info('Connecting to %s to convert report %s to %s', url,
                    report_xml.report_name, filetype)
        if filetype == 'pdf':
            options = report_xml.pdf_options_id or\
                report_xml.py3o_server_id.pdf_options_id
            if options:
                pdf_options_dict = options.odoo2libreoffice_options()
                fields['pdf_options'] = json.dumps(pdf_options_dict)
                logger.debug('PDF Export options: %s', pdf_options_dict)
        start_chrono = datetime.now()
        r = requests.post(url, data=fields, files=files)
        if r.status_code != 200:
            # server says we have an issue... let's tell that to enduser
            logger.error('Py3o fusion server error: %s', r.text)
            raise UserError(_('Fusion server error %s') % r.text, )

        chunk_size = 1024
        with open(result_path, 'w+') as fd:
            for chunk in r.iter_content(chunk_size):
                fd.write(chunk)
        end_chrono = datetime.now()
        convert_seconds = (end_chrono - start_chrono).total_seconds()
        logger.info('Report %s converted to %s in %s seconds',
                    report_xml.report_name, filetype, convert_seconds)
        if len(model_instance) == 1:
            self._postprocess_report(result_path, model_instance.id,
                                     save_in_attachment)
        return result_path
示例#3
0
    def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
        """ Overide this function to generate our py3o report
        """
        if report_xml.report_type != 'py3o':
            return super(Py3oParser, self).create_single_pdf(
                cr, uid, ids, data, report_xml, context=context
            )

        pool = registry(cr.dbname)
        model_data_ids = pool['ir.model.data'].search(
            cr, uid, [
                ('model', '=', 'ir.actions.report.xml'),
                ('res_id', '=', report_xml.id),
            ]
        )

        xml_id = None
        if model_data_ids:
            model_data = pool['ir.model.data'].browse(
                cr, uid, model_data_ids[0], context=context
            )
            xml_id = '%s.%s' % (model_data.module, model_data.name)

        parser_instance = self.parser(cr, uid, self.name2, context=context)
        parser_instance.set_context(
            self.getObjects(cr, uid, ids, context),
            data, ids, report_xml.report_type
        )

        if xml_id in _extender_functions:
            for fct in _extender_functions[xml_id]:
                fct(pool, cr, uid, parser_instance.localcontext, context)

        tmpl_data = self.get_template(report_xml)

        in_stream = StringIO(tmpl_data)
        out_stream = StringIO()
        template = Template(in_stream, out_stream)
        expressions = template.get_all_user_python_expression()
        py_expression = template.convert_py3o_to_python_ast(expressions)
        convertor = Py3oConvertor()
        data_struct = convertor(py_expression)

        filetype = report_xml.py3o_fusion_filetype

        datadict = parser_instance.localcontext

        parsed_datadict = data_struct.render(datadict)

        fusion_server_obj = pool.get('py3o.server')
        fusion_server_ids = fusion_server_obj.search(
            cr, uid, [('is_active', '=', True)], context=context, limit=1
        )
        if not fusion_server_ids:
            if filetype.fusion_ext == report_xml.py3o_template_id.filetype:
                # No format conversion is needed, render the template directly
                template.render(parsed_datadict)
                res = out_stream.getvalue()

            else:
                if USE_LOCAL_LIBREOFFICE:
                    import sh
                    import tempfile

                    template.render(parsed_datadict)
                    res = out_stream.getvalue()

                    arq = tempfile.NamedTemporaryFile(delete=False)
                    arq.seek(0)
                    arq.write(res)
                    arq.flush()

                    res_arq_name = arq.name + '.' + filetype.fusion_ext

                    sh.libreoffice('--headless', '--invisible', \
                        '--convert-to', filetype.fusion_ext, \
                        '--outdir', '/tmp', arq.name)

                    res = file(res_arq_name, 'r').read()

                    os.remove(res_arq_name)
                    os.remove(arq.name)

                else:
                    raise exceptions.MissingError(
                        _(u"No Py3o server configuration found")
                    )

        else:  # Call py3o.server to render the template in the desired format
            fusion_server_id = fusion_server_ids[0]

            fusion_server = fusion_server_obj.browse(
                cr, uid, fusion_server_id, context=context
            )
            in_stream.seek(0)
            files = {
                'tmpl_file': in_stream,
            }
            fields = {
                "targetformat": filetype.fusion_ext,
                "datadict": json.dumps(parsed_datadict),
                "image_mapping": "{}",
            }
            r = requests.post(fusion_server.url, data=fields, files=files)
            if r.status_code != 200:
                # server says we have an issue... let's tell that to enduser
                raise exceptions.Warning(
                    _('Fusion server error %s') % r.text,
                )

            # Here is a little joke about Odoo
            # we do nice chunked reading from the network...
            chunk_size = 1024
            with NamedTemporaryFile(
                    suffix=filetype.human_ext,
                    prefix='py3o-template-'
            ) as fd:
                for chunk in r.iter_content(chunk_size):
                    fd.write(chunk)
                fd.seek(0)
                # ... but odoo wants the whole data in memory anyways :)
                res = fd.read()

        return res, filetype.human_ext