diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index d9280d18aa9..b757dd163a5 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1189,7 +1189,7 @@ - + @@ -1202,10 +1202,18 @@ - + + + + + + + + @@ -1227,6 +1235,7 @@ + diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 457ee78f6b4..d8b24c86787 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -364,12 +364,7 @@ server_object_lines() # Actions that are run on the server side # class actions_server(osv.osv): - - def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False): - res = super(actions_server, self).fields_view_get(cr, user, view_id, view_type, context, toolbar) - #print 'RES : ',res - return res - + def _select_signals(self, cr, uid, context={}): cr.execute("select distinct t.signal as key, t.signal || ' - [ ' || w.osv || ' ] ' as val from wkf w, wkf_activity a, wkf_transition t "\ " where w.id = a.wkf_id " \ @@ -385,12 +380,15 @@ class actions_server(osv.osv): _name = 'ir.actions.server' _table = 'ir_act_server' _sequence = 'ir_actions_id_seq' + _order = 'sequence' _columns = { 'name': fields.char('Action Name', required=True, size=64), 'condition' : fields.char('Condition', size=256), + 'sub_condition' : fields.char('Condition', size=256), 'state': fields.selection([ ('client_action','Client Action'), ('dummy','Dummy'), + ('loop','Iteration'), ('code','Python Code'), ('trigger','Trigger'), ('email','Email'), @@ -398,7 +396,7 @@ class actions_server(osv.osv): ('object_create','Create Object'), ('object_write','Write Object'), ('other','Multi Actions'), - ], 'Action State', required=True, size=32), + ], 'Action Type', required=True, size=32), 'code':fields.text('Python Code'), 'sequence': fields.integer('Sequence'), 'model_id': fields.many2one('ir.model', 'Object', required=True), @@ -406,21 +404,25 @@ class actions_server(osv.osv): 'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128), 'wkf_model_id': fields.many2one('ir.model', 'Workflow on'), 'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On'), - 'email': fields.many2one('ir.model.fields', 'Contact'), + 'email': fields.char('Email Address', size=512), 'subject': fields.char('Subject', size=1024, translate=True), 'message': fields.text('Message', translate=True), - 'mobile': fields.many2one('ir.model.fields', 'Contact'), + 'mobile': fields.char('Mobile No', size=512), 'sms': fields.char('SMS', size=160, translate=True), 'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id', 'Others Actions'), 'usage': fields.char('Action Usage', size=32), 'type': fields.char('Action Type', size=32, required=True), 'srcmodel_id': fields.many2one('ir.model', 'Model', help="In which object you want to create / write the object if its empty refer to the Object field"), 'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Fields Mapping'), - 'record_id':fields.many2one('ir.model.fields', 'Record Id', help="privide the field name from where the record id refers, if its empty it will refer to the active id of the object") + 'record_id':fields.many2one('ir.model.fields', 'Create Id', help="Provide the field name from where the record id stores after the create operations, if its empty, you can not track the new record"), + 'write_id':fields.char('Write Id', size=256, help="Provide the field name from where the record id refer for the write operation, if its empty it will refer to the active id of the object"), + 'loop_action':fields.many2one('ir.actions.server', 'Loop Action'), + 'expression':fields.char('Loop Expression', size=512), } _defaults = { 'state': lambda *a: 'dummy', 'condition': lambda *a: 'True', + 'sub_condition': lambda *a: 'True', 'type': lambda *a: 'ir.actions.server', 'sequence': lambda *a: 5, 'code': lambda *a: """# You can use the following variables @@ -434,7 +436,6 @@ class actions_server(osv.osv): """, } - def get_email(self, cr, uid, action, context): logger = netsvc.Logger() obj_pool = self.pool.get(action.model_id.model) @@ -456,7 +457,6 @@ class actions_server(osv.osv): return obj - def get_mobile(self, cr, uid, action, context): logger = netsvc.Logger() obj_pool = self.pool.get(action.model_id.model) @@ -501,6 +501,7 @@ class actions_server(osv.osv): # OUT: # False : Finnished correctly # ACTION_ID : Action to launch + def run(self, cr, uid, ids, context={}): logger = netsvc.Logger() @@ -540,7 +541,12 @@ class actions_server(osv.osv): if action.state == 'email': user = config['email_from'] - address = self.get_email(cr, uid, action, context) + address = str(action.email) + try: + address = eval(str(action.email), cxt) + except: + pass + if not address: raise osv.except_osv(_('Error'), _("Please specify the Partner Email address !")) if not user: @@ -577,11 +583,30 @@ class actions_server(osv.osv): if action.state == 'other': res = [] for act in action.child_ids: + context['active_id'] = context['active_ids'][0] 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, + 'time':time, + 'cr': cr, + 'pool' : self.pool, + 'uid' : uid + } + expr = eval(str(action.expression), cxt) + context['object'] = obj + 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: @@ -589,29 +614,35 @@ class actions_server(osv.osv): if exp.type == 'equation': obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) - expr = eval(euq, {'context':context, 'object': obj, 'time':time}) + cxt = {'context':context, 'object': obj, 'time':time} + expr = eval(euq, cxt) else: expr = exp.value res[exp.col1.name] = expr - if not action.record_id: + if not action.write_id: if not action.srcmodel_id: obj_pool = self.pool.get(action.model_id.model) obj_pool.write(cr, uid, [context.get('active_id')], res) else: + write_id = context.get('active_id') obj_pool = self.pool.get(action.srcmodel_id.model) - obj_pool.write(cr, uid, [context.get('active_id')], res) - else: + obj_pool.write(cr, uid, [write_id], res) + + elif action.write_id: obj_pool = self.pool.get(action.srcmodel_id.model) - id = self.pool.get(action.model_id.model).read(cr, uid, [context.get('active_id')], [action.record_id.name]) - write_id = False - if action.record_id.ttype in ('char', 'int', 'float'): - write_id = int(id[0][action.record_id.name]) - elif action.record_id.ttype in ('many2one'): - write_id = int(id[0][action.record_id.name][0]) - + rec = self.pool.get(action.model_id.model).browse(cr, uid, context.get('active_id')) + id = eval(action.write_id, {'object': rec}) + try: + 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 obj_pool.write(cr, uid, [write_id], res) - + if action.state == 'object_create': res = {} for exp in action.fields_lines: @@ -628,10 +659,12 @@ class actions_server(osv.osv): res_id = False obj_pool = self.pool.get(action.srcmodel_id.model) res_id = obj_pool.create(cr, uid, res) + cr.commit() if action.record_id: self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id}) return False + actions_server() class act_window_close(osv.osv): diff --git a/bin/addons/base/res/res_company.py b/bin/addons/base/res/res_company.py index faddf9c1407..20a5a01d439 100644 --- a/bin/addons/base/res/res_company.py +++ b/bin/addons/base/res/res_company.py @@ -143,12 +143,12 @@ class res_company(osv.osv): [[ company.partner_id.name ]] - [[ company.partner_id.address and company.partner_id.address[0].street ]] - [[ company.partner_id.address and company.partner_id.address[0].zip ]] [[ company.partner_id.address and company.partner_id.address[0].city ]] - [[ company.partner_id.address and company.partner_id.address[0].country_id and company.partner_id.address[0].country_id.name ]] + [[ company.partner_id.address and company.partner_id.address[0].street or '' ]] + [[ company.partner_id.address and company.partner_id.address[0].zip or '' ]] [[ company.partner_id.address and company.partner_id.address[0].city or '' ]] - [[ company.partner_id.address and company.partner_id.address[0].country_id and company.partner_id.address[0].country_id.name or '']] Phone: - [[ company.partner_id.address and company.partner_id.address[0].phone ]] + [[ company.partner_id.address and company.partner_id.address[0].phone or '' ]] Mail: - [[ company.partner_id.address and company.partner_id.address[0].email ]] + [[ company.partner_id.address and company.partner_id.address[0].email or '' ]] 1.3cm 25.5cm 7cm 25.5cm diff --git a/bin/addons/base/rng/view.rng b/bin/addons/base/rng/view.rng index ba3db149eaf..e40f178d69f 100644 --- a/bin/addons/base/rng/view.rng +++ b/bin/addons/base/rng/view.rng @@ -144,6 +144,7 @@ + diff --git a/bin/report/printscreen/ps_list.py b/bin/report/printscreen/ps_list.py index 5349285b9ba..3c2f339ed80 100644 --- a/bin/report/printscreen/ps_list.py +++ b/bin/report/printscreen/ps_list.py @@ -132,7 +132,7 @@ class report_printscreen_list(report_int): for f in fields_order: field = new_doc.createElement("field") - field_txt = new_doc.createTextNode(str(fields[f]['string'] or '')) + field_txt = new_doc.createTextNode(fields[f]['string'] or '') field.appendChild(field_txt) header.appendChild(field) @@ -166,7 +166,7 @@ class report_printscreen_list(report_int): col.setAttribute('para','yes') col.setAttribute('tree','no') if line[f] != None: - txt = new_doc.createTextNode(str(line[f] or '')) + txt = new_doc.createTextNode(line[f] or '') if temp[count] == 1: tsum[count] = float(tsum[count]) + float(line[f]); @@ -203,7 +203,7 @@ class report_printscreen_list(report_int): 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()) + doc = libxml2.parseDoc(new_doc.toxml(encoding='utf-8')) rml_obj = style.applyStylesheet(doc, None) rml = style.saveResultToString(rml_obj) self.obj = render.rml(rml, title=self.title) diff --git a/bin/report/report_sxw.py b/bin/report/report_sxw.py index 501dd285f27..b26b32e6417 100644 --- a/bin/report/report_sxw.py +++ b/bin/report/report_sxw.py @@ -20,30 +20,28 @@ # ############################################################################## -import base64 -import xml.dom.minidom -import os, time -import ir, netsvc -import osv from interface import report_rml -import re -import tools -import pooler -import netsvc -import warnings -import locale -import copy import StringIO -import zipfile -import os +import base64 +import copy +import ir +import locale import mx.DateTime +import netsvc +import os +import osv +import pooler +import re +import time +import tools +import warnings +import xml.dom.minidom +import zipfile DT_FORMAT = '%Y-%m-%d' DHM_FORMAT = '%Y-%m-%d %H:%M:%S' HM_FORMAT = '%H:%M:%S' -import base64 - if not hasattr(locale, 'nl_langinfo'): locale.nl_langinfo = lambda *a: '%x' @@ -469,12 +467,11 @@ class rml_parse(object): if isinstance(newtext, list): todo.append((key, newtext)) else: - #if not isinstance(newtext, basestring): - newtext = str(newtext) # if there are two [[]] blocks the same, it will replace both # but it's ok because it should evaluate to the same thing # anyway - text = text.replace('[['+key+']]', newtext.decode('utf8')) + newtext = tools.ustr(newtext) + text = text.replace('[['+key+']]', newtext) self._node.data = text if len(todo): for key, newtext in todo: