Browse Source

[MIG][13.0] report_xml: Migration to 13.0

myc-14.0-py3o
Tatiana Deribina 5 years ago
committed by Enric Tobella
parent
commit
9df5049644
  1. 40
      report_xml/README.rst
  2. 2
      report_xml/__init__.py
  3. 20
      report_xml/__manifest__.py
  4. 10
      report_xml/controllers/main.py
  5. 12
      report_xml/demo/demo_report.xml
  6. 23
      report_xml/demo/demo_report.xsd
  7. 34
      report_xml/demo/report.xml
  8. 47
      report_xml/hooks.py
  9. 2
      report_xml/models/__init__.py
  10. 62
      report_xml/models/ir_actions_report.py
  11. 31
      report_xml/models/report_action.py
  12. 5
      report_xml/readme/CONTRIBUTORS.rst
  13. 22
      report_xml/readme/USAGE.rst
  14. 3
      report_xml/reports/__init__.py
  15. 123
      report_xml/reports/report_report_xml_abstract.py
  16. 44
      report_xml/static/description/index.html
  17. 17
      report_xml/static/src/js/report/action_manager_report.js
  18. 6
      report_xml/tests/test_report_xml.py
  19. 32
      report_xml/views/ir_actions_report_view.xml
  20. 13
      report_xml/views/ir_actions_views.xml
  21. 5
      report_xml/views/webclient_templates.xml

40
report_xml/README.rst

