~openerp-community/openobject-addons/taktik

« back to all changes in this revision

Viewing changes to report_openoffice/report_openoffice.py

  • Committer: Fabien Lydoire
  • Date: 2010-06-18 09:43:14 UTC
  • Revision ID: fl@taktik.be-20100618094314-rsei1ysqf6uwz6nf
added account reports in xls

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- encoding: utf-8 -*-
 
2
 
 
3
#########################################################################
 
4
#                                                                       #
 
5
# Copyright (C) 2009  Domsense s.r.l.                                   #
 
6
# @authors: Simone Orsi, KN dati Ltd (www.kndati.lv)                    #
 
7
#                                                                       #
 
8
#This program is free software: you can redistribute it and/or modify   #
 
9
#it under the terms of the GNU General Public License as published by   #
 
10
#the Free Software Foundation, either version 3 of the License, or      #
 
11
#(at your option) any later version.                                    #
 
12
#                                                                       #
 
13
#This program is distributed in the hope that it will be useful,        #
 
14
#but WITHOUT ANY WARRANTY; without even the implied warranty of         #
 
15
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
 
16
#GNU General Public License for more details.                           #
 
17
#                                                                       #
 
18
#You should have received a copy of the GNU General Public License      #
 
19
#along with this program.  If not, see <http://www.gnu.org/licenses/>.  #
 
20
#########################################################################
 
21
 
 
22
import os
 
23
import tempfile
 
24
import report
 
25
from report.report_sxw import *
 
26
import zipfile
 
27
import StringIO
 
28
from xml.dom import minidom
 
29
import base64
 
30
from osv import osv
 
31
from tools.translate import _
 
32
import time
 
33
 
 
34
from relatorio.templates.opendocument import Template
 
35
#from genshi.filters import Translator
 
36
import pooler
 
37
 
 
38
import netsvc
 
39
logger = netsvc.Logger()
 
40
 
 
41
try:
 
42
    from report_openoffice_pdf.DocumentConverter import DocumentConverter
 
43
except Exception, e:
 
44
    DocumentConverter = False
 
45
 
 
46
from ExtraFunctions import ExtraFunctions
 
47
 
 
48
from tools import debug
 
49
 
 
50
class OpenOffice_parser(report_sxw):
 
51
 
 
52
    def __init__(self, name, table, rml=False, parser=False, header=True, store=False):
 
53
        report_sxw.__init__(self, name, table, rml, parser, header, store)
 
54
 
 
55
    def _doc_optimized(self, cr, uid, data, document):
 
56
        pool = pooler.get_pool(cr.dbname)
 
57
        out_oo = StringIO.StringIO()
 
58
        in_oo = StringIO.StringIO(document)
 
59
        inzip = zipfile.ZipFile(in_oo, mode='r')
 
60
        content_data = inzip.read('content.xml')
 
61
        styles_data = inzip.read('styles.xml')
 
62
        meta_data = inzip.read('meta.xml')
 
63
        manifest_data = inzip.read('META-INF/manifest.xml')
 
64
        ##### manifest.xml editing #####
 
65
        manifestdoc = minidom.parseString(manifest_data)
 
66
        manifest = [x.getAttribute("manifest:full-path") for x in manifestdoc.getElementsByTagName('manifest:file-entry') \
 
67
                            if x.getAttribute("manifest:media-type")!="\\"]
 
68
        namelist = filter(lambda a: a not in ('META-INF/manifest.xml','mimetype'), inzip.namelist())
 
69
        thumbnails_nodes = filter(lambda a: a.getAttribute("manifest:full-path").startswith("Thumbnails"), \
 
70
                                    manifestdoc.getElementsByTagName('manifest:file-entry'))
 
71
        for thmb in thumbnails_nodes:
 
72
            manifestdoc.firstChild.removeChild(thmb)
 
73
        ################################
 
74
        for name in namelist:
 
75
            if name not in manifest:
 
76
                dirname = os.path.dirname(name)
 
77
                if dirname not in manifest:
 
78
                    newNode = manifestdoc.createElement("manifest:file-entry")
 
79
                    newNode.setAttribute("manifest:media-type", "")
 
80
                    newNode.setAttribute("manifest:full-path", dirname+"/")
 
81
                    manifestdoc.firstChild.appendChild(newNode)
 
82
                    manifest.append(dirname)                
 
83
                newNode = manifestdoc.createElement("manifest:file-entry")
 
84
                newNode.setAttribute("manifest:media-type", "")
 
85
                newNode.setAttribute("manifest:full-path", name)
 
86
                manifestdoc.firstChild.appendChild(newNode)
 
87
        ################################
 
88
 
 
89
        ####### meta.xml editing #######
 
90
        metadoc = minidom.parseString(meta_data)
 
91
        user_name = pool.get('res.users').browse(cr, uid, uid, {}).name
 
92
        model_id = pool.get('ir.model').search(cr, uid, [('model','=',data['model'])])[0]
 
93
        model_name = pool.get('ir.model').browse(cr, uid, model_id).name
 
94
        if metadoc.getElementsByTagName('meta:creation-date'):
 
95
            cdate_node = metadoc.getElementsByTagName('meta:creation-date')[0].childNodes[0]
 
96
            cdate_node.nodeValue=time.strftime('%Y-%m-%dT%H:%M:%S')
 
97
        else:
 
98
            newNode=metadoc.createElement("meta:creation-date")
 
99
            newText=metadoc.createTextNode(time.strftime('%Y-%m-%dT%H:%M:%S'))
 
100
            newNode.appendChild(newText)
 
101
        if metadoc.getElementsByTagName('dc:date'):
 
102
            date_node = metadoc.getElementsByTagName('dc:date')[0].childNodes[0]
 
103
            date_node.nodeValue=time.strftime('%Y-%m-%dT%H:%M:%S')
 
104
        else:
 
105
            newNode=metadoc.createElement("dc:date")
 
106
            newText=metadoc.createTextNode(time.strftime('%Y-%m-%dT%H:%M:%S'))
 
107
            newNode.appendChild(newText)
 
108
        if metadoc.getElementsByTagName('meta:editing-cycles'):
 
109
            date_node = metadoc.getElementsByTagName('meta:editing-cycles')[0].childNodes[0]
 
110
            date_node.nodeValue=1
 
111
        else:
 
112
            newNode=metadoc.createElement("meta:editing-cycles")
 
113
            newText=metadoc.createTextNode(1)
 
114
            newNode.appendChild(newText)
 
115
        if metadoc.getElementsByTagName('dc:creator'):
 
116
            date_node = metadoc.getElementsByTagName('dc:creator')[0].childNodes[0]
 
117
            date_node.nodeValue=user_name
 
118
        else:
 
119
            newNode=metadoc.createElement("dc:creator")
 
120
            newText=metadoc.createTextNode(user_name)
 
121
            newNode.appendChild(newText)
 
122
        if metadoc.getElementsByTagName('dc:title'):
 
123
            date_node = metadoc.getElementsByTagName('dc:title')[0].childNodes[0]
 
124
            date_node.nodeValue=model_name
 
125
        else:
 
126
            newNode=metadoc.createElement("dc:title")
 
127
            newText=metadoc.createTextNode(model_name)
 
128
            newNode.appendChild(newText)
 
129
        ################################
 
130
        outzip = zipfile.ZipFile(out_oo, mode='w')
 
131
        outzip.compression = 8
 
132
        for file_inf in inzip.infolist():
 
133
            if file_inf.filename=='META-INF/manifest.xml':
 
134
                outzip.writestr(file_inf.filename, manifestdoc.toxml('utf-8'))
 
135
            elif file_inf.filename=='meta.xml':
 
136
                outzip.writestr(file_inf.filename, metadoc.toxml('utf-8'))
 
137
            elif file_inf.filename=='content.xml' and not content_data.startswith('<?xml'):
 
138
                outzip.writestr(file_inf.filename, '<?xml version="1.0" encoding="UTF-8"?>\n'+content_data)
 
139
            elif file_inf.filename=='styles.xml' and not styles_data.startswith('<?xml'):
 
140
                outzip.writestr(file_inf.filename, '<?xml version="1.0" encoding="UTF-8"?>\n'+styles_data)
 
141
            elif file_inf.filename=='Thumbnails/thumbnail.png':
 
142
                continue
 
143
            else:
 
144
                outzip.writestr(file_inf.filename, inzip.read(file_inf.filename))
 
145
        inzip.close()
 
146
        in_oo.close()
 
147
        outzip.close()
 
148
        return out_oo.getvalue()
 
149
 
 
150
    def create_relatorio_report(self, cr, uid, ids, data, report_xml, context=None, output='odt'):
 
151
        """ Returns an odt or a pdf generated with relatorio
 
152
        """
 
153
        #####################################################################################################
 
154
        def replaceStyles(node_list1, node_list2, name):
 
155
            o_index = 0
 
156
            while(o_index<len(node_list1)):
 
157
                n_index=0
 
158
                while(n_index<len(node_list2)):
 
159
                    if node_list1[o_index].getAttribute(name)==node_list2[n_index].getAttribute(name):
 
160
                        node_list1[o_index].parentNode.replaceChild(node_list2[n_index], node_list1[o_index])
 
161
                    n_index+=1
 
162
                o_index+=1
 
163
            return node_list1
 
164
        ######################################################################################################
 
165
 
 
166
        if not context:
 
167
            context={}
 
168
        context = context.copy()
 
169
        
 
170
        objects = self.getObjects(cr, uid, ids, context)
 
171
        oo_parser = self.parser(cr, uid, self.name2, context=context)
 
172
        oo_parser.objects = objects
 
173
 
 
174
        ############# Get XML ############
 
175
        xml_data_fields = oo_parser.localcontext.get('xml_data_fields', False)
 
176
        if xml_data_fields:
 
177
            for field in xml_data_fields:
 
178
                for o in objects:
 
179
                    if getattr(o, field):
 
180
                        xml_data = base64.decodestring(getattr(o, field))
 
181
                        xmldoc = minidom.parseString(xml_data)
 
182
                        setattr(o, field, xmldoc.firstChild)
 
183
        ############## Get other Tamplate ##############
 
184
        file_data = report_xml.report_sxw_content
 
185
        if hasattr(oo_parser, 'get_template'):
 
186
            pool = pooler.get_pool(cr.dbname)
 
187
            record = pool.get(data['model']).browse(cr, uid, data['id'], {})
 
188
            new_template = oo_parser.get_template(cr, uid, record)
 
189
            file_data = new_template or file_data
 
190
        ################################################
 
191
        if not file_data:
 
192
            return False, output
 
193
        in_oo = StringIO.StringIO(file_data)
 
194
        inzip = zipfile.ZipFile(in_oo, mode='r')
 
195
        outzip = False
 
196
        ############### Styles usage #################
 
197
        if report_xml.styles_mode!='default':
 
198
            out_oo = StringIO.StringIO()
 
199
            outzip = zipfile.ZipFile(out_oo, mode='a')
 
200
            if report_xml.styles_mode=='global':
 
201
                pool = pooler.get_pool(cr.dbname)
 
202
                company_id = pool.get('res.users')._get_company(cr, uid, context=context)
 
203
                style_content = pool.get('res.company').browse(cr, uid, company_id, context=context).report_styles
 
204
            elif report_xml.styles_mode=='specified':
 
205
                style_content = report_xml.report_styles
 
206
            if style_content:
 
207
                style_info = None
 
208
                style_xml = None
 
209
                for f in inzip.infolist():
 
210
                    if f.filename == 'styles.xml':
 
211
                        style_info = f
 
212
                        style_xml = inzip.read(f.filename)
 
213
                        continue
 
214
                    outzip.writestr(f.filename, inzip.read(f.filename))
 
215
 
 
216
                pictures = []
 
217
                dom_style = minidom.parseString(style_xml)
 
218
                node_style = dom_style.documentElement
 
219
 
 
220
                style2_io = StringIO.StringIO()
 
221
                style2_io.write(base64.decodestring(style_content))
 
222
                style2_z = zipfile.ZipFile(style2_io, mode='r')
 
223
                style2_xml = style2_z.read('styles.xml')
 
224
                for file_name in style2_z.namelist():
 
225
                    if file_name.startswith('Pictures'):
 
226
                        picture = style2_z.read(file_name)
 
227
                        pictures.append((file_name, picture))
 
228
                style2_z.close()
 
229
                style2_io.close()
 
230
                dom_style2 = minidom.parseString(style2_xml)
 
231
                node_style2 = dom_style2.documentElement
 
232
                font_face_new = node_style2.getElementsByTagName('office:font-face-decls')
 
233
                font_face_orig = node_style.getElementsByTagName('office:font-face-decls')
 
