From 32062c987ed7c0058c8569261ffd4cdcb4406589 Mon Sep 17 00:00:00 2001 From: Laurent Mignon Date: Tue, 4 Oct 2016 08:23:12 +0200 Subject: [PATCH] [IMP] New API + Short Hearder --- report_py3o/__init__.py | 2 +- report_py3o/__openerp__.py | 24 +--- report_py3o/models/__init__.py | 8 +- report_py3o/models/ir_report.py | 77 +++++------ report_py3o/models/py3o_fusion_filetype.py | 19 +-- report_py3o/models/py3o_server.py | 22 +--- report_py3o/models/py3o_template.py | 39 +++--- report_py3o/py3o_parser.py | 8 +- report_py3o/py3o_report_modif.py | 146 --------------------- 9 files changed, 73 insertions(+), 272 deletions(-) delete mode 100644 report_py3o/py3o_report_modif.py diff --git a/report_py3o/__init__.py b/report_py3o/__init__.py index 2c4eac3f..9a7e03ed 100644 --- a/report_py3o/__init__.py +++ b/report_py3o/__init__.py @@ -1 +1 @@ -import models \ No newline at end of file +from . import models \ No newline at end of file diff --git a/report_py3o/__openerp__.py b/report_py3o/__openerp__.py index cafbe598..8a4d7990 100644 --- a/report_py3o/__openerp__.py +++ b/report_py3o/__openerp__.py @@ -1,26 +1,6 @@ # -*- 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 . -# -# Author: Anael LORIMIER -# Vincent Lhote-Hatakeyama -# -############################################################################## +# Copyright 2013 XCG Consulting (http://odoo.consulting) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'LibreOffice Report Engine', 'description': ''' diff --git a/report_py3o/models/__init__.py b/report_py3o/models/__init__.py index 28989d9f..ccf621aa 100644 --- a/report_py3o/models/__init__.py +++ b/report_py3o/models/__init__.py @@ -1,4 +1,4 @@ -import ir_report -import py3o_fusion_filetype -import py3o_template -import py3o_server \ No newline at end of file +from . import ir_report +from . import py3o_fusion_filetype +from . import py3o_template +from . import py3o_server \ No newline at end of file diff --git a/report_py3o/models/ir_report.py b/report_py3o/models/ir_report.py index 106bd332..927994e3 100644 --- a/report_py3o/models/ir_report.py +++ b/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 -from openerp.osv import fields, osv +from openerp import api, fields, models from openerp.report.interface import report_int from ..py3o_parser import Py3oParser +from openerp.exceptions import ValidationError from openerp import addons -class report_xml(osv.Model): +class ReportXml(models.Model): """ Inherit from ir.actions.report.xml to allow customizing the template file. The user cam chose a template from a list. 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' - _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): """Look up a report definition. """ @@ -95,4 +82,4 @@ class report_xml(osv.Model): if new_report: return new_report else: - return super(report_xml, self)._lookup_report(cr, name) + return super(ReportXml, self)._lookup_report(cr, name) diff --git a/report_py3o/models/py3o_fusion_filetype.py b/report_py3o/models/py3o_fusion_filetype.py index 570ca474..009494fc 100644 --- a/report_py3o/models/py3o_fusion_filetype.py +++ b/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' _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) diff --git a/report_py3o/models/py3o_server.py b/report_py3o/models/py3o_server.py index d815a845..bf434a59 100644 --- a/report_py3o/models/py3o_server.py +++ b/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' - _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) diff --git a/report_py3o/models/py3o_template.py b/report_py3o/models/py3o_template.py index 29b49dfd..7281f333 100644 --- a/report_py3o/models/py3o_template.py +++ b/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' - _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') diff --git a/report_py3o/py3o_parser.py b/report_py3o/py3o_parser.py index d7467f95..36ed669d 100644 --- a/report_py3o/py3o_parser.py +++ b/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 import json import pkg_resources @@ -66,8 +68,8 @@ class Py3oParser(report_sxw): or from the default template file provided by the implementer. 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 @type report_obj: openerp.model.recordset instance diff --git a/report_py3o/py3o_report_modif.py b/report_py3o/py3o_report_modif.py deleted file mode 100644 index 8683ea25..00000000 --- a/report_py3o/py3o_report_modif.py +++ /dev/null @@ -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