improved
[odoo/odoo.git] / bin / report / custom.py
index f7ff899..4b02901 100644 (file)
@@ -1,22 +1,21 @@
-# -*- encoding: utf-8 -*-
+# -*- coding: utf-8 -*-
 ##############################################################################
-#
-#    OpenERP, Open Source Management Solution  
-#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
-#    $Id$
+#    
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
 #
 #    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
+#    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 General Public License for more details.
+#    GNU Affero General Public License for more details.
 #
-#    You should have received a copy of the GNU General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
 #
 ##############################################################################
 
@@ -25,6 +24,7 @@ import time
 import netsvc
 
 import tools
+from tools.safe_eval import safe_eval as eval
 import print_xml
 import render
 from interface import report_int
@@ -33,12 +33,11 @@ from osv.osv import except_osv
 from osv.orm import browse_null
 from osv.orm import browse_record_list
 import pooler
-from xml.dom import minidom
-import libxml2
-import libxslt
 from pychart import *
 import misc
 import cStringIO
+from lxml import etree
+from tools.translate import _
 
 class external_pdf(render.render):
     def __init__(self, pdf):
@@ -74,7 +73,7 @@ class report_custom(report_int):
             for cond in conditions:
                 if cond and cond[0]:
                     c = cond[0]
-                    temp = c[0](eval('obj.'+c[1]))
+                    temp = c[0](eval('obj.'+c[1],{'obj': obj}))
                     if not eval('\''+temp+'\''+' '+c[2]+' '+'\''+str(c[3])+'\''):
                         tobreak = True
             if tobreak:
@@ -88,7 +87,7 @@ class report_custom(report_int):
                         row_canvas[i]=False
                 elif len(fields[i])==1:
                     if not isinstance(obj, browse_null):
-                        row.append(str(eval('obj.'+fields[i][0])))
+                        row.append(str(eval('obj.'+fields[i][0],{'obj': obj})))
                     else:
                         row.append(None)
                 else:
@@ -108,7 +107,7 @@ class report_custom(report_int):
                 else:
                     key = levels.keys()
                 for l in key:
-                    objs = eval('obj.'+l)
+                    objs = eval('obj.'+l,{'obj': obj})
                     if not isinstance(objs, browse_record_list) and type(objs) <> type([]):
                         objs = [objs]
                     field_new = []
@@ -193,7 +192,7 @@ class report_custom(report_int):
             def build_tree(obj, level, depth):
                 res = self._row_get(cr, uid,[obj], new_fields, new_cond)
                 level.append(depth)
-                new_obj = eval('obj.'+report['field_parent'][1])
+                new_obj = eval('obj.'+report['field_parent'][1],{'obj': obj})
                 if not isinstance(new_obj, list) :
                     new_obj = [new_obj]
                 for o in  new_obj:
@@ -287,17 +286,13 @@ class report_custom(report_int):
         if report['print_orientation']=='landscape':
             pageSize=[pageSize[1],pageSize[0]]
 
-        impl = minidom.getDOMImplementation()
-        new_doc = impl.createDocument(None, "report", None)
+        new_doc = etree.Element('report')
         
-        # build header
-        config = new_doc.createElement("config")
+        config = etree.SubElement(new_doc, 'config')
 
         def _append_node(name, text):
-            n = new_doc.createElement(name)
-            t = new_doc.createTextNode(text)
-            n.appendChild(t)
-            config.appendChild(n)
+            n = etree.SubElement(config, name)
+            n.text = text
 
         _append_node('date', time.strftime('%d/%m/%Y'))
         _append_node('PageFormat', '%s' % report['print_format'])
@@ -317,45 +312,33 @@ class report_custom(report_int):
         _append_node('report-header', '%s' % (report['title'],))
         _append_node('report-footer', '%s' % (report['footer'],))
 
-        new_doc.childNodes[0].appendChild(config)
-        header = new_doc.createElement("header")
-        
+        header = etree.SubElement(new_doc, 'header')
         for f in fields:
-            field = new_doc.createElement("field")
-            field_txt = new_doc.createTextNode('%s' % (f['name'],))
-            field.appendChild(field_txt)
-            header.appendChild(field)
-        
-        new_doc.childNodes[0].appendChild(header)
+            field = etree.SubElement(header, 'field')
+            field.text = f['name']
 
-        lines = new_doc.createElement("lines")
+        lines = etree.SubElement(new_doc, 'lines')
         level.reverse()
         for line in results:
             shift = level.pop()
-            node_line = new_doc.createElement("row")
+            node_line = etree.SubElement(lines, 'row')
             prefix = '+'
             for f in range(len(fields)):
-                col = new_doc.createElement("col")
+                col = etree.SubElement(node_line, 'col')
                 if f == 0:
