From 9e5cbd03f670d4b2d3b794ee4257c0d3c86152f7 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 1 Jun 2015 12:43:42 +0200 Subject: [PATCH 01/13] Add module report_xml. --- report_xml/README.rst | 82 + report_xml/__init__.py | 19 + report_xml/__openerp__.py | 32 + report_xml/controllers.py | 40 + report_xml/models.py | 70 + report_xml/static/description/icon.png | Bin 0 -> 4328 bytes report_xml/static/description/icon.svg | 3121 ++++++++++++++++++++++++ 7 files changed, 3364 insertions(+) create mode 100644 report_xml/README.rst create mode 100644 report_xml/__init__.py create mode 100644 report_xml/__openerp__.py create mode 100644 report_xml/controllers.py create mode 100644 report_xml/models.py create mode 100644 report_xml/static/description/icon.png create mode 100644 report_xml/static/description/icon.svg diff --git a/report_xml/README.rst b/report_xml/README.rst new file mode 100644 index 00000000..0a3b88ab --- /dev/null +++ b/report_xml/README.rst @@ -0,0 +1,82 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +Qweb 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 +templates. + +Installation +============ + +To install this module, you need to: + +* Install the repository `reporting-engine`_. + +Configuration +============= + +No manual configuration is needed. + +Usage +===== + +This module is technical, so its usage instructions are intended for module +developers. + +To use 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.xml`` 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 +``render_html``, even when this time you are creating a XML report. + +You can visit http:///report/xml// +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 + +Known issues / Roadmap +====================== + +None + +Credits +======= + +* Icon taken from http://commons.wikimedia.org/wiki/File:Text-xml.svg. + +Contributors +------------ + +* Jairo Llopis + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit http://odoo-community.org. + + +.. _reporting-engine: https://github.com/OCA/reporting-engine +.. _instructions to create reports: https://www.odoo.com/documentation/8.0/reference/reports.html +.. _custom report: https://www.odoo.com/documentation/8.0/reference/reports.html#custom-reports diff --git a/report_xml/__init__.py b/report_xml/__init__.py new file mode 100644 index 00000000..809441f6 --- /dev/null +++ b/report_xml/__init__.py @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- + +# Odoo, Open Source Management Solution +# Copyright (C) 2014-2015 Grupo ESOC +# +# 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 . + +from . import controllers, models diff --git a/report_xml/__openerp__.py b/report_xml/__openerp__.py new file mode 100644 index 00000000..ed9a6eeb --- /dev/null +++ b/report_xml/__openerp__.py @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- + +# Odoo, Open Source Management Solution +# Copyright (C) 2014-2015 Grupo ESOC +# +# 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 . + +{ + "name": "Qweb XML Reports", + "version": "1.0", + "category": "Reporting", + "author": "Odoo Community Association (OCA), Grupo ESOC", + "license": "AGPL-3", + "website": "https://odoo-community.org/", + "installable": True, + "application": False, + "summary": "Allow to generate XML reports", + "depends": [ + "report", + ], +} diff --git a/report_xml/controllers.py b/report_xml/controllers.py new file mode 100644 index 00000000..a8ffb04f --- /dev/null +++ b/report_xml/controllers.py @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +# Odoo, Open Source Management Solution +# Copyright (C) 2014-2015 Grupo ESOC +# +# 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 . + +from openerp.http import route +from openerp.addons.report.controllers import main as report + + +class ReportController(report.ReportController): + @route() + def report_routes(self, reportname, docids=None, converter=None, **data): + # Trick the main reporter to think we want an HTML report + new_converter = converter if converter != "xml" else "html" + response = super(ReportController, self).report_routes( + reportname, docids, new_converter, **data) + + # If it was an XML report, just download the generated response + if converter == "xml": + # XML header must be before any spaces, and it is a common error, + # so let's fix that here and make developers happier + response.data = response.data.strip() + + # XML files should be downloaded + response.headers.set("Content-Type", "text/xml") + + return response diff --git a/report_xml/models.py b/report_xml/models.py new file mode 100644 index 00000000..168e4de9 --- /dev/null +++ b/report_xml/models.py @@ -0,0 +1,70 @@ +# -*- encoding: utf-8 -*- + +# Odoo, Open Source Management Solution +# Copyright (C) 2014-2015 Grupo ESOC +# +# 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 . + +from openerp import api, fields, models + + +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: + 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 AS59n3B5_s&=I5v_fjq$RC@1H zLs5iFM3w#VD=Yv2fZfOtVosag{&c2` zv=OtMW=WeEa9|@#CRz(&a*L+znK6d8H~`>6<)3~bo)LeSCKSZ$+u$wG?s$I}EDYf9 z@2>#&M&O_>7?=VY>+v^5^9l{b@dsoH$0K0?JS+e&8h}F9tfa`&Gy;D#y1sZ%G!|fh zb@2{@;}9;Q78tZQ4u#h2 z!=SNv1)QIUwkV)GevxLF|BqokEX?JPRZ&Yg3I;ItMFxs0D=MnnhhPI}5cB^aXiOj$ z?%|0C=;?{-;_+CxtM8v9@)n-7py(pu2$<;qyoLUEn;#5{MxkgN|HKG{ghOF8x;T() zpghh6q@th*a*DKT0{}SXjUc*~0a+W_fl0!Xp(LHnc1lk6?EI|0ospq1Fv{(!bF_@8 zLOjX`A|P|=NfnQD8NZC$r!`pR?dm+o^7Z5R z>0K8M)iKMz`Xgo>0HX?Iu$-%{E%mS5Mj*_*n}R2zR%S#B~;)&;x89X0`sT*)BYBR z>}fzBVEUg8hTYV@#BDNSA^3WGyBh2y0Lfb~=#CDibes&6xxpE~Q18s94SqH}AOb7V|S zTd$|5t?G=?VOrlfZm`TKHC5*N1;wrWm1gy#v|qR0@hsQN z{aVD$BsUDU;Vypk+T4j~7O<(N(0*we6T~ zJ|$bDTgwGIQ&bGSJEzEGM3^2M|ZAme8w8pl9h7i>7ziOy#9s+~FudC_CoQ~qAOSQVj+`Lk9_mUM8d6||2MNlYI zq4|w;dHeo1X|lExD;?PC@tML#3hyruNSmqy2C zyK0I|RwVmeF*vIo_?iA0q&rVO z^Zl-aT#@Id;n;X>5@ozaJ)lrWrzHMSVo1A#{r4B5W)+RSxht}t^v5&{EsvdE>3z4J z$m0zXUrM5^-@6gT4ZxE*@! z)2_f3k^WsxxnaBFK_s2XK$`MqkYR?GR^BUlV52Hb`ez&Ujl--RBK1{W$*a1?lAk|4 zOKNK)X)L6Qm1hHxL3?BOQ=0L+4N=c;?4{3XNi?pM3rjco%`Xx=f)@ewk@QC$FE@{y za)kD{$RvT$Ig;Ck5d6mTBz&QHJh#oU`H=T?cAMalLY6q;9yF}FO09SRls?EnU}NW0 zxuq#w35<}Zdj`F+V+BlQ*%`XFCFY{0;xw|q?M@BP)q<6*22f?bRwhiEV!D}I*9xYW za5D*@RK1fHgjvkx{`YhB{8a(l%cl={!Oou}uDvTSXBT4_ViA5lWZq;UXh0&VVOJDS z4mO||jA$JRdI#clFtl0C*CmuXf|Li#eQAoho;wF_)4EclXFVnocQDrB{wc?CJ;cYO z;>TaXl(~1$x%%mnh}ZA7ZWJNY4&536;gN;+YPiRu8Rj=JWY&n0=A9Sr z8!fD~aDT6#c4FkR7n#ROVMLXqWJs?2zOVDvE!@4zVw8xD{%u1m+mGYL5OEWYZXBns zcRDtIFmi)2+kKtsJPc*9GEu*7=3d2%DKYiA%9Y&d31%$PY0f)GGF)=6dm0S4!$Rv9 z3R1zw5tX;Q`DflJ0*#)smR1e@o5Iti6COzX>$ZROlM20@21TGXyxzKvWtf=W-jMo& zPaOR%3ZC%LH%W!9_DS#T-HMf~1IK-_aAxyMUBW;QbC7B!7f_nNBz1>S$JcowFx+a! zhD~Zeb1N=Q=-hRmYi#O;O+c7f>v^M+#qD<%VoAeO{F5dHWKL_|nHww1x5p}_FDlUo zBc`Q8FXq?cr7f@hRzJ!#%y6jTa2tJ~avLa19TMiz+_>k*;(_a&ZR~^QjfX{uB_#g`;PZ?47%H%bm)E8@n(GAvG=G79U`~WE;uvXEAeCU-AmjqPw8%@ zJag_(EmoC1?{mAHFfml)8AI0lo{i1Wh%&UJl?v6%GDmNSRQ{cRxOumycjw^Eej}u! z+{9Z~p}iDKrx6qCi0&AsUo>6R4u2{(L~2Zz8fhm*P|{6H-9XuRV)} zu6^ZEP4=X*&@^oDt)f5@P_ij`X@c&ANV=&{>ew-b{EpvZBevG^tDHK0teKd5WK9j* zPdFBn;cG6b`Y>*jqTCvh{BCXLqJp$@bG!s0BjmZ~lZlh?_)dhq7`>R;k1)9=^*+>3 z8^T#~FiU%n=Z68^FZ|cazHFH})K?Hi5onhA72<+Nj?1t4f|o>Ip5VxvyX)DD{9i}{ z387~N|Kx{(g1_o@Wn`~i1uttK!Uin2cZkbFMf?(`_K&r5vLWTa)!h77WvX9264^fZ zX~K9@szKD<8MI(RmSbRwS+|YxUG-qily7H3oLwUV;d@=VOYOhs1sE?AFV`Ow*F2sW zN^q7oS^mT)AtBMWJF-wi8XYw=E3er#DViU=D7`OCNjy>FiA?sH?KlX7*z*Gp_FqDB z?ZkXK5BmaCL5CAU305v5kJq$q1&Vv+*0uQ)7VQuYsul+W9Sb~?an0;m!4}F79Ltq? zBAYZQoa}%Hy4Q1k%Jb>1+e&&5P`9d($ZpUMUUHKidJ!I zDIrRab;0N*tM1^{zcZknOj`RFPhvGN-XU^8;=w=&HRrB<(nFBjAVD{K_b~*kTT!(C zEf`oRLNr9$-AmHOou7GyhHhRV7`%C^Gb>d*p1qe99=6|fdmzRPV`%^naQ~pWs~?-t zwnc`9fgiP=NlbwiXOApz!^aV8r= z9nS;ZJ`I6C`H{bKheajU)$-5EMYiye z%An$RO9RQ9m8h$$@Vne&Z3L(Ac**fMOLbagZMCXba{IdUt#a>3ZWg6+do569yVx0-dHuwGMnxGuc$ma3fLte4|- zc>FQB@saU?c8!qflzwhmrS-z)^S>Y6C+tN~yW)l4fO6Fh--($h*kxY@W6y6UP{LU^ zsW~z+Yue$UsTa8%Y!L3=`pPv{>-*lPm8T_W z&@5*rdp^Ok^jYYc#27#8^WM_)MIj7Ep<=oc&OI zF1Xm9oD%yZP5YV3Ltov(?v5qIm?D(0@HpXv4CSB_60c87G4xR!+_GNR9s1V)Vws&i z;!J*ETt|R;*Xi7EYsj6wEjLV7k+0{NmWjRHX|r!<=l1{ZXE6KP{*Fg?tWYEy(l$+H z?;NmliG5v=HY$=59?abB6<6#}x{wjDwO6y`vmJg+FC`LvzKpCM%Q!wHbMo=CJNGBP zCs@@>j3`b%vCSM?)e@#K6n75|Jzz^`f0?j3^#M8uyX+&rp7=`HG=Lc=Xfe}siA84+ zPX}lI*9}5^ce*7hnIGzO&g2_vGy54=!>+farnWZqIwmaE{5yLOk3NLU-!-=D?7rt( z)^TT9#@i!W;#WKGr+-$Gi-OHc0!QkGYXR{e&gz<%-ajH|`4#V`RaYw|UQ;tWXk}#O zs|xUeex7oXd{#ZncP$6MSnF=+BT7hK z{W?n7^f%`v+P6L^h;K4+W<@e3q1iK5eU(7_Z@wCI+lVe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + July 2009 + + + Franziska Sponsel + + + + + Franziska Sponsel + + + + + RRZE + + + + + export + csv + text + + + + + Hendrik Eggers, Beate Kaspar + + + uses <http://ftp.uni-erlangen.de/pub/rrze/tango/rrze-icon-set/tango/scalable/emblems/report.svg> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 43e8ad297c1ee9bb5313f44bc5f04e809870c0d7 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 12 Jun 2015 11:09:09 +0200 Subject: [PATCH 02/13] Add template utf8_header. Almost any XML must start with this. Let's make it easier. --- report_xml/__openerp__.py | 3 +++ report_xml/views/report_xml_templates.xml | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 report_xml/views/report_xml_templates.xml diff --git a/report_xml/__openerp__.py b/report_xml/__openerp__.py index ed9a6eeb..e2f73bee 100644 --- a/report_xml/__openerp__.py +++ b/report_xml/__openerp__.py @@ -29,4 +29,7 @@ "depends": [ "report", ], + "data": [ + "views/report_xml_templates.xml", + ] } diff --git a/report_xml/views/report_xml_templates.xml b/report_xml/views/report_xml_templates.xml new file mode 100644 index 00000000..8a7c88ab --- /dev/null +++ b/report_xml/views/report_xml_templates.xml @@ -0,0 +1,13 @@ + + + + + + + + From 357d37dae038b4ac35254075b4f4e88c33449817 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 12 Jun 2015 11:10:00 +0200 Subject: [PATCH 03/13] Easier XSD checking reports. Any report inheriting this AbstractModel can check its XML results against any XSD. --- report_xml/README.rst | 2 ++ report_xml/models.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/report_xml/README.rst b/report_xml/README.rst index 0a3b88ab..b0969641 100644 --- a/report_xml/README.rst +++ b/report_xml/README.rst @@ -13,6 +13,7 @@ Installation To install this module, you need to: +* Install lxml_ in Odoo's ``$PYTHONPATH``. * Install the repository `reporting-engine`_. Configuration @@ -80,3 +81,4 @@ To contribute to this module, please visit http://odoo-community.org. .. _reporting-engine: https://github.com/OCA/reporting-engine .. _instructions to create reports: https://www.odoo.com/documentation/8.0/reference/reports.html .. _custom report: https://www.odoo.com/documentation/8.0/reference/reports.html#custom-reports +.. _lxml: http://lxml.de/ diff --git a/report_xml/models.py b/report_xml/models.py index 168e4de9..47e1b874 100644 --- a/report_xml/models.py +++ b/report_xml/models.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from lxml import etree from openerp import api, fields, models @@ -68,3 +69,33 @@ class ReportGenerator(models.Model): 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..``. + """ + _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.""" + docargs = {"docs": (self.env[self.env.context["active_model"]] + .browse(self.env.context["active_ids"]))} + xsd = etree.XMLSchema(etree.XML(self.xsd())) + parser = etree.XMLParser(schema=xsd) + result = (self.env["report"] + .render(self._name[len("report."):], docargs) + .strip()) + etree.fromstring(result, parser) + + return result From ae447728babfb475ff565af91217234574371bc3 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 12 Jun 2015 11:15:17 +0200 Subject: [PATCH 04/13] Add sample module. --- report_xml/README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/report_xml/README.rst b/report_xml/README.rst index b0969641..e8d2b380 100644 --- a/report_xml/README.rst +++ b/report_xml/README.rst @@ -42,6 +42,9 @@ as for HTML reports, and the method that you must override is also called You can visit http:///report/xml// to see your XML report online as a web page. +If you are a developer and you want a sample module to know how to use this +reporting engine, you can review `l10n_es_training`_. + For further information, please visit: * https://www.odoo.com/forum/help-1 @@ -81,4 +84,5 @@ To contribute to this module, please visit http://odoo-community.org. .. _reporting-engine: https://github.com/OCA/reporting-engine .. _instructions to create reports: https://www.odoo.com/documentation/8.0/reference/reports.html .. _custom report: https://www.odoo.com/documentation/8.0/reference/reports.html#custom-reports +.. _l10n_es_training: https://github.com/grupoesoc/l10n-spain/tree/l10n_es_training/l10n_es_training .. _lxml: http://lxml.de/ From fe6f0cc213573dc331617fb5e1c9a9c59ae4183f Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 12 Jun 2015 11:15:28 +0200 Subject: [PATCH 05/13] Sort links. --- report_xml/README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/report_xml/README.rst b/report_xml/README.rst index e8d2b380..6849c1e2 100644 --- a/report_xml/README.rst +++ b/report_xml/README.rst @@ -81,8 +81,8 @@ promote its widespread use. To contribute to this module, please visit http://odoo-community.org. -.. _reporting-engine: https://github.com/OCA/reporting-engine -.. _instructions to create reports: https://www.odoo.com/documentation/8.0/reference/reports.html .. _custom report: https://www.odoo.com/documentation/8.0/reference/reports.html#custom-reports +.. _instructions to create reports: https://www.odoo.com/documentation/8.0/reference/reports.html +.. _reporting-engine: https://github.com/OCA/reporting-engine .. _l10n_es_training: https://github.com/grupoesoc/l10n-spain/tree/l10n_es_training/l10n_es_training .. _lxml: http://lxml.de/ From 40adb5bbc76d642a4ec7bea0a30684a66350b56a Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 12 Jun 2015 11:39:14 +0200 Subject: [PATCH 06/13] Fix XML tag mismatch. --- report_xml/views/report_xml_templates.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/report_xml/views/report_xml_templates.xml b/report_xml/views/report_xml_templates.xml index 8a7c88ab..facfc328 100644 --- a/report_xml/views/report_xml_templates.xml +++ b/report_xml/views/report_xml_templates.xml @@ -9,5 +9,5 @@ - + From 93506ece59b445123057bba4ea5db4bfd3403b82 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 15 Jun 2015 11:49:43 +0200 Subject: [PATCH 07/13] Allow docargs to be loaded from context. --- report_xml/models.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/report_xml/models.py b/report_xml/models.py index 47e1b874..498346ad 100644 --- a/report_xml/models.py +++ b/report_xml/models.py @@ -89,8 +89,9 @@ class XSDCheckedReport(models.AbstractModel): @api.multi def render_html(self, data=None): """Return the XML report after checking it against an XSD.""" - docargs = {"docs": (self.env[self.env.context["active_model"]] - .browse(self.env.context["active_ids"]))} + docargs = self.env.context.get("docargs", dict()) + docargs["docs"] = (self.env[self.env.context["active_model"]] + .browse(self.env.context["active_ids"])) xsd = etree.XMLSchema(etree.XML(self.xsd())) parser = etree.XMLParser(schema=xsd) result = (self.env["report"] From 2c2cf1904ca62dea27a360ec8cf1d2d0fa3588ff Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 15 Jun 2015 12:35:39 +0200 Subject: [PATCH 08/13] Only replace the docs key if it is missing. --- report_xml/models.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/report_xml/models.py b/report_xml/models.py index 498346ad..c8234238 100644 --- a/report_xml/models.py +++ b/report_xml/models.py @@ -88,11 +88,16 @@ class XSDCheckedReport(models.AbstractModel): @api.multi def render_html(self, data=None): - """Return the XML report after checking it against an XSD.""" + """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. docargs = self.env.context.get("docargs", dict()) - docargs["docs"] = (self.env[self.env.context["active_model"]] - .browse(self.env.context["active_ids"])) xsd = etree.XMLSchema(etree.XML(self.xsd())) + if "docs" not in docargs: + docargs["docs"] = (self.env[self.env.context["active_model"]] + .browse(self.env.context["active_ids"])) parser = etree.XMLParser(schema=xsd) result = (self.env["report"] .render(self._name[len("report."):], docargs) From 3d5a0cb68da18657187b46b94d80b9d5186793bf Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 15 Jun 2015 12:36:01 +0200 Subject: [PATCH 09/13] Clearer code comments, add logging. --- report_xml/models.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/report_xml/models.py b/report_xml/models.py index c8234238..c83017a7 100644 --- a/report_xml/models.py +++ b/report_xml/models.py @@ -16,10 +16,14 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +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" @@ -93,15 +97,29 @@ class XSDCheckedReport(models.AbstractModel): 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()) - xsd = etree.XMLSchema(etree.XML(self.xsd())) 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()) - etree.fromstring(result, parser) + + # Validate XML with XSD + try: + etree.fromstring(result, parser) + except Exception as error: + _logger.error(result) + raise error return result From 6e15df4ae1a7f203231193c6b209f331120caf6b Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 17 Jun 2015 11:03:40 +0200 Subject: [PATCH 10/13] Oops, this header belongs to other module. --- report_xml/views/report_xml_templates.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/report_xml/views/report_xml_templates.xml b/report_xml/views/report_xml_templates.xml index facfc328..811eddec 100644 --- a/report_xml/views/report_xml_templates.xml +++ b/report_xml/views/report_xml_templates.xml @@ -4,9 +4,7 @@ From 8c53e967efbb6899b44dedf4b9a3d40ca33a5aa0 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 17 Jun 2015 11:09:52 +0200 Subject: [PATCH 11/13] Add module report_xml_sample. --- report_xml/README.rst | 29 +- report_xml_sample/README.rst | 69 + report_xml_sample/__init__.py | 19 + report_xml_sample/__openerp__.py | 36 + report_xml_sample/models.py | 39 + report_xml_sample/static/description/icon.png | Bin 0 -> 6825 bytes report_xml_sample/static/description/icon.svg | 3131 +++++++++++++++++ .../views/res_partner_templates.xml | 43 + report_xml_sample/xsd/sample_report.xsd | 22 + 9 files changed, 3380 insertions(+), 8 deletions(-) create mode 100644 report_xml_sample/README.rst create mode 100644 report_xml_sample/__init__.py create mode 100644 report_xml_sample/__openerp__.py create mode 100644 report_xml_sample/models.py create mode 100644 report_xml_sample/static/description/icon.png create mode 100644 report_xml_sample/static/description/icon.svg create mode 100644 report_xml_sample/views/res_partner_templates.xml create mode 100644 report_xml_sample/xsd/sample_report.xsd diff --git a/report_xml/README.rst b/report_xml/README.rst index 6849c1e2..564bedf3 100644 --- a/report_xml/README.rst +++ b/report_xml/README.rst @@ -16,6 +16,9 @@ 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. + Configuration ============= @@ -24,10 +27,18 @@ No manual configuration is needed. Usage ===== -This module is technical, so its usage instructions are intended for module -developers. +If you are a user +----------------- + +You will be able to download XML reports from the *Print* menu found on form +and list views. + +If you are a developer +---------------------- -To use this module, you need to: +To learn from an example, just check the `sample module`_. + +To develop with this module, you need to: * Create a module. * Make it depend on this one. @@ -39,11 +50,13 @@ 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 ``render_html``, even when this time you are creating a XML report. -You can visit http:///report/xml// -to see your XML report online as a web page. +You can make your custom report inherit ``report_xml.xsd_checked_report``, name +it like your XML ``