@ -14,16 +14,16 @@ XML Reports
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
:target: https://github.com/OCA/reporting-engine/tree/12.0/report_xml
:target: https://github.com/OCA/reporting-engine/tree/13.0/report_xml
:alt: OCA/reporting-engine :alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_xml
:target: https://translation.odoo-community.org/projects/reporting-engine-13-0/reporting-engine-13-0-report_xml
:alt: Translate me on Weblate :alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/143/12.0
:target: https://runbot.odoo-community.org/runbot/143/13.0
:alt: Try me on Runbot :alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
|badge1| |badge2| |badge3| |badge4| |badge5|
This module was written to extend the functionality of the reporting engine to 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 support XML reports and allow modules to generate them by code or by QWeb
@ -56,25 +56,30 @@ This module is intended as a base engine for other modules to use it, so no dire
If you are a developer If you are a developer
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
To learn from an example, just check the `sample module`_.
To learn from an example, just check the `demo report`_ on GitHub for
the model ``res.company`` or check it in interface from companies views.
To develop with this module, you need to: To develop with this module, you need to:
* Create a module. * Create a module.
* Make it depend on this one. * Make it depend on this one.
* Follow `instructions to create reports`_ having in mind that the * Follow `instructions to create reports`_ having in mind that the
``report_type`` field in your ``ir.actions.report.xml`` record must be
``report_type`` field in your ``ir.actions.report`` record must be
``qweb-xml``. ``qweb-xml``.
In case you want to create a `custom report`_, the instructions remain the same In case you want to create a `custom report`_, the instructions remain the same
as for HTML reports, and the method that you must override is also called as for HTML reports, and the method that you must override is also called
``_get_report_values``, even when this time you are creating a XML report. ``_get_report_values``, even when this time you are creating a XML report.
You can make your custom report inherit ``report_xml.xsd_checked_report``, name
it like your XML ``<template>`` id prepended by ``report.``, add a ``xsd()``
method that returns a XSD in a string, and have XSD automatic checking for
You can make your custom report inherit ``report.report_xml.abstract``, name
it in such way ``report.<module.report_name>``. Also you can add a XSD file for
report validation into ``xsd_schema`` field of your report (check
`report definition`_) and have XSD automatic checking for
free. free.
You can customize rendering process and validation way via changing logic of
``generate_report`` and ``validate_report`` methods in your report class.
You can visit ``http://<server-address>/report/xml/<module.report_name>/<ids>`` You can visit ``http://<server-address>/report/xml/<module.report_name>/<ids>``
to see your XML report online as a web page. to see your XML report online as a web page.
@ -83,9 +88,10 @@ For further information, please visit:
* https://www.odoo.com/forum/help-1 * https://www.odoo.com/forum/help-1
* https://github.com/OCA/reporting-engine * https://github.com/OCA/reporting-engine
.. _custom report: https://www.odoo.com/documentation/12.0/reference/reports.html#custom-reports
.. _instructions to create reports: https://www.odoo.com/documentation/12.0/reference/reports.html
.. _sample module: https://github.com/OCA/reporting-engine/tree/12.0/report_xml_sample
.. _custom report: https://www.odoo.com/documentation/13.0/reference/reports.html#custom-reports
.. _instructions to create reports: https://www.odoo.com/documentation/13.0/reference/reports.html
.. _demo report: https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/demo_report.xml
.. _report definition: https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/report.xml
Bug Tracker Bug Tracker
=========== ===========
@ -93,7 +99,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/issues>`_. Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/issues>`_.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_xml%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_xml%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues. Do not contact contributors directly about support or help with technical issues.
@ -104,14 +110,16 @@ Authors
~~~~~~~ ~~~~~~~
* Tecnativa * Tecnativa
* Avoin.Systems
Contributors Contributors
~~~~~~~~~~~~ ~~~~~~~~~~~~
* Enric Tobella <etobella@creublanca.es> * Enric Tobella <etobella@creublanca.es>
* `Tecnativa <https://www.tecnativa.com>`_: * `Tecnativa <https://www.tecnativa.com>`_:
Jairo Llopis
* Jairo Llopis
* `Avoin.Systems <https://avoin.systems/>`_:
* Tatiana Deribina
Other credits Other credits
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -131,6 +139,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use. promote its widespread use.
This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/12.0/report_xml>`_ project on GitHub.
This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/13.0/report_xml>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

2
report_xml/__init__.py

@ -2,3 +2,5 @@
from . import controllers from . import controllers
from . import models from . import models
from . import reports
from .hooks import post_init_hook

20
report_xml/__manifest__.py

@ -2,15 +2,27 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
{ {
"name": "XML Reports", "name": "XML Reports",
"version": "12.0.1.0.0",
"version": "13.0.1.0.0",
"category": "Reporting", "category": "Reporting",
"website": "https://github.com/OCA/reporting-engine", "website": "https://github.com/OCA/reporting-engine",
"author": "Tecnativa, " "Odoo Community Association (OCA)",
"author": "Tecnativa, Odoo Community Association (OCA), Avoin.Systems",
"license": "AGPL-3", "license": "AGPL-3",
"installable": True, "installable": True,
"application": False, "application": False,
"summary": "Allow to generate XML reports", "summary": "Allow to generate XML reports",
"depends": ["web"], "depends": ["web"],
"data": ["views/webclient_templates.xml", "views/ir_actions_views.xml"],
"demo": ["demo/report.xml"],
"data": [
"views/webclient_templates.xml", # add js handlers for action manager
"views/ir_actions_report_view.xml",
],
"demo": [
"demo/report.xml", # register report in the system
"demo/demo_report.xml", # report body definition
],
"external_dependencies": {
"python": [ # Python third party libraries required for module
"lxml" # XML and HTML with Python
]
},
"post_init_hook": "post_init_hook",
} }

10
report_xml/controllers/main.py

@ -39,9 +39,7 @@ class ReportController(report.ReportController):
] ]
return request.make_response(xml, headers=xmlhttpheaders) return request.make_response(xml, headers=xmlhttpheaders)
else: else:
return super(ReportController, self).report_routes(
reportname, docids, converter, **data
)
return super().report_routes(reportname, docids, converter, **data)
@route() @route()
def report_download(self, data, token): def report_download(self, data, token):
@ -73,13 +71,13 @@ class ReportController(report.ReportController):
filename = "%s.xml" % (report.name) filename = "%s.xml" % (report.name)
if docids: if docids:
ids = [int(x) for x in docids.split(",")]
ids = [int(doc_id) for doc_id in docids.split(",")]
records = request.env[report.model].browse(ids) records = request.env[report.model].browse(ids)
if report.print_report_name and not len(records) > 1: if report.print_report_name and not len(records) > 1:
report_name = safe_eval( report_name = safe_eval(
report.print_report_name, {"object": records, "time": time} report.print_report_name, {"object": records, "time": time}
) )
filename = "%s.xml" % (report_name)
filename = "{}.xml".format(report_name)
response.headers.add( response.headers.add(
"Content-Disposition", content_disposition(filename) "Content-Disposition", content_disposition(filename)
) )
@ -90,4 +88,4 @@ class ReportController(report.ReportController):
error = {"code": 200, "message": "Odoo Server Error", "data": se} error = {"code": 200, "message": "Odoo Server Error", "data": se}
return request.make_response(html_escape(json.dumps(error))) return request.make_response(html_escape(json.dumps(error)))
else: else:
return super(ReportController, self).report_download(data, token)
return super().report_download(data, token)

12
report_xml/demo/demo_report.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="demo_report_xml_view">
<root>
<user t-foreach="docs" t-as="doc">
<id t-esc="doc.id" />
<name t-esc="doc.name" />
<vat t-esc="doc.vat" />
</user>
</root>
</template>
</odoo>

23
report_xml/demo/demo_report.xsd

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root" type="root_type"/>
<xs:complexType name="root_type">
<xs:sequence>
<xs:element name="user"
type="user_type"
minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="user_type">
<xs:sequence>
<xs:element name="id" type="xs:int"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="vat" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

34
report_xml/demo/report.xml

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<template id="demo_report_xml_view">
<root>
<user t-foreach="docs" t-as="doc">
<name t-esc="doc.name"/>
<vat t-esc="doc.vat"/>
</user>
</root>
</template>
<report id="demo_xml_report"
name="report_xml.demo_report_xml_view"
string="Demo xml report"
report_type="qweb-xml"
print_report_name="'Demo xml report'"
file="report_xml.xml"
model="res.company"/>
<report
id="demo_xml_report"
name="report_xml.demo_report_xml_view"
string="Demo xml report"
report_type="qweb-xml"
print_report_name="'Demo xml report'"
model="res.company"
/>
<!--
In case of demo data next definition will not work. So it just example
how it should look. If report is a part of demo data you will need
add file to report instance via `post_install_hook`
-->
<record id="demo_xml_report" model="ir.actions.report">
<field name="xsd_schema" type="base64" file="report_xml/demo/demo_report.xsd" />
</record>
</odoo> </odoo>

47
report_xml/hooks.py

@ -0,0 +1,47 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
import os
from odoo import SUPERUSER_ID, api
def post_init_hook(cr, registry):
"""
Loaded after installing this module, and before the next module starts
installing.
Add XSD Validation Schema for a demo report if it's in the system.
Demo data records are always created with `noupdate == True` and render of
tag `report` doesn't support new `ir.actions.report` field `xsd_schema`.
Thus it is impossible to define `xsd_schema` in the demo definition or add
schema after that via xml update record. Therefore it possible to add value
to `xsd_schema` field for demo record only via hook.
Args:
* cr(odoo.sql_db.Cursor) - database cursor.
* registry(odoo.modules.registry.RegistryManager) - a mapping between
model names and model classes.
"""
with api.Environment.manage():
env = api.Environment(cr, SUPERUSER_ID, {})
report_domain = [
("report_name", "=", "report_xml.demo_report_xml_view") # report tech name
]
demo_report = env["ir.actions.report"].search(report_domain, limit=1)
if demo_report:
dir_path = os.path.dirname(__file__)
xsd_file_relative_path = "demo/demo_report.xsd"
xsd_file_full_path = os.path.join(dir_path, xsd_file_relative_path)
with open(xsd_file_full_path, "r") as xsd:
# `xsd_schema` is binary fields with an attribute
# `attachment=True` so XSD Schema will be added as attachment
attach_vals = {
"name": "Demo Report.xsd",
"datas": xsd.read(),
"res_model": "ir.actions.report",
"res_id": demo_report.id,
"res_field": "xsd_schema",
"type": "binary",
}
env["ir.attachment"].create(attach_vals)

2
report_xml/models/__init__.py

@ -1,3 +1,3 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from . import report_action
from . import ir_actions_report

62
report_xml/models/ir_actions_report.py

@ -0,0 +1,62 @@
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from odoo import fields, models
class IrActionsReport(models.Model):
_inherit = "ir.actions.report"
report_type = fields.Selection(selection_add=[("qweb-xml", "XML")])
xsd_schema = fields.Binary(
string="XSD Validation Schema",
attachment=True,
help=(
"File with XSD Schema for checking content of result report. "
"Can be empty if validation is not required."
),
)
xml_encoding = fields.Selection(
selection=[
("UTF-8", "UTF-8") # will be used as default even if nothing is selected
],
string="XML Encoding",
help=(
"Encoding for XML reports. If nothing is selected, "
"then UTF-8 will be applied."
),
)
xml_declaration = fields.Boolean(
string="XML Declaration",
help=(
"""Add `<?xml encoding="..." version="..."?>` at the start """
"""of final report file."""
),
)
def render_qweb_xml(self, docids, data=None):
"""
Call `generate_report` method of report abstract class
`report.<report technical name>` or of standard class for XML report
rendering - `report.report_xml.abstract`
Args:
* docids(list) - IDs of instances for those report will be generated
* data(dict, None) - variables for report rendering
Returns:
* str - result content of report
* str - type of result content
"""
report_model_name = "report.{}".format(self.report_name)
report_model = self.env.get(report_model_name)
if report_model is None:
report_model = self.env["report.report_xml.abstract"]
content, ttype = report_model.generate_report(
ir_report=self, # will be used to get settings of report
docids=docids,
data=data,
)
return content, ttype

31
report_xml/models/report_action.py

@ -1,31 +0,0 @@
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from lxml import etree
from odoo import api, fields, models
class ReportAction(models.Model):
_inherit = "ir.actions.report"
report_type = fields.Selection(selection_add=[("qweb-xml", "XML")])
@api.model
def render_qweb_xml(self, docids, data=None):
if not data:
data = {}
data.setdefault("report_type", "text")
data = self._get_rendering_context(docids, data)
result = self.render_template(self.report_name, data)
return (
etree.tostring(
etree.fromstring(
str(result, "UTF-8").lstrip("\n").lstrip().encode("UTF-8")
),
encoding="UTF-8",
xml_declaration=True,
pretty_print=True,
),
"xml",
)

5
report_xml/readme/CONTRIBUTORS.rst

@ -1,4 +1,5 @@
* Enric Tobella <etobella@creublanca.es> * Enric Tobella <etobella@creublanca.es>
* `Tecnativa <https://www.tecnativa.com>`_: * `Tecnativa <https://www.tecnativa.com>`_:
Jairo Llopis
* Jairo Llopis
* `Avoin.Systems <https://avoin.systems/>`_:
* Tatiana Deribina