234
                orig_styles = replaceStyles(font_face_orig, font_face_new, 'style:name')
 
235
                orig_styles = node_style.getElementsByTagName('style:style')
 
236
                new_styles = node_style2.getElementsByTagName('style:style')
 
237
                orig_styles = replaceStyles(orig_styles, new_styles, 'style:name')
 
238
 
 
239
                outzip.writestr(style_info,
 
240
                        '<?xml version="1.0" encoding="UTF-8"?>' + \
 
241
                                dom_style.documentElement.toxml('utf-8'))
 
242
 
 
243
                for ffile, picture in pictures:
 
244
                    outzip.writestr(ffile, picture)
 
245
        ##############################################
 
246
        if not outzip or not outzip.namelist():
 
247
            out_oo = StringIO.StringIO(file_data)
 
248
            outzip = zipfile.ZipFile(out_oo, mode='a')
 
249
        ############### Replace tags 'text:text-input' on 'text:placeholder' #################
 
250
        output_data = {}
 
251
        for file_name in ('content.xml','styles.xml'):
 
252
            content = outzip.read(file_name)
 
253
            xmldoc = minidom.parseString(content)
 
254
            for oldNode in xmldoc.getElementsByTagName('text:text-input'):
 
255
                input_val = oldNode.getAttribute("text:description")
 
256
                if input_val.startswith('<') and input_val.endswith('>'):
 
257
                    if input_val=='<_()>':
 
258
                        input_val = "<_('%s')>" % oldNode.firstChild.nodeValue
 
259
                    newNode = xmldoc.createElement("text:placeholder")
 
260
                    newNode.setAttribute("text:placeholder-type", "text")
 
261
                    textNode=xmldoc.createTextNode(input_val)
 
262
                    newNode.appendChild(textNode)
 
263
                    oldNode.parentNode.replaceChild(newNode,oldNode)
 
264
 
 
265
            output_data[file_name] = xmldoc.toxml('utf-8')
 
266
 
 
267
        outzip = zipfile.ZipFile(out_oo, mode='w')
 
268
        for f_info in inzip.infolist():
 
269
            if f_info.filename in output_data.keys():
 
270
                outzip.writestr(f_info.filename, output_data[f_info.filename])
 
271
            else:
 
272
                outzip.writestr(f_info.filename, inzip.read(f_info.filename))
 
273
        ######################################################################################
 
274
        inzip.close()
 
275
        in_oo.close()
 
276
        outzip.close()
 
277
        file_data = out_oo.getvalue()
 
278
        ##############################################
 
279
 
 
280
        oo_parser.localcontext['objects'] = objects
 
281
        oo_parser.localcontext['data'] = data
 
282
        if len(objects)==1:
 
283
            oo_parser.localcontext['o'] = objects[0]
 
284
        xfunc = ExtraFunctions(cr, uid, report_xml.id, oo_parser.localcontext)
 
285
        oo_parser.localcontext.update(xfunc.functions)
 
286
 
 
287
        toremove = [] # for temp objects to be removed
 
288
        toclose = [] # for StringIO objects to be closed
 
289
        odt_fd, odt_path = tempfile.mkstemp(suffix='.odt', prefix='openoffice-report-')
 
290
        toremove.append( (odt_fd,odt_path) )
 
291
        fd = file(odt_path, 'wb')
 
292
        fd.write( file_data )
 
293
        fd.close()
 
294
        
 
295
        basic = Template(source=None, filepath=odt_path)
 
296
 
 
297
        data = self._doc_optimized(cr, uid, data, basic.generate(**oo_parser.localcontext).render().getvalue())
 
298
 
 
299
        if output!='odt' and DocumentConverter:
 
300
            convert = False
 
301
            pool = pooler.get_pool(cr.dbname)
 
302
            module_id = pool.get('ir.module.module').search(cr, uid, [('name','=','report_openoffice_pdf')])
 
303
            if module_id:
 
304
                if pool.get('ir.module.module').browse(cr, uid, module_id[0], context=context).state=='installed':
 
305
                    convert = True
 
306
            else:
 
307
                convert = True
 
308
            if convert:
 
309
                try:
 
310
                    cr.execute("SELECT host, port FROM oo_config")
 
311
                    host, port = cr.fetchone()
 
312
                    DC = DocumentConverter(host, port)
 
