Browse Source

[IMP] New API + Short Hearder

pull/80/head
Laurent Mignon 8 years ago
parent
commit
6dae7de2c7
  1. 2
      report_py3o/__init__.py
  2. 24
      report_py3o/__openerp__.py
  3. 8
      report_py3o/models/__init__.py
  4. 77
      report_py3o/models/ir_report.py
  5. 19
      report_py3o/models/py3o_fusion_filetype.py
  6. 22
      report_py3o/models/py3o_server.py
  7. 39
      report_py3o/models/py3o_template.py
  8. 8
      report_py3o/py3o_parser.py
  9. 146
      report_py3o/py3o_report_modif.py

2
report_py3o/__init__.py

@ -1 +1 @@
import models
from . import models

24
report_py3o/__openerp__.py

@ -1,26 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
##############################################################################
#
# LibreOffice Report Engine, for OpenERP
# Copyright (C) 2013 XCG Consulting (http://odoo.consulting)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Anael LORIMIER <anael.lorimier@xcg-consulting.fr>
# Vincent Lhote-Hatakeyama <vincent.lhote@xcg-consulting.fr>
#
##############################################################################
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'LibreOffice Report Engine', 'name': 'LibreOffice Report Engine',
'description': ''' 'description': '''

8
report_py3o/models/__init__.py

@ -1,4 +1,4 @@
import ir_report
import py3o_fusion_filetype
import py3o_template
import py3o_server
from . import ir_report
from . import py3o_fusion_filetype
from . import py3o_template
from . import py3o_server

77
report_py3o/models/ir_report.py

@ -1,11 +1,15 @@
# -*- coding: utf-8 -*-
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import os import os
from openerp.osv import fields, osv
from openerp import api, fields, models
from openerp.report.interface import report_int from openerp.report.interface import report_int
from ..py3o_parser import Py3oParser from ..py3o_parser import Py3oParser
from openerp.exceptions import ValidationError
from openerp import addons from openerp import addons
class report_xml(osv.Model):
class ReportXml(models.Model):
""" Inherit from ir.actions.report.xml to allow customizing the template """ Inherit from ir.actions.report.xml to allow customizing the template
file. The user cam chose a template from a list. file. The user cam chose a template from a list.
The list is configurable in the configuration tab, see py3o_template.py The list is configurable in the configuration tab, see py3o_template.py
@ -13,49 +17,32 @@ class report_xml(osv.Model):
_inherit = 'ir.actions.report.xml' _inherit = 'ir.actions.report.xml'
_columns = {
# TODO required when report_type type is py3o, add python constraint
'py3o_fusion_filetype': fields.many2one(
'py3o.fusion.filetype',
u"Output Format",
),
'py3o_template_id': fields.many2one(
'py3o.template',
u"Template",
),
'module': fields.char(
u"Module",
size=64,
help=u"The implementer module that provides this report",
),
'py3o_template_fallback': fields.char(
u"Fallback",
size=128,
help=(
u"If the user does not provide a template this will be used "
u"it should be a relative path to root of YOUR module"
)
),
'report_type': fields.selection(
[
('qweb-pdf', u"PDF"),
('qweb-html', u"HTML"),
('controller', u"Controller"),
('pdf', u"RML pdf (deprecated)"),
('sxw', u"RML sxw (deprecated)"),
('webkit', u"Webkit (deprecated)"),
('py3o', u"Py3o"),
],
string=u"Report Type",
required=True,
help=u"HTML will open the report directly in your browser, "
u"PDF will use wkhtmltopdf to render the HTML into a PDF "
u"file and let you download it, Controller allows you to "
u"define the url of a custom controller outputting "
u"any kind of report.",
)
}
@api.one
@api.constrains("py3o_fusion_filetype", "report_type")
def _check_py3o_fusion_filetype(self):
if self.report_type == "py3o" and not self.py3o_fusion_filetype:
raise ValidationError(
"Field 'Output Format' is required for Py3O report")
py3o_fusion_filetype = fields.Many2one(
'py3o.fusion.filetype',
"Output Format")
py3o_template_id = fields.Many2one(
'py3o.template',
"Template")
module = fields.Char(
"Module",
help="The implementer module that provides this report")
py3o_template_fallback = fields.Char(
"Fallback",
size=128,
help=(
"If the user does not provide a template this will be used "
"it should be a relative path to root of YOUR module"
))
report_type = fields.Selection(selection_add=[('py3o', "Py3o")])
@api.cr
def _lookup_report(self, cr, name): def _lookup_report(self, cr, name):
"""Look up a report definition. """Look up a report definition.
""" """
@ -95,4 +82,4 @@ class report_xml(osv.Model):
if new_report: if new_report:
return new_report return new_report
else: else:
return super(report_xml, self)._lookup_report(cr, name)
return super(ReportXml, self)._lookup_report(cr, name)