22
report_xml/readme/USAGE.rst

@ -3,25 +3,30 @@ This module is intended as a base engine for other modules to use it, so no dire
If you are a developer If you are a developer
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
To learn from an example, just check the `sample module`_.
To learn from an example, just check the `demo report`_ on GitHub for
the model ``res.company`` or check it in interface from companies views.
To develop with this module, you need to: To develop with this module, you need to:
* Create a module. * Create a module.
* Make it depend on this one. * Make it depend on this one.
* Follow `instructions to create reports`_ having in mind that the * Follow `instructions to create reports`_ having in mind that the
``report_type`` field in your ``ir.actions.report.xml`` record must be
``report_type`` field in your ``ir.actions.report`` record must be
``qweb-xml``. ``qweb-xml``.
In case you want to create a `custom report`_, the instructions remain the same In case you want to create a `custom report`_, the instructions remain the same
as for HTML reports, and the method that you must override is also called as for HTML reports, and the method that you must override is also called
``_get_report_values``, even when this time you are creating a XML report. ``_get_report_values``, even when this time you are creating a XML report.
You can make your custom report inherit ``report_xml.xsd_checked_report``, name
it like your XML ``<template>`` id prepended by ``report.``, add a ``xsd()``
method that returns a XSD in a string, and have XSD automatic checking for
You can make your custom report inherit ``report.report_xml.abstract``, name
it in such way ``report.<module.report_name>``. Also you can add a XSD file for
report validation into ``xsd_schema`` field of your report (check
`report definition`_) and have XSD automatic checking for
free. free.
You can customize rendering process and validation way via changing logic of
``generate_report`` and ``validate_report`` methods in your report class.
You can visit ``http://<server-address>/report/xml/<module.report_name>/<ids>`` You can visit ``http://<server-address>/report/xml/<module.report_name>/<ids>``
to see your XML report online as a web page. to see your XML report online as a web page.
@ -30,6 +35,7 @@ For further information, please visit:
* https://www.odoo.com/forum/help-1 * https://www.odoo.com/forum/help-1
* https://github.com/OCA/reporting-engine * https://github.com/OCA/reporting-engine
.. _custom report: https://www.odoo.com/documentation/12.0/reference/reports.html#custom-reports
.. _instructions to create reports: https://www.odoo.com/documentation/12.0/reference/reports.html
.. _sample module: https://github.com/OCA/reporting-engine/tree/12.0/report_xml_sample
.. _custom report: https://www.odoo.com/documentation/13.0/reference/reports.html#custom-reports
.. _instructions to create reports: https://www.odoo.com/documentation/13.0/reference/reports.html
.. _demo report: https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/demo_report.xml
.. _report definition: https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/report.xml