-                    col.setAttribute('para','yes')
-                    col.setAttribute('tree','yes')
-                    col.setAttribute('space',str(3*shift)+'mm')
+                    col.attrib.update(para='yes',
+                                      tree='yes',
+                                      space=str(3*shift)+'mm')
                 if line[f] != None:
-                    txt = new_doc.createTextNode(prefix+str(line[f]) or '')
+                    col.text = prefix+str(line[f]) or ''
                 else:
-                    txt = new_doc.createTextNode('/')
-                col.appendChild(txt)
-                node_line.appendChild(col)
+                    col.text = '/'
                 prefix = ''
-            lines.appendChild(node_line)
-            
-        new_doc.childNodes[0].appendChild(lines)
 
-        styledoc = libxml2.parseFile(os.path.join(tools.config['root_path'],'addons/base/report/custom_new.xsl'))
-        style = libxslt.parseStylesheetDoc(styledoc)
-        doc = libxml2.parseDoc(new_doc.toxml())
-        rml_obj = style.applyStylesheet(doc, None)
-        rml = style.saveResultToString(rml_obj) 
+        transform = etree.XSLT(
+            etree.parse(os.path.join(tools.config['root_path'],
+                                     'addons/base/report/custom_new.xsl')))
+        rml = etree.tostring(transform(new_doc))
 
         self.obj = render.rml(rml)
         self.obj.render()
@@ -554,6 +537,7 @@ class report_custom(report_int):
                 abscissa.update(fields_bar[idx])
             idx0 += 1
         abscissa = map(lambda x : [x, None], abscissa)
+        abscissa.sort()
         ar.x_coord = category_coord.T(abscissa,0)
         ar.draw(can)
 
@@ -591,17 +575,12 @@ class report_custom(report_int):
         if report['print_orientation']=='landscape':
             pageSize=[pageSize[1],pageSize[0]]
 
-        impl = minidom.getDOMImplementation()
-        new_doc = impl.createDocument(None, "report", None)
-        
-        # build header
-        config = new_doc.createElement("config")
+        new_doc = etree.Element('report')
+        config = etree.SubElement(new_doc, 'config')
 
         def _append_node(name, text):
-            n = new_doc.createElement(name)
-            t = new_doc.createTextNode(text)
-            n.appendChild(t)
-            config.appendChild(n)
+            n = etree.SubElement(config, name)
+            n.text = text
 
         _append_node('date', time.strftime('%d/%m/%Y'))
         _append_node('PageSize', '%.2fmm,%.2fmm' % tuple(pageSize))
@@ -621,40 +600,25 @@ class report_custom(report_int):
         _append_node('report-header', '%s' % (report['title'],))
         _append_node('report-footer', '%s' % (report['footer'],))
 
-        new_doc.childNodes[0].appendChild(config)
-        header = new_doc.createElement("header")
-        
+        header = etree.SubElement(new_doc, 'header')
         for f in fields:
-            field = new_doc.createElement("field")
-            field_txt = new_doc.createTextNode('%s' % (f['name'],))
-            field.appendChild(field_txt)
-            header.appendChild(field)
-        
-        new_doc.childNodes[0].appendChild(header)
+            field = etree.SubElement(header, 'field')
+            field.text = f['name']
 
-        lines = new_doc.createElement("lines")
+        lines = etree.SubElement(new_doc, 'lines')
         for line in results:
-            node_line = new_doc.createElement("row")
+            node_line = etree.SubElement(lines, 'row')
             for f in range(len(fields)):
-                col = new_doc.createElement("col")
-                col.setAttribute('tree','no')
+                col = etree.SubElement(node_line, 'col', tree='no')
                 if line[f] != None:
-                    txt = new_doc.createTextNode(str(line[f] or ''))
+                    col.text = line[f] or ''
                 else:
-                    txt = new_doc.createTextNode('/')
-                col.appendChild(txt)
-                node_line.appendChild(col)
-            lines.appendChild(node_line)    
-            
-        new_doc.childNodes[0].appendChild(lines)
-
-#       file('/tmp/terp.xml','w+').write(new_doc.toxml())
-
-        styledoc = libxml2.parseFile(os.path.join(tools.config['root_path'],'addons/base/report/custom_new.xsl'))
-        style = libxslt.parseStylesheetDoc(styledoc)
-        doc = libxml2.parseDoc(new_doc.toxml())
-        rml_obj = style.applyStylesheet(doc, None)
-        rml = style.saveResultToString(rml_obj) 
+                    col.text = '/'
+
+        transform = etree.XSLT(
+            etree.parse(os.path.join(tools.config['root_path'],
+                                     'addons/base/report/custom_new.xsl')))
+        rml = etree.tostring(transform(new_doc))
 
         self.obj = render.rml(rml)
         self.obj.render()