19
report_py3o/models/py3o_fusion_filetype.py

@ -1,18 +1,13 @@
from openerp.osv import fields, osv
# -*- coding: utf-8 -*-
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class py3o_fusion_filetype(osv.Model):
class Py3oFusionFiletype(models.Model):
_name = 'py3o.fusion.filetype' _name = 'py3o.fusion.filetype'
_rec_name = 'human_ext' _rec_name = 'human_ext'
_columns = {
'fusion_ext': fields.char(
u"Fusion Extension",
size=8,
),
'human_ext': fields.char(
u"Human readble extension",
size=8,
),
}
fusion_ext = fields.Char("Fusion Extension", siez=8)
human_ext = fields.Char("Human readble extension", size=8)

22
report_py3o/models/py3o_server.py

@ -1,19 +1,11 @@
from openerp.osv import fields, osv
# -*- coding: utf-8 -*-
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class py3o_server(osv.Model):
class Py3oServer(models.Model):
_name = 'py3o.server' _name = 'py3o.server'
_columns = {
'url': fields.char(
u"URL",
size=256,
),
'is_active': fields.boolean(
u"Active",
)
}
_defaults = {
'is_active': True,
}
url = fields.Char("URL", required=True)
is_active = fields.Boolean("Active", default=True)

39
report_py3o/models/py3o_template.py

@ -1,28 +1,19 @@
from openerp.osv import fields, osv
# -*- coding: utf-8 -*-
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class py3o_template(osv.Model):
class Py3oTemplate(models.Model):
_name = 'py3o.template' _name = 'py3o.template'
_columns = {
'name': fields.char(
u"Name",
),
'py3o_template_data': fields.binary(
u"LibreOffice template",
),
'filetype': fields.selection(
[
('odt', u"ODF Text Document"),
('ods', u"ODF Spreadsheet"),
],
u"LibreOffice Template File Type",
required=True,
),
}
_defaults = {
'filetype': 'odt'
}
name = fields.Char(required=True)
py3o_template_data = fields.Binary("LibreOffice template")
filetype = fields.Selection(
selection=[
('odt', u"ODF Text Document"),
('ods', u"ODF Spreadsheet"),
],
string="LibreOffice Template File Type",
required=True,
default='odt')

8
report_py3o/py3o_parser.py

@ -1,4 +1,6 @@
# -*- encoding: utf-8 -*-
# -*- coding: utf-8 -*-
# Copyright 2013 XCG Consulting (http://odoo.consulting)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from cStringIO import StringIO from cStringIO import StringIO
import json import json
import pkg_resources import pkg_resources
@ -66,8 +68,8 @@ class Py3oParser(report_sxw):
or from the default template file provided by the implementer. or from the default template file provided by the implementer.
ATM this method takes a report definition recordset ATM this method takes a report definition recordset
to try and fetch the report template from database. If not found it will
fallback to the template file referenced in the report definition.
to try and fetch the report template from database. If not found it
will fallback to the template file referenced in the report definition.
@param report_obj: a recordset representing the report defintion @param report_obj: a recordset representing the report defintion
@type report_obj: openerp.model.recordset instance @type report_obj: openerp.model.recordset instance

146
report_py3o/py3o_report_modif.py

