diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index f37f8d2945d..3524a4857a6 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . # ############################################################################## @@ -129,7 +129,7 @@ class report_xml(osv.osv): ('sxw', 'sxw'), ('odt', 'odt'), ('html2html','HTML from HTML'), - ('mako2html','Mako from HTML'), + ('mako2html','HTML from HTML(Mako)'), ], string='Type', required=True), 'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'), 'attachment': fields.char('Save As Attachment Prefix', size=128, help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.'), @@ -151,7 +151,7 @@ class act_window(osv.osv): _name = 'ir.actions.act_window' _table = 'ir_act_window' _sequence = 'ir_actions_id_seq' - + def _check_model(self, cr, uid, ids, context={}): for action in self.browse(cr, uid, ids, context): if not self.pool.get(action.res_model): @@ -252,7 +252,7 @@ class act_window(osv.osv): 'filter': fields.boolean('Filter'), 'default_user_ids': fields.many2many('res.users', 'ir_act_window_user_rel', 'act_id', 'uid', 'Users'), 'search_view' : fields.function(_search_view, type='text', method=True, string='Search View'), - 'menus': fields.char('Menus', size=4096) + 'menus': fields.char('Menus', size=4096) } _defaults = { 'type': lambda *a: 'ir.actions.act_window', @@ -547,10 +547,10 @@ class actions_server(osv.osv): if result in (None, False): return str("--------") return str(result) - + com = re.compile('(\[\[.+?\]\])') message = com.sub(merge, keystr) - + return message # Context should contains: @@ -559,16 +559,16 @@ class actions_server(osv.osv): # OUT: # False : Finnished correctly # ACTION_ID : Action to launch - + def run(self, cr, uid, ids, context={}): logger = netsvc.Logger() - + for action in self.browse(cr, uid, ids, context): obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) cxt = { - 'context':context, - 'object': obj, + 'context':context, + 'object': obj, 'time':time, 'cr': cr, 'pool' : self.pool, @@ -577,10 +577,10 @@ class actions_server(osv.osv): expr = eval(str(action.condition), cxt) if not expr: continue - + if action.state=='client_action': if not action.action_id: - raise osv.except_osv(_('Error'), _("Please specify an action to launch !")) + raise osv.except_osv(_('Error'), _("Please specify an action to launch !")) result = self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context) return result @@ -605,16 +605,16 @@ class actions_server(osv.osv): address = eval(str(action.email), cxt) except: pass - + if not address: logger.notifyChannel('email', netsvc.LOG_INFO, 'Partner Email address not Specified!') continue if not user: raise osv.except_osv(_('Error'), _("Please specify server option --smtp-from !")) - + subject = self.merge_message(cr, uid, str(action.subject), action, context) body = self.merge_message(cr, uid, str(action.message), action, context) - + if tools.email_send(user, [address], subject, body, debug=False, subtype='html') == True: logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address)) else: @@ -639,7 +639,7 @@ class actions_server(osv.osv): logger.notifyChannel('sms', netsvc.LOG_INFO, 'SMS successfully send to : %s' % (action.address)) else: logger.notifyChannel('sms', netsvc.LOG_ERROR, 'Failed to send SMS to : %s' % (action.address)) - + if action.state == 'other': res = [] for act in action.child_ids: @@ -647,15 +647,15 @@ class actions_server(osv.osv): result = self.run(cr, uid, [act.id], context) if result: res.append(result) - + return res - + if action.state == 'loop': obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) cxt = { - 'context':context, - 'object': obj, + 'context':context, + 'object': obj, 'time':time, 'cr': cr, 'pool' : self.pool, @@ -666,7 +666,7 @@ class actions_server(osv.osv): for i in expr: context['active_id'] = i.id result = self.run(cr, uid, [action.loop_action.id], context) - + if action.state == 'object_write': res = {} for exp in action.fields_lines: @@ -688,7 +688,7 @@ class actions_server(osv.osv): write_id = context.get('active_id') obj_pool = self.pool.get(action.srcmodel_id.model) obj_pool.write(cr, uid, [write_id], res) - + elif action.write_id: obj_pool = self.pool.get(action.srcmodel_id.model) rec = self.pool.get(action.model_id.model).browse(cr, uid, context.get('active_id')) @@ -697,7 +697,7 @@ class actions_server(osv.osv): id = int(id) except: raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!")) - + if type(id) != type(1): raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!")) write_id = id @@ -741,9 +741,9 @@ act_window_close() # if action type is 'service', # - if start_type= 'at once', it will be start at one time on start date # - if start_type='auto', it will be start on auto starting from start date, and stop on stop date -# - if start_type="manual", it will start and stop on manually +# - if start_type="manual", it will start and stop on manually class ir_actions_todo(osv.osv): - _name = 'ir.actions.todo' + _name = 'ir.actions.todo' _columns={ 'name':fields.char('Name',size=64,required=True, select=True), 'note':fields.text('Text', translate=True), @@ -778,7 +778,7 @@ class ir_actions_configuration_wizard(osv.osv_memory): return item return False def _get_action_name(self, cr, uid, context={}): - next_action=self.next_configuration_action(cr,uid,context=context) + next_action=self.next_configuration_action(cr,uid,context=context) if next_action: return next_action.note else: diff --git a/bin/addons/base/report/mako_footer.html b/bin/addons/base/report/mako_footer.html index c1cda8499f5..7c2d5b67a08 100644 --- a/bin/addons/base/report/mako_footer.html +++ b/bin/addons/base/report/mako_footer.html @@ -1,13 +1,30 @@ -
-
- % if company['rml_footer1']: -