3
report_xml/reports/__init__.py

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from . import report_report_xml_abstract

123
report_xml/reports/report_report_xml_abstract.py

@ -0,0 +1,123 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from base64 import b64decode
from xml.dom import minidom
from lxml import etree
from odoo import api, models
from odoo.exceptions import ValidationError
class ReportXmlAbstract(models.AbstractModel):
"""
Model `report.report_xml.abstract`.
This class provide basic methods for rendering XML report and it's
validation by XSD schema.
"""
_name = "report.report_xml.abstract"
_description = "Abstract XML Report"
@api.model
def generate_report(self, ir_report, docids, data=None):
"""
Generate and validate XML report. Use incoming `ir_report` settings
to setup encoding and XMl declaration for result `xml`.
Methods:
* `_get_rendering_context` `ir.actions.report` - get report variables.
It will call `_get_report_values` of report's class if it's exist.
* `render_template` of `ir.actions.report` - get report content
* `validate_report` - check result content
Args:
* ir_report(`ir.actions.report`) - report definition instance in Odoo
* docids(list) - IDs of instances for those report will be generated
* data(dict, None) - variables for report rendering
Returns:
* str - result content of report
* str - `"xml"`
Extra Info:
* Default encoding is `UTF-8`
"""
# collect variable for rendering environment
if not data:
data = {}
data.setdefault("report_type", "text")
data = ir_report._get_rendering_context(docids, data)
# render template
result_bin = ir_report.render_template(ir_report.report_name, data)
# prettify result content
# normalize indents
parsed_result_bin = minidom.parseString(result_bin)
result = parsed_result_bin.toprettyxml(indent=" " * 4)
# remove empty lines
utf8 = "UTF-8"
result = "\n".join(
line for line in result.splitlines() if line and not line.isspace()
).encode(utf8)
content = etree.tostring(
etree.fromstring(result),
encoding=ir_report.xml_encoding or utf8,
xml_declaration=ir_report.xml_declaration,
pretty_print=True,
)
# validate content
xsd_schema_doc = ir_report.xsd_schema
self.validate_report(xsd_schema_doc, content)
return content, "xml"
@api.model
def validate_report(self, xsd_schema_doc, content):
"""
Validate final report content against value of `xsd_schema` field
("XSD Validation Schema") of `ir.actions.report` via `etree` lib.
Args:
* xsd_schema_doc(byte-string) - report validation schema
* content(str) - report content for validation
Raises:
* odoo.exceptions.ValidationError - Syntax of final report is wrong
Returns:
* bool - True
"""
if xsd_schema_doc:
# create validation parser
decoded_xsd_schema_doc = b64decode(xsd_schema_doc)
parsed_xsd_schema = etree.XML(decoded_xsd_schema_doc)
xsd_schema = etree.XMLSchema(parsed_xsd_schema)
parser = etree.XMLParser(schema=xsd_schema)
try:
# check content
etree.fromstring(content, parser)
except etree.XMLSyntaxError as error:
raise ValidationError(error.msg)
return True
@api.model
def _get_report_values(self, docids, data=None):
"""
Allow to generate extra variables for report environment.
Args:
* docids(list) - IDs of instances for those report will be generated
* data(dict, None) - variables for report rendering
Returns:
* dict - extra variables for report render
"""
if not data:
data = {}
return data