@ -1,146 +0,0 @@
from base64 import b64decode
from tempfile import NamedTemporaryFile as tempfile
from openerp import pooler
from openerp.report.report_sxw import *
from openerp.tools.translate import _
from openerp.osv.osv import except_osv
from py3o.template import Template
from oe_json_serializer import OESerializer
import json
import requests
import os
class py3o_report(report_sxw):
# def __init__(self, name, table):
# super(py3o_report, self).__init__(name, table)
def get_values(self, cr, uid, ids, data, context):
''' Override this function to customize the dictionary given to the
py3o.template renderer. '''
return {
'lang': self.get_lang(cr, uid, context),
'objects': self.getObjects(cr, uid, ids, context),
}
def get_lang(self, cr, uid, context):
pool = pooler.get_pool(cr.dbname)
lang_obj = pool.get('res.lang')
user_obj = pool.get('res.users')
lang_code = user_obj.browse(cr, uid, uid, context=context).lang
lang = lang_obj.search(cr, uid,
[('code', '=', lang_code)],
context=context)[0]
return lang_obj.browse(cr, uid, lang, context=context)
def format_date(self, date, values):
''' Return a date formatted according to the language extracted from
the "values" argument (which should be the result of get_values). '''
return date.strftime(values['lang'].date_format)
def create(self, cr, uid, ids, data, context=None):
# Find the report definition to get its settings.
pool = pooler.get_pool(cr.dbname)
report_xml_obj = pool.get('ir.actions.report.xml')
report_xml_ids = report_xml_obj.search(cr, uid,
[('report_name', '=', self.name[7:])], # Ignore "report."
context=context)
if not report_xml_ids:
return super(py3o_report, self).create(cr, uid, ids, data,
context=context)
report_xml = report_xml_obj.browse(cr, uid,
report_xml_ids[0],
context=context)
template = report_xml.py3o_template_id
filetype = report_xml.py3o_fusion_filetype
#Try to request fusion server:
fusion_server_obj = pool['py3o.server']
#TODO: Raise a message if no config found
fusion_server_id = fusion_server_obj.search(
cr, uid, [], context=context
)[0]
fusion_server = fusion_server_obj.browse(cr, uid, fusion_server_id)
# py3o.template operates on filenames so create temporary files.
in_temp = tempfile(suffix='.odt', prefix='py3o-template-')
in_temp.write(b64decode(template.py3o_template_data))
in_temp.seek(0)
out_temp = tempfile(suffix='.odt', prefix='py3o-report-')
# We need to get the variables used in the template
#TODO: Find a way to avoid calling Template
t = Template(in_temp.name, out_temp.name)
# Remove 'py3o.'
user_variable = [x[5:] for x in t.get_all_user_python_expression()]
print user_variable
values = self.get_values(cr, uid, ids, data, context)
t.render(values)
print values
#WARNING: We rely on the fact that there is a for loop on the report
# on objects (for object in objects) due to lack of time
val_dict = {}
for val in values:
if val == 'objects':
o = []
for obj in values[val]:
x = OESerializer.serialize(
obj,
[
v[len('object') + 1:]
for v in user_variable
if v.startswith('object')
]
)
o.append(x)
val_dict.update({val: o})
continue
x = OESerializer.serialize(
values[val],
[
v[len(val) + 1:]
for v in user_variable
if v.startswith(val)
]
)
val_dict.update({val: x})
import pprint
pprint.pprint(val_dict)
val_json = json.dumps(val_dict)
fields = {
'targetformat': filetype.fusion_ext,
'datadict': val_json,
'image_mapping': '{}',
}
print fields
r = requests.post(
fusion_server.url, data=fields, files={'tmpl_file': in_temp}
)
in_temp.close()
if r.status_code == 400:
raise Exception("Problem with fusion server: %s" % r.json())
chunk_size = 1024
ext = filetype.human_ext
for chunk in r.iter_content(chunk_size):
out_temp.write(chunk)
out_temp.seek(0)
return out_temp.read(), ext
Loading…
Cancel
Save