${company.rml_footer1}

- %endif - % if company['rml_footer2']: -

${company.rml_footer2}

- %endif - % if user['name']: -

Contact : ${user.name}

- %endif -
- +
+ + + + + + + + + + + + + +
+
+
+ % if company['rml_footer1']: +

${company.rml_footer1}

+ %endif +
+ % if company['rml_footer2']: +

${company.rml_footer2}

+ %endif +
+ % if user['name']: +

Contact : ${user.name}

+ %endif +
+
diff --git a/bin/addons/base/report/mako_header.html b/bin/addons/base/report/mako_header.html index 2958c0009ee..5bd3aaf18fb 100644 --- a/bin/addons/base/report/mako_header.html +++ b/bin/addons/base/report/mako_header.html @@ -1,34 +1,62 @@ -## -*- coding: utf-8 -*- - +
+ +% if company.logo: + +%endif + + + + - - - - - - % if company.logo: - - %endif -
- % if company['partner_id']['name']: - ${company.partner_id.name}
- %endif - % if company['partner_id']['address'] and company['partner_id']['address'][0]['street']: - ${company.partner_id.address[0].street}
- %endif - % if company['partner_id']['address'] and company['partner_id']['address'][0]['zip']: - ${company.partner_id.address[0].zip} - ${company.partner_id.address[0].city}-${company.partner_id.address[0].country_id and company.partner_id.address[0].country_id.name}
- %endif - % if company['partner_id']['address'] and company['partner_id']['address'][0]['phone']: - Phone:${company.partner_id.address and company.partner_id.address[0].phone}
- %endif - % if company['partner_id']['address'] and company['partner_id']['address'][0]['email']: - Mail:${company.partner_id.address and company.partner_id.address[0].email}
- %endif - % if company['rml_header1']: -

${company.rml_header1}

- %endif -
- - +
+ + + + + + + + + + + + + + + + + + + + + + +
+ % if company['partner_id']['name']: + ${company.partner_id.name}
+ %endif +
+ % if company['partner_id']['address'] and company['partner_id']['address'][0]['street']: + ${company.partner_id.address[0].street}
+ %endif +
+ % if company['partner_id']['address'] and company['partner_id']['address'][0]['zip']: + ${company.partner_id.address[0].zip} + ${company.partner_id.address[0].city}-${company.partner_id.address[0].country_id and company.partner_id.address[0].country_id.name}
+ %endif +
+ % if company['partner_id']['address'] and company['partner_id']['address'][0]['phone']: + Phone:${company.partner_id.address and company.partner_id.address[0].phone}
+ %endif +
+ % if company['partner_id']['address'] and company['partner_id']['address'][0]['email']: + Mail:${company.partner_id.address and company.partner_id.address[0].email}
+ %endif +
+ % if company['rml_header1']: +

${company.rml_header1}