44
report_xml/static/description/index.html

@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !! !! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/report_xml"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_xml"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/143/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/13.0/report_xml"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/reporting-engine-13-0/reporting-engine-13-0-report_xml"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/143/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module was written to extend the functionality of the reporting engine to <p>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 support XML reports and allow modules to generate them by code or by QWeb
templates.</p> templates.</p>
@ -404,22 +404,25 @@ installed it’s probably because there is another module that depends on it.</p
<p>This module is intended as a base engine for other modules to use it, so no direct result if you are a user.</p> <p>This module is intended as a base engine for other modules to use it, so no direct result if you are a user.</p>
<div class="section" id="if-you-are-a-developer"> <div class="section" id="if-you-are-a-developer">
<h2><a class="toc-backref" href="#id3">If you are a developer</a></h2> <h2><a class="toc-backref" href="#id3">If you are a developer</a></h2>
<p>To learn from an example, just check the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/report_xml_sample">sample module</a>.</p>
<p>To learn from an example, just check the <a class="reference external" href="https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/demo_report.xml">demo report</a>.</p>
<p>To develop with this module, you need to:</p> <p>To develop with this module, you need to:</p>
<ul class="simple"> <ul class="simple">
<li>Create a module.</li> <li>Create a module.</li>
<li>Make it depend on this one.</li> <li>Make it depend on this one.</li>
<li>Follow <a class="reference external" href="https://www.odoo.com/documentation/12.0/reference/reports.html">instructions to create reports</a> having in mind that the
<tt class="docutils literal">report_type</tt> field in your <tt class="docutils literal">ir.actions.report.xml</tt> record must be
<li>Follow <a class="reference external" href="https://www.odoo.com/documentation/13.0/reference/reports.html">instructions to create reports</a> having in mind that the
<tt class="docutils literal">report_type</tt> field in your <tt class="docutils literal">ir.actions.report</tt> record must be
<tt class="docutils literal"><span class="pre">qweb-xml</span></tt>.</li> <tt class="docutils literal"><span class="pre">qweb-xml</span></tt>.</li>
</ul> </ul>
<p>In case you want to create a <a class="reference external" href="https://www.odoo.com/documentation/12.0/reference/reports.html#custom-reports">custom report</a>, the instructions remain the same
<p>In case you want to create a <a class="reference external" href="https://www.odoo.com/documentation/13.0/reference/reports.html#custom-reports">custom report</a>, the instructions remain the same
as for HTML reports, and the method that you must override is also called as for HTML reports, and the method that you must override is also called
<tt class="docutils literal">_get_report_values</tt>, even when this time you are creating a XML report.</p> <tt class="docutils literal">_get_report_values</tt>, even when this time you are creating a XML report.</p>
<p>You can make your custom report inherit <tt class="docutils literal">report_xml.xsd_checked_report</tt>, name
it like your XML <tt class="docutils literal">&lt;template&gt;</tt> id prepended by <tt class="docutils literal">report.</tt>, add a <tt class="docutils literal">xsd()</tt>
method that returns a XSD in a string, and have XSD automatic checking for
<p>You can make your custom report inherit <tt class="docutils literal">report.report_xml.abstract</tt>, name
it in such way <tt class="docutils literal"><span class="pre">report.&lt;module.report_name&gt;</span></tt>. Also you can add a XSD file for
report validation into <tt class="docutils literal">xsd_schema</tt> field of your report (check
<a class="reference external" href="https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/report.xml">report definition</a>) and have XSD automatic checking for
free.</p> free.</p>
<p>You can customize rendering process and validation way via changing logic of
<tt class="docutils literal">generate_report</tt> and <tt class="docutils literal">validate_report</tt> methods in your report class.</p>
<p>You can visit <tt class="docutils literal"><span class="pre">http://&lt;server-address&gt;/report/xml/&lt;module.report_name&gt;/&lt;ids&gt;</span></tt> <p>You can visit <tt class="docutils literal"><span class="pre">http://&lt;server-address&gt;/report/xml/&lt;module.report_name&gt;/&lt;ids&gt;</span></tt>
to see your XML report online as a web page.</p> to see your XML report online as a web page.</p>
<p>For further information, please visit:</p> <p>For further information, please visit:</p>
@ -434,7 +437,7 @@ to see your XML report online as a web page.</p>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_xml%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_xml%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
@ -443,15 +446,28 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<h2><a class="toc-backref" href="#id6">Authors</a></h2> <h2><a class="toc-backref" href="#id6">Authors</a></h2>
<ul class="simple"> <ul class="simple">
<li>Tecnativa</li> <li>Tecnativa</li>
<li>Avoin.Systems</li>
</ul> </ul>
</div> </div>
<div class="section" id="contributors"> <div class="section" id="contributors">
<h2><a class="toc-backref" href="#id7">Contributors</a></h2> <h2><a class="toc-backref" href="#id7">Contributors</a></h2>
<ul>
<li><p class="first">Enric Tobella &lt;<a class="reference external" href="mailto:etobella&#64;creublanca.es">etobella&#64;creublanca.es</a>&gt;</p>
<ul class="simple">
<li>Enric Tobella &lt;<a class="reference external" href="mailto:etobella&#64;creublanca.es">etobella&#64;creublanca.es</a>&gt;</li>
<li><dl class="first docutils">
<dt><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:</dt>
<dd><ul class="first last">
<li>Jairo Llopis</li>
</ul>
</dd>
</dl>
</li> </li>
<li><p class="first"><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:</p>
<p>Jairo Llopis</p>
<li><dl class="first docutils">
<dt><a class="reference external" href="https://avoin.systems/">Avoin.Systems</a>:</dt>
<dd><ul class="first last">
<li>Tatiana Deribina</li>
</ul>
</dd>
</dl>
</li> </li>
</ul> </ul>
</div> </div>
@ -468,7 +484,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use.</p> promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/report_xml">OCA/reporting-engine</a> project on GitHub.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/13.0/report_xml">OCA/reporting-engine</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p> <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div> </div>
</div> </div>

