[MIG] report_xml: Migration to 10.0
parent
3ee85d8de9
commit
9bf581d2fe
|
@ -1,8 +1,10 @@
|
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
Qweb XML Reports
|
||||
================
|
||||
|
||||
===========
|
||||
XML Reports
|
||||
===========
|
||||
|
||||
This module was written to extend the functionality of the reporting engine to
|
||||
support XML reports and allow modules to generate them by code or by QWeb
|
||||
|
@ -19,11 +21,6 @@ To install this module, you need to:
|
|||
But this module does nothing for the end user by itself, so if you have it
|
||||
installed it's probably because there is another module that depends on it.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
No manual configuration is needed.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
|
@ -63,11 +60,6 @@ For further information, please visit:
|
|||
* https://www.odoo.com/forum/help-1
|
||||
* https://github.com/OCA/reporting-engine
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
None
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
|
@ -77,6 +69,7 @@ Contributors
|
|||
------------
|
||||
|
||||
* Jairo Llopis <j.llopis@grupoesoc.es>
|
||||
* Enric Tobella <etobella@creublanca.es>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import controllers, models
|
||||
from . import controllers
|
||||
from . import models
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
"name": "Qweb XML Reports",
|
||||
"version": "8.0.1.0.0",
|
||||
"name": "XML Reports",
|
||||
"version": "10.0.1.0.0",
|
||||
"category": "Reporting",
|
||||
"website": "https://grupoesoc.es",
|
||||
"website": "https://github.com/OCA/reporting-engine",
|
||||
"author": "Grupo ESOC Ingeniería de Servicios, "
|
||||
"Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
|
@ -17,5 +18,8 @@
|
|||
],
|
||||
"data": [
|
||||
"views/report_xml_templates.xml",
|
||||
],
|
||||
"demo": [
|
||||
"demo/report.xml",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import main
|
|
@ -1,8 +1,9 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from openerp.http import route
|
||||
from openerp.addons.report.controllers import main as report
|
||||
from odoo.addons.report.controllers import main as report
|
||||
from odoo.http import route
|
||||
|
||||
|
||||
class ReportController(report.ReportController):
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="demo_report_xml_view">
|
||||
<t t-call="report_xml.utf8_header">
|
||||
<root>
|
||||
<user t-foreach="docs" t-as="doc">
|
||||
<name t-esc="doc.name"/>
|
||||
<vat t-esc="doc.vat"/>
|
||||
</user>
|
||||
</root>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<report id="demo_xml_report"
|
||||
name="report_xml.demo_report_xml_view"
|
||||
string="Demo xml report"
|
||||
report_type="qweb-xml"
|
||||
model="res.company"/>
|
||||
|
||||
</odoo>
|
|
@ -1,111 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
|
||||
|
||||
import logging
|
||||
from lxml import etree
|
||||
from openerp import api, fields, models
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ReportAction(models.Model):
|
||||
_inherit = "ir.actions.report.xml"
|
||||
|
||||
report_type = fields.Selection(selection_add=[("qweb-xml", "XML")])
|
||||
|
||||
def _lookup_report(self, cr, name):
|
||||
"""Enable ``qweb-xml`` report lookup."""
|
||||
try:
|
||||
return super(ReportAction, self)._lookup_report(cr, name)
|
||||
except Exception as ex:
|
||||
# Somebody thought it was a good idea to use standard exceptions
|
||||
if "qweb-xml" not in ex.message:
|
||||
raise ex
|
||||
else:
|
||||
cr.execute(
|
||||
"SELECT * FROM ir_act_report_xml WHERE report_name=%s",
|
||||
(name,))
|
||||
return cr.dictfetchone()["report_name"]
|
||||
|
||||
@api.model
|
||||
def render_report(self, res_ids, name, data):
|
||||
"""Special handling for ``qweb-xml`` reports."""
|
||||
if data.get("report_type") == u"qweb-xml":
|
||||
new_report = self._lookup_report(name)
|
||||
recs = self.env[self.env.context["active_model"]].browse(res_ids)
|
||||
result = self.env["report"].get_html(recs, new_report, data=data)
|
||||
|
||||
# XML with spaces before the <?xml tag will fail, and trailing ones
|
||||
# do nothing, so let's strip them and make everyone happier
|
||||
result = (result.strip(), "xml")
|
||||
else:
|
||||
result = super(ReportAction, self).render_report(
|
||||
res_ids, name, data)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class ReportGenerator(models.Model):
|
||||
_inherit = "report"
|
||||
|
||||
@api.model
|
||||
def _get_report_from_name(self, report_name):
|
||||
"""Allow to view ``qweb-xml`` reports as web pages."""
|
||||
try:
|
||||
return (super(ReportGenerator, self)
|
||||
._get_report_from_name(report_name))
|
||||
except IndexError:
|
||||
return self.env["ir.actions.report.xml"].search(
|
||||
[("report_type", "=", "qweb-xml"),
|
||||
("report_name", "=", report_name)])[0]
|
||||
|
||||
|
||||
class XSDCheckedReport(models.AbstractModel):
|
||||
"""Check XML report against a XSD schema before downloading it.
|
||||
|
||||
This is an Abstract Model to be inherited by the real report models, which
|
||||
must implement :meth:`.xsd` and have a ``_name`` in the form
|
||||
``report.<module>.<report_name>``.
|
||||
"""
|
||||
_name = "report_xml.xsd_checked_report"
|
||||
_description = "Base model for reports that need XSD checking"
|
||||
|
||||
@api.multi
|
||||
def xsd(self):
|
||||
"""Return the XSD schema contents."""
|
||||
raise NotImplementedError
|
||||
|
||||
@api.multi
|
||||
def render_html(self, data=None):
|
||||
"""Return the XML report after checking it against an XSD.
|
||||
|
||||
If ``context`` contains a dict called ``docargs``, it will be used as
|
||||
the Qweb context. The special key ``docs`` will be added to ``docargs``
|
||||
automatically if missing.
|
||||
"""
|
||||
# Qweb context
|
||||
docargs = self.env.context.get("docargs", dict())
|
||||
if "docs" not in docargs:
|
||||
docargs["docs"] = (self.env[self.env.context["active_model"]]
|
||||
.browse(self.env.context["active_ids"]))
|
||||
|
||||
# Load XSD
|
||||
xsd = etree.XML(self.xsd())
|
||||
_logger.debug("XSD schema contents: %s", etree.tostring(xsd))
|
||||
xsd = etree.XMLSchema(xsd)
|
||||
parser = etree.XMLParser(schema=xsd)
|
||||
|
||||
# Generate XML report
|
||||
result = (self.env["report"]
|
||||
.render(self._name[len("report."):], docargs)
|
||||
.strip())
|
||||
|
||||
# Validate XML with XSD
|
||||
try:
|
||||
etree.fromstring(result, parser)
|
||||
except Exception as error:
|
||||
_logger.error(result)
|
||||
raise error
|
||||
|
||||
return result
|
|
@ -0,0 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import report_action
|
||||
from . import report_generator
|
|
@ -0,0 +1,49 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models
|
||||
from lxml import etree
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ReportAction(models.Model):
|
||||
_inherit = "ir.actions.report.xml"
|
||||
|
||||
report_type = fields.Selection(selection_add=[("qweb-xml", "XML")])
|
||||
|
||||
def _lookup_report(self, name):
|
||||
"""Enable ``qweb-xml`` report lookup."""
|
||||
try:
|
||||
return super(ReportAction, self)._lookup_report(name)
|
||||
except Exception as ex:
|
||||
# Somebody thought it was a good idea to use standard exceptions
|
||||
if "qweb-xml" not in ex.message:
|
||||
raise ex
|
||||
else:
|
||||
self._cr.execute(
|
||||
"SELECT * FROM ir_act_report_xml WHERE report_name=%s",
|
||||
(name,))
|
||||
return self._cr.dictfetchone()["report_name"]
|
||||
|
||||
@api.model
|
||||
def render_report(self, res_ids, name, data):
|
||||
"""Special handling for ``qweb-xml`` reports."""
|
||||
xml_report = self.search([('report_name', '=', name),
|
||||
('report_type', '=', 'qweb-xml')], limit=1)
|
||||
if xml_report:
|
||||
xml_report = xml_report.ensure_one()
|
||||
result = self.env["report"].get_html(res_ids,
|
||||
xml_report.report_name,
|
||||
data=data)
|
||||
return (
|
||||
etree.tostring(
|
||||
etree.fromstring(result.strip()),
|
||||
encoding='UTF-8', xml_declaration=True, pretty_print=True
|
||||
), "xml")
|
||||
else:
|
||||
return super(ReportAction, self).render_report(
|
||||
res_ids, name, data)
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ReportGenerator(models.Model):
|
||||
_inherit = "report"
|
||||
|
||||
@api.model
|
||||
def _get_report_from_name(self, report_name):
|
||||
res = super(ReportGenerator, self)._get_report_from_name(report_name)
|
||||
if res:
|
||||
return res
|
||||
report_obj = self.env['ir.actions.report.xml']
|
||||
qwebtypes = ['qweb-xml']
|
||||
conditions = [('report_type', 'in', qwebtypes),
|
||||
('report_name', '=', report_name)]
|
||||
context = self.env['res.users'].context_get()
|
||||
return report_obj.with_context(context).search(conditions, limit=1)
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import test_report_xml
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Creu Blanca
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from lxml import etree
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestXmlReport(common.TransactionCase):
|
||||
def test_xml(self):
|
||||
report_object = self.env['ir.actions.report.xml']
|
||||
report_name = 'report_xml.demo_report_xml_view'
|
||||
self.assertEqual(
|
||||
report_name, report_object._lookup_report(report_name))
|
||||
docs = self.env['res.company'].search([], limit=1)
|
||||
rep = report_object.render_report(
|
||||
docs.ids, report_name, {}
|
||||
)
|
||||
root = etree.fromstring(rep[0])
|
||||
el = root.xpath('/root/user/name')
|
||||
self.assertEqual(
|
||||
el[0].text,
|
||||
docs.ensure_one().name
|
||||
)
|
|
@ -1,11 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<odoo>
|
||||
|
||||
<template id="utf8_header">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<t t-raw="0"/>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
|
Loading…
Reference in New Issue