Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0] [MIG] report_xml #663

Merged
merged 50 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5d8f0ec
Add module report_xml.
Jun 1, 2015
fdff0c4
Add template utf8_header.
Jun 12, 2015
406b107
Easier XSD checking reports.
Jun 12, 2015
1a060cf
Add sample module.
Jun 12, 2015
3a385af
Sort links.
Jun 12, 2015
1fa4c83
Fix XML tag mismatch.
Jun 12, 2015
8056e8b
Allow docargs to be loaded from context.
Jun 15, 2015
74dd8c2
Only replace the docs key if it is missing.
Jun 15, 2015
067709f
Clearer code comments, add logging.
Jun 15, 2015
6e92184
Oops, this header belongs to other module.
Jun 17, 2015
a7a34e4
Add module report_xml_sample.
Jun 17, 2015
9ab8474
Clean AGPL garbage preserving copyright.
Jul 3, 2015
5879440
Return supers.
Oct 15, 2015
3a1db29
Credit creators, using same name across modules to avoid split statis…
Jan 5, 2016
d26273c
prefix versions with 8.0
sbidoul Oct 8, 2016
de675ef
[MIG] report_xml: Migration to 10.0
etobella Jun 23, 2017
9b002a7
OCA Transbot updated translations from Transifex
oca-transbot Mar 13, 2016
317f074
[MIG] report_xml: Migration to 11.0
etobella Oct 5, 2017
86a96d6
OCA Transbot updated translations from Transifex
oca-transbot Mar 3, 2018
563b6ed
[IMP] report_fillpdf, report_xlsx, report_xml: Use content_dispositio…
naglis Mar 11, 2018
c1e96e4
[FIX] report_xml readme
tarteo Jul 18, 2018
b6c064c
[UPD] Update report_xml.pot
oca-travis Jul 24, 2018
01f4a31
[IMP] report_xml: Clarification in README
pedrobaeza Dec 20, 2018
daa5c1e
report_xml: add custom filename to response headers
ernestotejeda May 24, 2019
3b5cd3e
[MIG] report_xml: Migration to 12.0
ernestotejeda Jun 10, 2019
befc97e
[UPD] Update report_xml.pot
oca-travis Jun 12, 2019
e9f489f
Update translation files
oca-transbot Jun 16, 2019
f36d784
[UPD] README.rst
OCA-git-bot Jul 31, 2019
2ed21f9
[IMP] report_xml: black, isort
Tatider Dec 20, 2019
a5384fc
[MIG][13.0] report_xml: Migration to 13.0
Tatider Dec 23, 2019
21ccdd9
[UPD] Update report_xml.pot
oca-travis Apr 24, 2020
ac4d208
[UPD] README.rst
OCA-git-bot Apr 24, 2020
b66a286
Update translation files
oca-transbot May 13, 2020
7549c95
Update translation files
oca-transbot Aug 16, 2020
183f76c
[IMP] report_xml: black, isort, prettier
ozono Jan 25, 2021
56b4dbe
[MIG] report_xml: Migration to 14.0
ozono Jan 25, 2021
9a4ac44
[UPD] Update report_xml.pot
oca-travis May 26, 2021
5a70c3f
[UPD] README.rst
OCA-git-bot May 26, 2021
de18499
report_xml: context and safe_eval fix
Du-ma Jun 4, 2021
eda0ad7
report_xml 14.0.1.0.1
OCA-git-bot Jun 9, 2021
8eee1e4
[IMP] report_xml: black, isort, prettier
aisopuro Nov 25, 2021
d68d28a
[MIG] report_xml: migrate 14 -> 15
aisopuro Nov 26, 2021
47adac3
[UPD] Update report_xml.pot
Jan 17, 2022
aadf89a
[UPD] README.rst
OCA-git-bot Jan 17, 2022
833c01d
[IMP] report_xml: Promote to Stable
etobella Apr 19, 2022
cda5975
[UPD] README.rst
OCA-git-bot Apr 21, 2022
d62abbe
report_xml 15.0.1.0.1
OCA-git-bot Apr 21, 2022
7c135e3
Translated using Weblate (Catalan)
jabelchi Jun 15, 2022
5da258e
[IMP] report_xml: pre-commit stuff
Du-ma Oct 17, 2022
3dfa12c
[MIG] report_xml: Migration to 16.0
Du-ma Oct 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions report_xml/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
===========
XML Reports
===========

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
:target: https://github.com/OCA/reporting-engine/tree/15.0/report_xml
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/reporting-engine-15-0/reporting-engine-15-0-report_xml
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/143/15.0
:alt: Try me on Runbot

|badge1| |badge2| |badge3| |badge4| |badge5|

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
templates.

**Table of contents**

.. contents::
:local:

Installation
============

To install this module, you need to:

* Install lxml_ in Odoo's ``$PYTHONPATH``.
* Install the repository `reporting-engine`_.

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.

.. _reporting-engine: https://github.com/OCA/reporting-engine
.. _lxml: http://lxml.de/

Usage
=====

This module is intended as a base engine for other modules to use it, so no direct result if you are a user.

If you are a developer
~~~~~~~~~~~~~~~~~~~~~~

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:

* Create a module.
* Make it depend on this one.
* Follow `instructions to create reports`_ having in mind that the
``report_type`` field in your ``ir.actions.report`` record must be
``qweb-xml``.

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
``_get_report_values``, even when this time you are creating a XML report.

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.

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>``
to see your XML report online as a web page.