17
report_xml/static/src/js/report/action_manager_report.js

@ -1,19 +1,18 @@
odoo.define('report_xml.ReportActionManager', function (require) {
'use strict';
odoo.define("report_xml.ReportActionManager", function(require) {
"use strict";
var ActionManager = require('web.ActionManager');
var ActionManager = require("web.ActionManager");
ActionManager.include({ ActionManager.include({
_executeReportAction: function (action, options) {
if (action.report_type === 'qweb-xml') {
return this._triggerDownload(action, options, 'xml');
_executeReportAction: function(action, options) {
if (action.report_type === "qweb-xml") {
return this._triggerDownload(action, options, "xml");
} }
return this._super(action, options); return this._super(action, options);
}, },
_makeReportUrls: function (action) {
_makeReportUrls: function(action) {
var reportUrls = this._super(action); var reportUrls = this._super(action);
reportUrls.xml = reportUrls.text.replace(
'/report/text/', '/report/xml/');
reportUrls.xml = reportUrls.text.replace("/report/text/", "/report/xml/");
return reportUrls; return reportUrls;
}, },
}); });

6
report_xml/tests/test_report_xml.py

@ -13,7 +13,7 @@ class TestXmlReport(common.TransactionCase):
report = report_object._get_report_from_name(report_name) report = report_object._get_report_from_name(report_name)
docs = self.env["res.company"].search([], limit=1) docs = self.env["res.company"].search([], limit=1)
self.assertEqual(report.report_type, "qweb-xml") self.assertEqual(report.report_type, "qweb-xml")
rep = report.render(docs.ids, {})
root = etree.fromstring(rep[0])
el = root.xpath("/root/user/name")
result_report = report.render(docs.ids, {})
result_tree = etree.fromstring(result_report[0])
el = result_tree.xpath("/root/user/name")
self.assertEqual(el[0].text, docs.ensure_one().name) self.assertEqual(el[0].text, docs.ensure_one().name)

32
report_xml/views/ir_actions_report_view.xml

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="ir_actions_report_view_form_report_xml" model="ir.ui.view">
<field name="name">ir.actions.report.view.form.report.xml</field>
<field name="model">ir.actions.report</field>
<field name="inherit_id" ref="base.act_report_xml_view" />
<field name="arch" type="xml">
<button name="associated_view" position="attributes">
<attribute name="attrs">{
'invisible': [
('report_type', 'not in', ('qweb-pdf', 'qweb-html', 'qweb-text', 'qweb-xml')),
],
}</attribute>
</button>
<xpath expr="//page[@name='advanced']/group" position="after">
<group
name="xml_reports"
string="XML Rreport Settings"
attrs="{
'invisible': [
('report_type', '!=', 'qweb-xml')
],
}"
>
<field name="xsd_schema" />
<field name="xml_encoding" />
<field name="xml_declaration" />
</group>
</xpath>
</field>
</record>
</odoo>

13
report_xml/views/ir_actions_views.xml

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="act_report_xml_view" model="ir.ui.view">
<field name="name">ir.actions.report.report.xml</field>
<field name="model">ir.actions.report</field>
<field name="inherit_id" ref="base.act_report_xml_view"/>
<field name="arch" type="xml">
<button name="associated_view" position="attributes">
<attribute name="attrs">{'invisible':[('report_type', 'not in', ['qweb-pdf', 'qweb-html', 'qweb-text', 'qweb-xml'])]}</attribute>
</button>
</field>
</record>
</odoo>

5
report_xml/views/webclient_templates.xml

@ -2,7 +2,10 @@
<odoo> <odoo>
<template id="report_xml.assets_backend" inherit_id="web.assets_backend"> <template id="report_xml.assets_backend" inherit_id="web.assets_backend">
<xpath expr="." position="inside"> <xpath expr="." position="inside">
<script type="text/javascript" src="/report_xml/static/src/js/report/action_manager_report.js"/>
<script
type="text/javascript"
src="/report_xml/static/src/js/report/action_manager_report.js"
/>
</xpath> </xpath>
</template> </template>
</odoo> </odoo>
Loading…
Cancel
Save