Merge commit 'origin/master' into mdv-gpl3-fwd
Conflicts: bin/addons/base/ir/ir_actions.py bin/netsvc.py bin/report/report_sxw.py bin/tools/translate.py bzr revid: p_christ@hol.gr-20081218164925-uarehzvo3ocu0x2w
This commit is contained in:
+87
-77
@@ -24,6 +24,7 @@ import os, sys, imp
|
||||
from os.path import join as opj
|
||||
import itertools
|
||||
from sets import Set
|
||||
import zipimport
|
||||
|
||||
import osv
|
||||
import tools
|
||||
@@ -268,25 +269,32 @@ def init_module_objects(cr, module_name, obj_list):
|
||||
t[1](cr, *t[2])
|
||||
cr.commit()
|
||||
|
||||
#
|
||||
# Register module named m, if not already registered
|
||||
#
|
||||
def register_class(m):
|
||||
"""
|
||||
Register module named m, if not already registered
|
||||
"""
|
||||
global loaded
|
||||
if m in loaded:
|
||||
return
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: registering objects' % m)
|
||||
loaded.append(m)
|
||||
mod_path = get_module_path(m)
|
||||
if not os.path.isfile(mod_path+'.zip'):
|
||||
imp.load_module(m, *imp.find_module(m, [ad, _ad]))
|
||||
else:
|
||||
import zipimport
|
||||
try:
|
||||
zimp = zipimport.zipimporter(mod_path+'.zip')
|
||||
try:
|
||||
zip_mod_path = mod_path + '.zip'
|
||||
if not os.path.isfile(zip_mod_path):
|
||||
imp.load_module(m, *imp.find_module(m, [ad, _ad]))
|
||||
else:
|
||||
zimp = zipimport.zipimporter(zip_mod_path)
|
||||
zimp.load_module(m)
|
||||
except zipimport.ZipImportError:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m)
|
||||
except zipimport.ZipImportError:
|
||||
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find zip module %s' % m)
|
||||
raise
|
||||
except ImportError:
|
||||
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find module %s' % m)
|
||||
raise
|
||||
except Exception:
|
||||
logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find module %s' % (m))
|
||||
raise
|
||||
|
||||
|
||||
class MigrationManager(object):
|
||||
@@ -535,84 +543,86 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs)
|
||||
def load_modules(db, force_demo=False, status=None, update_module=False):
|
||||
if not status:
|
||||
status={}
|
||||
|
||||
cr = db.cursor()
|
||||
force = []
|
||||
if force_demo:
|
||||
force.append('demo')
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
report = tools.assertion_report()
|
||||
if update_module:
|
||||
basegraph = create_graph(['base'], force)
|
||||
load_module_graph(cr, basegraph, status, check_access_rules=False, report=report)
|
||||
try:
|
||||
report = tools.assertion_report()
|
||||
if update_module:
|
||||
basegraph = create_graph(['base'], force)
|
||||
load_module_graph(cr, basegraph, status, check_access_rules=False, report=report)
|
||||
|
||||
modobj = pool.get('ir.module.module')
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list')
|
||||
modobj.update_list(cr, 1)
|
||||
modobj = pool.get('ir.module.module')
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list')
|
||||
modobj.update_list(cr, 1)
|
||||
|
||||
mods = [k for k in tools.config['init'] if tools.config['init'][k]]
|
||||
if mods:
|
||||
ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
|
||||
if ids:
|
||||
modobj.button_install(cr, 1, ids)
|
||||
mods = [k for k in tools.config['init'] if tools.config['init'][k]]
|
||||
if mods:
|
||||
ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
|
||||
if ids:
|
||||
modobj.button_install(cr, 1, ids)
|
||||
|
||||
mods = [k for k in tools.config['update'] if tools.config['update'][k]]
|
||||
if mods:
|
||||
ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)])
|
||||
if ids:
|
||||
modobj.button_upgrade(cr, 1, ids)
|
||||
|
||||
cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')")
|
||||
else:
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')")
|
||||
module_list = [name for (name,) in cr.fetchall()]
|
||||
graph = create_graph(module_list, force)
|
||||
|
||||
mods = [k for k in tools.config['update'] if tools.config['update'][k]]
|
||||
if mods:
|
||||
ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)])
|
||||
if ids:
|
||||
modobj.button_upgrade(cr, 1, ids)
|
||||
|
||||
cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')")
|
||||
else:
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')")
|
||||
module_list = [name for (name,) in cr.fetchall()]
|
||||
graph = create_graph(module_list, force)
|
||||
|
||||
# the 'base' module has already been updated
|
||||
base = graph['base']
|
||||
base.state = 'installed'
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
if hasattr(base, kind):
|
||||
delattr(base, kind)
|
||||
# the 'base' module has already been updated
|
||||
base = graph['base']
|
||||
base.state = 'installed'
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
if hasattr(base, kind):
|
||||
delattr(base, kind)
|
||||
|
||||
load_module_graph(cr, graph, status, report=report)
|
||||
if report.get_report():
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, report)
|
||||
load_module_graph(cr, graph, status, report=report)
|
||||
if report.get_report():
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, report)
|
||||
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
tools.config[kind]={}
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
tools.config[kind]={}
|
||||
|
||||
cr.commit()
|
||||
if update_module:
|
||||
cr.execute("select id,name from ir_module_module where state in ('to remove')")
|
||||
for mod_id, mod_name in cr.fetchall():
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,))
|
||||
for rmod,rid in cr.fetchall():
|
||||
uid = 1
|
||||
pool.get(rmod).unlink(cr, uid, [rid])
|
||||
cr.commit()
|
||||
#
|
||||
# TODO: remove menu without actions of childs
|
||||
#
|
||||
while True:
|
||||
cr.execute('''delete from
|
||||
ir_ui_menu
|
||||
where
|
||||
(id not in (select parent_id from ir_ui_menu where parent_id is not null))
|
||||
and
|
||||
(id not in (select res_id from ir_values where model='ir.ui.menu'))
|
||||
and
|
||||
(id not in (select res_id from ir_model_data where model='ir.ui.menu'))''')
|
||||
if not cr.rowcount:
|
||||
break
|
||||
else:
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,))
|
||||
|
||||
cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', ))
|
||||
cr.commit()
|
||||
#pooler.restart_pool(cr.dbname)
|
||||
cr.close()
|
||||
if update_module:
|
||||
cr.execute("select id,name from ir_module_module where state in ('to remove')")
|
||||
for mod_id, mod_name in cr.fetchall():
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,))
|
||||
for rmod,rid in cr.fetchall():
|
||||
uid = 1
|
||||
pool.get(rmod).unlink(cr, uid, [rid])
|
||||
cr.commit()
|
||||
#
|
||||
# TODO: remove menu without actions of childs
|
||||
#
|
||||
while True:
|
||||
cr.execute('''delete from
|
||||
ir_ui_menu
|
||||
where
|
||||
(id not in (select parent_id from ir_ui_menu where parent_id is not null))
|
||||
and
|
||||
(id not in (select res_id from ir_values where model='ir.ui.menu'))
|
||||
and
|
||||
(id not in (select res_id from ir_model_data where model='ir.ui.menu'))''')
|
||||
if not cr.rowcount:
|
||||
break
|
||||
else:
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,))
|
||||
|
||||
cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', ))
|
||||
cr.commit()
|
||||
finally:
|
||||
cr.close()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<field name="view_id" ref="view_menu"/>
|
||||
<field name="res_model">ir.ui.menu</field>
|
||||
<field name="view_type">tree</field>
|
||||
<field eval="'[(\'parent_id\',\'=\',False)]'" name="domain"/>
|
||||
<field name="domain">[('parent_id', '=', False)]</field>
|
||||
</record>
|
||||
|
||||
<record id="lang_en" model="res.lang">
|
||||
|
||||
+637
-490
File diff suppressed because it is too large
Load Diff
+39
-12
@@ -325,12 +325,25 @@
|
||||
</record>
|
||||
<menuitem action="ir_action_window" id="menu_ir_action_window" parent="base.next_id_6"/>
|
||||
|
||||
<record id="act_wizard_view" model="ir.ui.view">
|
||||
<record id="act_wizard_view_tree" model="ir.ui.view">
|
||||
<field name="name">ir.actions.wizard.tree</field>
|
||||
<field name="model">ir.actions.wizard</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Wizard">
|
||||
<field name="name" select="1"/>
|
||||
<field name="wiz_name" select="1"/>
|
||||
<field name="multi"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="act_wizard_view" model="ir.ui.view">
|
||||
<field name="name">ir.actions.wizard</field>
|
||||
<field name="model">ir.actions.wizard</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Wizard">
|
||||
<form string="Wizards">
|
||||
<field name="name" select="1"/>
|
||||
<field name="type" select="1"/>
|
||||
<field name="wiz_name" select="1"/>
|
||||
@@ -341,7 +354,7 @@
|
||||
</record>
|
||||
|
||||
<record id="ir_action_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Wizard</field>
|
||||
<field name="name">Wizards</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">ir.actions.wizard</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -688,9 +701,9 @@
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Field Type" colspan="2"/>
|
||||
<field name="ttype" select="2"/>
|
||||
<field name="relation_id" select="2" attrs="{'required': [('ttype','in',['many2one','one2many','many2many'])],
|
||||
<field name="relation" attrs="{'required': [('ttype','in',['many2one','one2many','many2many'])],
|
||||
'readonly': [('ttype','!=','one2many'), ('ttype','!=','many2one'), ('ttype','!=','many2many')]}"/>
|
||||
<field name="relation_field_id" domain="[('model_id','=',relation_id)]" attrs="{'required': [('ttype','=','one2many')],
|
||||
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')],
|
||||
'readonly': [('ttype','!=','one2many')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
|
||||
@@ -767,12 +780,9 @@
|
||||
<page string="Properties">
|
||||
<group colspan="2" col="2">
|
||||
<field name="ttype" select="2"/>
|
||||
<field name="relation_id" select="2" on_change="on_relation_change(relation_id)" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
|
||||
<field name="relation" select="2" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
|
||||
'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>
|
||||
<!-- <field name="relation" select="2" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],-->
|
||||
<!-- 'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>-->
|
||||
<field name="relation_field_id" domain="[('model_id','=',relation_id)]" attrs="{'required': [('ttype','=','one2many')],
|
||||
'readonly': [('ttype','!=','one2many')]}"/>
|
||||
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')], 'readonly': [('ttype','!=','one2many')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
|
||||
<field name="state"/>
|
||||
@@ -1142,7 +1152,14 @@
|
||||
<field name="state" select="1"/>
|
||||
<field name="model_id" select="1"/>
|
||||
<field name="sequence" select="2"/>
|
||||
<field name="condition" colspan="4"/>
|
||||
<notebook colspan="4">
|
||||
|
||||
<page string="Python Code" attrs="{'invisible':[('state','!=','code')]}">
|
||||
<separator colspan="4" string="Python Code"/>
|
||||
<field name="code" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
|
||||
<page string="Trigger" attrs="{'invisible':[('state','!=','trigger')]}">
|
||||
<separator colspan="4" string="Trigger Configuration"/>
|
||||
<field name="wkf_model_id"/>
|
||||
@@ -1157,6 +1174,7 @@
|
||||
<page string="Email Configuration" attrs="{'invisible':[('state','!=','email')]}">
|
||||
<separator colspan="4" string="Email Configuration"/>
|
||||
<field name="email" domain="[('model_id','=',model_id)]"/>
|
||||
<field name="subject" colspan="4"/>
|
||||
<field name="message" select="2" colspan="4"/>
|
||||
<newline/>
|
||||
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e. [[ object.partner_id.name ]]" align="0.0"/>
|
||||
@@ -1172,7 +1190,7 @@
|
||||
|
||||
<page string="Create / Write" attrs="{'invisible':[('state','!=','object_create'),('state','!=','object_write')]}">
|
||||
<separator colspan="4" string="Fields Mapping"/>
|
||||
<field name="srcmodel_id" select="2"/>
|
||||
<field name="srcmodel_id" select="2" attrs="{'required':[('state','!=','dummy'), ('state','!=','sms'), ('state','!=','code'), ('state','!=','loop'),('state','!=','trigger'), ('state','!=','client_action'), ('state','!=','email'), ('state','!=','sms'), ('state','!=','other')]}"/>
|
||||
<field name="fields_lines" nolabel="1" select="2" colspan="4">
|
||||
<tree string="Field Mappings" editable="top">
|
||||
<field name="col1" domain="[('model_id','=',parent.srcmodel_id or parent.model_id)]"/>
|
||||
@@ -1185,10 +1203,18 @@
|
||||
<field name="value" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
<field name="record_id" attrs="{'invisible':[('state','!=','object_create')]}" domain="[('model_id','in',[model_id])]"/>
|
||||
<field name="record_id" attrs="{'readonly':[('state','!=','object_create')]}" domain="[('model_id','in',[model_id])]"/>
|
||||
<field name="write_id" attrs="{'readonly':[('state','!=','object_write')]}"/>
|
||||
<label colspan="4" string="If you use a formula type, use a python expression using the variable 'object'." align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Iteration Actions" attrs="{'invisible':[('state','!=','loop')]}">
|
||||
<separator colspan="4" string="Iteration Action Configuration"/>
|
||||
<field name="loop_action" domain="[('state','!=','loop')]"/>
|
||||
<field name="expression" attrs="{'required':[('state','=','loop')]}"/>
|
||||
<label colspan="4" string="Define the expression that generate a list" align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Multi Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||
<separator colspan="4" string="Other Actions Configuration"/>
|
||||
<field name="child_ids" nolabel="1" colspan="4"/>
|
||||
@@ -1210,6 +1236,7 @@
|
||||
<tree string="Server Actions">
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
<field name="sequence"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -365,12 +365,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 " \
|
||||
@@ -386,52 +381,62 @@ 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'),
|
||||
('sms','SMS'),
|
||||
('object_create','Create Object'),
|
||||
('object_write','Write Object'),
|
||||
('other','Multi Actions'),
|
||||
], 'Action State', required=True, size=32),
|
||||
'code': fields.text('Python Code'),
|
||||
], 'Action Type', required=True, size=32),
|
||||
'code':fields.text('Python Code'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'model_id': fields.many2one('ir.model', 'Object', required=True),
|
||||
'action_id': fields.many2one('ir.actions.actions', 'Client Action'),
|
||||
'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
|
||||
'code': lambda *a: """# You can use the following variables
|
||||
# - object
|
||||
# - object2
|
||||
# - time
|
||||
# - cr
|
||||
# - uid
|
||||
# - ids
|
||||
# If you plan to return an action, assign: saction = {...}
|
||||
# If you plan to return an action, assign: action = {...}
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
def get_email(self, cr, uid, action, context):
|
||||
logger = netsvc.Logger()
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
@@ -453,7 +458,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)
|
||||
@@ -498,15 +502,31 @@ 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,
|
||||
'time':time,
|
||||
'cr': cr,
|
||||
'pool' : self.pool,
|
||||
'uid' : uid
|
||||
}
|
||||
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 !"))
|
||||
return self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context)
|
||||
|
||||
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
|
||||
|
||||
if action.state=='python':
|
||||
localdict = {
|
||||
'self': self.pool.get(action.model_id.model),
|
||||
@@ -522,14 +542,20 @@ class actions_server(osv.osv):
|
||||
|
||||
if action.state == 'email':
|
||||
user = config['email_from']
|
||||
subject = action.name
|
||||
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:
|
||||
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:
|
||||
@@ -556,13 +582,32 @@ class actions_server(osv.osv):
|
||||
logger.notifyChannel('sms', netsvc.LOG_ERROR, 'Failed to send SMS to : %s' % (action.address))
|
||||
|
||||
if action.state == 'other':
|
||||
res = None
|
||||
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 = 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:
|
||||
@@ -570,23 +615,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])
|
||||
obj_pool.write(cr, uid, [int(id[0][action.record_id.name])], res)
|
||||
|
||||
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:
|
||||
@@ -603,9 +660,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)
|
||||
self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})
|
||||
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):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -55,7 +55,7 @@ class ir_model(osv.osv):
|
||||
if model.state=='manual':
|
||||
if not model.model.startswith('x_'):
|
||||
return False
|
||||
if not re.match('^[a-z_A-Z0-9]+$',model.model):
|
||||
if not re.match('^[a-z_A-Z0-9.]+$',model.model):
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -193,9 +193,7 @@ class ir_model_fields(osv.osv):
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, size=64, select=1),
|
||||
'model': fields.char('Object Name', size=64, required=True),
|
||||
'relation_id':fields.many2one('ir.model', 'Object Relation'),
|
||||
'relation': fields.char('Object Relation', size=64),
|
||||
'relation_field_id':fields.many2one('ir.model.fields', 'Relation Field'),
|
||||
'relation_field': fields.char('Relation Field', size=64),
|
||||
'model_id': fields.many2one('ir.model', 'Object id', required=True, select=True, ondelete='cascade'),
|
||||
'field_description': fields.char('Field Label', required=True, size=256),
|
||||
@@ -233,38 +231,20 @@ class ir_model_fields(osv.osv):
|
||||
# MAY BE ADD A ALTER TABLE DROP ?
|
||||
#
|
||||
return super(ir_model_fields, self).unlink(cr, user, ids, context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
res = False
|
||||
if 'relation_id' in vals:
|
||||
model_data = self.pool.get('ir.model').browse(cr, uid, vals['relation_id'])
|
||||
vals['relation'] = model_data.model
|
||||
if 'relation_field_id' in vals:
|
||||
field_data = self.pool.get('ir.model.fields').browse(cr, uid, vals['relation_field_id'])
|
||||
vals['relation'] = field_data.name
|
||||
|
||||
res = super(ir_model_fields, self).write(cr, uid, ids, vals, context)
|
||||
return res
|
||||
|
||||
|
||||
def create(self, cr, user, vals, context=None):
|
||||
if 'relation_id' in vals:
|
||||
model_data = self.pool.get('ir.model').browse(cr,user,vals['relation_id'])
|
||||
vals['relation']=model_data.model
|
||||
if 'relation_field_id' in vals:
|
||||
field_data = self.pool.get('ir.model.fields').browse(cr, uid, vals['relation_field_id'])
|
||||
vals['relation_field'] = field_data.name
|
||||
if 'model_id' in vals:
|
||||
model_data=self.pool.get('ir.model').browse(cr,user,vals['model_id'])
|
||||
vals['model']=model_data.model
|
||||
model_data = self.pool.get('ir.model').browse(cr, user, vals['model_id'])
|
||||
vals['model'] = model_data.model
|
||||
if context and context.get('manual',False):
|
||||
vals['state']='manual'
|
||||
vals['state'] = 'manual'
|
||||
res = super(ir_model_fields,self).create(cr, user, vals, context)
|
||||
if vals.get('state','base')=='manual':
|
||||
if vals.get('state','base') == 'manual':
|
||||
if not vals['name'].startswith('x_'):
|
||||
raise except_orm(_('Error'), _("Custom fields must have a name that starts with 'x_' !"))
|
||||
if self.pool.get(vals['model']):
|
||||
self.pool.get(vals['model']).__init__(self.pool, cr)
|
||||
self.pool.get(vals['model'])._auto_init(cr,{})
|
||||
self.pool.get(vals['model'])._auto_init(cr, {})
|
||||
return res
|
||||
ir_model_fields()
|
||||
|
||||
@@ -298,7 +278,7 @@ class ir_model_access(osv.osv):
|
||||
model_name = model.name
|
||||
else:
|
||||
model_name = model
|
||||
|
||||
|
||||
if isinstance(group_ids, (int, long)):
|
||||
group_ids = [group_ids]
|
||||
for group_id in group_ids:
|
||||
@@ -324,7 +304,7 @@ class ir_model_access(osv.osv):
|
||||
|
||||
def check(self, cr, uid, model, mode='read', raise_exception=True):
|
||||
if uid==1:
|
||||
# User root have all accesses
|
||||
# User root have all accesses
|
||||
# TODO: exclude xml-rpc requests
|
||||
return True
|
||||
|
||||
@@ -335,7 +315,7 @@ class ir_model_access(osv.osv):
|
||||
model_name = model.name
|
||||
else:
|
||||
model_name = model
|
||||
|
||||
|
||||
# We check if a specific rule exists
|
||||
cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) '
|
||||
' FROM ir_model_access a '
|
||||
@@ -394,7 +374,7 @@ class ir_model_access(osv.osv):
|
||||
res = super(ir_model_access, self).write(cr, uid, *args, **argv)
|
||||
self.check() # clear the cache of check function
|
||||
return res
|
||||
|
||||
|
||||
def create(self, cr, uid, *args, **argv):
|
||||
res = super(ir_model_access, self).create(cr, uid, *args, **argv)
|
||||
self.check()
|
||||
|
||||
@@ -28,7 +28,7 @@ import os
|
||||
|
||||
def _check_xml(self, cr, uid, ids, context={}):
|
||||
for view in self.browse(cr, uid, ids, context):
|
||||
eview = etree.fromstring(view.arch)
|
||||
eview = etree.fromstring(view.arch.encode('utf8'))
|
||||
frng = tools.file_open(os.path.join('base','rng','view.rng'))
|
||||
relaxng = etree.RelaxNG(file=frng)
|
||||
if not relaxng.validate(eview):
|
||||
|
||||
@@ -206,7 +206,8 @@ class ir_values(osv.osv):
|
||||
del fields[pos]
|
||||
else:
|
||||
pos+=1
|
||||
datas = self.pool.get(model).read(cr, uid, [id], fields, context)[0]
|
||||
datas = self.pool.get(model).read(cr, uid, [id], fields, context)
|
||||
datas= datas and datas[0] or None
|
||||
if not datas:
|
||||
#ir_del(cr, uid, x[0])
|
||||
return False
|
||||
|
||||
@@ -461,7 +461,7 @@ class module(osv.osv):
|
||||
for lang in filter_lang:
|
||||
f = os.path.join(tools.config['addons_path'], mod.name, 'i18n', lang + '.po')
|
||||
if os.path.exists(f):
|
||||
logger.notifyChannel("init", netsvc.LOG_INFO, 'addon %s: loading translation file for language %s' % (mod.name, lang))
|
||||
logger.notifyChannel("init", netsvc.LOG_INFO, 'module %s: loading translation file for language %s' % (mod.name, lang))
|
||||
tools.trans_load(cr.dbname, f, lang, verbose=False)
|
||||
|
||||
module()
|
||||
|
||||
@@ -26,7 +26,6 @@ import base64
|
||||
import StringIO
|
||||
import csv
|
||||
import pooler
|
||||
|
||||
from osv import fields,osv
|
||||
|
||||
|
||||
@@ -51,7 +50,6 @@ class wizard_export_lang(osv.osv_memory):
|
||||
mods = map(lambda m: m.name, this.modules) or ['all']
|
||||
mods.sort()
|
||||
buf=StringIO.StringIO()
|
||||
|
||||
tools.trans_export(this.lang, mods, buf, this.format, dbname=cr.dbname)
|
||||
if this.format == 'csv':
|
||||
this.advice = _("Save this document to a .CSV file and open it with your favourite spreadsheet software. The file encoding is UTF-8. You have to translate the latest column before reimporting it.")
|
||||
@@ -64,7 +62,6 @@ class wizard_export_lang(osv.osv_memory):
|
||||
this.advice = _('Save this document to a .tgz file. This archive containt UTF-8 %s files and may be uploaded to launchpad.') % (ext,)
|
||||
|
||||
this.name = "%s.%s" % (this.lang or _('new'), this.format)
|
||||
|
||||
out=base64.encodestring(buf.getvalue())
|
||||
buf.close()
|
||||
return self.write(cr, uid, ids, {'state':'get', 'data':out, 'advice':this.advice, 'name':this.name}, context=context)
|
||||
|
||||
@@ -54,11 +54,8 @@ class wizard_lang_install(wizard.interface):
|
||||
modobj.update_translations(cr, uid, mids, lang)
|
||||
return {}
|
||||
|
||||
def _get_language(sel, cr, uid, context):
|
||||
return tools.scan_languages()
|
||||
|
||||
fields_form = {
|
||||
'lang': {'string':'Language', 'type':'selection', 'selection':_get_language,
|
||||
'lang': {'string':'Language', 'type':'selection', 'selection':tools.scan_languages(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ class res_partner(osv.osv):
|
||||
ref = res and res[0]['ref'] or '0'
|
||||
try:
|
||||
nextref = int(ref)+1
|
||||
except e:
|
||||
except:
|
||||
raise osv.except_osv(_('Warning'), _("Couldn't generate the next id because some partners have an alphabetic id !"))
|
||||
|
||||
# update the current partner
|
||||
|
||||
@@ -143,12 +143,12 @@ class res_company(osv.osv):
|
||||
|
||||
|
||||
<drawString x="1.3cm" y="27.2cm">[[ company.partner_id.name ]]</drawString>
|
||||
<drawString x="1.3cm" y="26.8cm">[[ company.partner_id.address and company.partner_id.address[0].street ]]</drawString>
|
||||
<drawString x="1.3cm" y="26.4cm">[[ 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 ]]</drawString>
|
||||
<drawString x="1.3cm" y="26.8cm">[[ company.partner_id.address and company.partner_id.address[0].street or '' ]]</drawString>
|
||||
<drawString x="1.3cm" y="26.4cm">[[ 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 '']]</drawString>
|
||||
<drawString x="1.3cm" y="26.0cm">Phone:</drawString>
|
||||
<drawRightString x="7cm" y="26.0cm">[[ company.partner_id.address and company.partner_id.address[0].phone ]]</drawRightString>
|
||||
<drawRightString x="7cm" y="26.0cm">[[ company.partner_id.address and company.partner_id.address[0].phone or '' ]]</drawRightString>
|
||||
<drawString x="1.3cm" y="25.6cm">Mail:</drawString>
|
||||
<drawRightString x="7cm" y="25.6cm">[[ company.partner_id.address and company.partner_id.address[0].email ]]</drawRightString>
|
||||
<drawRightString x="7cm" y="25.6cm">[[ company.partner_id.address and company.partner_id.address[0].email or '' ]]</drawRightString>
|
||||
<lines>1.3cm 25.5cm 7cm 25.5cm</lines>
|
||||
|
||||
<!--page bottom-->
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="image"/>
|
||||
<rng:ref name="form"/>
|
||||
<rng:ref name="vpaned"/>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
<rng:element name="properties"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
@@ -101,6 +102,15 @@
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="vpaned">
|
||||
<rng:element name="vpaned">
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:ref name="any" />
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="any">
|
||||
<rng:element>
|
||||
@@ -134,6 +144,9 @@
|
||||
<rng:ref name="button"/>
|
||||
<rng:ref name="form" />
|
||||
<rng:ref name="page" />
|
||||
<rng:ref name="notebook"/>
|
||||
<rng:ref name="hpaned"/>
|
||||
<rng:ref name="vpaned"/>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
|
||||
+19
-2
@@ -144,12 +144,16 @@ def service_exist(name):
|
||||
def get_rpc_paths():
|
||||
return map(lambda s: '/xmlrpc/%s' % s, _service)
|
||||
|
||||
|
||||
LOG_DEBUG_RPC = 'debug_rpc'
|
||||
LOG_DEBUG = 'debug'
|
||||
LOG_INFO = 'info'
|
||||
LOG_WARNING = 'warn'
|
||||
LOG_ERROR = 'error'
|
||||
LOG_CRITICAL = 'critical'
|
||||
|
||||
# add new log level below DEBUG
|
||||
logging.DEBUG_RPC = logging.DEBUG - 1
|
||||
|
||||
def init_logger():
|
||||
from tools import config
|
||||
@@ -188,6 +192,7 @@ def init_logger():
|
||||
background = lambda f: 40 + colors.index(f)
|
||||
|
||||
mapping = {
|
||||
'DEBUG_RPC': ('blue', 'white'),
|
||||
'DEBUG': ('blue', 'default'),
|
||||
'INFO': ('green', 'default'),
|
||||
'WARNING': ('yellow', 'default'),
|
||||
@@ -203,6 +208,11 @@ def init_logger():
|
||||
class Logger(object):
|
||||
def notifyChannel(self, name, level, msg):
|
||||
log = logging.getLogger(name)
|
||||
|
||||
if level == LOG_DEBUG_RPC and not hasattr(log, level):
|
||||
fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs)
|
||||
setattr(log, LOG_DEBUG_RPC, fct)
|
||||
|
||||
level_method = getattr(log, level)
|
||||
|
||||
result = str(msg).strip().split('\n')
|
||||
@@ -297,7 +307,7 @@ class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||
except:
|
||||
Logger().notifyChannel('init', LOG_ERROR, 'Address already in use')
|
||||
Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use')
|
||||
sys.exit(1)
|
||||
|
||||
class HttpDaemon(threading.Thread):
|
||||
@@ -368,6 +378,10 @@ class TinySocketClientThread(threading.Thread):
|
||||
threading.Thread.__init__(self)
|
||||
self.sock = sock
|
||||
self.threads = threads
|
||||
self._logger = Logger()
|
||||
|
||||
def log(self, msg):
|
||||
self._logger.notifyChannel('NETRPC', LOG_DEBUG_RPC, msg)
|
||||
|
||||
def run(self):
|
||||
import traceback
|
||||
@@ -388,6 +402,7 @@ class TinySocketClientThread(threading.Thread):
|
||||
self.threads.remove(self)
|
||||
return False
|
||||
try:
|
||||
self.log(msg)
|
||||
s = LocalService(msg[0])
|
||||
m = getattr(s, msg[1])
|
||||
s._service._response = None
|
||||
@@ -395,6 +410,7 @@ class TinySocketClientThread(threading.Thread):
|
||||
res = s._service._response
|
||||
if res != None:
|
||||
r = res
|
||||
self.log(r)
|
||||
ts.mysend(r)
|
||||
except Exception, e:
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
@@ -403,7 +419,8 @@ class TinySocketClientThread(threading.Thread):
|
||||
import pdb
|
||||
tb = sys.exc_info()[2]
|
||||
pdb.post_mortem(tb)
|
||||
e = Exception(e.message)
|
||||
e = Exception(str(e))
|
||||
self.log(str(e))
|
||||
ts.mysend(e, exception=True, traceback=tb_s)
|
||||
except:
|
||||
pass
|
||||
|
||||
+16
-6
@@ -284,10 +284,10 @@ class many2one(_column):
|
||||
_column.__init__(self, string=string, **args)
|
||||
self._obj = obj
|
||||
|
||||
#
|
||||
# TODO: speed improvement
|
||||
#
|
||||
# name is the name of the relation field
|
||||
def set_memory(self, cr, obj, id, field, values, user=None, context=None):
|
||||
obj.datas.setdefault(id, {})
|
||||
obj.datas[id][field] = values
|
||||
|
||||
def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None):
|
||||
result = {}
|
||||
for id in ids:
|
||||
@@ -426,6 +426,7 @@ class one2many(_column):
|
||||
context = {}
|
||||
if not values:
|
||||
return
|
||||
|
||||
_table = obj.pool.get(self._obj)._table
|
||||
obj = obj.pool.get(self._obj)
|
||||
for act in values:
|
||||
@@ -602,6 +603,9 @@ class function(_column):
|
||||
if store:
|
||||
self._classic_read = True
|
||||
self._classic_write = True
|
||||
if type=='binary':
|
||||
self._symbol_get=lambda x:x and str(x)
|
||||
|
||||
if type == 'float':
|
||||
self._symbol_c = float._symbol_c
|
||||
self._symbol_f = float._symbol_f
|
||||
@@ -688,15 +692,21 @@ class related(function):
|
||||
self._field_get2(cr, uid, obj, context)
|
||||
if not ids: return {}
|
||||
relation = obj._name
|
||||
res = {}
|
||||
res = {}.fromkeys(ids, False)
|
||||
objlst = obj.browse(cr, uid, ids)
|
||||
for data in objlst:
|
||||
if not data:
|
||||
continue
|
||||
t_data = data
|
||||
relation = obj._name
|
||||
for i in range(len(self.arg)):
|
||||
field_detail = self._relations[i]
|
||||
relation = field_detail['object']
|
||||
if not t_data[self.arg[i]]:
|
||||
try:
|
||||
if not t_data[self.arg[i]]:
|
||||
t_data = False
|
||||
break
|
||||
except:
|
||||
t_data = False
|
||||
break
|
||||
if field_detail['type'] in ('one2many', 'many2many'):
|
||||
|
||||
+13
-5
@@ -133,7 +133,6 @@ class browse_record(object):
|
||||
self._data[id] = {'id': id}
|
||||
|
||||
self._cache = cache
|
||||
pass
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name == 'id':
|
||||
@@ -930,6 +929,12 @@ class orm_template(object):
|
||||
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False):
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
def encode(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf8')
|
||||
return s
|
||||
|
||||
def _inherit_apply(src, inherit):
|
||||
def _find(node, node2):
|
||||
if node2.nodeType == node2.ELEMENT_NODE and node2.localName == 'xpath':
|
||||
@@ -952,9 +957,11 @@ class orm_template(object):
|
||||
if res:
|
||||
return res
|
||||
return None
|
||||
|
||||
|
||||
doc_src = dom.minidom.parseString(src)
|
||||
doc_dest = dom.minidom.parseString(inherit)
|
||||
netsvc.Logger().notifyChannel('orm', netsvc.LOG_DEBUG, type(src))
|
||||
doc_src = dom.minidom.parseString(encode(src))
|
||||
doc_dest = dom.minidom.parseString(encode(inherit))
|
||||
toparse = doc_dest.childNodes
|
||||
while len(toparse):
|
||||
node2 = toparse.pop(0)
|
||||
@@ -1069,7 +1076,7 @@ class orm_template(object):
|
||||
result['field_parent'] = False
|
||||
result['view_id'] = 0
|
||||
|
||||
doc = dom.minidom.parseString(result['arch'].encode('utf-8'))
|
||||
doc = dom.minidom.parseString(encode(result['arch']))
|
||||
xarch, xfields = self.__view_look_dom_arch(cr, user, doc, context=context)
|
||||
result['arch'] = xarch
|
||||
result['fields'] = xfields
|
||||
@@ -2070,7 +2077,8 @@ class orm(orm_template):
|
||||
'where id in ('+str_d+')', sub_ids)
|
||||
|
||||
for order, object, ids, fields in result_store:
|
||||
self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
|
||||
if object<>self._name:
|
||||
self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
|
||||
return True
|
||||
|
||||
#
|
||||
|
||||
+5
-3
@@ -37,9 +37,11 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False)
|
||||
pool_dic[db_name] = pool
|
||||
addons.load_modules(db, force_demo, status, update_module)
|
||||
cr = db.cursor()
|
||||
pool.init_set(cr, False)
|
||||
cr.commit()
|
||||
cr.close()
|
||||
try:
|
||||
pool.init_set(cr, False)
|
||||
cr.commit()
|
||||
finally:
|
||||
cr.close()
|
||||
|
||||
if not update_module:
|
||||
import report
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -204,7 +204,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)
|
||||
|
||||
+15
-22
@@ -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,15 +467,10 @@ class rml_parse(object):
|
||||
if isinstance(newtext, list):
|
||||
todo.append((key, newtext))
|
||||
else:
|
||||
if not isinstance(newtext, basestring):
|
||||
newtext = str(newtext)
|
||||
elif isinstance(newtext,unicode):
|
||||
pass
|
||||
elif isinstance(newtext,str):
|
||||
newtext = newtext.decode('utf8')
|
||||
# if there are two [[]] blocks the same, it will replace both
|
||||
# but it's ok because it should evaluate to the same thing
|
||||
# anyway
|
||||
newtext = tools.ustr(newtext)
|
||||
text = text.replace('[['+key+']]', newtext)
|
||||
self._node.data = text
|
||||
if len(todo):
|
||||
|
||||
+9
-1
@@ -140,6 +140,12 @@ class Cursor(object):
|
||||
self.sql_into_log[res_into.group(1)][1] += mdt.now() - now
|
||||
return res
|
||||
|
||||
def drop_view_if_exists(self, viewname):
|
||||
self._obj.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,))
|
||||
if self._obj.fetchone()[0]:
|
||||
self._obj.execute("DROP view %s" % (viewname,))
|
||||
self._obj.commit()
|
||||
|
||||
def print_log(self):
|
||||
def process(type):
|
||||
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log}
|
||||
@@ -220,13 +226,15 @@ class PoolManager(object):
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Connecting to %s' % (db_name,))
|
||||
PoolManager._pools[db_name] = ConnectionPool(ThreadedConnectionPool(1, PoolManager.maxconn, PoolManager.dsn(db_name)), db_name)
|
||||
except Exception, e:
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_CRITICAL, 'Unable to connect to %s: %s' % (db_name, e.message))
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_ERROR, 'Unable to connect to %s: %s' %
|
||||
(db_name, str(e)))
|
||||
raise
|
||||
return PoolManager._pools[db_name]
|
||||
get = staticmethod(get)
|
||||
|
||||
def close(db_name):
|
||||
if db_name in PoolManager._pools:
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Closing all connections to %s' % (db_name,))
|
||||
PoolManager._pools[db_name].closeall()
|
||||
del PoolManager._pools[db_name]
|
||||
|
||||
+7
-3
@@ -20,8 +20,12 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import ConfigParser,optparse,os,sys
|
||||
import netsvc,logging
|
||||
import ConfigParser
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
import netsvc
|
||||
import logging
|
||||
import release
|
||||
|
||||
class configmanager(object):
|
||||
@@ -66,7 +70,7 @@ class configmanager(object):
|
||||
'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise
|
||||
}
|
||||
|
||||
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG')])
|
||||
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC')])
|
||||
|
||||
version = "%s %s" % (release.description, release.version)
|
||||
parser = optparse.OptionParser(version=version)
|
||||
|
||||
@@ -493,7 +493,7 @@ form: module.record_id""" % (xml_id,)
|
||||
try:
|
||||
npid = self.pool.get('ir.model.data')._update_dummy(cr, self.uid, 'ir.ui.menu', self.module, xml_id, idx==len(m_l)-1)
|
||||
except:
|
||||
self.logger.notifyChannel('init', netsvc.LOG_ERROR, "addon: %s xml_id: %s" % (self.module, xml_id))
|
||||
self.logger.notifyChannel('init', netsvc.LOG_ERROR, "module: %s xml_id: %s" % (self.module, xml_id))
|
||||
else:
|
||||
# the menuitem does't exist but we are in branch (not a leaf)
|
||||
self.logger.notifyChannel("init", netsvc.LOG_WARNING, 'Warning no ID for submenu %s of menu %s !' % (menu_elem, str(m_l)))
|
||||
|
||||
+31
-1
@@ -715,11 +715,41 @@ def logged(f):
|
||||
|
||||
vector.append(' result: %s' % pformat(res))
|
||||
vector.append(' time delta: %s' % (time.time() - timeb4))
|
||||
#netsvc.Logger().notifyChannel('logged', netsvc.LOG_DEBUG, '\n'.join(vector))
|
||||
netsvc.Logger().notifyChannel('logged', netsvc.LOG_DEBUG, '\n'.join(vector))
|
||||
return res
|
||||
|
||||
return wrapper
|
||||
|
||||
def debug(what):
|
||||
"""
|
||||
This method allow you to debug your code without print
|
||||
Example:
|
||||
>>> def func_foo(bar)
|
||||
... baz = bar
|
||||
... debug(baz)
|
||||
... qnx = (baz, bar)
|
||||
... debug(qnx)
|
||||
...
|
||||
>>> func_foo(42)
|
||||
|
||||
This will output on the logger:
|
||||
|
||||
[Wed Dec 25 00:00:00 2008] DEBUG:func_foo:baz = 42
|
||||
[Wed Dec 25 00:00:00 2008] DEBUG:func_foo:qnx = (42, 42)
|
||||
|
||||
To view the DEBUG lines in the logger you must start the server with the option
|
||||
--log-level=debug
|
||||
|
||||
"""
|
||||
import netsvc
|
||||
from inspect import stack
|
||||
import re
|
||||
from pprint import pformat
|
||||
st = stack()[1]
|
||||
param = re.split("debug *\((.+)\)", st[4][0].strip())[1].strip()
|
||||
while param.count(')') > param.count('('): param = param[:param.rfind(')')]
|
||||
netsvc.Logger().notifyChannel(st[3], netsvc.LOG_DEBUG, "%s = %s" % (param, pformat(what)))
|
||||
|
||||
|
||||
icons = map(lambda x: (x,x), ['STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
|
||||
'STOCK_CANCEL', 'STOCK_CDROM', 'STOCK_CLEAR', 'STOCK_CLOSE', 'STOCK_COLOR_PICKER',
|
||||
|
||||
+37
-25
@@ -354,10 +354,17 @@ def trans_generate(lang, modules, dbname=None):
|
||||
tuple = (module, type, name, id, source)
|
||||
if source and tuple not in _to_translate:
|
||||
_to_translate.append(tuple)
|
||||
|
||||
|
||||
def encode(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf8')
|
||||
return s
|
||||
|
||||
for (xml_name,model,res_id,module) in cr.fetchall():
|
||||
xml_name = module+'.'+xml_name
|
||||
module = encode(module)
|
||||
model = encode(model)
|
||||
xml_name = "%s.%s" % (module, encode(xml_name))
|
||||
|
||||
if not pool.get(model):
|
||||
logger.notifyChannel("db", netsvc.LOG_ERROR, "unable to find object %r" % (model,))
|
||||
continue
|
||||
@@ -365,9 +372,9 @@ def trans_generate(lang, modules, dbname=None):
|
||||
if model=='ir.ui.view':
|
||||
d = xml.dom.minidom.parseString(obj.arch)
|
||||
for t in trans_parse_view(d.documentElement):
|
||||
push_translation(module, 'view', obj.model, 0, t)
|
||||
push_translation(module, 'view', encode(obj.model), 0, t)
|
||||
elif model=='ir.actions.wizard':
|
||||
service_name = 'wizard.'+obj.wiz_name
|
||||
service_name = 'wizard.'+encode(obj.wiz_name)
|
||||
try:
|
||||
obj2 = netsvc._service[service_name]
|
||||
except KeyError, exc:
|
||||
@@ -378,18 +385,23 @@ def trans_generate(lang, modules, dbname=None):
|
||||
result = state_def['result']
|
||||
if result['type'] != 'form':
|
||||
continue
|
||||
name = obj.wiz_name + ',' + state_name
|
||||
name = "%s,%s" % (encode(obj.wiz_name), state_name)
|
||||
|
||||
def_params = {
|
||||
'string': ('wizard_field', lambda s: [encode(s)]),
|
||||
'selection': ('selection', lambda s: [encode(e[1]) for e in s]),
|
||||
'help': ('help', lambda s: [encode(s)]),
|
||||
}
|
||||
|
||||
# export fields
|
||||
for field_name, field_def in result['fields'].iteritems():
|
||||
res_name = name + ',' + field_name
|
||||
if 'string' in field_def:
|
||||
source = field_def['string']
|
||||
push_translation(module, 'wizard_field', res_name, 0, source.encode('utf8'))
|
||||
|
||||
if 'selection' in field_def:
|
||||
for key, val in field_def['selection']:
|
||||
push_translation(module, 'selection', res_name, 0, val.encode('utf8'))
|
||||
|
||||
for fn in def_params:
|
||||
if fn in field_def:
|
||||
transtype, modifier = def_params[fn]
|
||||
for val in modifier(field_def[fn]):
|
||||
push_translation(module, transtype, res_name, 0, val)
|
||||
|
||||
# export arch
|
||||
arch = result['arch']
|
||||
@@ -407,7 +419,7 @@ def trans_generate(lang, modules, dbname=None):
|
||||
|
||||
elif model=='ir.model.fields':
|
||||
try:
|
||||
field_name = obj.name
|
||||
field_name = encode(obj.name)
|
||||
except AttributeError, exc:
|
||||
logger.notifyChannel("db", netsvc.LOG_ERROR, "name error in %s: %s" % (xml_name,str(exc)))
|
||||
continue
|
||||
@@ -416,11 +428,11 @@ def trans_generate(lang, modules, dbname=None):
|
||||
continue
|
||||
field_def = objmodel._columns[field_name]
|
||||
|
||||
name = obj.model + "," + field_name
|
||||
push_translation(module, 'field', name, 0, field_def.string.encode('utf8'))
|
||||
name = "%s,%s" % (encode(obj.model), field_name)
|
||||
push_translation(module, 'field', name, 0, encode(field_def.string))
|
||||
|
||||
if field_def.help:
|
||||
push_translation(module, 'help', name, 0, field_def.help.encode('utf8'))
|
||||
push_translation(module, 'help', name, 0, encode(field_def.help))
|
||||
|
||||
if field_def.translate:
|
||||
ids = objmodel.search(cr, uid, [])
|
||||
@@ -434,14 +446,14 @@ def trans_generate(lang, modules, dbname=None):
|
||||
('res_id', '=', res_id),
|
||||
])
|
||||
if not model_data_ids:
|
||||
push_translation(module, 'model', name, 0, obj_value[field_name])
|
||||
push_translation(module, 'model', name, 0, encode(obj_value[field_name]))
|
||||
|
||||
if hasattr(field_def, 'selection') and isinstance(field_def.selection, (list, tuple)):
|
||||
for key, val in field_def.selection:
|
||||
push_translation(module, 'selection', name, 0, val.encode('utf8'))
|
||||
push_translation(module, 'selection', name, 0, encode(val))
|
||||
|
||||
elif model=='ir.actions.report.xml':
|
||||
name = obj.report_name
|
||||
name = encode(obj.report_name)
|
||||
fname = ""
|
||||
if obj.report_rml:
|
||||
fname = obj.report_rml
|
||||
@@ -462,7 +474,7 @@ def trans_generate(lang, modules, dbname=None):
|
||||
|
||||
for constraint in pool.get(model)._constraints:
|
||||
msg = constraint[1]
|
||||
push_translation(module, 'constraint', model, 0, msg.encode('utf8'))
|
||||
push_translation(module, 'constraint', model, 0, encode(msg))
|
||||
|
||||
for field_name,field_def in pool.get(model)._columns.items():
|
||||
if field_def.translate:
|
||||
@@ -471,7 +483,7 @@ def trans_generate(lang, modules, dbname=None):
|
||||
trad = getattr(obj, field_name) or ''
|
||||
except:
|
||||
trad = ''
|
||||
push_translation(module, 'model', name, xml_name, trad)
|
||||
push_translation(module, 'model', name, xml_name, encode(trad))
|
||||
|
||||
# parse source code for _() calls
|
||||
def get_module_from_path(path):
|
||||
@@ -497,15 +509,15 @@ def trans_generate(lang, modules, dbname=None):
|
||||
'[^a-zA-Z0-9_]_\([\s]*["\'](.+?)["\'][\s]*\)',
|
||||
code_string, re.M)
|
||||
for i in iter:
|
||||
push_translation(module, 'code', frelativepath, 0, i.group(1).encode('utf8'))
|
||||
push_translation(module, 'code', frelativepath, 0, encode(i.group(1)))
|
||||
|
||||
|
||||
out = [["module","type","name","res_id","src","value"]] # header
|
||||
# translate strings marked as to be translated
|
||||
for module, type, name, id, source in _to_translate:
|
||||
trans = trans_obj._get_source(cr, uid, name, type, lang, source)
|
||||
out.append([module, type, name, id, source, trans or ''])
|
||||
|
||||
out.append([module, type, name, id, source, encode(trans) or ''])
|
||||
|
||||
cr.close()
|
||||
return out
|
||||
|
||||
@@ -519,7 +531,7 @@ def trans_load(db_name, filename, lang, strict=False, verbose=True):
|
||||
return r
|
||||
except IOError:
|
||||
if verbose:
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,)) # FIXME translate message
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
|
||||
return None
|
||||
|
||||
def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=None, verbose=True):
|
||||
|
||||
@@ -113,15 +113,22 @@ class interface(netsvc.Service):
|
||||
if lang:
|
||||
# translate fields
|
||||
for field in fields:
|
||||
trans = translate(cr, self.wiz_name+','+state+','+field, 'wizard_field', lang)
|
||||
res_name = "%s,%s,%s" % (self.wiz_name, state, field)
|
||||
|
||||
trans = translate(cr, res_name, 'wizard_field', lang)
|
||||
if trans:
|
||||
fields[field]['string'] = trans
|
||||
|
||||
if 'selection' in fields[field]:
|
||||
trans = lambda x: translate(cr, self.wiz_name+','+state+','+field, 'selection', lang, x) or x
|
||||
trans = lambda x: translate(cr, res_name, 'selection', lang, x) or x
|
||||
for idx, (key, val) in enumerate(fields[field]['selection']):
|
||||
fields[field]['selection'][idx] = (key, trans(val))
|
||||
|
||||
if 'help' in fields[field]:
|
||||
t = translate(cr, res_name, 'help', lang, fields[field]['help'])
|
||||
if t:
|
||||
fields[field]['help'] = t
|
||||
|
||||
# translate arch
|
||||
if not isinstance(arch, UpdateableStr):
|
||||
doc = dom.minidom.parseString(arch)
|
||||
|
||||
Reference in New Issue
Block a user