mirror of
https://github.com/OCA/reporting-engine.git
synced 2025-02-16 16:30:38 +02:00
[RFR] split off the fusion server to its own module
use libreoffice for conversions in the base version. Fixes #179
This commit is contained in:
committed by
Elmeri Niemelä
parent
238b24877e
commit
0a706a660f
@@ -1,5 +1,4 @@
|
||||
from . import ir_actions_report_xml
|
||||
from . import py3o_template
|
||||
from . import py3o_server
|
||||
from . import report
|
||||
from . import py3o_report
|
||||
|
||||
@@ -31,19 +31,6 @@ class IrActionsReportXml(models.Model):
|
||||
raise ValidationError(_(
|
||||
"Field 'Output Format' is required for Py3O report"))
|
||||
|
||||
@api.multi
|
||||
@api.constrains("py3o_is_local_fusion", "py3o_server_id",
|
||||
"py3o_filetype")
|
||||
def _check_py3o_server_id(self):
|
||||
for report in self:
|
||||
if report.report_type == "py3o":
|
||||
is_native = Formats().get_format(report.py3o_filetype).native
|
||||
if ((not is_native or not report.py3o_is_local_fusion) and
|
||||
not report.py3o_server_id):
|
||||
raise ValidationError(_(
|
||||
"Can not use not native format in local fusion. "
|
||||
"Please specify a Fusion Server"))
|
||||
|
||||
@api.model
|
||||
def _get_py3o_filetypes(self):
|
||||
formats = Formats()
|
||||
@@ -62,15 +49,6 @@ class IrActionsReportXml(models.Model):
|
||||
py3o_template_id = fields.Many2one(
|
||||
'py3o.template',
|
||||
"Template")
|
||||
py3o_is_local_fusion = fields.Boolean(
|
||||
"Local Fusion",
|
||||
help="Native formats will be processed without a server. "
|
||||
"You must use this mode if you call methods on your model into "
|
||||
"the template.",
|
||||
default=True)
|
||||
py3o_server_id = fields.Many2one(
|
||||
"py3o.server",
|
||||
"Fusion Server")
|
||||
module = fields.Char(
|
||||
"Module",
|
||||
help="The implementer module that provides this report")
|
||||
|
||||
@@ -5,26 +5,23 @@
|
||||
import base64
|
||||
from base64 import b64decode
|
||||
from cStringIO import StringIO
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from contextlib import closing
|
||||
import subprocess
|
||||
|
||||
import pkg_resources
|
||||
import requests
|
||||
import sys
|
||||
import tempfile
|
||||
from zipfile import ZipFile, ZIP_DEFLATED
|
||||
|
||||
from odoo.exceptions import AccessError
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.report.report_sxw import rml_parse
|
||||
from odoo import api, fields, models, tools, _
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
from py3o.template.helpers import Py3oConvertor
|
||||
from py3o.template import Template
|
||||
from py3o import formats
|
||||
from genshi.core import Markup
|
||||
@@ -244,60 +241,63 @@ class Py3oReport(models.TransientModel):
|
||||
""" 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.')
|
||||
suffix='.ods', 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)
|
||||
template.render(localcontext)
|
||||
out_stream.seek(0)
|
||||
tmpl_data = out_stream.read()
|
||||
|
||||
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,
|
||||
)
|
||||
result_path = self._convert_single_report(
|
||||
result_path, model_instance, data
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
@api.multi
|
||||
def _convert_single_report(self, result_path, model_instance, data):
|
||||
"""Run a command to convert to our target format"""
|
||||
filetype = self.ir_actions_report_xml_id.py3o_filetype
|
||||
if not Formats().get_format(filetype).native:
|
||||
command = self._convert_single_report_cmd(
|
||||
result_path, model_instance, data,
|
||||
)
|
||||
logger.debug('Running command %s', command)
|
||||
output = subprocess.check_output(
|
||||
command, cwd=os.path.dirname(result_path),
|
||||
)
|
||||
logger.debug('Output was %s', output)
|
||||
self._cleanup_tempfiles([result_path])
|
||||
result_path, result_filename = os.path.split(result_path)
|
||||
result_path = os.path.join(
|
||||
result_path, '%s.%s' % (
|
||||
os.path.splitext(result_filename)[0], filetype
|
||||
)
|
||||
)
|
||||
return result_path
|
||||
|
||||
@api.multi
|
||||
def _convert_single_report_cmd(self, result_path, model_instance, data):
|
||||
"""Return a command list suitable for use in subprocess.call"""
|
||||
return [
|
||||
self.env['ir.config_parameter'].get_param(
|
||||
'py3o.conversion_command', 'libreoffice',
|
||||
),
|
||||
'--headless',
|
||||
'--convert-to',
|
||||
self.ir_actions_report_xml_id.py3o_filetype,
|
||||
result_path,
|
||||
]
|
||||
|
||||
@api.multi
|
||||
def _get_or_create_single_report(self, model_instance, data,
|
||||
save_in_attachment):
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2013 XCG Consulting (http://odoo.consulting)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class Py3oServer(models.Model):
|
||||
_name = 'py3o.server'
|
||||
_rec_name = 'url'
|
||||
|
||||
url = fields.Char(
|
||||
"Py3o Fusion Server URL", required=True,
|
||||
help="If your Py3o Fusion server is on the same machine and runs "
|
||||
"on the default port, the URL is http://localhost:8765/form")
|
||||
is_active = fields.Boolean("Active", default=True)
|
||||
@@ -13,6 +13,10 @@ class Py3oTemplate(models.Model):
|
||||
selection=[
|
||||
('odt', "ODF Text Document"),
|
||||
('ods', "ODF Spreadsheet"),
|
||||
('odp', "ODF Presentation"),
|
||||
('fodt', "ODF Text Document (Flat)"),
|
||||
('fods', "ODF Spreadsheet (Flat)"),
|
||||
('fodp', "ODF Presentation (Flat)"),
|
||||
],
|
||||
string="LibreOffice Template File Type",
|
||||
required=True,
|
||||
|
||||
Reference in New Issue
Block a user