313
                    data = DC.convertByStream(data)
 
314
                    del DC
 
315
                except Exception, e:
 
316
                    print e
 
317
                    output='odt'
 
318
            else:
 
319
                output='odt'
 
320
 
 
321
        for item in toclose:
 
322
            item.close()
 
323
 
 
324
        for item in toremove:
 
325
            os.close(item[0])
 
326
            os.remove(item[1])
 
327
 
 
328
        return data, output
 
329
 
 
330
    # override needed to keep the attachments' storing procedure
 
331
    def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
 
332
        if not context:
 
333
            context={}
 
334
        if report_xml.report_type =='oo-pdf':
 
335
            return self.create_relatorio_report(cr, uid, ids, data, report_xml, context=context, output='pdf')
 
336
        elif report_xml.report_type =='oo-odt':
 
337
            return self.create_relatorio_report(cr, uid, ids, data, report_xml, context=context, output='odt')
 
338
        logo = None
 
339
        context = context.copy()
 
340
        title = report_xml.name
 
341
        rml = report_xml.report_rml_content
 
342
        oo_parser = self.parser(cr, uid, self.name2, context=context)
 
343
        objs = self.getObjects(cr, uid, ids, context)
 
344
        oo_parser.set_context(objs, data, ids, report_xml.report_type)
 
345
        processed_rml = self.preprocess_rml(etree.XML(rml),report_xml.report_type)
 
346
        if report_xml.header:
 
347
            oo_parser._add_header(processed_rml)
 
348
        if oo_parser.logo:
 
349
            logo = base64.decodestring(oo_parser.logo)
 
350
        create_doc = self.generators[report_xml.report_type]
 
351
        pdf = create_doc(etree.tostring(processed_rml),oo_parser.localcontext,logo,title.encode('utf8'))
 
352
        return (pdf, report_xml.report_type)
 
353
 
 
354
    def create_source_odt(self, cr, uid, ids, data, report_xml, context=None):
 
355
        if not context:
 
356
            context={}
 
357
        pool = pooler.get_pool(cr.dbname)
 
358
        attach = report_xml.attachment
 
359
        if attach:
 
360
            objs = self.getObjects(cr, uid, ids, context)
 
361
            results = []
 
362
            for obj in objs:
 
363
                aname = eval(attach, {'object':obj, 'time':time})
 
364
                result = False
 
365
                if report_xml.attachment_use and aname and context.get('attachment_use', True):
 
366
                    aids = pool.get('ir.attachment').search(cr, uid, [('datas_fname','=',aname+'.odt'),('res_model','=',self.table),('res_id','=',obj.id)])
 
367
                    if aids:
 
368
                        brow_rec = pool.get('ir.attachment').browse(cr, uid, aids[0])
 
369
                        if not brow_rec.datas:
 
370
                            continue
 
371
                        d = base64.decodestring(brow_rec.datas)
 
372
                        results.append((d,'odt'))
 
373
                        continue
 
374
                result = self.create_single_pdf(cr, uid, [obj.id], data, report_xml, context)
 
375
                try:
 
376
                    if aname:
 
377
                        name = aname+'.'+result[1]
 
378
                        pool.get('ir.attachment').create(cr, uid, {
 
379
                            'name': aname,
 
380
                            'datas': base64.encodestring(result[0]),
 
381
                            'datas_fname': name,
 
382
                            'res_model': self.table,
 
383
                            'res_id': obj.id,
 
384
                            }, context=context
 
385
                        )
 
386
                        cr.commit()
 
387
                except Exception,e:
 
388
                     import traceback, sys
 
389
                     tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
 
390
                     netsvc.Logger().notifyChannel('report', netsvc.LOG_ERROR,str(e))
 
391
                results.append(result)
 
392
 
 
393
        return self.create_single_pdf(cr, uid, ids, data, report_xml, context)
 
394
 
 
395
    # override needed to intercept the call to the proper 'create' method
 
396
    def create(self, cr, uid, ids, data, context=None):
 
397
        pool = pooler.get_pool(cr.dbname)
 
398
        ir_obj = pool.get('ir.actions.report.xml')
 
399
        report_xml_ids = ir_obj.search(cr, uid,
 
400
                [('report_name', '=', self.name[7:])], context=context)
 
401
        if report_xml_ids:
 
402
            report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
 