+ %endif +
+
+
+
\ No newline at end of file diff --git a/bin/report/interface.py b/bin/report/interface.py index c55582b04c0..8c44bc38de9 100644 --- a/bin/report/interface.py +++ b/bin/report/interface.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . # ############################################################################## @@ -82,6 +82,7 @@ class report_rml(report_int): 'sxw': self.create_sxw, 'odt': self.create_odt, 'html2html' : self.create_html2html, + 'makohtml2html' :self.create_makohtml2html, } def create(self, cr, uid, ids, datas, context): @@ -223,6 +224,11 @@ class report_rml(report_int): obj.render() return obj.get() + def create_makohtml2html(self,html,localcontext = None): + obj = render.makohtml2html(html,localcontext) + obj.render() + return obj.get() + from report_sxw import report_sxw def register_all(db): diff --git a/bin/report/render/__init__.py b/bin/report/render/__init__.py index cbc8fab0c9e..d28626dad86 100644 --- a/bin/report/render/__init__.py +++ b/bin/report/render/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,12 +15,12 @@ # 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 . +# along with this program. If not, see . # ############################################################################## from simple import simple -from rml import rml, rml2html, odt2odt , html2html +from rml import rml, rml2html, odt2odt, html2html, makohtml2html from render import render try: diff --git a/bin/report/render/makohtml2html/__init__.py b/bin/report/render/makohtml2html/__init__.py new file mode 100644 index 00000000000..3d7ac1c799b --- /dev/null +++ b/bin/report/render/makohtml2html/__init__.py @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## +from makohtml2html import parseNode \ No newline at end of file diff --git a/bin/report/render/makohtml2html/makohtml2html.py b/bin/report/render/makohtml2html/makohtml2html.py new file mode 100644 index 00000000000..dfa0fa8e16a --- /dev/null +++ b/bin/report/render/makohtml2html/makohtml2html.py @@ -0,0 +1,111 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## +from lxml import etree +from mako.template import Template +from mako.lookup import TemplateLookup +import netsvc +import traceback, sys, os + +class makohtml2html(object): + def __init__(self, html, localcontext): + self.localcontext = localcontext + self.html = html + + def format_header(self, html): + head = html.findall('head') + header = '' + for node in head: + header += etree.tostring(node) + return header + + def format_footer(self, footer): + html_footer = '' + for node in footer[0].getchildren(): + html_footer += etree.tostring(node) + return html_footer + + def format_body(self, html): + body = html.findall('body') + body_list = [] + footer = self.format_footer(body[-1].getchildren()) + for b in body[:-1]: + body_table = '' + body_table += etree.tostring(b) + body_list.append(body_table.replace('\t', '').replace('\n','')) + html_body =''' + + + +
+ %s +
+
+ %s +
+
+ + + + '''%(body_list,body_list[0],footer) + return html_body + + def render(self): + path = os.path.realpath('addons/base/report') + temp_lookup = TemplateLookup(directories=[path],output_encoding='utf-8', encoding_errors='replace') + template = Template(self.html, lookup=temp_lookup) + self.localcontext.update({'css_path':path}) + final_html =''' + ''' + try: + html = template.render_unicode(**self.localcontext) + etree_obj = etree.HTML(html) + final_html += self.format_header(etree_obj) + final_html += self.format_body(etree_obj) + return final_html + except Exception,e: + tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) + netsvc.Logger().notifyChannel('report', netsvc.LOG_ERROR, + 'report :\n%s\n%s\n' % (tb_s, str(e))) + +def parseNode(html, localcontext = {}): + r = makohtml2html(html, localcontext) + return r.render() \ No newline at end of file diff --git a/bin/report/render/rml.py b/bin/report/render/rml.py index 288cbc704c8..5b6b9dc9c8d 100644 --- a/bin/report/render/rml.py +++ b/bin/report/render/rml.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . # ############################################################################## @@ -24,6 +24,7 @@ import rml2pdf import rml2html as htmlizer import odt2odt as odt import html2html as html +import makohtml2html as makohtml class rml(render.render): @@ -56,7 +57,6 @@ class odt2odt(render.render): self.localcontext = localcontext self.output_type = 'odt' - def _render(self): return odt.parseNode(self.rml_dom,self.localcontext) @@ -66,9 +66,19 @@ class html2html(render.render): self.rml_dom = rml self.localcontext = localcontext self.output_type = 'html' - + def _render(self): return html.parseString(self.rml_dom,self.localcontext) +class makohtml2html(render.render): + def __init__(self, html, localcontext = None): + render.render.__init__(self) + self.html = html + self.localcontext = localcontext + self.output_type = 'html' + + def _render(self): + return makohtml.parseNode(self.html,self.localcontext) + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/report/report_sxw.py b/bin/report/report_sxw.py index da24d251f0b..a853df6545c 100644 --- a/bin/report/report_sxw.py +++ b/bin/report/report_sxw.py @@ -19,10 +19,7 @@ # ############################################################################## from lxml import etree -from mako.template import Template -from mako.lookup import TemplateLookup -from mako import exceptions - +import traceback, sys import StringIO import cStringIO import base64 @@ -567,17 +564,10 @@ class report_sxw(report_rml, preprocess.report): def create_single_mako2html(self, cr, uid, ids, data, report_xml, context=None): mako_html = report_xml.report_rml_content - path = os.path.realpath('addons/base/report') - report_type = report_xml.report_type html_parser = self.parser(cr, uid, self.name2, context) objs = self.getObjects(cr, uid, ids, context) - html_parser.set_context(objs, data, ids, report_type) - temp_lookup = TemplateLookup(directories=[path],output_encoding='utf-8', encoding_errors='replace') - template = Template(tools.ustr(mako_html), lookup=temp_lookup) - html_parser.localcontext.update({'css_path':path}) - try: - html = template.render_unicode(**html_parser.localcontext) - except: - return(exceptions.html_error_template().render(),'html') + html_parser.set_context(objs, data, ids, 'html') + create_doc = self.generators['makohtml2html'] + html = create_doc(mako_html,html_parser.localcontext) return (html,'html')