For further information, please visit:

* https://www.odoo.com/forum/help-1
* https://github.com/OCA/reporting-engine

.. _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
===========

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.
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:%2015.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.

Credits
=======

Authors
~~~~~~~

* Tecnativa
* Avoin.Systems

Contributors
~~~~~~~~~~~~

* Enric Tobella <etobella@creublanca.es>
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis
* `Avoin.Systems <https://avoin.systems/>`_:
* Tatiana Deribina
* Iván Antón <ozono@ozonomultimedia.com>

Other credits
~~~~~~~~~~~~~

* Icon taken from http://commons.wikimedia.org/wiki/File:Text-xml.svg

Maintainers
~~~~~~~~~~~

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/15.0/report_xml>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
6 changes: 6 additions & 0 deletions report_xml/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).

from . import controllers
from . import models
from . import reports
from .hooks import post_init_hook
33 changes: 33 additions & 0 deletions report_xml/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
{
"name": "XML Reports",
"version": "16.0.1.0.0",
"category": "Reporting",
"website": "https://github.com/OCA/reporting-engine",
"development_status": "Production/Stable",
"author": "Tecnativa, Odoo Community Association (OCA), Avoin.Systems",
"license": "AGPL-3",
"installable": True,
"application": False,
"summary": "Allow to generate XML reports",
"depends": ["web"],
"data": [
"views/ir_actions_report_view.xml",
],
"assets": {
"web.assets_backend": [
"report_xml/static/src/js/report/action_manager_report.esm.js",
],
},
"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",
}
3 changes: 3 additions & 0 deletions report_xml/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).

from . import report
90 changes: 90 additions & 0 deletions report_xml/controllers/report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).

import json
import logging

from werkzeug.urls import url_parse

from odoo.http import content_disposition, request, route, serialize_exception
from odoo.tools import html_escape
from odoo.tools.safe_eval import safe_eval, time

from odoo.addons.web.controllers import report

_logger = logging.getLogger(__name__)


class ReportController(report.ReportController):
@route()
def report_routes(
self, reportname, docids=None, converter=None, options=None, **kwargs
):
if converter != "xml":
return super().report_routes(
reportname,
docids=docids,
converter=converter,
options=options,
**kwargs,
)
docids = [int(_id) for _id in (docids or "").split(",")]
data = {**json.loads(options or "{}"), **kwargs}
context = dict(request.env.context)
if "context" in data:
data["context"] = json.loads(data["context"] or "{}")
# Ignore 'lang' here, because the context in data is the one from the
# webclient *but* if the user explicitely wants to change the lang, this
# mechanism overwrites it.
if "lang" in data["context"]:
del data["context"]["lang"]
context.update(data["context"])
report_Obj = request.env["ir.actions.report"]
xml = report_Obj.with_context(**context)._render_qweb_xml(
reportname, docids, data=data
)[0]
xmlhttpheaders = [("Content-Type", "text/xml"), ("Content-Length", len(xml))]
return request.make_response(xml, headers=xmlhttpheaders)

@route()
def report_download(self, data, context=None, token=None):
requestcontent = json.loads(data)
url, report_type = requestcontent[0], requestcontent[1]
reportname = "???"
if report_type != "qweb-xml":
return super().report_download(data, context=context, token=token)
try:
reportname = url.split("/report/xml/")[1].split("?")[0]
docids = None
if "/" in reportname:
reportname, docids = reportname.split("/")
report = request.env["ir.actions.report"]._get_report_from_name(reportname)
filename = None
if docids:
response = self.report_routes(
reportname, docids=docids, converter="xml", context=context
)
ids = [int(x) for x in docids.split(",")]
obj = request.env[report.model].browse(ids)
if report.print_report_name and not len(obj) > 1:
report_name = safe_eval(
report.print_report_name, {"object": obj, "time": time}
)
filename = f"{report_name}.xml"
else:
data = url_parse(url).decode_query(cls=dict)
if "context" in data:
context = json.loads(context or "{}")
data_context = json.loads(data.pop("context"))
context = json.dumps({**context, **data_context})
response = self.report_routes(
reportname, converter="xml", context=context, **data
)
filename = filename or f"{report.name}.xml"
response.headers.add("Content-Disposition", content_disposition(filename))
return response
except Exception as e:
_logger.exception(f"Error while generating report {reportname}")
se = serialize_exception(e)
error = {"code": 200, "message": "Odoo Server Error", "data": se}
return request.make_response(html_escape(json.dumps(error)))
12 changes: 12 additions & 0 deletions report_xml/demo/demo_report.xml
Original file line number Diff line number Diff line change
@@ -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>
25 changes: 25 additions & 0 deletions report_xml/demo/demo_report.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?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>
16 changes: 16 additions & 0 deletions report_xml/demo/report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="demo_xml_report" model="ir.actions.report">
<field name="name">Demo xml report</field>
<field name="model">res.company</field>
<field name="report_type">qweb-xml</field>
<field name="report_name">report_xml.demo_report_xml_view</field>
<field name="report_file">res_company</field>
<!--
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`
-->
<field name="xsd_schema" type="base64" file="report_xml/demo/demo_report.xsd" />
</record>
</odoo>
46 changes: 46 additions & 0 deletions report_xml/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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.
"""
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)
Loading