403
            report_xml.report_rml = None
 
404
            report_xml.report_rml_content = None
 
405
            report_xml.report_sxw_content_data = None
 
406
            report_rml.report_sxw_content = None
 
407
            report_rml.report_sxw = None
 
408
        else:
 
409
            title = ''
 
410
            rml = tools.file_open(self.tmpl, subdir=None).read()
 
411
            report_type= data.get('report_type', 'pdf')
 
412
            class a(object):
 
413
                def __init__(self, *args, **argv):
 
414
                    for key,arg in argv.items():
 
415
                        setattr(self, key, arg)
 
416
            report_xml = a(title=title, report_type=report_type, report_rml_content=rml, name=title, attachment=False, header=self.header)
 
417
 
 
418
        report_type = report_xml.report_type
 
419
        if report_type in ['sxw','odt']:
 
420
            fnct = self.create_source_odt
 
421
        elif report_type in ['pdf','raw','html','oo-pdf']:
 
422
            fnct = self.create_source_pdf
 
423
        elif report_type=='html2html':
 
424
            fnct = self.create_source_html2html
 
425
        elif report_type in ['oo-odt']:
 
426
            #fnct = self.create_relatorio_report
 
427
            fnct = self.create_source_odt
 
428
        else:
 
429
            raise ReportTypeException(_('Unknown report type: %s') % report_type)
 
430
        return fnct(cr, uid, ids, data, report_xml, context)
 
431
 
 
432
class ReportTypeException(Exception):
 
433
    def __init__(self, value):
 
434
      self.parameter = value
 
435
    def __str__(self):
 
436
      return repr(self.parameter)
 
437
 
 
438
#########################################################################
 
439
 
 
440
import imp, sys
 
441
 
 
442
def load_from_file(filepath, dbname, key):
 
443
    class_inst = None
 
444
    expected_class = 'Parser'
 
445
 
 
446
    try:
 
447
        if filepath.find(os.getcwd())==-1:
 
448
            filepath=os.getcwd()+filepath
 
449
        mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])
 
450
        mod_name = '%s_%s_%s' % (dbname,mod_name,key)
 
451
 
 
452
        if file_ext.lower() == '.py':
 
453
            py_mod = imp.load_source(mod_name, filepath)
 
454
 
 
455
        elif file_ext.lower() == '.pyc':
 
456
            py_mod = imp.load_compiled(mod_name, filepath)
 
457
 
 
458
        if expected_class in dir(py_mod):
 
459
            class_inst = py_mod.Parser
 
460
        return class_inst
 
461
    except Exception, e:
 
462
        return None
 
463
 
 
464
def load_from_source(source):
 
465
    expected_class = 'Parser'
 
466
    context = {'Parser':None}
 
467
    try:
 
468
        exec source in context
 
469
        return context['Parser']
 
470
    except Exception, e:
 
471
        return None
 
472
 
 
473
def register_report(name, model, tmpl_path, parser):
 
474
    name = 'report.%s' % name
 
475
    if netsvc.service_exist( name ):
 
476
        #service = netsvc.SERVICES[name].parser
 
477
        if isinstance( netsvc.SERVICES[name], OpenOffice_parser ):
 
478
                return
 
479
        del netsvc.SERVICES[name]
 
480
    OpenOffice_parser(name, model, tmpl_path, parser=parser)
 
481
 
 
482
old_register_all = report.interface.register_all
 
483
def new_register_all(db):
 
484
    value = old_register_all(db)
 
485
 
 
486
    cr = db.cursor()
 
487
 
 
488
    cr.execute("SELECT * FROM ir_act_report_xml")
 
489
    records = cr.dictfetchall()
 
490
    cr.close()
 
491
    for record in records:
 
492
        if record['report_type'] in ('oo-odt', 'oo-pdf'):
 
493
            parser=rml_parse
 
494
            if record['parser_state']=='loc' and record['parser_loc']:
 
495
                parser=load_from_file(record['parser_loc'], db.dbname, record['id']) or parser
 
496
            elif record['parser_state']=='def' and record['parser_def']:
 
497
                parser=load_from_source("from report import report_sxw\n"+record['parser_def']) or parser
 
498
            register_report( record['report_name'], record['model'], record['report_rml'], parser)
 
499
    return value
 
500
 
 
501
report.interface.register_all = new_register_all
 
502