Merge commit 'origin/master' into mdv-gpl3
Conflicts: bin/report/interface.py bin/tools/translate.py bzr revid: p_christ@hol.gr-20081215095422-9jc4m1qrknku6ux8
This commit is contained in:
commit
087f5bc171
|
@ -138,7 +138,7 @@ def get_module_path(module):
|
|||
if os.path.exists(opj(_ad, module)) or os.path.exists(opj(_ad, '%s.zip' % module)):
|
||||
return opj(_ad, module)
|
||||
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon %s: module not found' % (module,))
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,))
|
||||
return False
|
||||
raise IOError, 'Module not found : %s' % module
|
||||
|
||||
|
@ -216,7 +216,7 @@ def create_graph(module_list, force=None):
|
|||
try:
|
||||
info = eval(tools.file_open(terp_file).read())
|
||||
except:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon %s: eval file %s' % (module, terp_file))
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'module %s: eval file %s' % (module, terp_file))
|
||||
raise
|
||||
if info.get('installable', True):
|
||||
packages.append((module, info.get('depends', []), info))
|
||||
|
@ -246,17 +246,24 @@ def create_graph(module_list, force=None):
|
|||
|
||||
for package in later:
|
||||
unmet_deps = filter(lambda p: p not in graph, dependencies[package])
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps)))
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'module %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps)))
|
||||
|
||||
return graph
|
||||
|
||||
def init_module_objects(cr, module_name, obj_list):
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: creating or updating database tables' % module_name)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: creating or updating database tables' % module_name)
|
||||
todo = []
|
||||
for obj in obj_list:
|
||||
if hasattr(obj, 'init'):
|
||||
obj.init(cr)
|
||||
obj._auto_init(cr, {'module': module_name})
|
||||
result = obj._auto_init(cr, {'module': module_name})
|
||||
if result:
|
||||
todo += result
|
||||
cr.commit()
|
||||
todo.sort()
|
||||
for t in todo:
|
||||
t[1](cr, *t[2])
|
||||
cr.commit()
|
||||
|
||||
#
|
||||
|
@ -266,7 +273,7 @@ def register_class(m):
|
|||
global loaded
|
||||
if m in loaded:
|
||||
return
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: registering classes' % m)
|
||||
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'):
|
||||
|
@ -380,7 +387,7 @@ class MigrationManager(object):
|
|||
|
||||
from tools.parse_version import parse_version
|
||||
|
||||
parsed_installed_version = parse_version(pkg.latest_version)
|
||||
parsed_installed_version = parse_version(pkg.installed_version or '')
|
||||
current_version = parse_version(convert_version(pkg.data.get('version', '0')))
|
||||
|
||||
versions = _get_migration_versions(pkg)
|
||||
|
@ -401,20 +408,20 @@ class MigrationManager(object):
|
|||
mod = None
|
||||
try:
|
||||
mod = imp.load_source(name, pyfile, fp)
|
||||
logger.notifyChannel('migration', netsvc.LOG_INFO, 'addon %(addon)s: Running migration %(version)s %(name)s"' % mergedict({'name': mod.__name__},strfmt))
|
||||
mod.migrate(self.cr, pkg.latest_version)
|
||||
logger.notifyChannel('migration', netsvc.LOG_INFO, 'module %(addon)s: Running migration %(version)s %(name)s"' % mergedict({'name': mod.__name__},strfmt))
|
||||
mod.migrate(self.cr, pkg.installed_version)
|
||||
except ImportError:
|
||||
logger.notifyChannel('migration', netsvc.LOG_ERROR, 'addon %(addon)s: Unable to load %(stage)-migration file %(file)s' % mergedict({'file': opj(modulename,pyfile)}, strfmt))
|
||||
logger.notifyChannel('migration', netsvc.LOG_ERROR, 'module %(addon)s: Unable to load %(stage)-migration file %(file)s' % mergedict({'file': opj(modulename,pyfile)}, strfmt))
|
||||
raise
|
||||
except AttributeError:
|
||||
logger.notifyChannel('migration', netsvc.LOG_ERROR, 'addon %(addon)s: Each %(stage)-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
|
||||
logger.notifyChannel('migration', netsvc.LOG_ERROR, 'module %(addon)s: Each %(stage)-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
|
||||
except:
|
||||
raise
|
||||
fp.close()
|
||||
del mod
|
||||
|
||||
|
||||
def load_module_graph(cr, graph, status=None, **kwargs):
|
||||
def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs):
|
||||
# **kwargs is passed directly to convert_xml_import
|
||||
if not status:
|
||||
status={}
|
||||
|
@ -427,13 +434,14 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
|
||||
# update the graph with values from the database (if exist)
|
||||
## First, we set the default values for each package in graph
|
||||
additional_data = dict.fromkeys([p.name for p in graph], {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'latest_version': None})
|
||||
additional_data = dict.fromkeys([p.name for p in graph], {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'installed_version': None})
|
||||
## Then we get the values from the database
|
||||
cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version'
|
||||
cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version'
|
||||
' FROM ir_module_module'
|
||||
' WHERE name in (%s)' % (','.join(['%s'] * len(graph))),
|
||||
additional_data.keys()
|
||||
)
|
||||
|
||||
## and we update the default values with values from the database
|
||||
additional_data.update(dict([(x.pop('name'), x) for x in cr.dictfetchall()]))
|
||||
|
||||
|
@ -443,6 +451,7 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
|
||||
migrations = MigrationManager(cr, graph)
|
||||
|
||||
check_rules = False
|
||||
for package in graph:
|
||||
status['progress'] = (float(statusi)+0.1)/len(graph)
|
||||
m = package.name
|
||||
|
@ -451,19 +460,20 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
migrations.migrate_module(package, 'pre')
|
||||
|
||||
register_class(m)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s' % m)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s loading objects' % m)
|
||||
modules = pool.instanciate(m, cr)
|
||||
|
||||
idref = {}
|
||||
status['progress'] = (float(statusi)+0.4)/len(graph)
|
||||
if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'):
|
||||
check_rules = True
|
||||
init_module_objects(cr, m, modules)
|
||||
for kind in ('init', 'update'):
|
||||
for filename in package.data.get('%s_xml' % kind, []):
|
||||
mode = 'update'
|
||||
if hasattr(package, 'init') or package.state=='to install':
|
||||
mode = 'init'
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: loading %s' % (m, filename))
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, filename))
|
||||
name, ext = os.path.splitext(filename)
|
||||
fp = tools.file_open(opj(m, filename))
|
||||
if ext == '.csv':
|
||||
|
@ -481,17 +491,18 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
status['progress'] = (float(statusi)+0.75)/len(graph)
|
||||
for xml in package.data.get('demo_xml', []):
|
||||
name, ext = os.path.splitext(xml)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: loading %s' % (m, xml))
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, xml))
|
||||
fp = tools.file_open(opj(m, xml))
|
||||
if ext == '.csv':
|
||||
tools.convert_csv_import(cr, m, os.path.basename(xml), fp.read(), idref, noupdate=True)
|
||||
else:
|
||||
tools.convert_xml_import(cr, m, fp, idref, noupdate=True, **kwargs)
|
||||
fp.close()
|
||||
cr.execute('update ir_module_module set demo=%s where id=%d', (True, mid))
|
||||
cr.execute('update ir_module_module set demo=%s where id=%s', (True, mid))
|
||||
package_todo.append(package.name)
|
||||
ver = release.major_version + '.' + package.data.get('version', '1.0')
|
||||
cr.execute("update ir_module_module set state='installed', latest_version=%s where id=%d", (ver, mid,))
|
||||
# update the installed version in database...
|
||||
cr.execute("update ir_module_module set state='installed', latest_version=%s where id=%s", (ver, mid,))
|
||||
cr.commit()
|
||||
|
||||
# Set new modules and dependencies
|
||||
|
@ -501,18 +512,18 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
|||
if modobj:
|
||||
modobj.update_translations(cr, 1, [mid], None)
|
||||
cr.commit()
|
||||
|
||||
|
||||
migrations.migrate_module(package, 'post')
|
||||
|
||||
statusi+=1
|
||||
|
||||
if check_access_rules and check_rules:
|
||||
cr.execute("""select model,name from ir_model where id not in (select model_id from ir_model_access)""")
|
||||
for (model,name) in cr.fetchall():
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon object %s (%s) has no access rules!' % (model,name))
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'object %s (%s) has no access rules!' % (model,name))
|
||||
|
||||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
cr.execute('select * from ir_model where state=%s', ('manual',))
|
||||
cr.execute('select model from ir_model where state=%s', ('manual',))
|
||||
for model in cr.dictfetchall():
|
||||
pool.get('ir.model').instanciate(cr, 1, model['model'], {})
|
||||
|
||||
|
@ -527,31 +538,46 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
if force_demo:
|
||||
force.append('demo')
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
report = tools.assertion_report()
|
||||
if update_module:
|
||||
for module in tools.config['init']:
|
||||
cr.execute('update ir_module_module set state=%s where state=%s and name=%s', ('to install', 'uninstalled', module))
|
||||
cr.commit()
|
||||
basegraph = create_graph(['base'], force)
|
||||
load_module_graph(cr, basegraph, status, check_access_rules=False, report=report)
|
||||
|
||||
register_class('base')
|
||||
pool.instanciate('base', cr)
|
||||
modobj = pool.get('ir.module.module')
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list')
|
||||
cr.execute("select id from ir_module_module where state in ('to install','to upgrade') and name=%s", ('base',))
|
||||
if cr.rowcount:
|
||||
modobj.update_list(cr, 1)
|
||||
|
||||
mids = modobj.search(cr, 1, [('state','in',('installed','to install'))])
|
||||
for m in modobj.browse(cr, 1, mids):
|
||||
for dep in m.dependencies_id:
|
||||
if dep.state=='uninstalled':
|
||||
modobj.button_install(cr, 1, [m.id])
|
||||
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)
|
||||
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade','to remove')")
|
||||
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', 'to remove')")
|
||||
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)
|
||||
report = tools.assertion_report()
|
||||
|
||||
# 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, 'assert: %s' % report)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, report)
|
||||
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
tools.config[kind]={}
|
||||
|
@ -563,17 +589,13 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
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():
|
||||
#
|
||||
# TO BE Improved:
|
||||
# I can not use the class_pool has _table could be defined in __init__
|
||||
# and I can not use the pool has the module could not be loaded in the pool
|
||||
#
|
||||
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
|
||||
|
@ -582,10 +604,14 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
(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)
|
||||
#pooler.restart_pool(cr.dbname)
|
||||
cr.close()
|
||||
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
##############################################################################
|
||||
{
|
||||
"name" : "Base",
|
||||
"version" : "1.0",
|
||||
"version" : "1.1",
|
||||
"author" : "Tiny",
|
||||
"website" : "http://openerp.com",
|
||||
"website" : "http://www.openerp.com",
|
||||
"category" : "Generic Modules/Base",
|
||||
"description": "The kernel of OpenERP, needed for all installation.",
|
||||
"depends" : [],
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
<openerp>
|
||||
<data>
|
||||
<menuitem icon="terp-administration" id="menu_administration" name="Administration" sequence="20"/>
|
||||
<menuitem id="menu_custom" name="Custom" parent="base.menu_administration" sequence="2"/>
|
||||
<menuitem id="next_id_4" name="Low Level Objects" parent="base.menu_administration" sequence="3"/>
|
||||
<menuitem id="menu_low_workflow" name="Workflow Items" parent="base.next_id_4"/>
|
||||
<menuitem id="menu_custom" name="Customization" parent="base.menu_administration" sequence="2"/>
|
||||
<menuitem id="menu_custom_action" name="Actions" parent="base.menu_custom" sequence="20"/>
|
||||
<menuitem id="menu_config" name="Configuration" parent="base.menu_administration" sequence="1"/>
|
||||
<menuitem id="menu_translation" name="Translations" parent="base.menu_administration" sequence="4"/>
|
||||
<menuitem id="menu_translation_app" name="Application Terms" parent="base.menu_translation" sequence="4"/>
|
||||
<menuitem id="menu_translation_export" name="Import / Export" parent="base.menu_translation" sequence="4"/>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
Languages
|
||||
======================
|
||||
-->
|
||||
<menuitem id="next_id_2" name="Interface" parent="base.menu_custom"/>
|
||||
<menuitem id="next_id_2" name="User Interface" parent="base.menu_custom"/>
|
||||
|
||||
<!--
|
||||
======================
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</record>
|
||||
|
||||
<record id="act_values_form" model="ir.actions.act_window">
|
||||
<field name="name">Values</field>
|
||||
<field name="name">Client Actions Connections</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">ir.values</field>
|
||||
<field name="view_type">form</field>
|
||||
|
@ -49,7 +49,6 @@
|
|||
<field name="context">{'read':'default'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="next_id_4" name="Low Level" parent="menu_custom"/>
|
||||
<menuitem action="act_values_form" id="menu_values_form" parent="next_id_4"/>
|
||||
|
||||
<!-- Sequences -->
|
||||
|
@ -114,7 +113,7 @@
|
|||
<field name="view_id" ref="sequence_view_tree"/>
|
||||
<field name="context">{'active_test': False}</field>
|
||||
</record>
|
||||
<menuitem id="next_id_5" name="Sequences" parent="base.menu_custom"/>
|
||||
<menuitem id="next_id_5" name="Sequences" parent="base.menu_config"/>
|
||||
<menuitem action="ir_sequence_form" id="menu_ir_sequence_form" parent="next_id_5"/>
|
||||
|
||||
<!-- Sequences Types -->
|
||||
|
@ -152,7 +151,6 @@
|
|||
<field name="name" select="1"/>
|
||||
<field name="type" select="1"/>
|
||||
<field name="usage"/>
|
||||
<field name="parent_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -465,7 +463,7 @@
|
|||
<field name="model">ir.ui.view</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="User Interface - Views">
|
||||
<form string="Views">
|
||||
<field name="name" select="1"/>
|
||||
<field name="type" select="1"/>
|
||||
<field name="model" select="1"/>
|
||||
|
@ -481,7 +479,7 @@
|
|||
<field name="model">ir.ui.view</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<tree string="Views">
|
||||
<field name="name"/>
|
||||
<field name="type"/>
|
||||
<field name="model"/>
|
||||
|
@ -489,7 +487,7 @@
|
|||
</field>
|
||||
</record>
|
||||
<record id="action_ui_view" model="ir.actions.act_window">
|
||||
<field name="name">View</field>
|
||||
<field name="name">Views</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">ir.ui.view</field>
|
||||
<field name="view_id" ref="view_view_tree"/>
|
||||
|
@ -690,9 +688,9 @@
|
|||
<group colspan="2" col="2">
|
||||
<separator string="Field Type" colspan="2"/>
|
||||
<field name="ttype" select="2"/>
|
||||
<field name="relation" select="2" attrs="{'required': [('ttype','in',['many2one','one2many','many2many'])],
|
||||
'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>
|
||||
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')],
|
||||
<field name="relation_id" select="2" 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')],
|
||||
'readonly': [('ttype','!=','one2many')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
|
||||
|
@ -720,7 +718,7 @@
|
|||
</page>
|
||||
<page string="Access Rights">
|
||||
<field colspan="4" name="access_ids" select="1" nolabel="1">
|
||||
<tree string="Access Rules" editable="bottom" colspan="4">
|
||||
<tree string="Access Rules" editable="bottom">
|
||||
<field name="group_id"/>
|
||||
<field name="perm_read"/>
|
||||
<field name="perm_write"/>
|
||||
|
@ -769,9 +767,11 @@
|
|||
<page string="Properties">
|
||||
<group colspan="2" col="2">
|
||||
<field name="ttype" select="2"/>
|
||||
<field name="relation" select="2" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
|
||||
<field name="relation_id" select="2" on_change="on_relation_change(relation_id)" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
|
||||
'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>
|
||||
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')],
|
||||
<!-- <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="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
|
||||
|
@ -787,7 +787,7 @@
|
|||
<field name="on_delete" attrs="{'readonly': [('ttype','!=','many2one')]}"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Security on Groups" colspan="4">
|
||||
<page string="Security on Groups">
|
||||
<field name="groups" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
|
@ -934,7 +934,7 @@
|
|||
</field>
|
||||
</record>
|
||||
<record id="grant_menu_access" model="ir.actions.act_window">
|
||||
<field name="name">Grant access to menu</field>
|
||||
<field name="name">Grant Access To Menus</field>
|
||||
<field name="res_model">ir.ui.menu</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="edit_menu"/>
|
||||
|
@ -992,7 +992,7 @@
|
|||
<field name="context">{'active_test': False}</field>
|
||||
<field name="view_id" ref="ir_cron_view_tree"/>
|
||||
</record>
|
||||
<menuitem id="next_id_10" name="Scheduler" parent="base.menu_custom"/>
|
||||
<menuitem id="next_id_10" name="Scheduler" parent="base.menu_config"/>
|
||||
<menuitem action="ir_cron_act" id="menu_ir_cron_act" parent="next_id_10"/>
|
||||
|
||||
|
||||
|
@ -1143,15 +1143,16 @@
|
|||
<field name="model_id" select="1"/>
|
||||
<field name="sequence" select="2"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Python Code" attrs="{'invisible':[('state','!=','python')]}">
|
||||
<!--<page string="Python Code" attrs="{'invisible':[('state','!=','python')]}">
|
||||
<separator colspan="4" string="Python code"/>
|
||||
<field name="code" colspan="4" nolabel="1" />
|
||||
<button string="Create Action" name="%(wizard_server_action_create)d" type="action"/>
|
||||
</page>
|
||||
|
||||
<page string="Trigger" attrs="{'invisible':[('state','!=','trigger')]}">
|
||||
--><page string="Trigger" attrs="{'invisible':[('state','!=','trigger')]}">
|
||||
<separator colspan="4" string="Trigger Configuration"/>
|
||||
<field name="trigger_obj_id" select="2" colspan="4"/>
|
||||
<field name="wkf_model_id"/>
|
||||
<field name="trigger_obj_id" select="2" domain="[('model_id','=',model_id)]" on_change="on_trigger_obj_id(trigger_obj_id)"/>
|
||||
<field name="trigger_name" select="2"/>
|
||||
</page>
|
||||
|
||||
|
@ -1159,42 +1160,49 @@
|
|||
<field name="action_id" select="2" colspan="4"/>
|
||||
</page>
|
||||
|
||||
<page string="Email / SMS" attrs="{'invisible':[('state','!=','sms'),('state','!=','email')]}">
|
||||
<page string="Email Configuration" attrs="{'invisible':[('state','!=','email')]}">
|
||||
<separator colspan="4" string="Email Configuration"/>
|
||||
<field name="address" domain="[('model_id','=',model_id)]"/>
|
||||
<field name="sms" colspan="4" attrs="{'readonly':[('state','!=','sms')]}"/>
|
||||
<field name="message" select="2" colspan="4" attrs="{'readonly':[('state','!=','email')]}" />
|
||||
<field name="email" domain="[('model_id','=',model_id)]"/>
|
||||
<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"/>
|
||||
</page>
|
||||
|
||||
<page string="SMS Configuration" attrs="{'invisible':[('state','!=','sms')]}">
|
||||
<separator colspan="4" string="SMS Configuration"/>
|
||||
<field name="mobile" domain="[('model_id','=',model_id)]"/>
|
||||
<field name="sms" 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"/>
|
||||
</page>
|
||||
|
||||
<page string="Create / Write" attrs="{'invisible':[('state','!=','object_create'),('state','!=','object_write')]}">
|
||||
<separator colspan="4" string="Fields Mapping"/>
|
||||
<field name="otype"/>
|
||||
<field name="srcmodel_id" select="2"/>
|
||||
<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)]"/>
|
||||
<field name="type"/>
|
||||
<field name="value" colsapan="4"/>
|
||||
<field name="value" colspan="4"/>
|
||||
</tree>
|
||||
<form string="Field Mapping">
|
||||
<field name="col1" domain="[('model_id','=',parent.srcmodel_id or parent.model_id)]"/>
|
||||
<field name="type"/>
|
||||
<field name="value" colsapan="4"/>
|
||||
<field name="value" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
<field name="record_id" attrs="{'invisible':[('state','!=','object_create')]}" domain="[('model_id','in',[model_id])]"/>
|
||||
<label colspan="4" string="If you use a formula type, use a python expression using the variable 'object'." align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Other Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||
<page string="Multi Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||
<separator colspan="4" string="Other Actions Configuration"/>
|
||||
<field name="child_ids" nolabel="1" colspan="4" />
|
||||
<field name="child_ids" nolabel="1" colspan="4"/>
|
||||
<label colspan="4" string="Only one client action will be execute, last clinent action will be consider in case of multipls clinets actions" align="0.0"/>
|
||||
</page>
|
||||
|
||||
</notebook>
|
||||
<field name="usage"/>
|
||||
<field name="type"/>
|
||||
<field name="type" readonly="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -1219,7 +1227,7 @@
|
|||
<field name="view_id" ref="view_server_action_tree"/>
|
||||
<field name="context">{'key':'server_action'}</field>
|
||||
</record>
|
||||
<menuitem action="action_server_action" id="menu_server_action" parent="base.next_id_6"/>
|
||||
<menuitem action="action_server_action" id="menu_server_action" parent="base.menu_custom_action"/>
|
||||
|
||||
<record id="view_model_fields_tree" model="ir.ui.view">
|
||||
<field name="name">ir.model.fields.tree</field>
|
||||
|
@ -1279,7 +1287,8 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="domain">[('type','=','configure')]</field>
|
||||
</record>
|
||||
<menuitem id="next_id_11" name="Configuration Wizards" parent="base.menu_custom"/><menuitem action="act_ir_actions_todo_form" id="menu_ir_actions_todo_form" parent="next_id_11"/>
|
||||
<menuitem id="next_id_11" name="Configuration Wizards" parent="base.menu_config" sequence="1"/>
|
||||
<menuitem action="act_ir_actions_todo_form" id="menu_ir_actions_todo_form" parent="next_id_11"/>
|
||||
|
||||
<record id="view_config_wizard_form" model="ir.ui.view">
|
||||
<field name="name">Main Configuration Wizard</field>
|
||||
|
|
|
@ -34,7 +34,6 @@ class actions(osv.osv):
|
|||
'name': fields.char('Action Name', required=True, size=64),
|
||||
'type': fields.char('Action Type', required=True, size=32),
|
||||
'usage': fields.char('Action Usage', size=32),
|
||||
'parent_id': fields.many2one('ir.actions.server', 'Parent Action'),
|
||||
}
|
||||
_defaults = {
|
||||
'usage': lambda *a: False,
|
||||
|
@ -291,7 +290,7 @@ class ir_model_fields(osv.osv):
|
|||
'complete_name': fields.char('Complete Name', size=64, select=1),
|
||||
}
|
||||
|
||||
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80):
|
||||
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=800):
|
||||
def get_fields(cr, uid, field, rel):
|
||||
result = []
|
||||
mobj = self.pool.get('ir.model')
|
||||
|
@ -366,6 +365,23 @@ server_object_lines()
|
|||
# Actions that are run on the server side
|
||||
#
|
||||
class actions_server(osv.osv):
|
||||
|
||||
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 " \
|
||||
" and t.act_from = a.wkf_id " \
|
||||
" or t.act_to = a.wkf_id ")
|
||||
return cr.fetchall()
|
||||
|
||||
def on_trigger_obj_id(self, cr, uid, ids, context={}):
|
||||
cr.execute("select distinct t.signal as key, t.signal as val from wkf w, wkf_activity a, wkf_transition t "\
|
||||
" where w.id = a.wkf_id " \
|
||||
" and t.act_from = a.wkf_id " \
|
||||
" or t.act_to = a.wkf_id " \
|
||||
" and w.osv = %s ", ('account.invoice'))
|
||||
data = cr.fetchall()
|
||||
return {"values":{'trigger_name':data}}
|
||||
|
||||
_name = 'ir.actions.server'
|
||||
_table = 'ir_act_server'
|
||||
_sequence = 'ir_actions_id_seq'
|
||||
|
@ -373,33 +389,31 @@ class actions_server(osv.osv):
|
|||
'name': fields.char('Action Name', required=True, size=64),
|
||||
'state': fields.selection([
|
||||
('client_action','Client Action'),
|
||||
('python','Python Code'),
|
||||
('dummy','Dummy'),
|
||||
('trigger','Trigger'),
|
||||
('email','Email'),
|
||||
('sms','SMS'),
|
||||
('object_create','Create Object'),
|
||||
('object_write','Write Object'),
|
||||
('other','Others Actions'),
|
||||
('other','Multi Actions'),
|
||||
], 'Action State', 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.char('Trigger Name', size=128),
|
||||
'trigger_obj_id': fields.reference('Trigger On', selection=model_get, size=128),
|
||||
'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'),
|
||||
'message': fields.text('Message', translate=True),
|
||||
'address': fields.many2one('ir.model.fields', 'Email / Mobile'),
|
||||
'mobile': fields.many2one('ir.model.fields', 'Contact'),
|
||||
'sms': fields.char('SMS', size=160, translate=True),
|
||||
'child_ids': fields.one2many('ir.actions.actions', 'parent_id', 'Others Actions'),
|
||||
'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('Report Type', size=32, required=True),
|
||||
'srcmodel_id': fields.many2one('ir.model', 'Model'),
|
||||
'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'),
|
||||
'otype': fields.selection([
|
||||
('copy','Create in Same Model'),
|
||||
('new','Create in Other Model')
|
||||
], 'Create Model', size=32, change_default=True),
|
||||
'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")
|
||||
}
|
||||
_defaults = {
|
||||
'state': lambda *a: 'dummy',
|
||||
|
@ -414,26 +428,49 @@ class actions_server(osv.osv):
|
|||
# - ids
|
||||
# If you plan to return an action, assign: action = {...}
|
||||
""",
|
||||
'otype': lambda *a: 'copy',
|
||||
}
|
||||
|
||||
def get_field_value(self, cr, uid, action, context):
|
||||
|
||||
def get_email(self, cr, uid, action, context):
|
||||
logger = netsvc.Logger()
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
id = context.get('active_id')
|
||||
obj = obj_pool.browse(cr, uid, id)
|
||||
|
||||
fields = None
|
||||
|
||||
if '/' in action.address.complete_name:
|
||||
fields = action.address.complete_name.split('/')
|
||||
elif '.' in action.address.complete_name:
|
||||
fields = action.address.complete_name.split('.')
|
||||
if '/' in action.email.complete_name:
|
||||
fields = action.email.complete_name.split('/')
|
||||
elif '.' in action.email.complete_name:
|
||||
fields = action.email.complete_name.split('.')
|
||||
|
||||
for field in fields:
|
||||
try:
|
||||
obj = getattr(obj, field)
|
||||
except Exception,e :
|
||||
logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (match.group()))
|
||||
logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (field))
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def get_mobile(self, cr, uid, action, context):
|
||||
logger = netsvc.Logger()
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
id = context.get('active_id')
|
||||
obj = obj_pool.browse(cr, uid, id)
|
||||
|
||||
fields = None
|
||||
|
||||
if '/' in action.mobile.complete_name:
|
||||
fields = action.mobile.complete_name.split('/')
|
||||
elif '.' in action.mobile.complete_name:
|
||||
fields = action.mobile.complete_name.split('.')
|
||||
|
||||
for field in fields:
|
||||
try:
|
||||
obj = getattr(obj, field)
|
||||
except Exception,e :
|
||||
logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (field))
|
||||
|
||||
return obj
|
||||
|
||||
|
@ -443,13 +480,17 @@ class actions_server(osv.osv):
|
|||
obj_pool = self.pool.get(action.model_id.model)
|
||||
id = context.get('active_id')
|
||||
obj = obj_pool.browse(cr, uid, id)
|
||||
return eval(match[2:-2], {'object':obj, 'context': context,'time':time})
|
||||
exp = str(match.group()[2:-2]).strip()
|
||||
result = eval(exp, {'object':obj, 'context': context,'time':time})
|
||||
if result in (None, False):
|
||||
return str("--------")
|
||||
return str(result)
|
||||
|
||||
com = re.compile('(\[\[.+?\]\])')
|
||||
message = com.sub(merge, keystr)
|
||||
|
||||
return message
|
||||
|
||||
#
|
||||
# Context should contains:
|
||||
# ids : original ids
|
||||
# id : current id of the object
|
||||
|
@ -459,10 +500,12 @@ class actions_server(osv.osv):
|
|||
def run(self, cr, uid, ids, context={}):
|
||||
logger = netsvc.Logger()
|
||||
for action in self.browse(cr, uid, ids, context):
|
||||
|
||||
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)
|
||||
|
||||
if action.state=='python':
|
||||
localdict = {
|
||||
'self': self.pool.get(action.model_id.model),
|
||||
|
@ -479,20 +522,24 @@ class actions_server(osv.osv):
|
|||
if action.state == 'email':
|
||||
user = config['email_from']
|
||||
subject = action.name
|
||||
address = self.get_field_value(cr, uid, action, context)
|
||||
address = self.get_email(cr, uid, action, context)
|
||||
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 !"))
|
||||
|
||||
body = self.merge_message(cr, uid, str(action.message), action, context)
|
||||
if tools.email_send_attach(user, address, subject, body, debug=False) == True:
|
||||
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:
|
||||
logger.notifyChannel('email', netsvc.LOG_ERROR, 'Failed to send email to : %s' % (address))
|
||||
|
||||
if action.state == 'trigger':
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
res = str(action.trigger_obj_id).split(',')
|
||||
model = res[0]
|
||||
id = res[1]
|
||||
model = action.wkf_model_id.model
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
res_id = self.pool.get(action.model_id.model).read(cr, uid, [context.get('active_id')], [action.trigger_obj_id.name])
|
||||
id = res_id [0][action.trigger_obj_id.name]
|
||||
wf_service.trg_validate(uid, model, int(id), action.trigger_name, cr)
|
||||
|
||||
if action.state == 'sms':
|
||||
|
@ -500,27 +547,20 @@ class actions_server(osv.osv):
|
|||
# for the sms gateway user / password
|
||||
api_id = ''
|
||||
text = action.sms
|
||||
to = self.get_field_value(cr, uid, action, context)
|
||||
to = self.get_mobile(cr, uid, action, context)
|
||||
#TODO: Apply message mearge with the field
|
||||
if tools.sms_send(user, password, api_id, text, to) == True:
|
||||
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':
|
||||
localdict = {
|
||||
'self': self.pool.get(action.model_id.model),
|
||||
'context': context,
|
||||
'time': time,
|
||||
'ids': ids,
|
||||
'cr': cr,
|
||||
'uid': uid
|
||||
}
|
||||
|
||||
if action.state == 'other':
|
||||
res = None
|
||||
for act in action.child_ids:
|
||||
code = """action = {'model':'%s','type':'%s', %s}""" % (action.model_id.model, act.type, act.usage)
|
||||
exec code in localdict
|
||||
if 'action' in localdict:
|
||||
return localdict['action']
|
||||
result = self.run(cr, uid, [act.id], context)
|
||||
if result:
|
||||
res = result
|
||||
return res
|
||||
|
||||
if action.state == 'object_write':
|
||||
res = {}
|
||||
|
@ -533,8 +573,18 @@ class actions_server(osv.osv):
|
|||
else:
|
||||
expr = exp.value
|
||||
res[exp.col1.name] = expr
|
||||
|
||||
if not action.record_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:
|
||||
obj_pool = self.pool.get(action.srcmodel_id.model)
|
||||
obj_pool.write(cr, uid, [context.get('active_id')], res)
|
||||
else:
|
||||
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)
|
||||
|
||||
if action.state == 'object_create':
|
||||
res = {}
|
||||
|
@ -549,13 +599,10 @@ class actions_server(osv.osv):
|
|||
res[exp.col1.name] = expr
|
||||
|
||||
obj_pool = None
|
||||
if action.state == 'object_create' and action.otype == 'new':
|
||||
res_id = False
|
||||
obj_pool = self.pool.get(action.srcmodel_id.model)
|
||||
obj_pool.create(cr, uid, res)
|
||||
else:
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
id = context.get('active_id')
|
||||
obj_pool.copy(cr, uid, id, res)
|
||||
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})
|
||||
|
||||
return False
|
||||
actions_server()
|
||||
|
|
|
@ -25,19 +25,15 @@ from osv.orm import except_orm
|
|||
import tools
|
||||
|
||||
class ir_attachment(osv.osv):
|
||||
|
||||
def check(self, cr, uid, ids, mode):
|
||||
if not ids:
|
||||
return
|
||||
ima = self.pool.get('ir.model.access')
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
objs = self.browse(cr, uid, ids) or []
|
||||
for o in objs:
|
||||
if o and o.res_model:
|
||||
ima.check(cr, uid, o.res_model, mode)
|
||||
|
||||
check = tools.cache()(check)
|
||||
cr.execute('select distinct res_model from ir_attachment where id in ('+','.join(map(str, ids))+')')
|
||||
for obj in cr.fetchall():
|
||||
ima.check(cr, uid, obj[0], mode)
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||
context=None, count=False):
|
||||
|
@ -83,24 +79,12 @@ class ir_attachment(osv.osv):
|
|||
self.pool.get('ir.model.access').check(cr, uid, values['res_model'], 'create')
|
||||
return super(ir_attachment, self).create(cr, uid, values, *args, **kwargs)
|
||||
|
||||
def clear_cache(self):
|
||||
self.check()
|
||||
|
||||
def action_get(self, cr, uid, context=None):
|
||||
dataobj = self.pool.get('ir.model.data')
|
||||
data_id = dataobj._get_id(cr, 1, 'base', 'action_attachment')
|
||||
res_id = dataobj.browse(cr, uid, data_id, context).res_id
|
||||
return self.pool.get('ir.actions.act_window').read(cr, uid, res_id, [], context)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
r = super(ir_attachment, self).__init__(*args, **kwargs)
|
||||
self.pool.get('ir.model.access').register_cache_clearing_method(self._name, 'clear_cache')
|
||||
return r
|
||||
|
||||
def __del__(self):
|
||||
self.pool.get('ir.model.access').unregister_cache_clearing_method(self._name, 'clear_cache')
|
||||
return super(ir_attachment, self).__del__()
|
||||
|
||||
def _get_preview(self, cr, uid, ids, name, arg, context=None):
|
||||
result = {}
|
||||
if context is None:
|
||||
|
|
|
@ -101,7 +101,7 @@ class ir_cron(osv.osv, netsvc.Agent):
|
|||
addsql=''
|
||||
if not numbercall:
|
||||
addsql = ', active=False'
|
||||
cr.execute("update ir_cron set nextcall=%s, numbercall=%d"+addsql+" where id=%d", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id']))
|
||||
cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id']))
|
||||
cr.commit()
|
||||
finally:
|
||||
cr.close()
|
||||
|
|
|
@ -193,7 +193,9 @@ 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),
|
||||
|
@ -232,7 +234,25 @@ class ir_model_fields(osv.osv):
|
|||
#
|
||||
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
|
||||
|
@ -266,7 +286,7 @@ class ir_model_access(osv.osv):
|
|||
if not grouparr:
|
||||
return False
|
||||
|
||||
cr.execute("select 1 from res_groups_users_rel where uid=%d and gid in(select res_id from ir_model_data where module=%s and name=%s)", (uid, grouparr[0], grouparr[1],))
|
||||
cr.execute("select 1 from res_groups_users_rel where uid=%s and gid in(select res_id from ir_model_data where module=%s and name=%s)", (uid, grouparr[0], grouparr[1],))
|
||||
return bool(cr.fetchone())
|
||||
|
||||
def check_group(self, cr, uid, model, mode, group_ids):
|
||||
|
@ -285,7 +305,7 @@ class ir_model_access(osv.osv):
|
|||
cr.execute("SELECT perm_" + mode + " "
|
||||
" FROM ir_model_access a "
|
||||
" JOIN ir_model m ON (m.id = a.model_id) "
|
||||
" WHERE m.model = %s AND a.group_id = %d", (model_name, group_id)
|
||||
" WHERE m.model = %s AND a.group_id = %s", (model_name, group_id)
|
||||
)
|
||||
r = cr.fetchone()
|
||||
if r is None:
|
||||
|
@ -415,7 +435,7 @@ class ir_model_data(osv.osv):
|
|||
ids = self.search(cr, uid, [('module','=',module),('name','=', xml_id)])
|
||||
assert len(ids)==1, '%d reference(s) to %s.%s. You should have one and only one !' % (len(ids), module, xml_id)
|
||||
return ids[0]
|
||||
_get_id = tools.cache()(_get_id)
|
||||
_get_id = tools.cache(skiparg=2)(_get_id)
|
||||
|
||||
def _update_dummy(self,cr, uid, model, module, xml_id=False, store=True):
|
||||
if not xml_id:
|
||||
|
@ -442,10 +462,10 @@ class ir_model_data(osv.osv):
|
|||
cr.execute('select id,res_id from ir_model_data where module=%s and name=%s', (module,xml_id))
|
||||
results = cr.fetchall()
|
||||
for action_id2,res_id2 in results:
|
||||
cr.execute('select id from '+self.pool.get(model)._table+' where id=%d', (res_id2,))
|
||||
cr.execute('select id from '+self.pool.get(model)._table+' where id=%s', (res_id2,))
|
||||
result3 = cr.fetchone()
|
||||
if not result3:
|
||||
cr.execute('delete from ir_model_data where id=%d', (action_id2,))
|
||||
cr.execute('delete from ir_model_data where id=%s', (action_id2,))
|
||||
else:
|
||||
res_id,action_id = res_id2,action_id2
|
||||
|
||||
|
@ -513,7 +533,7 @@ class ir_model_data(osv.osv):
|
|||
#self.pool.get(model).unlink(cr, uid, ids)
|
||||
for id in ids:
|
||||
self.unlink_mark[(model, id)]=False
|
||||
cr.execute('delete from ir_model_data where res_id=%d and model=\'%s\'', (id,model))
|
||||
cr.execute('delete from ir_model_data where res_id=%s and model=\'%s\'', (id,model))
|
||||
return True
|
||||
|
||||
def ir_set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False):
|
||||
|
@ -525,7 +545,7 @@ class ir_model_data(osv.osv):
|
|||
model = models[0]
|
||||
|
||||
if res_id:
|
||||
where = ' and res_id=%d' % (res_id,)
|
||||
where = ' and res_id=%s' % (res_id,)
|
||||
else:
|
||||
where = ' and (res_id is null)'
|
||||
|
||||
|
@ -552,10 +572,10 @@ class ir_model_data(osv.osv):
|
|||
if (module,name) not in self.loads:
|
||||
self.unlink_mark[(model,res_id)] = id
|
||||
if model=='workflow.activity':
|
||||
cr.execute('select res_type,res_id from wkf_instance where id in (select inst_id from wkf_workitem where act_id=%d)', (res_id,))
|
||||
cr.execute('select res_type,res_id from wkf_instance where id in (select inst_id from wkf_workitem where act_id=%s)', (res_id,))
|
||||
wkf_todo.extend(cr.fetchall())
|
||||
cr.execute("update wkf_transition set condition='True', role_id=NULL, signal=NULL,act_to=act_from,act_from=%d where act_to=%d", (res_id,res_id))
|
||||
cr.execute("delete from wkf_transition where act_to=%d", (res_id,))
|
||||
cr.execute("update wkf_transition set condition='True', role_id=NULL, signal=NULL,act_to=act_from,act_from=%s where act_to=%s", (res_id,res_id))
|
||||
cr.execute("delete from wkf_transition where act_to=%s", (res_id,))
|
||||
|
||||
for model,id in wkf_todo:
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
|
|
|
@ -25,6 +25,7 @@ from osv.orm import browse_null
|
|||
import ir
|
||||
import report.custom
|
||||
from tools.translate import _
|
||||
import netsvc
|
||||
|
||||
class report_custom(osv.osv):
|
||||
_name = 'ir.report.custom'
|
||||
|
@ -187,7 +188,7 @@ class report_custom_fields(osv.osv):
|
|||
}
|
||||
}
|
||||
else:
|
||||
print _("Warning: using a relation field which uses an unknown object") #TODO use the logger
|
||||
netsvc.Logger().notifyChannel('web-services', netsvc.LOG_WARNING, _("Using a relation field which uses an unknown object"))
|
||||
return {'required': {next_level_field_name: True}}
|
||||
else:
|
||||
return {'domain': {next_level_field_name: []}}
|
||||
|
|
|
@ -148,7 +148,7 @@ class ir_rule(osv.osv):
|
|||
WHERE m.model = %s
|
||||
AND (g.id IN (SELECT rule_group_id FROM group_rule_group_rel g_rel
|
||||
JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid)
|
||||
WHERE u_rel.uid = %d) OR g.global)""", (model_name, uid))
|
||||
WHERE u_rel.uid = %s) OR g.global)""", (model_name, uid))
|
||||
ids = map(lambda x:x[0], cr.fetchall())
|
||||
if not ids:
|
||||
return '', []
|
||||
|
|
|
@ -69,11 +69,11 @@ class ir_sequence(osv.osv):
|
|||
'sec': time.strftime('%S'),
|
||||
}
|
||||
|
||||
def get_id(self, cr, uid, sequence_id, test='id=%d'):
|
||||
def get_id(self, cr, uid, sequence_id, test='id=%s'):
|
||||
cr.execute('select id,number_next,number_increment,prefix,suffix,padding from ir_sequence where '+test+' and active=True FOR UPDATE', (sequence_id,))
|
||||
res = cr.dictfetchone()
|
||||
if res:
|
||||
cr.execute('update ir_sequence set number_next=number_next+number_increment where id=%d and active=True', (res['id'],))
|
||||
cr.execute('update ir_sequence set number_next=number_next+number_increment where id=%s and active=True', (res['id'],))
|
||||
if res['number_next']:
|
||||
return self._process(res['prefix']) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix'])
|
||||
else:
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
from osv.osv import Cacheable
|
||||
import tools
|
||||
|
||||
TRANSLATION_TYPE = [
|
||||
|
@ -39,7 +38,7 @@ TRANSLATION_TYPE = [
|
|||
('constraint', 'Constraint'),
|
||||
]
|
||||
|
||||
class ir_translation(osv.osv, Cacheable):
|
||||
class ir_translation(osv.osv):
|
||||
_name = "ir.translation"
|
||||
_log_access = False
|
||||
|
||||
|
@ -48,7 +47,7 @@ class ir_translation(osv.osv, Cacheable):
|
|||
lang_ids = lang_obj.search(cr, uid, [('translatable', '=', True)],
|
||||
context=context)
|
||||
langs = lang_obj.browse(cr, uid, lang_ids, context=context)
|
||||
res = [(lang.code, unicode(lang.name,'utf-8')) for lang in langs]
|
||||
res = [(lang.code, lang.name) for lang in langs]
|
||||
for lang_dict in tools.scan_languages():
|
||||
if lang_dict not in res:
|
||||
res.append(lang_dict)
|
||||
|
@ -81,27 +80,19 @@ class ir_translation(osv.osv, Cacheable):
|
|||
cr.commit()
|
||||
|
||||
def _get_ids(self, cr, uid, name, tt, lang, ids):
|
||||
translations, to_fetch = {}, []
|
||||
for id in ids:
|
||||
trans = self.get((lang, name, id))
|
||||
if trans is not None:
|
||||
translations[id] = trans
|
||||
else:
|
||||
to_fetch.append(id)
|
||||
if to_fetch:
|
||||
translations = {}
|
||||
if ids:
|
||||
cr.execute('select res_id,value ' \
|
||||
'from ir_translation ' \
|
||||
'where lang=%s ' \
|
||||
'and type=%s ' \
|
||||
'and name=%s ' \
|
||||
'and res_id in ('+','.join(map(str, to_fetch))+')',
|
||||
'and res_id in ('+','.join(map(str, ids))+')',
|
||||
(lang,tt,name))
|
||||
for res_id, value in cr.fetchall():
|
||||
self.add((lang, tt, name, res_id), value)
|
||||
translations[res_id] = value
|
||||
for res_id in ids:
|
||||
if res_id not in translations:
|
||||
self.add((lang, tt, name, res_id), False)
|
||||
translations[res_id] = False
|
||||
return translations
|
||||
|
||||
|
@ -122,11 +113,8 @@ class ir_translation(osv.osv, Cacheable):
|
|||
})
|
||||
return len(ids)
|
||||
|
||||
@tools.cache(skiparg=3)
|
||||
def _get_source(self, cr, uid, name, tt, lang, source=None):
|
||||
trans = self.get((lang, tt, name, source))
|
||||
if trans is not None:
|
||||
return trans
|
||||
|
||||
if source:
|
||||
#if isinstance(source, unicode):
|
||||
# source = source.encode('utf8')
|
||||
|
@ -145,26 +133,9 @@ class ir_translation(osv.osv, Cacheable):
|
|||
'and name=%s',
|
||||
(lang, tt, str(name)))
|
||||
res = cr.fetchone()
|
||||
|
||||
trad = res and res[0] or ''
|
||||
self.add((lang, tt, name, source), trad)
|
||||
return trad
|
||||
|
||||
def unlink(self, cursor, user, ids, context=None):
|
||||
self.clear()
|
||||
return super(ir_translation, self).unlink(cursor, user, ids,
|
||||
context=context)
|
||||
|
||||
def create(self, cursor, user, vals, context=None):
|
||||
self.clear()
|
||||
return super(ir_translation, self).create(cursor, user, vals,
|
||||
context=context)
|
||||
|
||||
def write(self, cursor, user, ids, vals, context=None):
|
||||
self.clear()
|
||||
return super(ir_translation, self).write(cursor, user, ids, vals,
|
||||
context=context)
|
||||
|
||||
ir_translation()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -41,7 +41,7 @@ class many2many_unique(fields.many2many):
|
|||
for act in values:
|
||||
if act[0]==4:
|
||||
cr.execute('SELECT * FROM '+self._rel+' \
|
||||
WHERE '+self._id1+'=%d AND '+self._id2+'=%d', (id, act[1]))
|
||||
WHERE '+self._id1+'=%s AND '+self._id2+'=%s', (id, act[1]))
|
||||
if cr.fetchall():
|
||||
val.remove(act)
|
||||
return super(many2many_unique, self).set(cr, obj, id, name, val, user=user,
|
||||
|
|
|
@ -27,14 +27,13 @@ import netsvc
|
|||
import os
|
||||
|
||||
def _check_xml(self, cr, uid, ids, context={}):
|
||||
return True
|
||||
for view in self.browse(cr, uid, ids, context):
|
||||
eview = etree.fromstring(view.arch)
|
||||
frng = tools.file_open(os.path.join('base','rng','view.rng'))
|
||||
relaxng = etree.RelaxNG(file=frng)
|
||||
if not relaxng.validate(eview):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'The view do not fit the required schema !')
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'The view does not fit the required schema !')
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, relaxng.error_log.last_error)
|
||||
return False
|
||||
return True
|
||||
|
@ -99,7 +98,7 @@ class view(osv.osv):
|
|||
|
||||
for rs in result:
|
||||
if rs.get('model') == 'board.board':
|
||||
cr.execute("select id,arch,ref_id from ir_ui_view_custom where user_id=%d and ref_id=%d", (uid, rs['id']))
|
||||
cr.execute("select id,arch,ref_id from ir_ui_view_custom where user_id=%s and ref_id=%s", (uid, rs['id']))
|
||||
oview = cr.dictfetchall()
|
||||
if oview:
|
||||
rs['arch'] = oview[0]['arch']
|
||||
|
|
|
@ -211,7 +211,7 @@ class ir_values(osv.osv):
|
|||
#ir_del(cr, uid, x[0])
|
||||
return False
|
||||
else:
|
||||
datas = pickle.loads(x[2])
|
||||
datas = pickle.loads(str(x[2]))
|
||||
if meta:
|
||||
meta2 = pickle.loads(x[4])
|
||||
return (x[0],x[1],datas,meta2)
|
||||
|
|
|
@ -28,7 +28,7 @@ import report,pooler,tools
|
|||
|
||||
def graph_get(cr, graph, wkf_id, nested=False, workitem={}):
|
||||
import pydot
|
||||
cr.execute('select * from wkf_activity where wkf_id=%d', (wkf_id,))
|
||||
cr.execute('select * from wkf_activity where wkf_id=%s', (wkf_id,))
|
||||
nodes = cr.dictfetchall()
|
||||
activities = {}
|
||||
actfrom = {}
|
||||
|
@ -36,7 +36,7 @@ def graph_get(cr, graph, wkf_id, nested=False, workitem={}):
|
|||
for n in nodes:
|
||||
activities[n['id']] = n
|
||||
if n['subflow_id'] and nested:
|
||||
cr.execute('select * from wkf where id=%d', (n['subflow_id'],))
|
||||
cr.execute('select * from wkf where id=%s', (n['subflow_id'],))
|
||||
wkfinfo = cr.dictfetchone()
|
||||
graph2 = pydot.Cluster('subflow'+str(n['subflow_id']), fontsize='12', label = """\"Subflow: %s\\nOSV: %s\"""" % ( n['name'], wkfinfo['osv']) )
|
||||
(s1,s2) = graph_get(cr, graph2, n['subflow_id'], nested,workitem)
|
||||
|
@ -78,9 +78,9 @@ def graph_get(cr, graph, wkf_id, nested=False, workitem={}):
|
|||
activity_to = actto[t['act_to']][1].get(t['signal'], actto[t['act_to']][0])
|
||||
graph.add_edge(pydot.Edge( str(activity_from) ,str(activity_to), fontsize='10', **args))
|
||||
nodes = cr.dictfetchall()
|
||||
cr.execute('select id from wkf_activity where flow_start=True and wkf_id=%d limit 1', (wkf_id,))
|
||||
cr.execute('select id from wkf_activity where flow_start=True and wkf_id=%s limit 1', (wkf_id,))
|
||||
start = cr.fetchone()[0]
|
||||
cr.execute("select 'subflow.'||name,id from wkf_activity where flow_stop=True and wkf_id=%d", (wkf_id,))
|
||||
cr.execute("select 'subflow.'||name,id from wkf_activity where flow_stop=True and wkf_id=%s", (wkf_id,))
|
||||
stop = cr.fetchall()
|
||||
stop = (stop[0][1], dict(stop))
|
||||
return ((start,{}),stop)
|
||||
|
@ -88,14 +88,14 @@ def graph_get(cr, graph, wkf_id, nested=False, workitem={}):
|
|||
|
||||
def graph_instance_get(cr, graph, inst_id, nested=False):
|
||||
workitems = {}
|
||||
cr.execute('select * from wkf_instance where id=%d', (inst_id,))
|
||||
cr.execute('select * from wkf_instance where id=%s', (inst_id,))
|
||||
inst = cr.dictfetchone()
|
||||
|
||||
def workitem_get(instance):
|
||||
cr.execute('select act_id,count(*) from wkf_workitem where inst_id=%d group by act_id', (instance,))
|
||||
cr.execute('select act_id,count(*) from wkf_workitem where inst_id=%s group by act_id', (instance,))
|
||||
workitems = dict(cr.fetchall())
|
||||
|
||||
cr.execute('select subflow_id from wkf_workitem where inst_id=%d', (instance,))
|
||||
cr.execute('select subflow_id from wkf_workitem where inst_id=%s', (instance,))
|
||||
for (subflow_id,) in cr.fetchall():
|
||||
workitems.update(workitem_get(subflow_id))
|
||||
return workitems
|
||||
|
@ -130,7 +130,7 @@ class report_graph_instance(object):
|
|||
showpage'''
|
||||
else:
|
||||
cr.execute('SELECT id FROM wkf_instance \
|
||||
WHERE res_id=%d AND wkf_id=%d \
|
||||
WHERE res_id=%s AND wkf_id=%s \
|
||||
ORDER BY state LIMIT 1',
|
||||
(data['id'], wkfinfo['id']))
|
||||
inst_id = cr.fetchone()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<menuitem id="menu_workflow_root" name="Workflows" parent="menu_custom"/>
|
||||
<menuitem id="menu_workflow_root" name="Workflow Definitions" parent="menu_custom"/>
|
||||
|
||||
<!--
|
||||
================================
|
||||
|
@ -110,7 +110,7 @@
|
|||
</record>
|
||||
|
||||
<record id="action_workflow_activity_form" model="ir.actions.act_window">
|
||||
<field name="name">Activites</field>
|
||||
<field name="name">Activities</field>
|
||||
<field name="res_model">workflow.activity</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_workflow_activity_tree"/>
|
||||
|
@ -207,7 +207,7 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_workflow_instance_tree"/>
|
||||
</record>
|
||||
<menuitem action="action_workflow_instance_form" id="menu_workflow_instance" parent="base.menu_workflow_root"/>
|
||||
<menuitem action="action_workflow_instance_form" id="menu_workflow_instance" parent="base.menu_low_workflow"/>
|
||||
|
||||
<!--
|
||||
================================
|
||||
|
@ -248,7 +248,7 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_workflow_workitem_tree"/>
|
||||
</record>
|
||||
<menuitem action="action_workflow_workitem_form" id="menu_workflow_workitem" parent="base.menu_workflow_root"/>
|
||||
<menuitem action="action_workflow_workitem_form" id="menu_workflow_workitem" parent="base.menu_low_workflow"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -32,78 +32,46 @@ from osv import osv, fields
|
|||
import pooler
|
||||
import time
|
||||
import math
|
||||
from pprint import pprint as pp
|
||||
|
||||
from tools import config
|
||||
import xmlrpclib
|
||||
|
||||
class maintenance_contract_module(osv.osv):
|
||||
_name ="maintenance.contract.module"
|
||||
_description = "maintenance contract modules"
|
||||
_columns = {
|
||||
'name' : fields.char('Name', size=128, required=True),
|
||||
'version': fields.char('Version', size=64,),
|
||||
}
|
||||
|
||||
maintenance_contract_module()
|
||||
|
||||
class maintenance_contract(osv.osv):
|
||||
_name = "maintenance.contract"
|
||||
_description = "Maintenance Contract"
|
||||
|
||||
def _valid_get(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = {}
|
||||
for contract in self.browse(cr, uid, ids, context=context):
|
||||
res[contract.id] = ("unvalid", "valid")[contract.date_stop >= time.strftime('%Y-%m-%d')]
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Contract ID', size=256, required=True, readonly=True),
|
||||
'password' : fields.char('Password', size=64, invisible=True, required=True, readonly=True),
|
||||
'date_start' : fields.date('Starting Date', readonly=True),
|
||||
'date_stop' : fields.date('Ending Date', readonly=True),
|
||||
'modules': fields.text('Covered Modules')
|
||||
'module_ids' : fields.many2many('maintenance.contract.module', 'maintenance_contract_module_rel', 'contract_id', 'module_id', 'Covered Modules', readonly=True),
|
||||
'state' : fields.function(_valid_get, method=True, string="State", type="selection", selection=[('valid', 'Valid'),('unvalid', 'Unvalid')], readonly=True),
|
||||
'kind' : fields.selection([('full', 'Full'),('partial', 'Partial')], 'Kind', required=True, readonly=True),
|
||||
}
|
||||
_defaults = {
|
||||
'password' : lambda obj,cr,uid,context={} : '',
|
||||
}
|
||||
def _test_maintenance(self, cr, uid, ids, context):
|
||||
remote_db='trunk'
|
||||
remote_server='localhost'
|
||||
port=8069
|
||||
module_obj=self.pool.get('ir.module.module')
|
||||
contract_obj=self.pool.get('maintenance.contract')
|
||||
module_ids=module_obj.search(cr, uid, [('state','=','installed')])
|
||||
modules=module_obj.read(cr, uid, module_ids, ['name','installed_version'])
|
||||
contract_obj=contract_obj.read(cr, uid, ids[0])
|
||||
local_url = 'http://%s:%d/xmlrpc/common'%(remote_server,port)
|
||||
rpc = xmlrpclib.ServerProxy(local_url)
|
||||
ruid = rpc.login(remote_db, 'admin', 'admin')
|
||||
local_url = 'http://%s:%d/xmlrpc/object'%(remote_server,port)
|
||||
rrpc = xmlrpclib.ServerProxy(local_url)
|
||||
try:
|
||||
result=rrpc.execute(remote_db, ruid, 'admin', 'maintenance.maintenance', 'check_contract' , modules,contract_obj)
|
||||
except:
|
||||
raise osv.except_osv(_('Maintenance Error !'),('''Module Maintenance_Editor is not installed at server : %s Database : %s'''%(remote_server,remote_db)))
|
||||
if context.get('active_id',False):
|
||||
if result['status']=='ko':
|
||||
raise osv.except_osv(_('Maintenance Error !'),('''Maintenance Contract
|
||||
-----------------------------------------------------------
|
||||
You have no valid maintenance contract! If you are using
|
||||
Open ERP, it is highly suggested to take maintenance contract.
|
||||
The maintenance program offers you:
|
||||
* Migrations on new versions,
|
||||
* Bugfix guarantee,
|
||||
* Monthly announces of bugs,
|
||||
* Security alerts,
|
||||
* Access to the customer portal.
|
||||
* Check the maintenance contract (www.openerp.com)'''))
|
||||
elif result['status']=='partial':
|
||||
raise osv.except_osv(_('Maintenance Error !'),('''Maintenance Contract
|
||||
-----------------------------------------------------------
|
||||
You have a maintenance contract, But you installed modules those
|
||||
are not covered by your maintenance contract:
|
||||
%s
|
||||
It means we can not offer you the garantee of maintenance on
|
||||
your whole installation.
|
||||
The maintenance program includes:
|
||||
* Migrations on new versions,
|
||||
* Bugfix guarantee,
|
||||
* Monthly announces of bugs,
|
||||
* Security alerts,
|
||||
* Access to the customer portal.
|
||||
|
||||
To include these modules in your maintenance contract, you should
|
||||
extend your contract with the editor. We will review and validate
|
||||
your installed modules.
|
||||
|
||||
* Extend your maintenance to the modules you used.
|
||||
* Check your maintenance contract''') % ','.join(result['modules']))
|
||||
else:
|
||||
raise osv.except_osv(_('Valid Maintenance Contract !'),('''Your Maintenance Contract is up to date'''))
|
||||
return result
|
||||
_sql_constraints = [
|
||||
('uniq_name', 'unique(name)', "Your maintenance contract is already subscribed in the system !")
|
||||
]
|
||||
|
||||
maintenance_contract()
|
||||
|
||||
|
@ -114,12 +82,56 @@ class maintenance_contract_wizard(osv.osv_memory):
|
|||
_columns = {
|
||||
'name' : fields.char('Contract ID', size=256, required=True ),
|
||||
'password' : fields.char('Password', size=64, required=True),
|
||||
'state' : fields.selection([('draft', 'Draft'),('validated', 'Validated'),('unvalidated', 'Unvalidated')], 'States'),
|
||||
}
|
||||
|
||||
def validate_cb(self, cr, uid, ids, context):
|
||||
print "Validate_cb"
|
||||
_defaults = {
|
||||
'state' : lambda *a: 'draft',
|
||||
}
|
||||
|
||||
def action_validate(self, cr, uid, ids, context):
|
||||
if not ids:
|
||||
return False
|
||||
|
||||
module_proxy = self.pool.get('ir.module.module')
|
||||
module_ids = module_proxy.search(cr, uid, [('state', '=', 'installed')])
|
||||
modules = module_proxy.read(cr, uid, module_ids, ['name', 'installed_version'])
|
||||
|
||||
contract = self.read(cr, uid, ids, ['name', 'password'])[0]
|
||||
|
||||
login, password, remote_db, remote_server, port = 'admin', 'admin', 'trunk', 'localhost', 8069
|
||||
|
||||
rpc = xmlrpclib.ServerProxy('http://%s:%d/xmlrpc/common' % (remote_server, port))
|
||||
ruid = rpc.login(remote_db, login, password)
|
||||
rpc = xmlrpclib.ServerProxy('http://%s:%d/xmlrpc/object' % (remote_server, port))
|
||||
contract_info = rpc.execute(remote_db, ruid, password, 'maintenance.maintenance', 'check_contract', modules, contract )
|
||||
is_ok = contract_info['status'] in ('partial', 'full')
|
||||
if is_ok:
|
||||
if contract_info['modules_with_contract']:
|
||||
module_ids = []
|
||||
for name, version in contract_info['modules_with_contract']:
|
||||
contract_module = self.pool.get('maintenance.contract.module')
|
||||
res = contract_module.search(cr, uid, [('name', '=', name),('version', '=', version)])
|
||||
if not res:
|
||||
id = contract_module.create(cr, uid, { 'name' : name, 'version' : version } )
|
||||
else:
|
||||
id = res[0]
|
||||
module_ids.append(id)
|
||||
|
||||
self.pool.get('maintenance.contract').create(
|
||||
cr,
|
||||
uid, {
|
||||
'name' : contract['name'],
|
||||
'password' : contract['password'],
|
||||
'date_start' : contract_info['date_from'],
|
||||
'date_stop' : contract_info['date_to'],
|
||||
'kind' : contract_info['status'],
|
||||
'module_ids' : [(6,0,module_ids)],
|
||||
}
|
||||
)
|
||||
|
||||
return self.write(cr, uid, ids, {'state' : ('unvalidated', 'validated')[is_ok] }, context=context)
|
||||
|
||||
maintenance_contract_wizard()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<field name="name"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="state" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -22,11 +23,17 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Maintenance Contract">
|
||||
<separator string="Information" colspan="4"/>
|
||||
<field name="name" select="1" colspan="4"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="state" />
|
||||
<field name="date_start" select="1"/>
|
||||
<field name="date_stop" select="1"/>
|
||||
<separator string="Covered Modules" colspan="4"/>
|
||||
<field name="modules" nolabel="1" colspan="4"/>
|
||||
<field name="module_ids" nolabel="1" colspan="4">
|
||||
<tree string="Covered Modules">
|
||||
<field name="name" />
|
||||
<field name="version" />
|
||||
</tree>
|
||||
</field>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -54,14 +61,28 @@
|
|||
<field name="model">maintenance.contract.wizard</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Add Maintenance Contract">
|
||||
<separator string="Add Maintenance Contract" colspan="2"/>
|
||||
<newline />
|
||||
<field name="name" />
|
||||
<form string="Add Maintenance Contract" col="2">
|
||||
<image name="gtk-dialog-info" />
|
||||
<group col="1">
|
||||
<separator string="Add Maintenance Contract" />
|
||||
<group states="draft">
|
||||
<field name="name" width="250" />
|
||||
<newline />
|
||||
<field name="password" password="True" />
|
||||
<newline />
|
||||
<label string="" /><button name="validate_cb" type="object" string="Validate" />
|
||||
<field name="state" invisible="1" />
|
||||
</group>
|
||||
<group states="validated">
|
||||
<label string="Maintenance contract added !"/>
|
||||
</group>
|
||||
<group states="unvalidated">
|
||||
<label string="Could you check your contract information ?" />
|
||||
</group>
|
||||
</group>
|
||||
<group colspan="4">
|
||||
<button type="object" string="_Cancel" icon="gtk-cancel" special="cancel" states="draft"/>
|
||||
<button type="object" string="_Validate" icon="gtk-apply" name="action_validate" states="draft"/>
|
||||
<button type="object" string="_Close" icon="gtk-close" special="cancel" states="validated,unvalidated"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -68,7 +68,7 @@ class module_category(osv.osv):
|
|||
cr.execute('select category_id,count(*) from ir_module_module where category_id in ('+','.join(map(str,ids))+') or category_id in (select id from ir_module_category where parent_id in ('+','.join(map(str,ids))+')) group by category_id')
|
||||
result = dict(cr.fetchall())
|
||||
for id in ids:
|
||||
cr.execute('select id from ir_module_category where parent_id=%d', (id,))
|
||||
cr.execute('select id from ir_module_category where parent_id=%s', (id,))
|
||||
childs = [c for c, in cr.fetchall()]
|
||||
result[id] = reduce(lambda x,y:x+y, [result.get(c, 0) for c in childs], result.get(id, 0))
|
||||
return result
|
||||
|
@ -98,58 +98,43 @@ class module(osv.osv):
|
|||
return {}
|
||||
return info
|
||||
|
||||
def _get_installed_version(self, cr, uid, ids, field_name=None, arg=None, context={}):
|
||||
res = {}
|
||||
def _get_latest_version(self, cr, uid, ids, field_name=None, arg=None, context={}):
|
||||
res = dict.fromkeys(ids, '')
|
||||
for m in self.browse(cr, uid, ids):
|
||||
if m.state in ('installed', 'to upgrade', 'to remove'):
|
||||
res[m.id] = self.get_module_info(m.name).get('version', '')
|
||||
else:
|
||||
res[m.id] = ''
|
||||
return res
|
||||
|
||||
def _get_menus(self, cr, uid, ids, field_name=None, arg=None, context={}):
|
||||
res = {}
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
menu_obj = self.pool.get('ir.ui.menu')
|
||||
for m in self.browse(cr, uid, ids):
|
||||
if m.state == 'installed':
|
||||
menu_txt = ''
|
||||
menus_id = model_data_obj.search(cr,uid,[('module','=',m.name),('model','=','ir.ui.menu')])
|
||||
for data_id in model_data_obj.browse(cr,uid,menus_id):
|
||||
menu_txt += menu_obj.browse(cr,uid,data_id.res_id).complete_name + '\n'
|
||||
res[m.id] = menu_txt
|
||||
else:
|
||||
res[m.id] = ''
|
||||
return res
|
||||
|
||||
def _get_reports(self, cr, uid, ids, field_name=None, arg=None, context={}):
|
||||
res = {}
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
report_obj = self.pool.get('ir.actions.report.xml')
|
||||
for m in self.browse(cr, uid, ids):
|
||||
if m.state == 'installed':
|
||||
report_txt = ''
|
||||
report_id = model_data_obj.search(cr,uid,[('module','=',m.name),('model','=','ir.actions.report.xml')])
|
||||
for data_id in model_data_obj.browse(cr,uid,report_id):
|
||||
report_txt += report_obj.browse(cr,uid,data_id.res_id).name + '\n'
|
||||
res[m.id] = report_txt
|
||||
else:
|
||||
res[m.id] = ''
|
||||
return res
|
||||
|
||||
def _get_views(self, cr, uid, ids, field_name=None, arg=None, context={}):
|
||||
res = {}
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
view_obj = self.pool.get('ir.ui.view')
|
||||
for m in self.browse(cr, uid, ids, context=context):
|
||||
if m.state == 'installed':
|
||||
view_txt = ''
|
||||
view_id = model_data_obj.search(cr,uid,[('module','=',m.name),('model','=','ir.ui.view')])
|
||||
for data_id in model_data_obj.browse(cr,uid,view_id):
|
||||
view_txt += view_obj.browse(cr,uid,data_id.res_id).name + '\n'
|
||||
res[m.id] = view_txt
|
||||
else:
|
||||
res[m.id] = ''
|
||||
report_obj = self.pool.get('ir.actions.report.xml')
|
||||
menu_obj = self.pool.get('ir.ui.menu')
|
||||
mlist = self.browse(cr, uid, ids, context=context)
|
||||
mnames = {}
|
||||
for m in mlist:
|
||||
mnames[m.name] = m.id
|
||||
res[m.id] = {
|
||||
'menus_by_module':'',
|
||||
'reports_by_module':'',
|
||||
'views_by_module': ''
|
||||
}
|
||||
view_id = model_data_obj.search(cr,uid,[('module','in', mnames.keys()),
|
||||
('model','in',('ir.ui.view','ir.actions.report.xml','ir.ui.menu'))])
|
||||
for data_id in model_data_obj.browse(cr,uid,view_id,context):
|
||||
# We use try except, because views or menus may not exist
|
||||
try:
|
||||
key = data_id['model']
|
||||
if key=='ir.ui.view':
|
||||
v = view_obj.browse(cr,uid,data_id.res_id)
|
||||
aa = v.inherit_id and '* INHERIT ' or ''
|
||||
res[mnames[data_id.module]]['views_by_module'] += aa + v.name + ' ('+v.type+')\n'
|
||||
elif key=='ir.actions.report.xml':
|
||||
res[mnames[data_id.module]]['reports_by_module'] += report_obj.browse(cr,uid,data_id.res_id).name + '\n'
|
||||
elif key=='ir.ui.menu':
|
||||
res[mnames[data_id.module]]['menus_by_module'] += menu_obj.browse(cr,uid,data_id.res_id).complete_name + '\n'
|
||||
except KeyError, e:
|
||||
pass
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
|
@ -159,10 +144,16 @@ class module(osv.osv):
|
|||
'description': fields.text("Description", readonly=True, translate=True),
|
||||
'author': fields.char("Author", size=128, readonly=True),
|
||||
'website': fields.char("Website", size=256, readonly=True),
|
||||
'installed_version': fields.function(_get_installed_version, method=True,
|
||||
string='Installed version', type='char'),
|
||||
'latest_version': fields.char('Latest version', size=64, readonly=True),
|
||||
|
||||
# attention: Incorrect field names !!
|
||||
# installed_version refer the latest version (the one on disk)
|
||||
# latest_version refer the installed version (the one in database)
|
||||
# published_version refer the version available on the repository
|
||||
'installed_version': fields.function(_get_latest_version, method=True,
|
||||
string='Latest version', type='char'),
|
||||
'latest_version': fields.char('Installed version', size=64, readonly=True),
|
||||
'published_version': fields.char('Published Version', size=64, readonly=True),
|
||||
|
||||
'url': fields.char('URL', size=128),
|
||||
'dependencies_id': fields.one2many('ir.module.module.dependency',
|
||||
'module_id', 'Dependencies', readonly=True),
|
||||
|
@ -182,9 +173,9 @@ class module(osv.osv):
|
|||
('GPL-3 or any later version', 'GPL-3 or later version'),
|
||||
('Other proprietary', 'Other proprietary')
|
||||
], string='License', readonly=True),
|
||||
'menus_by_module': fields.function(_get_menus, method=True, string='Menus', type='text'),
|
||||
'reports_by_module': fields.function(_get_reports, method=True, string='Reports', type='text'),
|
||||
'views_by_module': fields.function(_get_views, method=True, string='Views', type='text'),
|
||||
'menus_by_module': fields.function(_get_views, method=True, string='Menus', type='text', multi="meta", store=True),
|
||||
'reports_by_module': fields.function(_get_views, method=True, string='Reports', type='text', multi="meta", store=True),
|
||||
'views_by_module': fields.function(_get_views, method=True, string='Views', type='text', multi="meta", store=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -270,9 +261,22 @@ class module(osv.osv):
|
|||
_("Can not upgrade module '%s'. It is not installed.") % (mod.name,))
|
||||
iids = depobj.search(cr, uid, [('name', '=', mod.name)], context=context)
|
||||
for dep in depobj.browse(cr, uid, iids, context=context):
|
||||
if dep.module_id.state=='installed':
|
||||
if dep.module_id.state=='installed' and dep.module_id not in todo:
|
||||
todo.append(dep.module_id)
|
||||
self.write(cr,uid, map(lambda x: x.id, todo), {'state':'to upgrade'}, context=context)
|
||||
|
||||
ids = map(lambda x: x.id, todo)
|
||||
self.write(cr, uid, ids, {'state':'to upgrade'}, context=context)
|
||||
|
||||
to_install = []
|
||||
for mod in todo:
|
||||
for dep in mod.dependencies_id:
|
||||
if dep.state == 'unknown':
|
||||
raise orm.except_orm(_('Error'), _('You try to upgrade a module that depends on the module: %s.\nBut this module is not available in your system.') % (dep.name,))
|
||||
if dep.state == 'uninstalled':
|
||||
ids2 = self.search(cr, uid, [('name','=',dep.name)])
|
||||
to_install.extend(ids2)
|
||||
|
||||
self.button_install(cr, uid, to_install, context=context)
|
||||
return True
|
||||
|
||||
def button_upgrade_cancel(self, cr, uid, ids, context={}):
|
||||
|
@ -301,7 +305,6 @@ class module(osv.osv):
|
|||
self.write(cr, uid, id, {'state': 'uninstalled'})
|
||||
if parse_version(terp.get('version', '')) > parse_version(mod.latest_version or ''):
|
||||
self.write(cr, uid, id, {
|
||||
'latest_version': terp.get('version'),
|
||||
'url': ''})
|
||||
res[0] += 1
|
||||
self.write(cr, uid, id, {
|
||||
|
@ -312,7 +315,7 @@ class module(osv.osv):
|
|||
'license': terp.get('license', 'GPL-2'),
|
||||
})
|
||||
cr.execute('DELETE FROM ir_module_module_dependency\
|
||||
WHERE module_id = %d', (id,))
|
||||
WHERE module_id = %s', (id,))
|
||||
self._update_dependencies(cr, uid, ids[0], terp.get('depends',
|
||||
[]))
|
||||
self._update_category(cr, uid, ids[0], terp.get('category',
|
||||
|
@ -340,7 +343,6 @@ class module(osv.osv):
|
|||
'shortdesc': terp.get('name', ''),
|
||||
'author': terp.get('author', 'Unknown'),
|
||||
'website': terp.get('website', ''),
|
||||
'latest_version': terp.get('version', ''),
|
||||
'license': terp.get('license', 'GPL-2'),
|
||||
})
|
||||
res[1] += 1
|
||||
|
@ -377,7 +379,6 @@ class module(osv.osv):
|
|||
if not ids:
|
||||
self.create(cr, uid, {
|
||||
'name': name,
|
||||
'latest_version': version,
|
||||
'published_version': version,
|
||||
'url': url,
|
||||
'state': 'uninstalled',
|
||||
|
@ -385,16 +386,15 @@ class module(osv.osv):
|
|||
res[1] += 1
|
||||
else:
|
||||
id = ids[0]
|
||||
latest_version = self.read(cr, uid, id, ['latest_version'])\
|
||||
['latest_version']
|
||||
if latest_version == 'x': # 'x' version was a mistake
|
||||
latest_version = '0'
|
||||
if parse_version(version) > parse_version(latest_version):
|
||||
self.write(cr, uid, id,
|
||||
{'latest_version': version, 'url': url})
|
||||
installed_version = self.read(cr, uid, id, ['latest_version'])['latest_version']
|
||||
if installed_version == 'x': # 'x' version was a mistake
|
||||
installed_version = '0'
|
||||
if parse_version(version) > parse_version(installed_version):
|
||||
self.write(cr, uid, id, {
|
||||
'url': url
|
||||
})
|
||||
res[0] += 1
|
||||
published_version = self.read(cr, uid, id, ['published_version'])\
|
||||
['published_version']
|
||||
published_version = self.read(cr, uid, id, ['published_version'])['published_version']
|
||||
if published_version == 'x' or not published_version:
|
||||
published_version = '0'
|
||||
if parse_version(version) > parse_version(published_version):
|
||||
|
@ -433,7 +433,7 @@ class module(osv.osv):
|
|||
'license': terp.get('license', 'GPL-2'),
|
||||
})
|
||||
cr.execute('DELETE FROM ir_module_module_dependency ' \
|
||||
'WHERE module_id = %d', (mod.id,))
|
||||
'WHERE module_id = %s', (mod.id,))
|
||||
self._update_dependencies(cr, uid, mod.id, terp.get('depends',
|
||||
[]))
|
||||
self._update_category(cr, uid, mod.id, terp.get('category',
|
||||
|
@ -445,21 +445,21 @@ class module(osv.osv):
|
|||
|
||||
def _update_dependencies(self, cr, uid, id, depends=[]):
|
||||
for d in depends:
|
||||
cr.execute('INSERT INTO ir_module_module_dependency (module_id, name) values (%d, %s)', (id, d))
|
||||
cr.execute('INSERT INTO ir_module_module_dependency (module_id, name) values (%s, %s)', (id, d))
|
||||
|
||||
def _update_category(self, cr, uid, id, category='Uncategorized'):
|
||||
categs = category.split('/')
|
||||
p_id = None
|
||||
while categs:
|
||||
if p_id is not None:
|
||||
cr.execute('select id from ir_module_category where name=%s and parent_id=%d', (categs[0], p_id))
|
||||
cr.execute('select id from ir_module_category where name=%s and parent_id=%s', (categs[0], p_id))
|
||||
else:
|
||||
cr.execute('select id from ir_module_category where name=%s and parent_id is NULL', (categs[0],))
|
||||
c_id = cr.fetchone()
|
||||
if not c_id:
|
||||
cr.execute('select nextval(\'ir_module_category_id_seq\')')
|
||||
c_id = cr.fetchone()[0]
|
||||
cr.execute('insert into ir_module_category (id, name, parent_id) values (%d, %s, %d)', (c_id, categs[0], p_id))
|
||||
cr.execute('insert into ir_module_category (id, name, parent_id) values (%s, %s, %s)', (c_id, categs[0], p_id))
|
||||
else:
|
||||
c_id = c_id[0]
|
||||
p_id = c_id
|
||||
|
|
|
@ -13,57 +13,62 @@
|
|||
<blockTableStyle id="Table1">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<blockBackground colorName="#e6e6e6" start="0,0" stop="0,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="1,0" stop="1,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="2,0" stop="2,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="0,1" stop="0,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="1,1" stop="1,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="2,1" stop="2,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Tableau1">
|
||||
<blockTableStyle id="module_tbl_heading">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#000000" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#000000" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#000000" start="0,0" stop="0,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
|
||||
<blockBackground colorName="#ff6633" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Tableau2">
|
||||
<blockTableStyle id="module_tbl_content">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<blockBackground colorName="#e6e6e6" start="0,0" stop="0,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="1,0" stop="1,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="0,1" stop="0,-1"/>
|
||||
<blockBackground colorName="#e6e6e6" start="1,1" stop="1,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Tableau3">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#800000" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#800000" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#800000" start="0,0" stop="0,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#800000" start="0,-1" stop="0,-1"/>
|
||||
<blockBackground colorName="#ffcc99" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Tableau4">
|
||||
<blockTableStyle id="Table2">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
|
||||
</blockTableStyle>
|
||||
<initialize>
|
||||
<paraStyle name="all" alignment="justify"/>
|
||||
</initialize>
|
||||
<paraStyle name="P1" fontName="Times-Roman" fontSize="20.0" leading="25" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P2" fontName="Times-Roman" fontSize="10.0" leading="13" alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P3" fontName="Times-Roman" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P4" fontName="Times-Roman" fontSize="11.0" leading="14" alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P5" fontName="Times-Roman" fontSize="11.0" leading="14" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P6" fontName="Times-Roman"/>
|
||||
<paraStyle name="P7" fontName="Times-Roman" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P8" fontName="Times-Roman"/>
|
||||
<paraStyle name="P9" fontName="Times-Roman" fontSize="16.0" leading="20" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P10" fontName="Times-Roman" fontSize="15.0" leading="19" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P11" fontName="Times-Roman" fontSize="12.0" leading="15" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P1" fontName="Helvetica-Oblique" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="Standard" fontName="Times-Roman"/>
|
||||
<paraStyle name="Text body" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="Heading" fontName="Helvetica" fontSize="14.0" leading="17" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||
|
@ -72,6 +77,28 @@
|
|||
<paraStyle name="Table Heading" fontName="Times-Roman" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="Caption" fontName="Times-Roman" fontSize="12.0" leading="15" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="Index" fontName="Times-Roman"/>
|
||||
<paraStyle name="Footer" fontName="Times-Roman"/>
|
||||
<paraStyle name="Horizontal Line" fontName="Times-Roman" fontSize="6.0" leading="8" spaceBefore="0.0" spaceAfter="14.0"/>
|
||||
<paraStyle name="terp_header" fontName="Helvetica-Bold" fontSize="15.0" leading="19" alignment="LEFT" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="Heading 9" fontName="Helvetica-Bold" fontSize="75%" leading="NaN" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_tblheader_General" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_tblheader_Details" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_default_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_Bold_8" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_tblheader_General_Right" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_tblheader_Details_Centre" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_tblheader_Details_Right" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_default_Right_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_Centre_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_header_Right" fontName="Helvetica-Bold" fontSize="15.0" leading="19" alignment="LEFT" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_header_Centre" fontName="Helvetica-Bold" fontSize="15.0" leading="19" alignment="CENTER" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_default_address" fontName="Helvetica" fontSize="10.0" leading="13" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_9" fontName="Helvetica" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_Bold_9" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_Centre_9" fontName="Helvetica" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_Right_9" fontName="Helvetica" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_default_1" fontName="Helvetica" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
</stylesheet>
|
||||
<images/>
|
||||
<story>
|
||||
|
@ -81,28 +108,28 @@
|
|||
<blockTable colWidths="139.0,220.0,152.0" repeatRows="1" style="Table1">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="Table Contents">
|
||||
<para style="terp_header_Centre">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P1">Reference Guide</para>
|
||||
<para style="terp_header_Centre">Reference Guide</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P2">
|
||||
<para style="terp_header_Centre">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<para style="Table Contents">[[ company.name ]]</para>
|
||||
<para style="terp_default_9">[[ company.name ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P3">Introspection report on objects</para>
|
||||
<para style="terp_default_Centre_9">Introspection report on objects</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P4">Printed: [[ time.strftime('%y-%m-%d')]]</para>
|
||||
<para style="terp_default_Right_9">Printed: [[ time.strftime('%y-%m-%d')]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
@ -111,70 +138,86 @@
|
|||
</para>
|
||||
<section>
|
||||
<para style="Text body">[[ repeatIn(objects, 'module') ]]</para>
|
||||
<blockTable colWidths="510.0" repeatRows="1" style="Tableau1">
|
||||
<blockTable colWidths="102.0,102.0,102.0,102.0,102.0" style="module_tbl_heading">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P9">Module: [[ module.name ]]</para>
|
||||
<para style="terp_tblheader_General_Centre">Module</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Name</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Version</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Directory</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Web</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="277.0,234.0" repeatRows="1" style="Tableau2">
|
||||
<blockTable colWidths="102.0,102.0,102.0,102.0,102.0" style="module_tbl_content">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="Standard">Name: [[ module.shortdesc]]</para>
|
||||
<para style="terp_default_Centre_8">[[ module.name ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="Standard">Version: [[module.latest_version]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<para style="Standard">Directory: [[ module.name ]]</para>
|
||||
<para style="terp_default_Centre_8">[[ module.shortdesc]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="Standard">Web: [[ module.website ]]</para>
|
||||
<para style="terp_default_Centre_8">[[module.latest_version]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8">[[ module.name ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8">[[ module.website ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<para style="P6">[[ format(module.description or '') ]]</para>
|
||||
<para style="terp_default_9">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="terp_default_9">[[ module.description ]]</para>
|
||||
<section>
|
||||
<para style="Standard">[[ repeatIn(findobj(module.name) ,'object') ]]</para>
|
||||
<para style="terp_default_9">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="terp_default_9">[[ repeatIn(findobj(module.name) ,'object') ]]</para>
|
||||
<para style="terp_default_1">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<blockTable colWidths="510.0" repeatRows="1" style="Tableau3">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P10">Object: [[ object.model ]]</para>
|
||||
<para style="P11">Description : [[ object.name ]]</para>
|
||||
<para style="P5">[[ format(objdoc(object.model)) ]]</para>
|
||||
<para style="terp_tblheader_Details">Object: [[ object.name ]] [[ objdoc(object.model) ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="113.0,397.0" repeatRows="1" style="Tableau4">
|
||||
<section>
|
||||
<para style="terp_default_1">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<para style="P1">[[ repeatIn(findflds(object.model), 'field') ]]</para>
|
||||
<blockTable colWidths="113.0,397.0" repeatRows="1" style="Table2">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P7">[[ repeatIn(findflds(object.model), 'field') ]] <i>[[ field[0] ]]</i></para>
|
||||
<para style="terp_default_9">[[ field[0] ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P8">[[ field[1].get('string', 'Unknown') ]], [[ field[1]['type'] ]] [[field[1].get('required',False) and ', required']] [[field[1].get('readonly',False) and ', readonly']] </para>
|
||||
<para style="Standard">[[ field[1].get('help', '') ]]</para>
|
||||
<para style="terp_default_9">[[ field[1].get('string', 'Unknown') ]], [[ field[1]['type'] ]] [[field[1].get('required',False) and ', required']] [[field[1].get('readonly',False) and ', readonly']] </para>
|
||||
<para style="terp_default_9">[[ field[1].get('help', '') ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<para style="Standard">
|
||||
<para style="terp_default_1">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
</section>
|
||||
<para style="Standard">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="Standard">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="Standard">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
</section>
|
||||
<para style="Standard">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
</section>
|
||||
</story>
|
||||
</document>
|
||||
|
|
Binary file not shown.
|
@ -38,7 +38,8 @@
|
|||
<field name="domain">[('res_id','=',False)]</field>
|
||||
<field name="view_id" ref="ir_property_view_tree"/>
|
||||
</record>
|
||||
<menuitem id="next_id_15" name="Properties" parent="base.menu_custom"/><menuitem action="ir_property_form" id="menu_ir_property_form" parent="next_id_15"/>
|
||||
<menuitem id="next_id_15" name="Properties" parent="base.menu_config"/>
|
||||
<menuitem action="ir_property_form" id="menu_ir_property_form" parent="next_id_15"/>
|
||||
|
||||
<record id="ir_property_form_all" model="ir.actions.act_window">
|
||||
<field name="name">All Properties</field>
|
||||
|
|
|
@ -259,7 +259,7 @@ class res_partner(osv.osv):
|
|||
raise osv.except_osv(_('Warning'), _("Couldn't generate the next id because some partners have an alphabetic id !"))
|
||||
|
||||
# update the current partner
|
||||
cr.execute("update res_partner set ref=%d where id=%d", (nextref, ids[0]))
|
||||
cr.execute("update res_partner set ref=%s where id=%s", (nextref, ids[0]))
|
||||
return True
|
||||
|
||||
def view_header_get(self, cr, uid, view_id, view_type, context):
|
||||
|
@ -306,10 +306,10 @@ class res_partner_address(osv.osv):
|
|||
if context.get('contact_display', 'contact')=='partner':
|
||||
res.append((r['id'], r['partner_id'][1]))
|
||||
else:
|
||||
addr = str(r['name'] or '')
|
||||
addr = r['name'] or ''
|
||||
if r['name'] and (r['zip'] or r['city']):
|
||||
addr += ', '
|
||||
addr += str(r['street'] or '') + ' ' + str(r['zip'] or '') + ' ' + str(r['city'] or '')
|
||||
addr += (r['street'] or '') + ' ' + (r['zip'] or '') + ' ' + (r['city'] or '')
|
||||
res.append((r['id'], addr.strip() or '/'))
|
||||
return res
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
<field name="fax"/>
|
||||
<newline/>
|
||||
<field name="mobile" select="2"/>
|
||||
<field name="email" select="2"/>
|
||||
<field name="email" select="2" widget="email"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -146,7 +146,7 @@
|
|||
<field name="fax"/>
|
||||
<newline/>
|
||||
<field name="mobile"/>
|
||||
<field name="email"/>
|
||||
<field name="email" widget="email"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -183,7 +183,7 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="domain">[('domain','=','partner')]</field>
|
||||
</record>
|
||||
<menuitem action="action_partner_title_partner" id="menu_partner_title_partner" parent="action_partner_title"/>
|
||||
<menuitem action="action_partner_title_partner" id="menu_partner_title_partner" parent="menu_partner_title"/>
|
||||
|
||||
<record id="action_partner_title_contact" model="ir.actions.act_window">
|
||||
<field name="name">Contacts Titles</field>
|
||||
|
@ -192,7 +192,7 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="domain">[('domain','=','contact')]</field>
|
||||
</record>
|
||||
<menuitem action="action_partner_title_contact" id="menu_partner_title_contact" parent="action_partner_title"/>
|
||||
<menuitem action="action_partner_title_contact" id="menu_partner_title_contact" parent="menu_partner_title"/>
|
||||
|
||||
<!--
|
||||
=======================
|
||||
|
|
|
@ -39,7 +39,7 @@ class res_currency(osv.osv):
|
|||
date=time.strftime('%Y-%m-%d')
|
||||
date= date or time.strftime('%Y-%m-%d')
|
||||
for id in ids:
|
||||
cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %d AND name <= '%s' ORDER BY name desc LIMIT 1" % (id, date))
|
||||
cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= '%s' ORDER BY name desc LIMIT 1" % (id, date))
|
||||
if cr.rowcount:
|
||||
id, rate=cr.fetchall()[0]
|
||||
res[id]=rate
|
||||
|
@ -91,7 +91,7 @@ class res_currency(osv.osv):
|
|||
if account and (account.currency_mode=='average') and account.currency_id:
|
||||
q = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
|
||||
cr.execute('select sum(debit-credit),sum(amount_currency) from account_move_line l ' \
|
||||
'where l.currency_id=%d and l.account_id=%d and '+q, (account.currency_id.id,account.id,))
|
||||
'where l.currency_id=%s and l.account_id=%s and '+q, (account.currency_id.id,account.id,))
|
||||
tot1,tot2 = cr.fetchone()
|
||||
if tot2 and not account_invert:
|
||||
rate = float(tot1)/float(tot2)
|
||||
|
|
|
@ -21,24 +21,118 @@
|
|||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
from locale import localeconv
|
||||
|
||||
class lang(osv.osv):
|
||||
_name = "res.lang"
|
||||
_description = "Languages"
|
||||
|
||||
def _get_default_date_format(self,cursor,user,context={}):
|
||||
return '%Y-%m-%d'
|
||||
|
||||
def _get_default_time_format(self,cursor,user,context={}):
|
||||
return '%H:%M:%S'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True),
|
||||
'code': fields.char('Code', size=5, required=True),
|
||||
'translatable': fields.boolean('Translatable'),
|
||||
'active': fields.boolean('Active'),
|
||||
'direction': fields.selection([('ltr', 'Left-to-right'), ('rtl', 'Right-to-left')], 'Direction',resuired=True),
|
||||
'direction': fields.selection([('ltr', 'Left-to-Right'), ('rtl', 'Right-to-Left')], 'Direction',required=True),
|
||||
'date_format':fields.char('Date Format',size=64,required=True),
|
||||
'time_format':fields.char('Time Format',size=64,required=True),
|
||||
'grouping':fields.char('Separator Format',size=64,required=True,help="The Separator Format should be like [,n] where 0 < n :starting from Unit digit.-1 will end the separation. e.g. [3,2,-1] will represent 106500 to be 1,06,500;[1,2,-1] will represent it to be 106,50,0;[3] will represent it as 106,500. Provided ',' as the thousand separator in each case."),
|
||||
'decimal_point':fields.char('Decimal Separator', size=64,required=True),
|
||||
'thousands_sep':fields.char('Thousands Separator',size=64),
|
||||
}
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'translatable': lambda *a: 0,
|
||||
'direction': lambda *a: 'ltr',
|
||||
'date_format':_get_default_date_format,
|
||||
'time_format':_get_default_time_format,
|
||||
'grouping':lambda *a: '[]',
|
||||
'decimal_point':lambda *a: '.',
|
||||
'thousands_sep':lambda *a: ',',
|
||||
}
|
||||
|
||||
def _group(self,cr,uid,ids,s, monetary=False):
|
||||
conv = localeconv()
|
||||
|
||||
lang_obj=self.browse(cr,uid,ids[0])
|
||||
thousands_sep = lang_obj.thousands_sep or conv[monetary and 'mon_thousands_sep' or 'thousands_sep']
|
||||
|
||||
grouping = eval(lang_obj.grouping)
|
||||
|
||||
if not grouping:
|
||||
return (s, 0)
|
||||
result = ""
|
||||
seps = 0
|
||||
spaces = ""
|
||||
if s[-1] == ' ':
|
||||
sp = s.find(' ')
|
||||
spaces = s[sp:]
|
||||
s = s[:sp]
|
||||
while s and grouping:
|
||||
# if grouping is -1, we are done
|
||||
if grouping[0] == -1:
|
||||
break
|
||||
# 0: re-use last group ad infinitum
|
||||
elif grouping[0] != 0:
|
||||
#process last group
|
||||
group = grouping[0]
|
||||
grouping = grouping[1:]
|
||||
if result:
|
||||
result = s[-group:] + thousands_sep + result
|
||||
seps += 1
|
||||
else:
|
||||
result = s[-group:]
|
||||
s = s[:-group]
|
||||
if s and s[-1] not in "0123456789":
|
||||
# the leading string is only spaces and signs
|
||||
return s + result + spaces, seps
|
||||
if not result:
|
||||
return s + spaces, seps
|
||||
if s:
|
||||
result = s + thousands_sep + result
|
||||
seps += 1
|
||||
return result + spaces, seps
|
||||
|
||||
def format(self,cr,uid,ids,percent, value, grouping=False, monetary=False):
|
||||
""" Format() will return the language-specific output for float values"""
|
||||
|
||||
if percent[0] != '%':
|
||||
raise ValueError("format() must be given exactly one %char format specifier")
|
||||
|
||||
lang_obj=self.browse(cr,uid,ids[0])
|
||||
|
||||
formatted = percent % value
|
||||
# floats and decimal ints need special action!
|
||||
if percent[-1] in 'eEfFgG':
|
||||
seps = 0
|
||||
parts = formatted.split('.')
|
||||
|
||||
if grouping:
|
||||
parts[0], seps = self._group(cr,uid,ids,parts[0], monetary=monetary)
|
||||
|
||||
decimal_point=lang_obj.decimal_point
|
||||
formatted = decimal_point.join(parts)
|
||||
while seps:
|
||||
sp = formatted.find(' ')
|
||||
if sp == -1: break
|
||||
formatted = formatted[:sp] + formatted[sp+1:]
|
||||
seps -= 1
|
||||
elif percent[-1] in 'diu':
|
||||
if grouping:
|
||||
formatted = self._group(cr,uid,ids,formatted, monetary=monetary)[0]
|
||||
|
||||
return formatted
|
||||
|
||||
# import re, operator
|
||||
# _percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
|
||||
# r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')
|
||||
|
||||
lang()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -15,6 +15,88 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="res_lang_form" model="ir.ui.view">
|
||||
<field name="name">res.lang.form</field>
|
||||
<field name="model">res.lang</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Languages">
|
||||
<group col="4" colspan="4">
|
||||
<field name="name" />
|
||||
<field name="code" />
|
||||
<field name="active" />
|
||||
<field name="translatable"/>
|
||||
<field name="grouping" />
|
||||
<field name="direction" />
|
||||
<newline/>
|
||||
<field name="date_format"/>
|
||||
<field name="time_format"/>
|
||||
<field name="decimal_point"/>
|
||||
<field name="thousands_sep"/>
|
||||
<newline/>
|
||||
</group>
|
||||
<separator colspan="4" string="Legends for Date and Time Formats"/>
|
||||
<group col="4" colspan="4">
|
||||
<label align="0.0" string="%%a - Abbreviated weekday name."/>
|
||||
<label align="0.0" string="%%A - Full weekday name."/>
|
||||
<newline/>
|
||||
<label align="0.0" string="%%b - Abbreviated month name."/>
|
||||
<label align="0.0" string="%%B - Full month name." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%c - Appropriate date and time representation." />
|
||||
<label align="0.0" string="%%d - Day of the month as a decimal number [01,31]." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%H - Hour (24-hour clock) as a decimal number [00,23]." />
|
||||
<label align="0.0" string="%%I - Hour (12-hour clock) as a decimal number [01,12]." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%j - Day of the year as a decimal number [001,366]." />
|
||||
<label align="0.0" string="%%m - Month as a decimal number [01,12]." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%M - Minute as a decimal number [00,59]." />
|
||||
<label align="0.0" string="%%p - Equivalent of either AM or PM." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%S - Second as a decimal number [00,61]." />
|
||||
<label align="0.0" string="%%w - Weekday as a decimal number [0(Sunday),6]." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%x - Appropriate date representation." />
|
||||
<label align="0.0" string="%%X - Appropriate time representation." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%y - Year without century as a decimal number [00,99]." />
|
||||
<label align="0.0" string="%%Y - Year with century as a decimal number." />
|
||||
<newline/>
|
||||
<label align="0.0" string="%%U - Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0." />
|
||||
<label align="0.0" string="%%W - Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0." />
|
||||
<newline/>
|
||||
<label align="0.0" string="======================================================" />
|
||||
</group>
|
||||
<newline/>
|
||||
<group colspan="4" col="4">
|
||||
<separator string="Examples"/>
|
||||
<newline/>
|
||||
<label align="0.0" string="1. %%c ==> Fri Dec 5 18:25:20 2008"/>
|
||||
<label align="0.0" string="2. %%a ,%%A ==> Fri, Friday"/>
|
||||
<newline/>
|
||||
<label align="0.0" string="3. %%x ,%%X ==> 12/05/08, 18:25:20"/>
|
||||
<label align="0.0" string="4. %%b, %%B ==> Dec, December"/>
|
||||
<newline/>
|
||||
<label align="0.0" string="5. %%y, %%Y ==> 08, 2008"/>
|
||||
<label align="0.0" string="6. %%d, %%m ==> 05, 12"/>
|
||||
<newline/>
|
||||
<label align="0.0" string="7. %%H:%%M:%%S ==> 18:25:20"/>
|
||||
<label align="0.0" string="8. %%I:%%M:%%S %%p ==> 06:25:20 PM"/>
|
||||
<newline/>
|
||||
<label align="0.0" string="9. %%j ==> 340"/>
|
||||
<label align="0.0" string="10. %%S ==> 20"/>
|
||||
<newline/>
|
||||
<label align="0.0" string="11. %%U or %%W ==> 48 (49th week)"/>
|
||||
<label align="0.0" string="12. %%w ==> 5 ( Friday is the 6th day)"/>
|
||||
<newline/>
|
||||
</group>
|
||||
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_lang_act_window" model="ir.actions.act_window">
|
||||
<field name="name">Languages</field>
|
||||
<field name="res_model">res.lang</field>
|
||||
|
|
|
@ -34,8 +34,8 @@ class res_request(osv.osv):
|
|||
|
||||
def request_send(self, cr, uid, ids, *args):
|
||||
for id in ids:
|
||||
cr.execute('update res_request set state=%s,date_sent=%s where id=%d', ('waiting', time.strftime('%Y-%m-%d %H:%M:%S'), id))
|
||||
cr.execute('select act_from,act_to,body,date_sent from res_request where id=%d', (id,))
|
||||
cr.execute('update res_request set state=%s,date_sent=%s where id=%s', ('waiting', time.strftime('%Y-%m-%d %H:%M:%S'), id))
|
||||
cr.execute('select act_from,act_to,body,date_sent from res_request where id=%s', (id,))
|
||||
values = cr.dictfetchone()
|
||||
if values['body'] and (len(values['body']) > 128):
|
||||
values['name'] = values['body'][:125] + '...'
|
||||
|
@ -47,7 +47,7 @@ class res_request(osv.osv):
|
|||
|
||||
def request_reply(self, cr, uid, ids, *args):
|
||||
for id in ids:
|
||||
cr.execute("update res_request set state='active', act_from=%d, act_to=act_from, trigger_date=NULL, body='' where id=%d", (uid,id))
|
||||
cr.execute("update res_request set state='active', act_from=%s, act_to=act_from, trigger_date=NULL, body='' where id=%s", (uid,id))
|
||||
return True
|
||||
|
||||
def request_close(self, cr, uid, ids, *args):
|
||||
|
@ -55,9 +55,9 @@ class res_request(osv.osv):
|
|||
return True
|
||||
|
||||
def request_get(self, cr, uid):
|
||||
cr.execute('select id from res_request where act_to=%d and (trigger_date<=%s or trigger_date is null) and active=True', (uid,time.strftime('%Y-%m-%d')))
|
||||
cr.execute('select id from res_request where act_to=%s and (trigger_date<=%s or trigger_date is null) and active=True', (uid,time.strftime('%Y-%m-%d')))
|
||||
ids = map(lambda x:x[0], cr.fetchall())
|
||||
cr.execute('select id from res_request where act_from=%d and (act_to<>%d) and (trigger_date<=%s or trigger_date is null) and active=True', (uid,uid,time.strftime('%Y-%m-%d')))
|
||||
cr.execute('select id from res_request where act_from=%s and (act_to<>%s) and (trigger_date<=%s or trigger_date is null) and active=True', (uid,uid,time.strftime('%Y-%m-%d')))
|
||||
ids2 = map(lambda x:x[0], cr.fetchall())
|
||||
return (ids, ids2)
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class roles(osv.osv):
|
|||
def check(self, cr, uid, ids, role_id):
|
||||
if role_id in ids:
|
||||
return True
|
||||
cr.execute('select parent_id from res_roles where id=%d', (role_id,))
|
||||
cr.execute('select parent_id from res_roles where id=%s', (role_id,))
|
||||
roles = cr.fetchone()[0]
|
||||
if roles:
|
||||
return self.check(cr, uid, ids, roles)
|
||||
|
@ -152,7 +152,7 @@ class users(osv.osv):
|
|||
'groups_id': _get_group,
|
||||
}
|
||||
def company_get(self, cr, uid, uid2):
|
||||
company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id
|
||||
company_id = self.pool.get('res.users').browse(cr, uid, uid2).company_id.id
|
||||
return company_id
|
||||
company_get = tools.cache()(company_get)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<rng:optional><rng:attribute name="editable"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="type"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="link"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="notebook"/>
|
||||
|
@ -33,12 +34,15 @@
|
|||
<rng:optional><rng:attribute name="editable"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="toolbar"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="link"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="type"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="field"/>
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="tree"/>
|
||||
<rng:ref name="group"/>
|
||||
<rng:ref name="button"/>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
|
@ -57,6 +61,35 @@
|
|||
<rng:optional><rng:attribute name="nolabel"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="colspan"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="string"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="angle"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:text/>
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="level">
|
||||
<rng:element name="level">
|
||||
<rng:optional><rng:attribute name="object"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="link"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="domain"/></rng:optional>
|
||||
<rng:oneOrMore>
|
||||
<rng:optional><rng:ref name="field"/></rng:optional>
|
||||
</rng:oneOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="gantt">
|
||||
<rng:element name="gantt">
|
||||
<rng:optional><rng:attribute name="color"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="date_delay"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="date_start"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="date_string"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="string"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:optional><rng:ref name="level"/></rng:optional>
|
||||
<rng:optional><rng:ref name="field"/></rng:optional>
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
|
@ -123,6 +156,17 @@
|
|||
<rng:optional><rng:attribute name="col"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="select"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="button"/>
|
||||
<rng:ref name="field"/>
|
||||
<rng:ref name="label" />
|
||||
<rng:ref name="group" />
|
||||
<rng:element name="properties"><rng:empty/></rng:element>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
|
@ -135,6 +179,7 @@
|
|||
<rng:ref name="notebook" />
|
||||
<rng:ref name="graph" />
|
||||
<rng:ref name="calendar" />
|
||||
<rng:ref name="gantt" />
|
||||
<rng:ref name="form"/>
|
||||
<rng:ref name="tree"/>
|
||||
<rng:ref name="field"/>
|
||||
|
@ -181,17 +226,25 @@
|
|||
<rng:optional><rng:attribute name="digits"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="icon"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="mode"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="img_width"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="img_height"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="size"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="filename"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="fieldname"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="height"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="rowspan"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="align"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="form"/>
|
||||
<rng:ref name="tree"/>
|
||||
<rng:ref name="field"/>
|
||||
<rng:ref name="label"/>
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="xpath"/>
|
||||
<rng:ref name="button"/>
|
||||
<rng:ref name="group"/>
|
||||
<rng:ref name="graph"/>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
|
@ -203,12 +256,15 @@
|
|||
<rng:optional><rng:attribute name="attrs"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="col"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="colspan"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="expand"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="states"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="groups"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="string"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="fill"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="height"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="name"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="color" /></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="separator"/>
|
||||
|
@ -231,6 +287,7 @@
|
|||
<rng:optional><rng:attribute name="date_stop" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="day_length" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="date_delay" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="type" /></rng:optional>
|
||||
<rng:oneOrMore>
|
||||
<rng:ref name="field"/>
|
||||
</rng:oneOrMore>
|
||||
|
@ -242,6 +299,7 @@
|
|||
<rng:optional><rng:attribute name="string" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="orientation" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="type" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="color"/></rng:optional>
|
||||
<rng:oneOrMore>
|
||||
<rng:ref name="field"/>
|
||||
</rng:oneOrMore>
|
||||
|
@ -263,6 +321,7 @@
|
|||
<rng:optional><rng:attribute name="target"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="readonly"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="context"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="form" />
|
||||
|
@ -271,6 +330,7 @@
|
|||
<rng:ref name="notebook" />
|
||||
<rng:ref name="graph" />
|
||||
<rng:ref name="calendar" />
|
||||
<rng:ref name="gantt" />
|
||||
<rng:ref name="xpath" />
|
||||
<rng:ref name="page" />
|
||||
<rng:ref name="separator"/>
|
||||
|
@ -286,11 +346,13 @@
|
|||
<rng:start>
|
||||
<rng:choice>
|
||||
<rng:ref name="form" />
|
||||
<rng:ref name="group" />
|
||||
<rng:ref name="field" />
|
||||
<rng:ref name="tree" />
|
||||
<rng:ref name="notebook" />
|
||||
<rng:ref name="graph" />
|
||||
<rng:ref name="calendar" />
|
||||
<rng:ref name="gantt" />
|
||||
<rng:ref name="xpath" />
|
||||
<rng:ref name="page" />
|
||||
<rng:ref name="separator"/>
|
||||
|
|
|
@ -157,13 +157,12 @@ def init_logger():
|
|||
|
||||
if config['logfile']:
|
||||
logf = config['logfile']
|
||||
# test if the directories exist, else create them
|
||||
try:
|
||||
dirname = os.path.dirname(logf)
|
||||
if not os.path.isdir(dirname):
|
||||
res = os.makedirs(dirname)
|
||||
if dirname and not os.path.isdir(dirname):
|
||||
os.makedirs(dirname)
|
||||
handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
|
||||
except:
|
||||
except Exception, ex:
|
||||
sys.stderr.write("ERROR: couldn't create the logfile directory\n")
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
else:
|
||||
|
@ -177,7 +176,7 @@ def init_logger():
|
|||
|
||||
# add the handler to the root logger
|
||||
logging.getLogger().addHandler(handler)
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
logging.getLogger().setLevel(config['log_level'])
|
||||
|
||||
if (not isinstance(handler, logging.FileHandler)) and os.name != 'nt':
|
||||
# change color of level names
|
||||
|
@ -204,8 +203,16 @@ def init_logger():
|
|||
class Logger(object):
|
||||
def notifyChannel(self, name, level, msg):
|
||||
log = logging.getLogger(name)
|
||||
getattr(log, level)(msg)
|
||||
level_method = getattr(log, level)
|
||||
|
||||
result = str(msg).strip().split('\n')
|
||||
if len(result)>1:
|
||||
for idx, s in enumerate(result):
|
||||
level_method('[%02d]: %s' % (idx+1, s,))
|
||||
elif result:
|
||||
level_method(result[0])
|
||||
|
||||
init_logger()
|
||||
|
||||
class Agent(object):
|
||||
_timers = []
|
||||
|
@ -391,12 +398,14 @@ class TinySocketClientThread(threading.Thread):
|
|||
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))
|
||||
s = str(e)
|
||||
print e
|
||||
print tb_s
|
||||
import tools
|
||||
if tools.config['debug_mode']:
|
||||
import pdb
|
||||
tb = sys.exc_info()[2]
|
||||
pdb.post_mortem(tb)
|
||||
e = Exception(e.message)
|
||||
ts.mysend(e, exception=True, traceback=tb_s)
|
||||
except:
|
||||
pass
|
||||
|
|
|
@ -53,23 +53,24 @@ __version__ = release.version
|
|||
# get logger
|
||||
#----------------------------------------------------------
|
||||
import netsvc
|
||||
|
||||
netsvc.init_logger()
|
||||
|
||||
logger = netsvc.Logger()
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# import the tools module so that the commandline parameters are parsed
|
||||
#-----------------------------------------------------------------------
|
||||
import tools
|
||||
|
||||
logger.notifyChannel("server", netsvc.LOG_INFO, "version - %s" % release.version )
|
||||
for name, value in [('addons_path', tools.config['addons_path']),
|
||||
('database hostname', tools.config['db_host'] or 'localhost')]:
|
||||
logger.notifyChannel("server", netsvc.LOG_INFO, "%s - %s" % ( name, value ))
|
||||
|
||||
import time
|
||||
|
||||
if sys.platform == 'win32':
|
||||
import mx.DateTime
|
||||
mx.DateTime.strptime = lambda x, y: mx.DateTime.mktime(time.strptime(x, y))
|
||||
|
||||
#os.chdir(tools.file_path_root)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# init net service
|
||||
#----------------------------------------------------------
|
||||
|
@ -81,35 +82,13 @@ dispatcher.monitor(signal.SIGINT)
|
|||
#---------------------------------------------------------------
|
||||
# connect to the database and initialize it with base if needed
|
||||
#---------------------------------------------------------------
|
||||
import psycopg
|
||||
import pooler
|
||||
|
||||
db_name = tools.config["db_name"]
|
||||
|
||||
# test whether it is needed to initialize the db (the db is empty)
|
||||
#try:
|
||||
# cr = pooler.get_db_only(db_name).cursor()
|
||||
#except psycopg.OperationalError:
|
||||
# logger.notifyChannel("init", netsvc.LOG_INFO, "could not connect to database '%s'!" % db_name,)
|
||||
# cr = None
|
||||
#if cr:
|
||||
# cr.execute("SELECT relname FROM pg_class WHERE relkind='r' AND relname='ir_ui_menu'")
|
||||
# if len(cr.fetchall())==0:
|
||||
##if False:
|
||||
# logger.notifyChannel("init", netsvc.LOG_INFO, "init db")
|
||||
# tools.init_db(cr)
|
||||
# # in that case, force --init=all
|
||||
# tools.config["init"]["all"] = 1
|
||||
# tools.config['update']['all'] = 1
|
||||
# if not tools.config['without_demo']:
|
||||
# tools.config["demo"]['all'] = 1
|
||||
# cr.close()
|
||||
|
||||
#----------------------------------------------------------
|
||||
# launch modules install/upgrade/removes if needed
|
||||
#----------------------------------------------------------
|
||||
if tools.config['upgrade']:
|
||||
print 'Upgrading new modules...'
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'Upgrading new modules...')
|
||||
import tools.upgrade
|
||||
(toinit, toupdate) = tools.upgrade.upgrade()
|
||||
for m in toinit:
|
||||
|
@ -120,15 +99,24 @@ if tools.config['upgrade']:
|
|||
#----------------------------------------------------------
|
||||
# import basic modules
|
||||
#----------------------------------------------------------
|
||||
import osv, workflow, report, service
|
||||
import osv
|
||||
import workflow
|
||||
import report
|
||||
import service
|
||||
|
||||
#----------------------------------------------------------
|
||||
# import addons
|
||||
#----------------------------------------------------------
|
||||
|
||||
import addons
|
||||
|
||||
if tools.config['init'] or tools.config['update']:
|
||||
pooler.get_db_and_pool(tools.config['db_name'], update_module=True)
|
||||
#----------------------------------------------------------
|
||||
# Load and update databases if requested
|
||||
#----------------------------------------------------------
|
||||
|
||||
if tools.config['db_name']:
|
||||
for db in tools.config['db_name'].split(','):
|
||||
pooler.get_db_and_pool(db, update_module=tools.config['init'] or tools.config['update'])
|
||||
|
||||
#----------------------------------------------------------
|
||||
# translation stuff
|
||||
|
@ -179,17 +167,14 @@ if tools.config['xmlrpc']:
|
|||
if tools.config["xmlrpc"]:
|
||||
xml_gw = netsvc.xmlrpc.RpcGateway('web-services')
|
||||
httpd.attach("/xmlrpc", xml_gw)
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO,
|
||||
"starting XML-RPC" + \
|
||||
(tools.config['secure'] and ' Secure' or '') + \
|
||||
" services, port " + str(port))
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting XML-RPC%s services, port %s" % ((tools.config['secure'] and ' Secure' or ''), port))
|
||||
|
||||
#
|
||||
#if tools.config["soap"]:
|
||||
# soap_gw = netsvc.xmlrpc.RpcGateway('web-services')
|
||||
# httpd.attach("/soap", soap_gw )
|
||||
# logger.notifyChannel("web-services", netsvc.LOG_INFO, 'starting SOAP services, port '+str(port))
|
||||
#
|
||||
#
|
||||
#if tools.config["soap"]:
|
||||
# soap_gw = netsvc.xmlrpc.RpcGateway('web-services')
|
||||
# httpd.attach("/soap", soap_gw )
|
||||
# logger.notifyChannel("web-services", netsvc.LOG_INFO, 'starting SOAP services, port '+str(port))
|
||||
#
|
||||
|
||||
if tools.config['netrpc']:
|
||||
try:
|
||||
|
|
|
@ -51,7 +51,7 @@ class expression(object):
|
|||
subids = ids[i:i+cr.IN_MAX]
|
||||
cr.execute('SELECT "%s"' \
|
||||
' FROM "%s"' \
|
||||
' WHERE "%s" in (%s)' % (s, f, w, ','.join(['%d']*len(subids))),
|
||||
' WHERE "%s" in (%s)' % (s, f, w, ','.join(['%s']*len(subids))),
|
||||
subids)
|
||||
res.extend([r[0] for r in cr.fetchall()])
|
||||
return res
|
||||
|
@ -244,7 +244,7 @@ class expression(object):
|
|||
|
||||
if len_after:
|
||||
if left == 'id':
|
||||
instr = ','.join(['%d'] * len_after)
|
||||
instr = ','.join(['%s'] * len_after)
|
||||
else:
|
||||
instr = ','.join([table._columns[left]._symbol_set[0]] * len_after)
|
||||
query = '(%s.%s %s (%s))' % (table._table, left, operator, instr)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
import string
|
||||
import netsvc
|
||||
|
||||
import psycopg
|
||||
from psycopg2 import Binary
|
||||
import warnings
|
||||
|
||||
import tools
|
||||
|
@ -86,7 +86,7 @@ class _column(object):
|
|||
pass
|
||||
|
||||
def set(self, cr, obj, id, name, value, user=None, context=None):
|
||||
cr.execute('update '+obj._table+' set '+name+'='+self._symbol_set[0]+' where id=%d', (self._symbol_set[1](value), id))
|
||||
cr.execute('update '+obj._table+' set '+name+'='+self._symbol_set[0]+' where id=%s', (self._symbol_set[1](value), id))
|
||||
|
||||
def set_memory(self, cr, obj, id, name, value, user=None, context=None):
|
||||
raise Exception(_('Not implemented set_memory method !'))
|
||||
|
@ -118,13 +118,13 @@ class boolean(_column):
|
|||
|
||||
class integer_big(_column):
|
||||
_type = 'integer_big'
|
||||
_symbol_c = '%d'
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = lambda x: int(x or 0)
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
|
||||
class integer(_column):
|
||||
_type = 'integer'
|
||||
_symbol_c = '%d'
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = lambda x: int(x or 0)
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
|
||||
|
@ -168,10 +168,9 @@ class text(_column):
|
|||
|
||||
import __builtin__
|
||||
|
||||
|
||||
class float(_column):
|
||||
_type = 'float'
|
||||
_symbol_c = '%f'
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = lambda x: __builtin__.float(x or 0.0)
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
|
||||
|
@ -195,8 +194,9 @@ class time(_column):
|
|||
class binary(_column):
|
||||
_type = 'binary'
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = lambda symb: symb and psycopg.Binary(symb) or None
|
||||
_symbol_f = lambda symb: symb and Binary(symb) or None
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
_symbol_get = lambda self, x: x and str(x)
|
||||
|
||||
_classic_read = False
|
||||
|
||||
|
@ -209,7 +209,6 @@ class binary(_column):
|
|||
context = {}
|
||||
if not values:
|
||||
values = []
|
||||
|
||||
res = {}
|
||||
for i in ids:
|
||||
val = None
|
||||
|
@ -217,10 +216,10 @@ class binary(_column):
|
|||
if v['id'] == i:
|
||||
val = v[name]
|
||||
break
|
||||
res.setdefault(i, val)
|
||||
if context.get('bin_size', False):
|
||||
res[i] = tools.human_size(val)
|
||||
|
||||
else:
|
||||
res[i] = val
|
||||
return res
|
||||
|
||||
get = get_memory
|
||||
|
@ -263,9 +262,9 @@ class one2one(_column):
|
|||
self._table = obj_src.pool.get(self._obj)._table
|
||||
if act[0] == 0:
|
||||
id_new = obj.create(cr, user, act[1])
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%d where id=%d', (id_new, id))
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%s where id=%s', (id_new, id))
|
||||
else:
|
||||
cr.execute('select '+field+' from '+obj_src._table+' where id=%d', (act[0],))
|
||||
cr.execute('select '+field+' from '+obj_src._table+' where id=%s', (act[0],))
|
||||
id = cr.fetchone()[0]
|
||||
obj.write(cr, user, [id], act[1], context=context)
|
||||
|
||||
|
@ -277,6 +276,9 @@ class many2one(_column):
|
|||
_classic_read = False
|
||||
_classic_write = True
|
||||
_type = 'many2one'
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = lambda x: x or None
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
|
||||
def __init__(self, obj, string='unknown', **args):
|
||||
_column.__init__(self, string=string, **args)
|
||||
|
@ -331,20 +333,20 @@ class many2one(_column):
|
|||
for act in values:
|
||||
if act[0] == 0:
|
||||
id_new = obj.create(cr, act[2])
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%d where id=%d', (id_new, id))
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%s where id=%s', (id_new, id))
|
||||
elif act[0] == 1:
|
||||
obj.write(cr, [act[1]], act[2], context=context)
|
||||
elif act[0] == 2:
|
||||
cr.execute('delete from '+self._table+' where id=%d', (act[1],))
|
||||
cr.execute('delete from '+self._table+' where id=%s', (act[1],))
|
||||
elif act[0] == 3 or act[0] == 5:
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=null where id=%d', (id,))
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=null where id=%s', (id,))
|
||||
elif act[0] == 4:
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%d where id=%d', (act[1], id))
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%s where id=%s', (act[1], id))
|
||||
else:
|
||||
if values:
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%d where id=%d', (values, id))
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=%s where id=%s', (values, id))
|
||||
else:
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=null where id=%d', (id,))
|
||||
cr.execute('update '+obj_src._table+' set '+field+'=null where id=%s', (id,))
|
||||
|
||||
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None):
|
||||
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', 'like', value)], offset, limit)
|
||||
|
@ -435,19 +437,19 @@ class one2many(_column):
|
|||
elif act[0] == 2:
|
||||
obj.unlink(cr, user, [act[1]], context=context)
|
||||
elif act[0] == 3:
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=null where id=%d', (act[1],))
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=null where id=%s', (act[1],))
|
||||
elif act[0] == 4:
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=%d where id=%d', (id, act[1]))
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=%s where id=%s', (id, act[1]))
|
||||
elif act[0] == 5:
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=null where '+self._fields_id+'=%d', (id,))
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=null where '+self._fields_id+'=%s', (id,))
|
||||
elif act[0] == 6:
|
||||
if not act[2]:
|
||||
ids2 = [0]
|
||||
else:
|
||||
ids2 = act[2]
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=NULL where '+self._fields_id+'=%d and id not in ('+','.join(map(str, ids2))+')', (id,))
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=NULL where '+self._fields_id+'=%s and id not in ('+','.join(map(str, ids2))+')', (id,))
|
||||
if act[2]:
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=%d where id in ('+','.join(map(str, act[2]))+')', (id,))
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=%s where id in ('+','.join(map(str, act[2]))+')', (id,))
|
||||
|
||||
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
|
||||
return obj.pool.get(self._obj).name_search(cr, uid, value, self._domain, offset, limit)
|
||||
|
@ -500,7 +502,7 @@ class many2many(_column):
|
|||
FROM '+self._rel+' , '+obj._table+' \
|
||||
WHERE '+self._rel+'.'+self._id1+' in ('+ids_s+') \
|
||||
AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+d1
|
||||
+limit_str+' order by '+obj._table+'.'+obj._order+' offset %d',
|
||||
+limit_str+' order by '+obj._table+'.'+obj._order+' offset %s',
|
||||
d2+[offset])
|
||||
for r in cr.fetchall():
|
||||
res[r[1]].append(r[0])
|
||||
|
@ -515,26 +517,26 @@ class many2many(_column):
|
|||
for act in values:
|
||||
if act[0] == 0:
|
||||
idnew = obj.create(cr, user, act[2])
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%d,%d)', (id, idnew))
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, idnew))
|
||||
elif act[0] == 1:
|
||||
obj.write(cr, user, [act[1]], act[2], context=context)
|
||||
elif act[0] == 2:
|
||||
obj.unlink(cr, user, [act[1]], context=context)
|
||||
elif act[0] == 3:
|
||||
cr.execute('delete from '+self._rel+' where ' + self._id1 + '=%d and '+ self._id2 + '=%d', (id, act[1]))
|
||||
cr.execute('delete from '+self._rel+' where ' + self._id1 + '=%s and '+ self._id2 + '=%s', (id, act[1]))
|
||||
elif act[0] == 4:
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%d,%d)', (id, act[1]))
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, act[1]))
|
||||
elif act[0] == 5:
|
||||
cr.execute('update '+self._rel+' set '+self._id2+'=null where '+self._id2+'=%d', (id,))
|
||||
cr.execute('update '+self._rel+' set '+self._id2+'=null where '+self._id2+'=%s', (id,))
|
||||
elif act[0] == 6:
|
||||
|
||||
d1, d2 = obj.pool.get('ir.rule').domain_get(cr, user, obj._name)
|
||||
if d1:
|
||||
d1 = ' and ' + d1
|
||||
cr.execute('delete from '+self._rel+' where '+self._id1+'=%d AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+obj._table+' WHERE '+self._rel+'.'+self._id1+'=%d AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
|
||||
cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+obj._table+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
|
||||
|
||||
for act_nbr in act[2]:
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%d, %d)', (id, act_nbr))
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s, %s)', (id, act_nbr))
|
||||
|
||||
#
|
||||
# TODO: use a name_search
|
||||
|
@ -601,9 +603,9 @@ class function(_column):
|
|||
self._classic_read = True
|
||||
self._classic_write = True
|
||||
if type == 'float':
|
||||
self._symbol_c = '%f'
|
||||
self._symbol_f = lambda x: __builtin__.float(x or 0.0)
|
||||
self._symbol_set = (self._symbol_c, self._symbol_f)
|
||||
self._symbol_c = float._symbol_c
|
||||
self._symbol_f = float._symbol_f
|
||||
self._symbol_set = float._symbol_set
|
||||
|
||||
def search(self, cr, uid, obj, name, args):
|
||||
if not self._fnct_search:
|
||||
|
@ -655,8 +657,33 @@ class related(function):
|
|||
i -= 1
|
||||
return [(self._arg[0], 'in', sarg)]
|
||||
|
||||
def _fnct_write(self,obj,cr, uid, ids,values, field_name, args, context=None):
|
||||
raise 'Not Implemented Yet'
|
||||
def _fnct_write(self,obj,cr, uid, ids, field_name, values, args, context=None):
|
||||
print 'Related Write', obj._name
|
||||
if values and field_name:
|
||||
self._field_get2(cr, uid, obj, context)
|
||||
relation = obj._name
|
||||
res = {}
|
||||
if type(ids) != type([]):
|
||||
ids=[ids]
|
||||
objlst = obj.browse(cr, uid, ids)
|
||||
for data in objlst:
|
||||
t_id=None
|
||||
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]]:
|
||||
t_data = False
|
||||
break
|
||||
if field_detail['type'] in ('one2many', 'many2many'):
|
||||
t_id=t_data.id
|
||||
t_data = t_data[self.arg[i]][0]
|
||||
else:
|
||||
t_id=t_data['id']
|
||||
t_data = t_data[self.arg[i]]
|
||||
if t_id:
|
||||
obj.pool.get(field_detail['object']).write(cr,uid,[t_id],{args[-1]:values})
|
||||
|
||||
def _fnct_read(self, obj, cr, uid, ids, field_name, args, context=None):
|
||||
self._field_get2(cr, uid, obj, context)
|
||||
|
@ -686,7 +713,7 @@ class related(function):
|
|||
def __init__(self, *arg, **args):
|
||||
self.arg = arg
|
||||
self._relations = []
|
||||
super(related, self).__init__(self._fnct_read, arg, fnct_inv_arg=arg, method=True, fnct_search=self._fnct_search, **args)
|
||||
super(related, self).__init__(self._fnct_read, arg, self._fnct_write, fnct_inv_arg=arg, method=True, fnct_search=self._fnct_search, **args)
|
||||
|
||||
def _field_get2(self, cr, uid, obj, context={}):
|
||||
if self._relations:
|
||||
|
@ -728,7 +755,7 @@ class property(function):
|
|||
nid = property.search(cr, uid, [('fields_id', '=', definition_id),
|
||||
('res_id', '=', obj._name+','+str(id))])
|
||||
while len(nid):
|
||||
cr.execute('DELETE FROM ir_property WHERE id=%d', (nid.pop(),))
|
||||
cr.execute('DELETE FROM ir_property WHERE id=%s', (nid.pop(),))
|
||||
|
||||
nid = property.search(cr, uid, [('fields_id', '=', definition_id),
|
||||
('res_id', '=', False)])
|
||||
|
|
379
bin/osv/orm.py
379
bin/osv/orm.py
|
@ -349,7 +349,7 @@ class orm_template(object):
|
|||
id, model_id, model, name, field_description, ttype,
|
||||
relation,view_load,state,select_level
|
||||
) VALUES (
|
||||
%d,%s,%s,%s,%s,%s,%s,%s,%s,%s
|
||||
%s,%s,%s,%s,%s,%s,%s,%s,%s,%s
|
||||
)""", (
|
||||
id, vals['model_id'], vals['model'], vals['name'], vals['field_description'], vals['ttype'],
|
||||
vals['relation'], bool(vals['view_load']), 'base',
|
||||
|
@ -732,7 +732,6 @@ class orm_template(object):
|
|||
and getattr(self._columns[f], arg):
|
||||
res[f][arg] = getattr(self._columns[f], arg)
|
||||
|
||||
# translate the field label
|
||||
res_trans = translation_obj._get_source(cr, user,
|
||||
self._name + ',' + f, 'field', context.get('lang', False) or 'en_US')
|
||||
if res_trans:
|
||||
|
@ -843,15 +842,15 @@ class orm_template(object):
|
|||
# translate view
|
||||
if ('lang' in context) and not result:
|
||||
if node.hasAttribute('string') and node.getAttribute('string'):
|
||||
trans = tools.translate(cr, self._name, 'view', context['lang'], node.getAttribute('string').encode('utf8'))
|
||||
trans = self.pool.get('ir.translation')._get_source(cr, user, self._name, 'view', context['lang'], node.getAttribute('string').encode('utf8'))
|
||||
if not trans and ('base_model_name' in context):
|
||||
trans = tools.translate(cr, context['base_model_name'], 'view', context['lang'], node.getAttribute('string').encode('utf8'))
|
||||
trans = self.pool.get('ir.translation')._get_source(cr, user, context['base_model_name'], 'view', context['lang'], node.getAttribute('string').encode('utf8'))
|
||||
if trans:
|
||||
node.setAttribute('string', trans.decode('utf8'))
|
||||
node.setAttribute('string', trans)
|
||||
if node.hasAttribute('sum') and node.getAttribute('sum'):
|
||||
trans = tools.translate(cr, self._name, 'view', context['lang'], node.getAttribute('sum').encode('utf8'))
|
||||
trans = self.pool.get('ir.translation')._get_source(cr, user, self._name, 'view', context['lang'], node.getAttribute('sum').encode('utf8'))
|
||||
if trans:
|
||||
node.setAttribute('sum', trans.decode('utf8'))
|
||||
node.setAttribute('sum', trans)
|
||||
|
||||
if childs:
|
||||
for f in node.childNodes:
|
||||
|
@ -1004,7 +1003,7 @@ class orm_template(object):
|
|||
while ok:
|
||||
if view_id:
|
||||
where = (model and (" and model='%s'" % (self._name,))) or ''
|
||||
cr.execute('SELECT arch,name,field_parent,id,type,inherit_id FROM ir_ui_view WHERE id=%d'+where, (view_id,))
|
||||
cr.execute('SELECT arch,name,field_parent,id,type,inherit_id FROM ir_ui_view WHERE id=%s'+where, (view_id,))
|
||||
else:
|
||||
cr.execute('''SELECT
|
||||
arch,name,field_parent,id,type,inherit_id
|
||||
|
@ -1030,7 +1029,7 @@ class orm_template(object):
|
|||
|
||||
def _inherit_apply_rec(result, inherit_id):
|
||||
# get all views which inherit from (ie modify) this view
|
||||
cr.execute('select arch,id from ir_ui_view where inherit_id=%d and model=%s order by priority', (inherit_id, self._name))
|
||||
cr.execute('select arch,id from ir_ui_view where inherit_id=%s and model=%s order by priority', (inherit_id, self._name))
|
||||
sql_inherit = cr.fetchall()
|
||||
for (inherit, id) in sql_inherit:
|
||||
result = _inherit_apply(result, inherit)
|
||||
|
@ -1377,15 +1376,36 @@ class orm(orm_template):
|
|||
childs = cr.fetchall()
|
||||
for id in childs:
|
||||
pos2 = browse_rec(id[0], pos2)
|
||||
cr.execute('update '+self._table+' set parent_left=%d, parent_right=%d where id=%d', (pos,pos2,root))
|
||||
cr.execute('update '+self._table+' set parent_left=%s, parent_right=%s where id=%s', (pos,pos2,root))
|
||||
return pos2+1
|
||||
browse_rec(None)
|
||||
return True
|
||||
|
||||
def _update_store(self, cr, f, k):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, "storing computed values of fields.function '%s'" % (k,))
|
||||
ss = self._columns[k]._symbol_set
|
||||
update_query = 'UPDATE "%s" SET "%s"=%s WHERE id=%%s' % (self._table, k, ss[0])
|
||||
cr.execute('select id from '+self._table)
|
||||
ids_lst = map(lambda x: x[0], cr.fetchall())
|
||||
while ids_lst:
|
||||
iids = ids_lst[:40]
|
||||
ids_lst = ids_lst[40:]
|
||||
res = f.get(cr, self, iids, k, 1, {})
|
||||
for key,val in res.items():
|
||||
if f._multi:
|
||||
val = val[k]
|
||||
# if val is a many2one, just write the ID
|
||||
if type(val)==tuple:
|
||||
val = val[0]
|
||||
if (val<>False) or (type(val)<>bool):
|
||||
cr.execute(update_query, (ss[1](val), key))
|
||||
|
||||
def _auto_init(self, cr, context={}):
|
||||
store_compute = False
|
||||
logger = netsvc.Logger()
|
||||
create = False
|
||||
todo_end = []
|
||||
self._field_create(cr, context=context)
|
||||
if not hasattr(self, "_auto") or self._auto:
|
||||
cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname='%s'" % self._table)
|
||||
|
@ -1405,8 +1425,8 @@ class orm(orm_template):
|
|||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'create a column parent_right on object %s: fields.integer(\'Right Parent\', select=1)' % (self._table, ))
|
||||
if self._columns[self._parent_name].ondelete<>'cascade':
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, "the columns %s on object must be set as ondelete='cascasde'" % (self._name, self._parent_name))
|
||||
cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" INTEGER" % (self._table, 'parent_left'))
|
||||
cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" INTEGER" % (self._table, 'parent_right'))
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "parent_left" INTEGER' % (self._table,))
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "parent_right" INTEGER' % (self._table,))
|
||||
cr.commit()
|
||||
store_compute = True
|
||||
|
||||
|
@ -1418,15 +1438,13 @@ class orm(orm_template):
|
|||
'write_date': 'TIMESTAMP'
|
||||
}
|
||||
for k in logs:
|
||||
cr.execute(
|
||||
"""
|
||||
cr.execute("""
|
||||
SELECT c.relname
|
||||
FROM pg_class c, pg_attribute a
|
||||
WHERE c.relname='%s' AND a.attname='%s' AND c.oid=a.attrelid
|
||||
""" % (self._table, k))
|
||||
WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid
|
||||
""", (self._table, k))
|
||||
if not cr.rowcount:
|
||||
cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s" %
|
||||
(self._table, k, logs[k]))
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, logs[k]))
|
||||
cr.commit()
|
||||
|
||||
# iterate on the database columns to drop the NOT NULL constraints
|
||||
|
@ -1434,12 +1452,12 @@ class orm(orm_template):
|
|||
cr.execute(
|
||||
"SELECT a.attname, a.attnotnull "\
|
||||
"FROM pg_class c, pg_attribute a "\
|
||||
"WHERE c.oid=a.attrelid AND c.relname='%s'" % self._table)
|
||||
"WHERE c.oid=a.attrelid AND c.relname=%s", (self._table,))
|
||||
db_columns = cr.dictfetchall()
|
||||
for column in db_columns:
|
||||
if column['attname'] not in ('id', 'oid', 'tableoid', 'ctid', 'xmin', 'xmax', 'cmin', 'cmax'):
|
||||
if column['attnotnull'] and column['attname'] not in self._columns:
|
||||
cr.execute("ALTER TABLE \"%s\" ALTER COLUMN \"%s\" DROP NOT NULL" % (self._table, column['attname']))
|
||||
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" DROP NOT NULL' % (self._table, column['attname']))
|
||||
|
||||
# iterate on the "object columns"
|
||||
todo_update_store = []
|
||||
|
@ -1452,10 +1470,10 @@ class orm(orm_template):
|
|||
if isinstance(f, fields.one2many):
|
||||
cr.execute("SELECT relname FROM pg_class WHERE relkind='r' AND relname=%s", (f._obj,))
|
||||
if cr.fetchone():
|
||||
cr.execute("SELECT count(*) as c FROM pg_class c,pg_attribute a WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid", (f._obj, f._fields_id))
|
||||
cr.execute("SELECT count(1) as c FROM pg_class c,pg_attribute a WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid", (f._obj, f._fields_id))
|
||||
res = cr.fetchone()[0]
|
||||
if not res:
|
||||
cr.execute("ALTER TABLE \"%s\" ADD FOREIGN KEY (%s) REFERENCES \"%s\" ON DELETE SET NULL" % (self._obj, f._fields_id, f._table))
|
||||
cr.execute('ALTER TABLE "%s" ADD FOREIGN KEY (%s) REFERENCES "%s" ON DELETE SET NULL' % (self._obj, f._fields_id, f._table))
|
||||
elif isinstance(f, fields.many2many):
|
||||
cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname=%s", (f._rel,))
|
||||
if not cr.dictfetchall():
|
||||
|
@ -1464,29 +1482,40 @@ class orm(orm_template):
|
|||
ref = self.pool.get(f._obj)._table
|
||||
except AttributeError:
|
||||
ref = f._obj.replace('.', '_')
|
||||
cr.execute("CREATE TABLE \"%s\" (\"%s\" INTEGER NOT NULL REFERENCES \"%s\" ON DELETE CASCADE, \"%s\" INTEGER NOT NULL REFERENCES \"%s\" ON DELETE CASCADE) WITH OIDS"%(f._rel, f._id1, self._table, f._id2, ref))
|
||||
cr.execute("CREATE INDEX \"%s_%s_index\" ON \"%s\" (\"%s\")" % (f._rel, f._id1, f._rel, f._id1))
|
||||
cr.execute("CREATE INDEX \"%s_%s_index\" ON \"%s\" (\"%s\")" % (f._rel, f._id2, f._rel, f._id2))
|
||||
cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE, "%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE) WITH OIDS' % (f._rel, f._id1, self._table, f._id2, ref))
|
||||
cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id1, f._rel, f._id1))
|
||||
cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id2, f._rel, f._id2))
|
||||
cr.commit()
|
||||
else:
|
||||
cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN a.atttypmod-4 ELSE a.attlen END as size FROM pg_class c,pg_attribute a,pg_type t WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid AND a.atttypid=t.oid", (self._table, k))
|
||||
cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN a.atttypmod-4 ELSE a.attlen END as size " \
|
||||
"FROM pg_class c,pg_attribute a,pg_type t " \
|
||||
"WHERE c.relname=%s " \
|
||||
"AND a.attname=%s " \
|
||||
"AND c.oid=a.attrelid " \
|
||||
"AND a.atttypid=t.oid", (self._table, k))
|
||||
res = cr.dictfetchall()
|
||||
if not res:
|
||||
if not isinstance(f, fields.function) or f.store:
|
||||
|
||||
# add the missing field
|
||||
cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s" % (self._table, k, get_pg_type(f)[1]))
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, get_pg_type(f)[1]))
|
||||
|
||||
# initialize it
|
||||
if not create and k in self._defaults:
|
||||
default = self._defaults[k](self, cr, 1, {})
|
||||
if not default:
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"=NULL" % (self._table, k))
|
||||
else:
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"='%s'" % (self._table, k, default))
|
||||
ss = self._columns[k]._symbol_set
|
||||
query = 'UPDATE "%s" SET "%s"=%s' % (self._table, k, ss[0])
|
||||
cr.execute(query, (ss[1](default),))
|
||||
cr.commit()
|
||||
logger.notifyChannel('init', netsvc.LOG_DEBUG, 'setting default value of new column %s of table %s'% (k, self._table))
|
||||
elif not create:
|
||||
logger.notifyChannel('init', netsvc.LOG_DEBUG, 'creating new column %s of table %s'% (k, self._table))
|
||||
|
||||
if isinstance(f, fields.function):
|
||||
todo_update_store.append((f,k))
|
||||
order = 10
|
||||
if f.store is not True:
|
||||
order = f.store[f.store.keys()[0]][2]
|
||||
todo_update_store.append((order, f,k))
|
||||
|
||||
# and add constraints if needed
|
||||
if isinstance(f, fields.many2one):
|
||||
|
@ -1497,14 +1526,14 @@ class orm(orm_template):
|
|||
ref = f._obj.replace('.', '_')
|
||||
# ir_actions is inherited so foreign key doesn't work on it
|
||||
if ref != 'ir_actions':
|
||||
cr.execute("ALTER TABLE \"%s\" ADD FOREIGN KEY (\"%s\") REFERENCES \"%s\" ON DELETE %s" % (self._table, k, ref, f.ondelete))
|
||||
cr.execute('ALTER TABLE "%s" ADD FOREIGN KEY ("%s") REFERENCES "%s" ON DELETE %s' % (self._table, k, ref, f.ondelete))
|
||||
if f.select:
|
||||
cr.execute("CREATE INDEX \"%s_%s_index\" ON \"%s\" (\"%s\")" % (self._table, k, self._table, k))
|
||||
cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (self._table, k, self._table, k))
|
||||
if f.required:
|
||||
cr.commit()
|
||||
try:
|
||||
cr.execute("ALTER TABLE \"%s\" ALTER COLUMN \"%s\" SET NOT NULL" % (self._table, k))
|
||||
except:
|
||||
cr.commit()
|
||||
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k))
|
||||
except Exception, e:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'WARNING: unable to set column %s of table %s not null !\nTry to re-run: openerp-server.py --update=module\nIf it doesn\'t work, update records and execute manually:\nALTER TABLE %s ALTER COLUMN %s SET NOT NULL' % (k, self._table, self._table, k))
|
||||
cr.commit()
|
||||
elif len(res)==1:
|
||||
|
@ -1513,78 +1542,89 @@ class orm(orm_template):
|
|||
f_pg_size = f_pg_def['size']
|
||||
f_pg_notnull = f_pg_def['attnotnull']
|
||||
if isinstance(f, fields.function) and not f.store:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'column %s (%s) in table %s was converted to a function !\nYou should remove this column from your database.' % (k, f.string, self._table))
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'column %s (%s) in table %s removed: converted to a function !\n' % (k, f.string, self._table))
|
||||
cr.execute('ALTER TABLE %s DROP COLUMN %s'% (self._table, k))
|
||||
cr.commit()
|
||||
f_obj_type = None
|
||||
else:
|
||||
f_obj_type = get_pg_type(f) and get_pg_type(f)[0]
|
||||
|
||||
if f_obj_type:
|
||||
if f_pg_type != f_obj_type:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, "column '%s' in table '%s' has changed type (DB = %s, def = %s) !" % (k, self._table, f_pg_type, f._type))
|
||||
ok = False
|
||||
casts = [
|
||||
('text', 'char', 'VARCHAR(%d)' % (f.size or 0,), '::VARCHAR(%d)'%(f.size or 0,)),
|
||||
('varchar', 'text', 'TEXT', ''),
|
||||
('int4', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
|
||||
('date', 'datetime', 'TIMESTAMP', '::TIMESTAMP'),
|
||||
]
|
||||
if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size != f.size:
|
||||
# columns with the name 'type' cannot be changed for an unknown reason?!
|
||||
if k != 'type':
|
||||
if f_pg_size > f.size:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, "column '%s' in table '%s' has changed size (DB = %d, def = %d), DB size will be kept !" % (k, self._table, f_pg_size, f.size))
|
||||
# If actual DB size is < than new
|
||||
# We update varchar size, otherwise, we keep DB size
|
||||
# to avoid truncated string...
|
||||
if f_pg_size < f.size:
|
||||
cr.execute("ALTER TABLE \"%s\" RENAME COLUMN \"%s\" TO temp_change_size" % (self._table, k))
|
||||
cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" VARCHAR(%d)" % (self._table, k, f.size))
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"=temp_change_size::VARCHAR(%d)" % (self._table, k, f.size))
|
||||
cr.execute("ALTER TABLE \"%s\" DROP COLUMN temp_change_size" % (self._table,))
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, "column '%s' in table '%s' changed size" % (k, self._table))
|
||||
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" VARCHAR(%d)' % (self._table, k, f.size))
|
||||
cr.execute('UPDATE "%s" SET "%s"=temp_change_size::VARCHAR(%d)' % (self._table, k, f.size))
|
||||
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size' % (self._table,))
|
||||
cr.commit()
|
||||
if f_pg_type == 'date' and f._type == 'datetime':
|
||||
cr.execute("ALTER TABLE \"%s\" RENAME COLUMN \"%s\" TO temp_change_type" % (self._table, k))
|
||||
cr.execute("ALTER TABLE \"%s\" ADD COLUMN \"%s\" TIMESTAMP " % (self._table, k))
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"=temp_change_type::TIMESTAMP" % (self._table, k))
|
||||
cr.execute("ALTER TABLE \"%s\" DROP COLUMN temp_change_type" % (self._table,))
|
||||
for c in casts:
|
||||
if (f_pg_type==c[0]) and (f._type==c[1]):
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1]))
|
||||
ok = True
|
||||
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2]))
|
||||
cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k))
|
||||
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
|
||||
cr.commit()
|
||||
|
||||
if f_pg_type != f_obj_type:
|
||||
if not ok:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, "column '%s' in table '%s' has changed type (DB = %s, def = %s) but unable to migrate this change !" % (k, self._table, f_pg_type, f._type))
|
||||
|
||||
# if the field is required and hasn't got a NOT NULL constraint
|
||||
if f.required and f_pg_notnull == 0:
|
||||
# set the field to the default value if any
|
||||
if k in self._defaults:
|
||||
default = self._defaults[k](self, cr, 1, {})
|
||||
if not (default is False):
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"='%s' WHERE %s is NULL" % (self._table, k, default, k))
|
||||
cr.commit()
|
||||
if (default is not None):
|
||||
ss = self._columns[k]._symbol_set
|
||||
query = 'UPDATE "%s" SET "%s"=%s WHERE %s is NULL' % (self._table, k, ss[0], k)
|
||||
cr.execute(query, (ss[1](default),))
|
||||
# add the NOT NULL constraint
|
||||
try:
|
||||
cr.execute("ALTER TABLE \"%s\" ALTER COLUMN \"%s\" SET NOT NULL" % (self._table, k))
|
||||
cr.commit()
|
||||
except:
|
||||
try:
|
||||
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k))
|
||||
cr.commit()
|
||||
except Exception, e:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'unable to set a NOT NULL constraint on column %s of the %s table !\nIf you want to have it, you should update the records and execute manually:\nALTER TABLE %s ALTER COLUMN %s SET NOT NULL' % (k, self._table, self._table, k))
|
||||
cr.commit()
|
||||
elif not f.required and f_pg_notnull == 1:
|
||||
cr.execute("ALTER TABLE \"%s\" ALTER COLUMN \"%s\" DROP NOT NULL" % (self._table, k))
|
||||
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" DROP NOT NULL' % (self._table, k))
|
||||
cr.commit()
|
||||
cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = '%s_%s_index' and tablename = '%s'" % (self._table, k, self._table))
|
||||
indexname = '%s_%s_index' % (self._table, k)
|
||||
cr.execute("SELECT indexname FROM pg_indexes WHERE indexname = %s and tablename = %s", (indexname, self._table))
|
||||
res = cr.dictfetchall()
|
||||
if not res and f.select:
|
||||
cr.execute("CREATE INDEX \"%s_%s_index\" ON \"%s\" (\"%s\")" % (self._table, k, self._table, k))
|
||||
cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (self._table, k, self._table, k))
|
||||
cr.commit()
|
||||
if res and not f.select:
|
||||
cr.execute("DROP INDEX \"%s_%s_index\"" % (self._table, k))
|
||||
cr.execute('DROP INDEX "%s_%s_index"' % (self._table, k))
|
||||
cr.commit()
|
||||
if isinstance(f, fields.many2one):
|
||||
ref = self.pool.get(f._obj)._table
|
||||
if ref != 'ir_actions':
|
||||
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, ' \
|
||||
'pg_attribute as att1, pg_attribute as att2 ' \
|
||||
'WHERE con.conrelid = cl1.oid ' \
|
||||
'AND cl1.relname = %s ' \
|
||||
'AND con.confrelid = cl2.oid ' \
|
||||
'AND cl2.relname = %s ' \
|
||||
'AND array_lower(con.conkey, 1) = 1 ' \
|
||||
'AND con.conkey[1] = att1.attnum ' \
|
||||
'AND att1.attrelid = cl1.oid ' \
|
||||
'AND att1.attname = %s ' \
|
||||
'AND array_lower(con.confkey, 1) = 1 ' \
|
||||
'AND con.confkey[1] = att2.attnum ' \
|
||||
'AND att2.attrelid = cl2.oid ' \
|
||||
'AND att2.attname = %s ' \
|
||||
'AND con.contype = \'f\'', (self._table, ref, k, 'id'))
|
||||
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, '
|
||||
'pg_attribute as att1, pg_attribute as att2 '
|
||||
'WHERE con.conrelid = cl1.oid '
|
||||
'AND cl1.relname = %s '
|
||||
'AND con.confrelid = cl2.oid '
|
||||
'AND cl2.relname = %s '
|
||||
'AND array_lower(con.conkey, 1) = 1 '
|
||||
'AND con.conkey[1] = att1.attnum '
|
||||
'AND att1.attrelid = cl1.oid '
|
||||
'AND att1.attname = %s '
|
||||
'AND array_lower(con.confkey, 1) = 1 '
|
||||
'AND con.confkey[1] = att2.attnum '
|
||||
'AND att2.attrelid = cl2.oid '
|
||||
'AND att2.attname = %s '
|
||||
"AND con.contype = 'f'", (self._table, ref, k, 'id'))
|
||||
res = cr.dictfetchall()
|
||||
if res:
|
||||
confdeltype = {
|
||||
|
@ -1599,31 +1639,21 @@ class orm(orm_template):
|
|||
cr.execute('ALTER TABLE "' + self._table + '" ADD FOREIGN KEY ("' + k + '") REFERENCES "' + ref + '" ON DELETE ' + f.ondelete)
|
||||
cr.commit()
|
||||
else:
|
||||
print "ERROR"
|
||||
for f,k in todo_update_store:
|
||||
cr.execute('select id from '+self._table)
|
||||
ids_lst = map(lambda x: x[0], cr.fetchall())
|
||||
while ids_lst:
|
||||
iids = ids_lst[:40]
|
||||
ids_lst = ids_lst[40:]
|
||||
res = f.get(cr, self, iids, k, 1, {})
|
||||
for key,val in res.items():
|
||||
if f._multi:
|
||||
val = val[k]
|
||||
if (val<>False) or (type(val)<>bool):
|
||||
cr.execute("UPDATE \"%s\" SET \"%s\"='%s' where id=%d"% (self._table, k, val, key))
|
||||
#else:
|
||||
# cr.execute("UPDATE \"%s\" SET \"%s\"=NULL where id=%d"% (self._table, k, key))
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('orm', netsvc.LOG_ERROR, "Programming error !")
|
||||
for order,f,k in todo_update_store:
|
||||
todo_end.append((order, self._update_store, (f, k)))
|
||||
|
||||
else:
|
||||
cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname='%s'" % self._table)
|
||||
cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname=%s", (self._table,))
|
||||
create = not bool(cr.fetchone())
|
||||
|
||||
for (key, con, _) in self._sql_constraints:
|
||||
cr.execute("SELECT conname FROM pg_constraint where conname='%s_%s'" % (self._table, key))
|
||||
conname = '%s_%s' % (self._table, key)
|
||||
cr.execute("SELECT conname FROM pg_constraint where conname=%s", (conname,))
|
||||
if not cr.dictfetchall():
|
||||
try:
|
||||
cr.execute('alter table \"%s\" add constraint \"%s_%s\" %s' % (self._table, self._table, key, con,))
|
||||
cr.execute('alter table "%s" add constraint "%s_%s" %s' % (self._table, self._table, key, con,))
|
||||
cr.commit()
|
||||
except:
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'unable to add \'%s\' constraint on table %s !\n If you want to have it, you should update the records and execute manually:\nALTER table %s ADD CONSTRAINT %s_%s %s' % (con, self._table, self._table, self._table, key, con,))
|
||||
|
@ -1637,6 +1667,7 @@ class orm(orm_template):
|
|||
cr.commit()
|
||||
if store_compute:
|
||||
self._parent_store_compute(cr)
|
||||
return todo_end
|
||||
|
||||
def __init__(self, cr):
|
||||
super(orm, self).__init__(cr)
|
||||
|
@ -1648,18 +1679,15 @@ class orm(orm_template):
|
|||
if not f.store:
|
||||
continue
|
||||
if self._columns[store_field].store is True:
|
||||
sm = {self._name:(lambda self,cr, uid, ids, c={}: ids, None)}
|
||||
sm = {self._name:(lambda self,cr, uid, ids, c={}: ids, None, 10)}
|
||||
else:
|
||||
sm = self._columns[store_field].store
|
||||
for object, aa in sm.items():
|
||||
if len(aa)==2:
|
||||
(fnct,fields2)=aa
|
||||
order = 1
|
||||
elif len(aa)==3:
|
||||
if len(aa)==3:
|
||||
(fnct,fields2,order)=aa
|
||||
else:
|
||||
raise except_orm(_('Error'),
|
||||
_('Invalid function definition %s in object %s !' % (store_field, self._name)))
|
||||
raise except_orm('Error',
|
||||
('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority)}.' % (store_field, self._name)))
|
||||
self.pool._store_function.setdefault(object, [])
|
||||
ok = True
|
||||
for x,y,z,e,f in self.pool._store_function[object]:
|
||||
|
@ -1780,7 +1808,6 @@ class orm(orm_template):
|
|||
value[key[8:]] = context[key]
|
||||
return value
|
||||
|
||||
|
||||
#
|
||||
# Update objects that uses this one to update their _inherits fields
|
||||
#
|
||||
|
@ -1845,7 +1872,6 @@ class orm(orm_template):
|
|||
if isinstance(self._columns[f], fields.binary) and context.get('bin_size', False):
|
||||
return "length(%s) as %s" % (f,f)
|
||||
return '"%s"' % (f,)
|
||||
#fields_pre2 = map(lambda x: (x in ('create_date', 'write_date')) and ('date_trunc(\'second\', '+x+') as '+x) or '"'+x+'"', fields_pre)
|
||||
fields_pre2 = map(convert_field, fields_pre)
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
sub_ids = ids[i:i+cr.IN_MAX]
|
||||
|
@ -1897,7 +1923,7 @@ class orm(orm_template):
|
|||
# to get the _symbol_get in each occurence
|
||||
for r in res:
|
||||
for f in fields_post:
|
||||
r[f] = self.columns[f]._symbol_get(r[f])
|
||||
r[f] = self._columns[f]._symbol_get(r[f])
|
||||
ids = map(lambda x: x['id'], res)
|
||||
|
||||
# all non inherited fields for which the attribute whose name is in load is False
|
||||
|
@ -1995,12 +2021,7 @@ class orm(orm_template):
|
|||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
|
||||
fn_list = []
|
||||
for fnct in self.pool._store_function.get(self._name, []):
|
||||
ids2 = filter(None, fnct[2](self,cr, uid, ids, context))
|
||||
if ids2:
|
||||
fn_list.append( (fnct[0], fnct[1], ids2) )
|
||||
|
||||
result_store = self._store_get_values(cr, uid, ids, None, context)
|
||||
delta = context.get('read_delta', False)
|
||||
if delta and self._log_access:
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
|
@ -2031,7 +2052,7 @@ class orm(orm_template):
|
|||
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
sub_ids = ids[i:i+cr.IN_MAX]
|
||||
str_d = string.join(('%d',)*len(sub_ids), ',')
|
||||
str_d = string.join(('%s',)*len(sub_ids), ',')
|
||||
if d1:
|
||||
cr.execute('SELECT id FROM "'+self._table+'" ' \
|
||||
'WHERE id IN ('+str_d+')'+d1, sub_ids+d2)
|
||||
|
@ -2047,10 +2068,8 @@ class orm(orm_template):
|
|||
cr.execute('delete from "'+self._table+'" ' \
|
||||
'where id in ('+str_d+')', sub_ids)
|
||||
|
||||
for object,field,ids in fn_list:
|
||||
ids = self.pool.get(object).search(cr, uid, [('id','in', ids)], context=context)
|
||||
if ids:
|
||||
self.pool.get(object)._store_set_values(cr, uid, ids, field, context)
|
||||
for order, object, ids, fields in result_store:
|
||||
self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
|
||||
return True
|
||||
|
||||
#
|
||||
|
@ -2148,7 +2167,7 @@ class orm(orm_template):
|
|||
% (vals[field], field))
|
||||
|
||||
if self._log_access:
|
||||
upd0.append('write_uid=%d')
|
||||
upd0.append('write_uid=%s')
|
||||
upd0.append('write_date=now()')
|
||||
upd1.append(user)
|
||||
|
||||
|
@ -2214,14 +2233,14 @@ class orm(orm_template):
|
|||
if self.pool._init:
|
||||
self.pool._init_parent[self._name]=True
|
||||
else:
|
||||
cr.execute('select parent_left,parent_right from '+self._table+' where id=%d', (vals[self._parent_name],))
|
||||
cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (vals[self._parent_name],))
|
||||
res = cr.fetchone()
|
||||
if res:
|
||||
pleft,pright = res
|
||||
else:
|
||||
cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
|
||||
pleft,pright = cr.fetchone()
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%d',ids))+')', ids)
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%s',ids))+')', ids)
|
||||
dest = pleft + 1
|
||||
for cleft,cright,cid in cr.fetchall():
|
||||
if cleft > pleft:
|
||||
|
@ -2241,37 +2260,31 @@ class orm(orm_template):
|
|||
cr.execute('UPDATE '+self._table+'''
|
||||
SET
|
||||
parent_left = CASE
|
||||
WHEN parent_left BETWEEN %d AND %d THEN parent_left + %d
|
||||
WHEN parent_left BETWEEN %d AND %d THEN parent_left + %d
|
||||
WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
|
||||
WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
|
||||
ELSE parent_left
|
||||
END,
|
||||
parent_right = CASE
|
||||
WHEN parent_right BETWEEN %d AND %d THEN parent_right + %d
|
||||
WHEN parent_right BETWEEN %d AND %d THEN parent_right + %d
|
||||
WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
|
||||
WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
|
||||
ELSE parent_right
|
||||
END
|
||||
WHERE
|
||||
parent_left<%d OR parent_right>%d;
|
||||
parent_left<%s OR parent_right>%s;
|
||||
''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
|
||||
cwidth,cleft,cright,treeshift,leftrange,rightrange))
|
||||
|
||||
if 'read_delta' in context:
|
||||
del context['read_delta']
|
||||
|
||||
|
||||
result = self._store_get_values(cr, user, ids, vals.keys(), context)
|
||||
for order, object, ids, fields in result:
|
||||
self.pool.get(object)._store_set_values(cr, user, ids, fields, context)
|
||||
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
for id in ids:
|
||||
wf_service.trg_write(user, self._name, id, cr)
|
||||
|
||||
for fnct in self.pool._store_function.get(self._name, []):
|
||||
ok = False
|
||||
for key in vals.keys():
|
||||
if (not fnct[3]) or (key in fnct[3]):
|
||||
ok = True
|
||||
if ok:
|
||||
ids2 = fnct[2](self,cr, user, ids, context)
|
||||
ids2 = filter(None, ids2)
|
||||
if ids2:
|
||||
self.pool.get(fnct[0])._store_set_values(cr, user, ids2, fnct[1], context)
|
||||
return True
|
||||
|
||||
#
|
||||
|
@ -2322,7 +2335,7 @@ class orm(orm_template):
|
|||
for table in tocreate:
|
||||
id = self.pool.get(table).create(cr, user, tocreate[table])
|
||||
upd0 += ','+self._inherits[table]
|
||||
upd1 += ',%d'
|
||||
upd1 += ',%s'
|
||||
upd2.append(id)
|
||||
|
||||
for field in vals:
|
||||
|
@ -2352,7 +2365,7 @@ class orm(orm_template):
|
|||
% (vals[field], field))
|
||||
if self._log_access:
|
||||
upd0 += ',create_uid,create_date'
|
||||
upd1 += ',%d,now()'
|
||||
upd1 += ',%s,now()'
|
||||
upd2.append(user)
|
||||
cr.execute('insert into "'+self._table+'" (id'+upd0+") values ("+str(id_new)+upd1+')', tuple(upd2))
|
||||
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
|
||||
|
@ -2367,43 +2380,83 @@ class orm(orm_template):
|
|||
else:
|
||||
parent = vals.get(self._parent_name, False)
|
||||
if parent:
|
||||
cr.execute('select parent_left from '+self._table+' where id=%d', (parent,))
|
||||
cr.execute('select parent_left from '+self._table+' where id=%s', (parent,))
|
||||
pleft = cr.fetchone()[0]
|
||||
else:
|
||||
cr.execute('select max(parent_right) from '+self._table)
|
||||
pleft = cr.fetchone()[0] or 0
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%d', (pleft,))
|
||||
cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%d', (pleft,))
|
||||
cr.execute('update '+self._table+' set parent_left=%d,parent_right=%d where id=%d', (pleft+1,pleft+2,id_new))
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%s', (pleft,))
|
||||
cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%s', (pleft,))
|
||||
cr.execute('update '+self._table+' set parent_left=%s,parent_right=%s where id=%s', (pleft+1,pleft+2,id_new))
|
||||
|
||||
result = self._store_get_values(cr, user, [id_new], vals.keys(), context)
|
||||
for order, object, ids, fields in result:
|
||||
self.pool.get(object)._store_set_values(cr, user, ids, fields, context)
|
||||
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_create(user, self._name, id_new, cr)
|
||||
|
||||
for fnct in self.pool._store_function.get(self._name, []):
|
||||
ids2 = fnct[2](self,cr, user, [id_new], context)
|
||||
ids2 = filter(None, ids2)
|
||||
if ids2:
|
||||
self.pool.get(fnct[0])._store_set_values(cr, user, ids2, fnct[1], context)
|
||||
return id_new
|
||||
|
||||
def _store_set_values(self, cr, uid, ids, field, context):
|
||||
args = {}
|
||||
result = self._columns[field].get(cr, self, ids, field, uid, context=context)
|
||||
def _store_get_values(self, cr, uid, ids, fields, context):
|
||||
result = {}
|
||||
fncts = self.pool._store_function.get(self._name, [])
|
||||
for fnct in range(len(fncts)):
|
||||
result.setdefault(fncts[fnct][0], {})
|
||||
ids2 = fncts[fnct][2](self,cr, uid, ids, context)
|
||||
for id in filter(None, ids2):
|
||||
result[fncts[fnct][0]].setdefault(id, [])
|
||||
result[fncts[fnct][0]][id].append(fnct)
|
||||
result2 = []
|
||||
for object in result:
|
||||
k2 = {}
|
||||
for id,fnct in result[object].items():
|
||||
k2.setdefault(tuple(fnct), [])
|
||||
k2[tuple(fnct)].append(id)
|
||||
for fnct,id in k2.items():
|
||||
result2.append((fncts[fnct[0]][4],object,id,map(lambda x: fncts[x][1], fnct)))
|
||||
result2.sort()
|
||||
return result2
|
||||
|
||||
def _store_set_values(self, cr, uid, ids, fields, context):
|
||||
todo = {}
|
||||
keys = []
|
||||
for f in fields:
|
||||
if self._columns[f]._multi not in keys:
|
||||
keys.append(self._columns[f]._multi)
|
||||
todo.setdefault(self._columns[f]._multi, [])
|
||||
todo[self._columns[f]._multi].append(f)
|
||||
for key in keys:
|
||||
val = todo[key]
|
||||
if key:
|
||||
result = self._columns[val[0]].get(cr, self, ids, val, uid, context=context)
|
||||
for id,value in result.items():
|
||||
upd0 = []
|
||||
upd1 = []
|
||||
if self._columns[field]._multi:
|
||||
value = value[field]
|
||||
if self._columns[field]._type in ('many2one', 'one2one'):
|
||||
for v in value:
|
||||
if v not in val:
|
||||
continue
|
||||
if self._columns[v]._type in ('many2one', 'one2one'):
|
||||
try:
|
||||
value[v] = value[v][0]
|
||||
except:
|
||||
pass
|
||||
upd0.append('"'+v+'"='+self._columns[v]._symbol_set[0])
|
||||
upd1.append(self._columns[v]._symbol_set[1](value[v]))
|
||||
upd1.append(id)
|
||||
cr.execute('update "' + self._table + '" set ' + \
|
||||
string.join(upd0, ',') + ' where id = %s', upd1)
|
||||
|
||||
else:
|
||||
for f in val:
|
||||
result = self._columns[f].get(cr, self, ids, f, uid, context=context)
|
||||
for id,value in result.items():
|
||||
if self._columns[f]._type in ('many2one', 'one2one'):
|
||||
try:
|
||||
value = value[0]
|
||||
except:
|
||||
pass
|
||||
upd0.append('"'+field+'"='+self._columns[field]._symbol_set[0])
|
||||
upd1.append(self._columns[field]._symbol_set[1](value))
|
||||
upd1.append(id)
|
||||
cr.execute('update "' + self._table + '" set ' + \
|
||||
string.join(upd0, ',') + ' where id = %d', upd1)
|
||||
'"'+f+'"='+self._columns[f]._symbol_set[0] + ' where id = %s', (self._columns[f]._symbol_set[1](value),id))
|
||||
return True
|
||||
|
||||
#
|
||||
|
@ -2501,7 +2554,7 @@ class orm(orm_template):
|
|||
return []
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
return [(r['id'], str(r[self._rec_name])) for r in self.read(cr, user, ids,
|
||||
return [(r['id'], tools.ustr(r[self._rec_name])) for r in self.read(cr, user, ids,
|
||||
[self._rec_name], context, load='_classic_write')]
|
||||
|
||||
def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=None):
|
||||
|
|
128
bin/osv/osv.py
128
bin/osv/osv.py
|
@ -30,7 +30,7 @@ import pooler
|
|||
import copy
|
||||
import sys
|
||||
|
||||
import psycopg
|
||||
from psycopg2 import IntegrityError
|
||||
from netsvc import Logger, LOG_ERROR
|
||||
from tools.misc import UpdateableDict
|
||||
|
||||
|
@ -87,7 +87,7 @@ class osv_pool(netsvc.Service):
|
|||
self.abortResponse(1, inst.name, 'warning', inst.value)
|
||||
except except_osv, inst:
|
||||
self.abortResponse(1, inst.name, inst.exc_type, inst.value)
|
||||
except psycopg.IntegrityError, inst:
|
||||
except IntegrityError, inst:
|
||||
for key in self._sql_error.keys():
|
||||
if key in inst[0]:
|
||||
self.abortResponse(1, 'Constraint Error', 'warning', self._sql_error[key])
|
||||
|
@ -96,8 +96,7 @@ class osv_pool(netsvc.Service):
|
|||
import traceback
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
logger = Logger()
|
||||
for idx, s in enumerate(tb_s.split('\n')):
|
||||
logger.notifyChannel("web-services", LOG_ERROR, '[%2d]: %s' % (idx, s,))
|
||||
logger.notifyChannel('web-services', LOG_ERROR, tb_s)
|
||||
raise
|
||||
|
||||
def execute(self, db, uid, obj, method, *args, **kw):
|
||||
|
@ -185,7 +184,7 @@ class osv_memory(orm.orm_memory):
|
|||
name = hasattr(cls, '_name') and cls._name or cls._inherit
|
||||
parent_name = hasattr(cls, '_inherit') and cls._inherit
|
||||
if parent_name:
|
||||
print 'Inherit not supported in osv_memory object !'
|
||||
raise 'Inherit not supported in osv_memory object !'
|
||||
obj = object.__new__(cls)
|
||||
obj.__init__(pool, cr)
|
||||
return obj
|
||||
|
@ -252,122 +251,3 @@ class osv(orm.orm):
|
|||
self.pool = pool
|
||||
orm.orm.__init__(self, cr)
|
||||
|
||||
|
||||
class Cacheable(object):
|
||||
|
||||
_cache = UpdateableDict()
|
||||
|
||||
def add(self, key, value):
|
||||
self._cache[key] = value
|
||||
|
||||
def invalidate(self, key):
|
||||
del self._cache[key]
|
||||
|
||||
def get(self, key):
|
||||
try:
|
||||
w = self._cache[key]
|
||||
return w
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def clear(self):
|
||||
self._cache.clear()
|
||||
self._items = []
|
||||
|
||||
|
||||
def filter_dict(d, fields):
|
||||
res = {}
|
||||
for f in fields + ['id']:
|
||||
if f in d:
|
||||
res[f] = d[f]
|
||||
return res
|
||||
|
||||
|
||||
class cacheable_osv(osv, Cacheable):
|
||||
|
||||
_relevant = ['lang']
|
||||
|
||||
def __init__(self):
|
||||
super(cacheable_osv, self).__init__()
|
||||
|
||||
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
|
||||
if not fields:
|
||||
fields = []
|
||||
if not context:
|
||||
context = {}
|
||||
fields = fields or self._columns.keys()
|
||||
ctx = [context.get(x, False) for x in self._relevant]
|
||||
result, tofetch = [], []
|
||||
for id in ids:
|
||||
res = self.get(self._name, id, ctx)
|
||||
if not res:
|
||||
tofetch.append(id)
|
||||
else:
|
||||
result.append(filter_dict(res, fields))
|
||||
|
||||
# gen the list of "local" (ie not inherited) fields which are classic or many2one
|
||||
nfields = filter(lambda x: x[1]._classic_write, self._columns.items())
|
||||
# gen the list of inherited fields
|
||||
inherits = map(lambda x: (x[0], x[1][2]), self._inherit_fields.items())
|
||||
# complete the field list with the inherited fields which are classic or many2one
|
||||
nfields += filter(lambda x: x[1]._classic_write, inherits)
|
||||
nfields = [x[0] for x in nfields]
|
||||
|
||||
res = super(cacheable_osv, self).read(cr, user, tofetch, nfields, context, load)
|
||||
for r in res:
|
||||
self.add((self._name, r['id'], ctx), r)
|
||||
result.append(filter_dict(r, fields))
|
||||
|
||||
# Appel de fonction si necessaire
|
||||
tofetch = []
|
||||
for f in fields:
|
||||
if f not in nfields:
|
||||
tofetch.append(f)
|
||||
for f in tofetch:
|
||||
fvals = self._columns[f].get(cr, self, ids, f, user, context=context)
|
||||
for r in result:
|
||||
r[f] = fvals[r['id']]
|
||||
|
||||
# TODO: tri par self._order !!
|
||||
return result
|
||||
|
||||
def invalidate(self, key):
|
||||
del self._cache[key[0]][key[1]]
|
||||
|
||||
def write(self, cr, user, ids, values, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
for id in ids:
|
||||
self.invalidate((self._name, id))
|
||||
return super(cacheable_osv, self).write(cr, user, ids, values, context)
|
||||
|
||||
def unlink(self, cr, user, ids):
|
||||
self.clear()
|
||||
return super(cacheable_osv, self).unlink(cr, user, ids)
|
||||
|
||||
#cacheable_osv = osv
|
||||
|
||||
|
||||
#class FakePool(object):
|
||||
# def __init__(self, module):
|
||||
# self.preferred_module = module
|
||||
|
||||
# def get(self, name):
|
||||
# localpool = module_objects_dict.get(self.preferred_module, {'dict': {}})['dict']
|
||||
# if name in localpool:
|
||||
# obj = localpool[name]
|
||||
# else:
|
||||
# obj = pooler.get_pool(cr.dbname).get(name)
|
||||
# return obj
|
||||
|
||||
# fake_pool = self
|
||||
# class fake_class(obj.__class__):
|
||||
# def __init__(self):
|
||||
# super(fake_class, self).__init__()
|
||||
# self.pool = fake_pool
|
||||
|
||||
# return fake_class()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -20,30 +20,19 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import sql_db
|
||||
import osv.osv
|
||||
import tools
|
||||
import addons
|
||||
import netsvc
|
||||
|
||||
db_dic = {}
|
||||
pool_dic = {}
|
||||
|
||||
|
||||
def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False):
|
||||
if not status:
|
||||
status={}
|
||||
if db_name in db_dic:
|
||||
db = db_dic[db_name]
|
||||
else:
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('pooler', netsvc.LOG_INFO, 'Connecting to %s' % (db_name.lower()))
|
||||
db = sql_db.db_connect(db_name)
|
||||
db_dic[db_name] = db
|
||||
|
||||
db = get_db_only(db_name)
|
||||
|
||||
if db_name in pool_dic:
|
||||
pool = pool_dic[db_name]
|
||||
else:
|
||||
import addons
|
||||
import osv.osv
|
||||
pool = osv.osv.osv_pool()
|
||||
pool_dic[db_name] = pool
|
||||
addons.load_modules(db, force_demo, status, update_module)
|
||||
|
@ -60,49 +49,28 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False)
|
|||
|
||||
|
||||
def restart_pool(db_name, force_demo=False, update_module=False):
|
||||
# del db_dic[db_name]
|
||||
del pool_dic[db_name]
|
||||
return get_db_and_pool(db_name, force_demo, update_module=update_module)
|
||||
|
||||
|
||||
def close_db(db_name):
|
||||
if db_name in db_dic:
|
||||
db_dic[db_name].truedb.close()
|
||||
del db_dic[db_name]
|
||||
if db_name in pool_dic:
|
||||
del pool_dic[db_name]
|
||||
|
||||
|
||||
def get_db_only(db_name):
|
||||
if db_name in db_dic:
|
||||
db = db_dic[db_name]
|
||||
else:
|
||||
# ATTENTION:
|
||||
# do not put this import outside this function
|
||||
# sql_db must not be loaded before the logger is initialized.
|
||||
# sql_db import psycopg2.tool which create a default logger if there is not.
|
||||
# this resulting of having the logs outputed twice...
|
||||
import sql_db
|
||||
db = sql_db.db_connect(db_name)
|
||||
db_dic[db_name] = db
|
||||
return db
|
||||
|
||||
|
||||
def get_db(db_name):
|
||||
# print "get_db", db_name
|
||||
return get_db_and_pool(db_name)[0]
|
||||
|
||||
|
||||
def get_pool(db_name, force_demo=False, status=None, update_module=False):
|
||||
# print "get_pool", db_name
|
||||
pool = get_db_and_pool(db_name, force_demo, status, update_module)[1]
|
||||
# addons.load_modules(db_name, False)
|
||||
# if not pool.obj_list():
|
||||
# pool.instanciate()
|
||||
# print "pool", pool
|
||||
return pool
|
||||
# return get_db_and_pool(db_name)[1]
|
||||
|
||||
|
||||
def init():
|
||||
global db
|
||||
# db = get_db_only(tools.config['db_name'])
|
||||
sql_db.init()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -86,20 +86,13 @@ class report_rml(report_int):
|
|||
|
||||
def create(self, cr, uid, ids, datas, context):
|
||||
xml = self.create_xml(cr, uid, ids, datas, context)
|
||||
#file('/tmp/terp.xml','wb+').write(xml)
|
||||
if datas.get('report_type', 'pdf') == 'raw':
|
||||
return xml
|
||||
rml = self.create_rml(cr, xml, uid, context)
|
||||
#file('/tmp/terp.rml','wb+').write(rml)
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
ir_actions_report_xml_obj = pool.get('ir.actions.report.xml')
|
||||
try:
|
||||
report_xml_ids = ir_actions_report_xml_obj.search(cr, uid,
|
||||
[('report_name', '=', self.name[7:])], context=context)
|
||||
self.title = ir_actions_report_xml_obj.browse(cr,uid,report_xml_ids)[0].name
|
||||
except:
|
||||
print 'Report not Found !'
|
||||
self.title = 'Unknown'
|
||||
report_xml_ids = ir_actions_report_xml_obj.search(cr, uid, [('report_name', '=', self.name[7:])], context=context)
|
||||
self.title = report_xml_ids and ir_actions_report_xml_obj.browse(cr,uid,report_xml_ids)[0].name or 'OpenERP Report'
|
||||
report_type = datas.get('report_type', 'pdf')
|
||||
create_doc = self.generators[report_type]
|
||||
pdf = create_doc(rml, title=self.title)
|
||||
|
|
|
@ -78,17 +78,13 @@ class document(object):
|
|||
fields = field_path.split('.')
|
||||
|
||||
if not len(fields):
|
||||
print "WARNING: field name is empty!"
|
||||
return ''
|
||||
|
||||
value = browser
|
||||
for f in fields:
|
||||
if isinstance(value, list):
|
||||
if len(value)==0:
|
||||
print "WARNING: empty list found!"
|
||||
return ''
|
||||
# elif len(value)>1:
|
||||
# print "WARNING:", len(value), "possibilities for", value[0]._table_name , "picking first..."
|
||||
value = value[0]
|
||||
if isinstance(value, browse_null):
|
||||
return ''
|
||||
|
@ -128,12 +124,6 @@ class document(object):
|
|||
# parent = the parent node in the xml data tree we are creating
|
||||
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
# print '-'*60
|
||||
# print "parse_node", node
|
||||
# print "parent: ", parent
|
||||
# print "ids:", ids
|
||||
# print "model:", model
|
||||
# print "datas:", datas
|
||||
|
||||
# convert the attributes of the node to a dictionary
|
||||
|
||||
|
@ -203,9 +193,6 @@ class document(object):
|
|||
el.appendChild(el_txt)
|
||||
|
||||
elif attrs['type']=='eval':
|
||||
#TODO: faire ca plus proprement
|
||||
if isinstance(browser, list):
|
||||
print "ERROR: EVAL!"
|
||||
el = self.doc.createElement(node.localName)
|
||||
parent.appendChild(el)
|
||||
value = self.eval(browser, attrs['expr'])
|
||||
|
@ -270,8 +257,6 @@ class document(object):
|
|||
parent.appendChild(el)
|
||||
atr = self.node_attrs_get(node)
|
||||
if 'value' in atr:
|
||||
#print "type=>",type(datas[atr['value']])
|
||||
#print "value=>",datas[atr['value']]
|
||||
if not isinstance(datas[atr['value']], (str, unicode)):
|
||||
txt = self.doc.createTextNode(str(datas[atr['value']]))
|
||||
else:
|
||||
|
|
|
@ -36,6 +36,7 @@ import copy
|
|||
import StringIO
|
||||
import zipfile
|
||||
import os
|
||||
import mx.DateTime
|
||||
|
||||
DT_FORMAT = '%Y-%m-%d'
|
||||
DHM_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||
|
@ -255,6 +256,7 @@ class rml_parse(object):
|
|||
'format': self.format,
|
||||
'formatLang': self.formatLang,
|
||||
'logo' : user.company_id.logo,
|
||||
'lang' : user.company_id.partner_id.lang,
|
||||
}
|
||||
self.localcontext.update(context)
|
||||
self.rml_header = user.company_id.rml_header
|
||||
|
@ -333,31 +335,61 @@ class rml_parse(object):
|
|||
else:
|
||||
obj._cache[table][id] = {'id': id}
|
||||
|
||||
def formatLang(self, value, digit=2, date=False):
|
||||
def formatLang(self, value, digits=2, date=False,date_time=False, grouping=True, monetary=False, currency=None):
|
||||
if not value:
|
||||
return ''
|
||||
lc, encoding = locale.getdefaultlocale()
|
||||
if not encoding:
|
||||
encoding = 'UTF-8'
|
||||
if encoding == 'utf':
|
||||
encoding = 'UTF-8'
|
||||
if encoding == 'cp1252':
|
||||
encoding= '1252'
|
||||
|
||||
pool_lang=self.pool.get('res.lang')
|
||||
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
|
||||
try:
|
||||
if os.name == 'nt':
|
||||
locale.setlocale(locale.LC_ALL, _LOCALE2WIN32.get(lang, lang) + '.' + encoding)
|
||||
lang_obj = pool_lang.browse(self.cr,self.uid,pool_lang.search(self.cr,self.uid,[('code','=',lang)])[0])
|
||||
|
||||
if date or date_time:
|
||||
date_format = lang_obj.date_format
|
||||
if date_time:
|
||||
date_format = lang_obj.date_format + " " + lang_obj.time_format
|
||||
|
||||
if not isinstance(value, time.struct_time):
|
||||
# assume string, parse it
|
||||
if len(str(value)) == 10:
|
||||
# length of date like 2001-01-01 is ten
|
||||
# assume format '%Y-%m-%d'
|
||||
date = mx.DateTime.strptime(str(value),DT_FORMAT)
|
||||
else:
|
||||
locale.setlocale(locale.LC_ALL, lang + '.' + encoding)
|
||||
except Exception:
|
||||
netsvc.Logger().notifyChannel('report', netsvc.LOG_WARNING,
|
||||
'report %s: unable to set locale "%s"' % (self.name,
|
||||
self.localcontext.get('lang', 'en_US') or 'en_US'))
|
||||
if date:
|
||||
date = time.strptime(value, DT_FORMAT)
|
||||
return time.strftime(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'),
|
||||
date)
|
||||
return locale.format('%.' + str(digit) + 'f', value, True)
|
||||
# assume format '%Y-%m-%d %H:%M:%S'
|
||||
value = str(value)[:19]
|
||||
date = mx.DateTime.strptime(str(value),DHM_FORMAT)
|
||||
else:
|
||||
date = mx.DateTime.DateTime(*(value.timetuple()[:6]))
|
||||
|
||||
return date.strftime(date_format)
|
||||
|
||||
return lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
|
||||
|
||||
# def formatLang(self, value, digit=2, date=False):
|
||||
# if not value:
|
||||
# return ''
|
||||
# lc, encoding = locale.getdefaultlocale()
|
||||
# if not encoding:
|
||||
# encoding = 'UTF-8'
|
||||
# if encoding == 'utf':
|
||||
# encoding = 'UTF-8'
|
||||
# if encoding == 'cp1252':
|
||||
# encoding= '1252'
|
||||
# lang = self.localcontext.get('lang', 'en_US') or 'en_US'
|
||||
# try:
|
||||
# if os.name == 'nt':
|
||||
# locale.setlocale(locale.LC_ALL, _LOCALE2WIN32.get(lang, lang) + '.' + encoding)
|
||||
# else:
|
||||
# locale.setlocale(locale.LC_ALL, lang + '.' + encoding)
|
||||
# except Exception:
|
||||
# netsvc.Logger().notifyChannel('report', netsvc.LOG_WARNING,
|
||||
# 'report %s: unable to set locale "%s"' % (self.name,
|
||||
# self.localcontext.get('lang', 'en_US') or 'en_US'))
|
||||
# if date:
|
||||
# date = time.strptime(value, DT_FORMAT)
|
||||
# return time.strftime(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'),
|
||||
# date)
|
||||
# return locale.format('%.' + str(digit) + 'f', value, True)
|
||||
|
||||
def repeatIn(self, lst, name, nodes_parent=False):
|
||||
self._node.data = ''
|
||||
|
@ -555,7 +587,7 @@ class report_sxw(report_rml):
|
|||
|
||||
def getObjects(self, cr, uid, ids, context):
|
||||
table_obj = pooler.get_pool(cr.dbname).get(self.table)
|
||||
return table_obj.browse(cr, uid, ids, list_class=browse_record_list, context=context, fields_process=_fields_process)
|
||||
return table_obj.browse(cr, uid, ids, list_class=browse_record_list, context=context)
|
||||
|
||||
def create(self, cr, uid, ids, data, context=None):
|
||||
logo = None
|
||||
|
|
|
@ -46,7 +46,7 @@ def check(db, uid, passwd):
|
|||
return True
|
||||
|
||||
cr = pooler.get_db(db).cursor()
|
||||
cr.execute('select count(*) from res_users where id=%d and password=%s', (int(uid), passwd))
|
||||
cr.execute('select count(*) from res_users where id=%s and password=%s', (int(uid), passwd))
|
||||
res = cr.fetchone()[0]
|
||||
cr.close()
|
||||
if not bool(res):
|
||||
|
|
|
@ -29,7 +29,6 @@ import logging
|
|||
import threading, thread
|
||||
|
||||
import time
|
||||
import base64
|
||||
import addons
|
||||
|
||||
import sql_db
|
||||
|
@ -65,8 +64,8 @@ class db(netsvc.Service):
|
|||
self.actions[id] = {'clean': False}
|
||||
|
||||
db = sql_db.db_connect('template1', serialize=1)
|
||||
db.truedb.autocommit()
|
||||
cr = db.cursor()
|
||||
cr.autocommit(True)
|
||||
time.sleep(0.2)
|
||||
cr.execute('CREATE DATABASE ' + db_name + ' ENCODING \'unicode\'')
|
||||
cr.close()
|
||||
|
@ -108,13 +107,12 @@ class db(netsvc.Service):
|
|||
traceback.print_exc(file=e_str)
|
||||
traceback_str = e_str.getvalue()
|
||||
e_str.close()
|
||||
print traceback_str
|
||||
netsvc.Logger().notifyChannel('web-services', netsvc.LOG_ERROR, 'CREATE DATABASE\n%s' % (traceback_str))
|
||||
serv.actions[id]['traceback'] = traceback_str
|
||||
if cr:
|
||||
cr.close()
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO,
|
||||
'CREATE DB: %s' % (db_name.lower()))
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, 'CREATE DATABASE: %s' % (db_name.lower()))
|
||||
dbi = DBInitialize()
|
||||
create_thread = threading.Thread(target=dbi,
|
||||
args=(self, id, db_name, demo, lang, user_password))
|
||||
|
@ -140,19 +138,19 @@ class db(netsvc.Service):
|
|||
|
||||
def drop(self, password, db_name):
|
||||
security.check_super(password)
|
||||
pooler.close_db(db_name)
|
||||
sql_db.close_db(db_name)
|
||||
logger = netsvc.Logger()
|
||||
|
||||
db = sql_db.db_connect('template1', serialize=1)
|
||||
db.truedb.autocommit()
|
||||
cr = db.cursor()
|
||||
cr.autocommit(True)
|
||||
try:
|
||||
try:
|
||||
cr.execute('DROP DATABASE ' + db_name)
|
||||
except:
|
||||
except Exception, e:
|
||||
logger.notifyChannel("web-services", netsvc.LOG_ERROR,
|
||||
'DROP DB: %s failed' % (db_name,))
|
||||
raise
|
||||
'DROP DB: %s failed:\n%s' % (db_name, e))
|
||||
raise Exception("Couldn't drop database %s: %s" % (db_name, e))
|
||||
else:
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO,
|
||||
'DROP DB: %s' % (db_name))
|
||||
|
@ -195,8 +193,8 @@ class db(netsvc.Service):
|
|||
raise Exception, "Database already exists"
|
||||
|
||||
db = sql_db.db_connect('template1', serialize=1)
|
||||
db.truedb.autocommit()
|
||||
cr = db.cursor()
|
||||
cr.autocommit(True)
|
||||
cr.execute('CREATE DATABASE ' + db_name + ' ENCODING \'unicode\'')
|
||||
cr.close()
|
||||
|
||||
|
@ -231,7 +229,6 @@ class db(netsvc.Service):
|
|||
def db_exist(self, db_name):
|
||||
try:
|
||||
db = sql_db.db_connect(db_name)
|
||||
db.truedb.close()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
@ -256,7 +253,6 @@ class db(netsvc.Service):
|
|||
cr.close()
|
||||
except:
|
||||
res = []
|
||||
db.truedb.close()
|
||||
res.sort()
|
||||
return res
|
||||
|
||||
|
@ -285,6 +281,7 @@ class common(netsvc.Service):
|
|||
self.exportMethod(self.ir_del)
|
||||
self.exportMethod(self.about)
|
||||
self.exportMethod(self.login)
|
||||
self.exportMethod(self.logout)
|
||||
self.exportMethod(self.timezone_get)
|
||||
|
||||
def ir_set(self, db, uid, password, keys, args, name, value, replace=True, isobject=False):
|
||||
|
@ -319,9 +316,14 @@ class common(netsvc.Service):
|
|||
res = security.login(db, login, password)
|
||||
logger = netsvc.Logger()
|
||||
msg = res and 'successful login' or 'bad login or password'
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, login, db.lower()))
|
||||
logger.notifyChannel("web-service", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, login, db.lower()))
|
||||
return res or False
|
||||
|
||||
def logout(self, db, login, password):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db))
|
||||
return True
|
||||
|
||||
def about(self, extended=False):
|
||||
"""Return information about the OpenERP Server.
|
||||
|
||||
|
|
235
bin/sql_db.py
235
bin/sql_db.py
|
@ -20,135 +20,218 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import psycopg
|
||||
import netsvc
|
||||
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_SERIALIZABLE
|
||||
from psycopg2.pool import ThreadedConnectionPool
|
||||
from psycopg2.psycopg1 import cursor as psycopg1cursor
|
||||
|
||||
import psycopg2.extensions
|
||||
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||
|
||||
types_mapping = {
|
||||
'date': (1082,),
|
||||
'time': (1083,),
|
||||
'datetime': (1114,),
|
||||
}
|
||||
|
||||
def unbuffer(symb, cr):
|
||||
if symb is None: return None
|
||||
return str(symb)
|
||||
|
||||
def undecimalize(symb, cr):
|
||||
if symb is None: return None
|
||||
return float(symb)
|
||||
|
||||
for name, typeoid in types_mapping.items():
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.new_type(typeoid, name, lambda x, cr: x))
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.new_type((700, 701, 1700,), 'float', undecimalize))
|
||||
|
||||
|
||||
import tools
|
||||
import sys,os
|
||||
|
||||
#try:
|
||||
# import decimal
|
||||
#except ImportError:
|
||||
# from tools import decimal
|
||||
|
||||
|
||||
import re
|
||||
|
||||
from mx import DateTime as mdt
|
||||
re_from = re.compile('.* from "?([a-zA-Z_0-9]+)"? .*$');
|
||||
re_into = re.compile('.* into "?([a-zA-Z_0-9]+)"? .*$');
|
||||
|
||||
class fake_cursor:
|
||||
def log(msg, lvl=netsvc.LOG_DEBUG):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('sql', lvl, msg)
|
||||
|
||||
class Cursor(object):
|
||||
IN_MAX = 1000
|
||||
nbr = 0
|
||||
_tables = {}
|
||||
sql_from_log = {}
|
||||
sql_into_log = {}
|
||||
sql_log = False
|
||||
count = 0
|
||||
|
||||
def __init__(self, db, con, dbname):
|
||||
self.db = db
|
||||
self.obj = db.cursor()
|
||||
self.con = con
|
||||
self.dbname = dbname
|
||||
def check(f):
|
||||
from tools.func import wraps
|
||||
|
||||
def execute(self, sql, params=None):
|
||||
if not params:
|
||||
@wraps(f)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
if not hasattr(self, '_obj'):
|
||||
raise psycopg2.ProgrammingError('Unable to use the cursor after having closing it')
|
||||
return f(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
def __init__(self, pool):
|
||||
self._pool = pool
|
||||
self._cnx = pool.getconn()
|
||||
self._obj = self._cnx.cursor(cursor_factory=psycopg1cursor)
|
||||
self.autocommit(False)
|
||||
self.dbname = pool.dbname
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, '_obj'):
|
||||
# Oops. 'self' has not been closed explicitly.
|
||||
# The cursor will be deleted by the garbage collector,
|
||||
# but the database connection is not put back into the connection
|
||||
# pool, preventing some operation on the database like dropping it.
|
||||
# This can also lead to a server overload.
|
||||
log('Cursor not closed explicitly', netsvc.LOG_WARNING)
|
||||
self.close()
|
||||
|
||||
@check
|
||||
def execute(self, query, params=None):
|
||||
if params is None:
|
||||
params=()
|
||||
if not isinstance(params, (tuple, list)):
|
||||
params = (params,)
|
||||
|
||||
def base_string(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf-8')
|
||||
return s
|
||||
p=map(base_string, params)
|
||||
if isinstance(sql, unicode):
|
||||
sql = sql.encode('utf-8')
|
||||
query = base_string(query)
|
||||
|
||||
if '%d' in query or '%f' in query:
|
||||
#import traceback
|
||||
#traceback.print_stack()
|
||||
log(query, netsvc.LOG_WARNING)
|
||||
log("SQL queries mustn't containt %d or %f anymore. Use only %s", netsvc.LOG_WARNING)
|
||||
if p:
|
||||
query = query.replace('%d', '%s').replace('%f', '%s')
|
||||
|
||||
if self.sql_log:
|
||||
now = mdt.now()
|
||||
print "SQL LOG query:", sql
|
||||
print "SQL LOG params:", repr(p)
|
||||
if p:
|
||||
res = self.obj.execute(sql, p)
|
||||
else:
|
||||
res = self.obj.execute(sql)
|
||||
|
||||
res = self._obj.execute(query, p or None)
|
||||
|
||||
if self.sql_log:
|
||||
log("query: %s" % self._obj.query)
|
||||
self.count+=1
|
||||
res_from = re_from.match(sql.lower())
|
||||
res_from = re_from.match(query.lower())
|
||||
if res_from:
|
||||
self.sql_from_log.setdefault(res_from.group(1), [0, 0])
|
||||
self.sql_from_log[res_from.group(1)][0] += 1
|
||||
self.sql_from_log[res_from.group(1)][1] += mdt.now() - now
|
||||
res_into = re_into.match(sql.lower())
|
||||
res_into = re_into.match(query.lower())
|
||||
if res_into:
|
||||
self.sql_into_log.setdefault(res_into.group(1), [0, 0])
|
||||
self.sql_into_log[res_into.group(1)][0] += 1
|
||||
self.sql_into_log[res_into.group(1)][1] += mdt.now() - now
|
||||
return res
|
||||
|
||||
def print_log(self, type='from'):
|
||||
print "SQL LOG %s:" % (type,)
|
||||
if type == 'from':
|
||||
logs = self.sql_from_log.items()
|
||||
else:
|
||||
logs = self.sql_into_log.items()
|
||||
logs.sort(lambda x, y: cmp(x[1][1], y[1][1]))
|
||||
sum=0
|
||||
for r in logs:
|
||||
print "table:", r[0], ":", str(r[1][1]), "/", r[1][0]
|
||||
def print_log(self):
|
||||
def process(type):
|
||||
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log}
|
||||
if not sqllogs[type]:
|
||||
return
|
||||
sqllogitems = sqllogs[type].items()
|
||||
sqllogitems.sort(key=lambda k: k[1][1])
|
||||
sum = 0
|
||||
log("SQL LOG %s:" % (type,))
|
||||
for r in sqllogitems:
|
||||
log("table: %s: %s/%s" %(r[0], str(r[1][1]), r[1][0]))
|
||||
sum+= r[1][1]
|
||||
print "SUM:%s/%d"% (sum, self.count)
|
||||
log("SUM:%s/%d" % (sum, self.count))
|
||||
sqllogs[type].clear()
|
||||
process('from')
|
||||
process('into')
|
||||
self.count = 0
|
||||
|
||||
@check
|
||||
def close(self):
|
||||
if self.sql_log:
|
||||
self.print_log('from')
|
||||
self.print_log('into')
|
||||
self.obj.close()
|
||||
self.print_log()
|
||||
self._obj.close()
|
||||
|
||||
# This force the cursor to be freed, and thus, available again. It is
|
||||
# important because otherwise we can overload the server very easily
|
||||
# because of a cursor shortage (because cursors are not garbage
|
||||
# collected as fast as they should). The problem is probably due in
|
||||
# part because browse records keep a reference to the cursor.
|
||||
del self.obj
|
||||
del self._obj
|
||||
self._pool.putconn(self._cnx)
|
||||
|
||||
@check
|
||||
def autocommit(self, on):
|
||||
self._cnx.set_isolation_level([ISOLATION_LEVEL_SERIALIZABLE, ISOLATION_LEVEL_AUTOCOMMIT][bool(on)])
|
||||
|
||||
@check
|
||||
def commit(self):
|
||||
return self._cnx.commit()
|
||||
|
||||
@check
|
||||
def rollback(self):
|
||||
return self._cnx.rollback()
|
||||
|
||||
@check
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.obj, name)
|
||||
return getattr(self._obj, name)
|
||||
|
||||
class fakedb:
|
||||
def __init__(self, truedb, dbname):
|
||||
self.truedb = truedb
|
||||
class ConnectionPool(object):
|
||||
def __init__(self, pool, dbname):
|
||||
self.dbname = dbname
|
||||
self._pool = pool
|
||||
|
||||
def cursor(self):
|
||||
return fake_cursor(self.truedb, {}, self.dbname)
|
||||
return Cursor(self)
|
||||
|
||||
def decimalize(symb):
|
||||
if symb is None: return None
|
||||
if isinstance(symb, float):
|
||||
return decimal.Decimal('%f' % symb)
|
||||
return decimal.Decimal(symb)
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._pool, name)
|
||||
|
||||
class PoolManager(object):
|
||||
_pools = {}
|
||||
_dsn = None
|
||||
maxconn = int(tools.config['db_maxconn']) or 64
|
||||
|
||||
def dsn(db_name):
|
||||
if PoolManager._dsn is None:
|
||||
PoolManager._dsn = ''
|
||||
for p in ('host', 'port', 'user', 'password'):
|
||||
cfg = tools.config['db_' + p]
|
||||
if cfg:
|
||||
PoolManager._dsn += '%s=%s ' % (p, cfg)
|
||||
return '%s dbname=%s' % (PoolManager._dsn, db_name)
|
||||
dsn = staticmethod(dsn)
|
||||
|
||||
def get(db_name):
|
||||
if db_name not in PoolManager._pools:
|
||||
logger = netsvc.Logger()
|
||||
try:
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Connecting to %s' % (db_name,))
|
||||
PoolManager._pools[db_name] = ConnectionPool(ThreadedConnectionPool(0, PoolManager.maxconn, PoolManager.dsn(db_name)), db_name)
|
||||
except Exception, e:
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_CRITICAL, 'Unable to connect to %s: %r' % (db_name, e))
|
||||
raise
|
||||
return PoolManager._pools[db_name]
|
||||
get = staticmethod(get)
|
||||
|
||||
def close(db_name):
|
||||
if db_name is PoolManager._pools:
|
||||
logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Closing all connections to %s' % (db_name,))
|
||||
PoolManager._pools[db_name].closeall()
|
||||
del PoolManager._pools[db_name]
|
||||
close = staticmethod(close)
|
||||
|
||||
def db_connect(db_name, serialize=0):
|
||||
host = tools.config['db_host'] and "host=%s" % tools.config['db_host'] or ''
|
||||
port = tools.config['db_port'] and "port=%s" % tools.config['db_port'] or ''
|
||||
name = "dbname=%s" % db_name
|
||||
user = tools.config['db_user'] and "user=%s" % tools.config['db_user'] or ''
|
||||
password = tools.config['db_password'] and "password=%s" % tools.config['db_password'] or ''
|
||||
maxconn = int(tools.config['db_maxconn']) or 64
|
||||
tdb = psycopg.connect('%s %s %s %s %s' % (host, port, name, user, password),
|
||||
serialize=serialize, maxconn=maxconn)
|
||||
fdb = fakedb(tdb, db_name)
|
||||
return fdb
|
||||
|
||||
def init():
|
||||
#define DATEOID 1082, define TIMESTAMPOID 1114 see pgtypes.h
|
||||
psycopg.register_type(psycopg.new_type((1082,), "date", lambda x:x))
|
||||
psycopg.register_type(psycopg.new_type((1083,), "time", lambda x:x))
|
||||
psycopg.register_type(psycopg.new_type((1114,), "datetime", lambda x:x))
|
||||
#psycopg.register_type(psycopg.new_type((700, 701, 1700), 'decimal', decimalize))
|
||||
|
||||
psycopg.register_type(psycopg.new_type((1082,), "date", lambda x:x))
|
||||
psycopg.register_type(psycopg.new_type((1083,), "time", lambda x:x))
|
||||
psycopg.register_type(psycopg.new_type((1114,), "datetime", lambda x:x))
|
||||
return PoolManager.get(db_name)
|
||||
|
||||
def close_db(db_name):
|
||||
return PoolManager.close(db_name)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -116,15 +116,14 @@ def amount_to_text(nbr, lang='en', currency='euro'):
|
|||
Example:
|
||||
1654: thousands six cent cinquante-quatre.
|
||||
"""
|
||||
import netsvc
|
||||
if nbr > 10000000:
|
||||
#TODO: use logger
|
||||
print "WARNING: number too large '%d', can't translate it!" % (nbr,)
|
||||
netsvc.Logger().notifyChannel('translate', netsvc.LOG_WARNING, _("Number too large '%d', can not translate it"))
|
||||
return str(nbr)
|
||||
|
||||
if not _translate_funcs.has_key(lang):
|
||||
#TODO: use logger
|
||||
print "WARNING: no translation function found for lang: '%s'" % (lang,)
|
||||
#TODO: (default should be en) same as above
|
||||
netsvc.Logger().notifyChannel('translate', netsvc.LOG_WARNING, _("no translation function found for lang: '%s'" % (lang,)))
|
||||
#TODO: (default should be en) same as above
|
||||
lang = 'en'
|
||||
return _translate_funcs[lang](nbr, currency)
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class configmanager(object):
|
|||
'netport': '8070',
|
||||
'db_host': False,
|
||||
'db_port': False,
|
||||
'db_name': 'terp',
|
||||
'db_name': False,
|
||||
'db_user': False,
|
||||
'db_password': False,
|
||||
'db_maxconn': 64,
|
||||
|
@ -62,10 +62,11 @@ class configmanager(object):
|
|||
'stop_after_init': False, # this will stop the server after initialization
|
||||
'price_accuracy': 2,
|
||||
|
||||
'assert_exit_level': logging.WARNING, # level above which a failed assert will
|
||||
'log_level': logging.INFO,
|
||||
'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise
|
||||
}
|
||||
|
||||
assert_exit_levels = (netsvc.LOG_CRITICAL, netsvc.LOG_ERROR, netsvc.LOG_WARNING, netsvc.LOG_INFO, netsvc.LOG_DEBUG)
|
||||
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG')])
|
||||
|
||||
version = "%s %s" % (release.description, release.version)
|
||||
parser = optparse.OptionParser(version=version)
|
||||
|
@ -89,7 +90,8 @@ class configmanager(object):
|
|||
# stops the server from launching after initialization
|
||||
parser.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False, help="stop the server after it initializes")
|
||||
parser.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode')
|
||||
parser.add_option("--assert-exit-level", dest='assert_exit_level', help="specify the level at which a failed assertion will stop the server " + str(assert_exit_levels))
|
||||
parser.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(), help='specify the level of the logging. Accepted values: ' + str(loglevels.keys()))
|
||||
parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=loglevels.keys(), help="specify the level at which a failed assertion will stop the server. Accepted values: " + str(loglevels.keys()))
|
||||
parser.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False)
|
||||
|
||||
parser.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email')
|
||||
|
@ -163,8 +165,9 @@ class configmanager(object):
|
|||
self.options[arg] = getattr(opt, arg)
|
||||
|
||||
if opt.assert_exit_level:
|
||||
assert opt.assert_exit_level in assert_exit_levels, 'ERROR: The assert-exit-level must be one of those values: '+str(assert_exit_levels)
|
||||
self.options['assert_exit_level'] = getattr(logging, opt.assert_exit_level.upper())
|
||||
self.options['assert_exit_level'] = loglevels[opt.assert_exit_level]
|
||||
if opt.log_level:
|
||||
self.options['log_level'] = loglevels[opt.log_level]
|
||||
|
||||
if not self.options['root_path'] or self.options['root_path']=='None':
|
||||
self.options['root_path'] = os.path.abspath(os.path.dirname(sys.argv[0]))
|
||||
|
|
|
@ -100,7 +100,7 @@ def _eval_xml(self,node, pool, cr, uid, idref, context=None):
|
|||
import pytz
|
||||
except:
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel("init", netsvc.LOG_INFO, 'could not find pytz library')
|
||||
logger.notifyChannel("init", netsvc.LOG_WARNING, 'could not find pytz library')
|
||||
class pytzclass(object):
|
||||
all_timezones=[]
|
||||
pytz=pytzclass()
|
||||
|
@ -479,7 +479,7 @@ form: module.record_id""" % (xml_id,)
|
|||
pid = False
|
||||
for idx, menu_elem in enumerate(m_l):
|
||||
if pid:
|
||||
cr.execute('select id from ir_ui_menu where parent_id=%d and name=%s', (pid, menu_elem))
|
||||
cr.execute('select id from ir_ui_menu where parent_id=%s and name=%s', (pid, menu_elem))
|
||||
else:
|
||||
cr.execute('select id from ir_ui_menu where parent_id is null and name=%s', (menu_elem,))
|
||||
res = cr.fetchone()
|
||||
|
@ -491,7 +491,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:
|
||||
print 'Menu Error', self.module, xml_id, idx==len(m_l)-1
|
||||
self.logger.notifyChannel('init', netsvc.LOG_ERROR, "addon: %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)))
|
||||
|
@ -518,15 +518,15 @@ form: module.record_id""" % (xml_id,)
|
|||
values['icon'] = icons.get(a_type,'STOCK_NEW')
|
||||
if a_type=='act_window':
|
||||
a_id = self.id_get(cr, 'ir.actions.%s'% a_type, a_action)
|
||||
cr.execute('select view_type,view_mode,name,view_id,target from ir_act_window where id=%d', (int(a_id),))
|
||||
cr.execute('select view_type,view_mode,name,view_id,target from ir_act_window where id=%s', (int(a_id),))
|
||||
rrres = cr.fetchone()
|
||||
assert rrres, "No window action defined for this id %s !\n" \
|
||||
"Verify that this is a window action or add a type argument." % (a_action,)
|
||||
action_type,action_mode,action_name,view_id,target = rrres
|
||||
if view_id:
|
||||
cr.execute('SELECT type FROM ir_ui_view WHERE id=%d', (int(view_id),))
|
||||
cr.execute('SELECT type FROM ir_ui_view WHERE id=%s', (int(view_id),))
|
||||
action_mode, = cr.fetchone()
|
||||
cr.execute('SELECT view_mode FROM ir_act_window_view WHERE act_window_id=%d ORDER BY sequence LIMIT 1', (int(a_id),))
|
||||
cr.execute('SELECT view_mode FROM ir_act_window_view WHERE act_window_id=%s ORDER BY sequence LIMIT 1', (int(a_id),))
|
||||
if cr.rowcount:
|
||||
action_mode, = cr.fetchone()
|
||||
if action_type=='tree':
|
||||
|
@ -543,7 +543,7 @@ form: module.record_id""" % (xml_id,)
|
|||
values['name'] = action_name
|
||||
elif a_type=='wizard':
|
||||
a_id = self.id_get(cr, 'ir.actions.%s'% a_type, a_action)
|
||||
cr.execute('select name from ir_act_wizard where id=%d', (int(a_id),))
|
||||
cr.execute('select name from ir_act_wizard where id=%s', (int(a_id),))
|
||||
resw = cr.fetchone()
|
||||
if (not values.get('name', False)) and resw:
|
||||
values['name'] = resw[0]
|
||||
|
@ -612,7 +612,12 @@ form: module.record_id""" % (xml_id,)
|
|||
count = int(rec_src_count)
|
||||
if len(ids) != count:
|
||||
self.assert_report.record_assertion(False, severity)
|
||||
self.logger.notifyChannel('init', severity, 'assertion "' + rec_string + '" failed ! (search count is incorrect: ' + str(len(ids)) + ')' )
|
||||
msg = 'assertion "%s" failed!\n' \
|
||||
' Incorrect search count:\n' \
|
||||
' expected count: %d\n' \
|
||||
' obtained count: %d\n' \
|
||||
% (rec_string, count, len(ids))
|
||||
self.logger.notifyChannel('init', severity, msg)
|
||||
sevval = getattr(logging, severity.upper())
|
||||
if sevval >= config['assert_exit_level']:
|
||||
# TODO: define a dedicated exception
|
||||
|
@ -635,10 +640,16 @@ form: module.record_id""" % (xml_id,)
|
|||
globals['_ref'] = ref
|
||||
for test in [i for i in rec.childNodes if (i.nodeType == i.ELEMENT_NODE and i.nodeName=="test")]:
|
||||
f_expr = test.getAttribute("expr").encode('utf-8')
|
||||
f_val = _eval_xml(self, test, self.pool, cr, uid, self.idref, context=context) or True
|
||||
if eval(f_expr, globals) != f_val: # assertion failed
|
||||
expected_value = _eval_xml(self, test, self.pool, cr, uid, self.idref, context=context) or True
|
||||
expression_value = eval(f_expr, globals)
|
||||
if expression_value != expected_value: # assertion failed
|
||||
self.assert_report.record_assertion(False, severity)
|
||||
self.logger.notifyChannel('init', severity, 'assertion "' + rec_string + '" failed ! (tag ' + test.toxml() + ')' )
|
||||
msg = 'assertion "%s" failed!\n' \
|
||||
' xmltag: %s\n' \
|
||||
' expected value: %r\n' \
|
||||
' obtained value: %r\n' \
|
||||
% (rec_string, test.toxml(), expected_value, expression_value)
|
||||
self.logger.notifyChannel('init', severity, msg)
|
||||
sevval = getattr(logging, severity.upper())
|
||||
if sevval >= config['assert_exit_level']:
|
||||
# TODO: define a dedicated exception
|
||||
|
@ -657,7 +668,7 @@ form: module.record_id""" % (xml_id,)
|
|||
# if not rec_id and not self.isnoupdate(data_node):
|
||||
# print "Warning", rec_model
|
||||
|
||||
if self.isnoupdate(data_node) and not self.mode == 'init':
|
||||
if self.isnoupdate(data_node) and not self.mode in ('init','update'):
|
||||
# check if the xml record has an id string
|
||||
if rec_id:
|
||||
id = self.pool.get('ir.model.data')._update_dummy(cr, self.uid, rec_model, self.module, rec_id)
|
||||
|
@ -718,10 +729,11 @@ form: module.record_id""" % (xml_id,)
|
|||
if isinstance(model._columns[f_name], osv.fields.integer):
|
||||
f_val = int(f_val)
|
||||
res[f_name] = f_val
|
||||
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, rec_model, self.module, res, rec_id or False, not self.isnoupdate(data_node), noupdate=self.isnoupdate(data_node), mode=self.mode )
|
||||
if rec_id:
|
||||
self.idref[rec_id] = int(id)
|
||||
if config.get('import_partial', False):
|
||||
if config.get('i mport_partial', False):
|
||||
cr.commit()
|
||||
return rec_model, id
|
||||
|
||||
|
@ -743,7 +755,7 @@ form: module.record_id""" % (xml_id,)
|
|||
raise Exception( "Mismatch xml format: only terp or openerp as root tag" )
|
||||
|
||||
if de.nodeName == 'terp':
|
||||
self.logger.notifyChannel("init", netsvc.LOG_WARNING, "The tag <terp /> is deprecated, use <openerp/>")
|
||||
self.logger.notifyChannel("init", netsvc.LOG_WARNING, "The tag <terp/> is deprecated, use <openerp/>")
|
||||
|
||||
for n in [i for i in de.childNodes if (i.nodeType == i.ELEMENT_NODE and i.nodeName=="data")]:
|
||||
for rec in n.childNodes:
|
||||
|
@ -752,7 +764,7 @@ form: module.record_id""" % (xml_id,)
|
|||
try:
|
||||
self._tags[rec.nodeName](self.cr, rec, n)
|
||||
except:
|
||||
self.logger.notifyChannel("init", netsvc.LOG_INFO, '\n'+rec.toxml())
|
||||
self.logger.notifyChannel("init", netsvc.LOG_ERROR, '\n'+rec.toxml())
|
||||
self.cr.rollback()
|
||||
raise
|
||||
return True
|
||||
|
@ -824,9 +836,10 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
|||
if (not line) or not reduce(lambda x,y: x or y, line) :
|
||||
continue
|
||||
try:
|
||||
datas.append( map(lambda x:x.decode('utf8').encode('utf8'), line))
|
||||
datas.append(map(lambda x: misc.ustr(x), line))
|
||||
except:
|
||||
print "ERROR while importing the line: ", line
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "Can not import the line: %s" % line)
|
||||
pool.get(model).import_data(cr, uid, fields, datas,mode, module,noupdate,filename=fname_partial)
|
||||
if config.get('import_partial'):
|
||||
data = pickle.load(file(config.get('import_partial')))
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
try:
|
||||
from functools import wraps
|
||||
except ImportError:
|
||||
# this module doesn't exist in python < 2.5
|
||||
# we define a identity decorator
|
||||
def wraps(f):
|
||||
def identity(x):
|
||||
return x
|
||||
return identity
|
|
@ -759,8 +759,6 @@ if __name__=='__main__':
|
|||
g.process(starting_node)
|
||||
g.scale(radius*3,radius*3, radius, radius)
|
||||
|
||||
print g
|
||||
|
||||
import Image
|
||||
import ImageDraw
|
||||
img = Image.new("RGB", (800, 600), "#ffffff")
|
||||
|
|
|
@ -27,10 +27,7 @@ Miscelleanous tools used by OpenERP.
|
|||
import os, time, sys
|
||||
import inspect
|
||||
|
||||
import psycopg
|
||||
#import netsvc
|
||||
from config import config
|
||||
#import tools
|
||||
|
||||
import zipfile
|
||||
import release
|
||||
|
@ -71,7 +68,7 @@ def init_db(cr):
|
|||
if p_id is not None:
|
||||
cr.execute('select id \
|
||||
from ir_module_category \
|
||||
where name=%s and parent_id=%d', (categs[0], p_id))
|
||||
where name=%s and parent_id=%s', (categs[0], p_id))
|
||||
else:
|
||||
cr.execute('select id \
|
||||
from ir_module_category \
|
||||
|
@ -82,7 +79,7 @@ def init_db(cr):
|
|||
c_id = cr.fetchone()[0]
|
||||
cr.execute('insert into ir_module_category \
|
||||
(id, name, parent_id) \
|
||||
values (%d, %s, %d)', (c_id, categs[0], p_id))
|
||||
values (%s, %s, %s)', (c_id, categs[0], p_id))
|
||||
else:
|
||||
c_id = c_id[0]
|
||||
p_id = c_id
|
||||
|
@ -100,11 +97,10 @@ def init_db(cr):
|
|||
cr.execute('select nextval(\'ir_module_module_id_seq\')')
|
||||
id = cr.fetchone()[0]
|
||||
cr.execute('insert into ir_module_module \
|
||||
(id, author, latest_version, website, name, shortdesc, description, \
|
||||
(id, author, website, name, shortdesc, description, \
|
||||
category_id, state) \
|
||||
values (%d, %s, %s, %s, %s, %s, %s, %d, %s)', (
|
||||
values (%s, %s, %s, %s, %s, %s, %s, %s)', (
|
||||
id, info.get('author', ''),
|
||||
release.major_version + '.' + info.get('version', ''),
|
||||
info.get('website', ''), i, info.get('name', False),
|
||||
info.get('description', ''), p_id, state))
|
||||
dependencies = info.get('depends', [])
|
||||
|
@ -388,7 +384,7 @@ def sms_send(user, password, api_id, text, to):
|
|||
params = urllib.urlencode({'user': user, 'password': password, 'api_id': api_id, 'text': text, 'to':to})
|
||||
#f = urllib.urlopen("http://api.clickatell.com/http/sendmsg", params)
|
||||
f = urllib.urlopen("http://196.7.150.220/http/sendmsg", params)
|
||||
print f.read()
|
||||
# FIXME: Use the logger if there is an error
|
||||
return True
|
||||
|
||||
#---------------------------------------------------------
|
||||
|
@ -540,29 +536,36 @@ def is_hashable(h):
|
|||
# Timeout: 0 = no timeout, otherwise in seconds
|
||||
#
|
||||
class cache(object):
|
||||
def __init__(self, timeout=10000, skiparg=2):
|
||||
def __init__(self, timeout=10000, skiparg=2, multi=None):
|
||||
self.timeout = timeout
|
||||
self.skiparg = skiparg
|
||||
self.multi = multi
|
||||
self.cache = {}
|
||||
|
||||
def __call__(self, fn):
|
||||
arg_names = inspect.getargspec(fn)[0][2:]
|
||||
arg_names = inspect.getargspec(fn)[0][self.skiparg:]
|
||||
def cached_result(self2, cr=None, *args, **kwargs):
|
||||
if cr is None:
|
||||
self.cache = {}
|
||||
return True
|
||||
if ('clear_keys' in kwargs):
|
||||
if (kwargs['clear_keys'] in self.cache):
|
||||
del self.cache[kwargs['clear_keys']]
|
||||
return True
|
||||
|
||||
# Update named arguments with positional argument values
|
||||
kwargs.update(dict(zip(arg_names, args)))
|
||||
for k in kwargs:
|
||||
if isinstance(kwargs[k], (list, dict, set)):
|
||||
kwargs[k] = tuple(kwargs[k])
|
||||
elif not is_hashable(kwargs[k]):
|
||||
kwargs[k] = repr(kwargs[k])
|
||||
kwargs = kwargs.items()
|
||||
kwargs.sort()
|
||||
kwargs2 = kwargs.copy()
|
||||
kwargs2.update(dict(zip(arg_names, args)))
|
||||
for k in kwargs2:
|
||||
if isinstance(kwargs2[k], (list, dict, set)):
|
||||
kwargs2[k] = tuple(kwargs2[k])
|
||||
elif not is_hashable(kwargs2[k]):
|
||||
kwargs2[k] = repr(kwargs2[k])
|
||||
kwargs2 = kwargs2.items()
|
||||
kwargs2.sort()
|
||||
|
||||
# Work out key as a tuple of ('argname', value) pairs
|
||||
key = (('dbname', cr.dbname),) + tuple(kwargs)
|
||||
key = (('dbname', cr.dbname),) + tuple(kwargs2)
|
||||
|
||||
# Check cache and return cached value if possible
|
||||
if key in self.cache:
|
||||
|
@ -574,7 +577,7 @@ class cache(object):
|
|||
# Work out new value, cache it and return it
|
||||
# FIXME Should copy() this value to avoid futur modifications of the cache ?
|
||||
# FIXME What about exceptions ?
|
||||
result = fn(self2,cr,**dict(kwargs))
|
||||
result = fn(self2,cr,*args, **kwargs)
|
||||
|
||||
self.cache[key] = (result, time.time())
|
||||
return result
|
||||
|
@ -583,6 +586,28 @@ class cache(object):
|
|||
def to_xml(s):
|
||||
return s.replace('&','&').replace('<','<').replace('>','>')
|
||||
|
||||
def ustr(value):
|
||||
"""This method is similar to the builtin `str` method, except
|
||||
it will return Unicode string.
|
||||
|
||||
@param value: the value to convert
|
||||
|
||||
@rtype: unicode
|
||||
@return: unicode string
|
||||
"""
|
||||
|
||||
if isinstance(value, unicode):
|
||||
return value
|
||||
|
||||
if hasattr(value, '__unicode__'):
|
||||
return unicode(value)
|
||||
|
||||
if not isinstance(value, str):
|
||||
value = str(value)
|
||||
|
||||
return unicode(value, 'utf-8')
|
||||
|
||||
|
||||
def get_languages():
|
||||
languages={
|
||||
'bg_BG': u'Bulgarian / български',
|
||||
|
@ -633,7 +658,7 @@ def get_user_companies(cr, user):
|
|||
res=[x[0] for x in cr.fetchall()]
|
||||
res.extend(_get_company_children(cr, res))
|
||||
return res
|
||||
cr.execute('SELECT comp.id FROM res_company AS comp, res_users AS u WHERE u.id = %d AND comp.id = u.company_id' % (user,))
|
||||
cr.execute('SELECT comp.id FROM res_company AS comp, res_users AS u WHERE u.id = %s AND comp.id = u.company_id' % (user,))
|
||||
compids=[cr.fetchone()[0]]
|
||||
compids.extend(_get_company_children(cr, compids))
|
||||
return compids
|
||||
|
@ -669,39 +694,30 @@ def human_size(sz):
|
|||
i = i + 1
|
||||
return "%0.2f %s" % (s, units[i])
|
||||
|
||||
def logged(when):
|
||||
def log(f, res, *args, **kwargs):
|
||||
vector = ['Call -> function: %s' % f]
|
||||
def logged(f):
|
||||
from tools.func import wraps
|
||||
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwargs):
|
||||
import netsvc
|
||||
from pprint import pformat
|
||||
|
||||
vector = ['Call -> function: %r' % f]
|
||||
for i, arg in enumerate(args):
|
||||
vector.append( ' arg %02d: %r' % ( i, arg ) )
|
||||
vector.append(' arg %02d: %s' % (i, pformat(arg)))
|
||||
for key, value in kwargs.items():
|
||||
vector.append( ' kwarg %10s: %r' % ( key, value ) )
|
||||
vector.append( ' result: %r' % res )
|
||||
print "\n".join(vector)
|
||||
vector.append(' kwarg %10s: %s' % (key, pformat(value)))
|
||||
|
||||
def pre_logged(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
timeb4 = time.time()
|
||||
res = f(*args, **kwargs)
|
||||
log(f, res, *args, **kwargs)
|
||||
|
||||
vector.append(' result: %s' % pformat(res))
|
||||
vector.append(' time delta: %s' % (time.time() - timeb4))
|
||||
#netsvc.Logger().notifyChannel('logged', netsvc.LOG_DEBUG, '\n'.join(vector))
|
||||
return res
|
||||
|
||||
return wrapper
|
||||
|
||||
def post_logged(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
now = time.time()
|
||||
res = None
|
||||
try:
|
||||
res = f(*args, **kwargs)
|
||||
return res
|
||||
finally:
|
||||
log(f, res, *args, **kwargs)
|
||||
print " time delta: %s" % (time.time() - now)
|
||||
return wrapper
|
||||
|
||||
try:
|
||||
return { "pre" : pre_logged, "post" : post_logged}[when]
|
||||
except KeyError, e:
|
||||
raise ValueError(e), "must to be 'pre' or 'post'"
|
||||
|
||||
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',
|
||||
|
|
|
@ -34,7 +34,7 @@ def listdir(dir, recursive=False):
|
|||
return os.listdir(dir)
|
||||
|
||||
res = []
|
||||
for root, dirs, files in os.walk(dir):
|
||||
for root, dirs, files in walksymlinks(dir):
|
||||
root = root[len(dir)+1:]
|
||||
res.extend([opj(root, f) for f in files])
|
||||
return res
|
||||
|
|
|
@ -41,7 +41,7 @@ class UNIX_LINE_TERMINATOR(csv.excel):
|
|||
csv.register_dialect("UNIX", UNIX_LINE_TERMINATOR)
|
||||
|
||||
#
|
||||
# TODO: a caching method
|
||||
# Warning: better use self.pool.get('ir.translation')._get_source if you can
|
||||
#
|
||||
def translate(cr, name, source_type, lang, source=None):
|
||||
if source and name:
|
||||
|
@ -64,8 +64,10 @@ class GettextAlias(object):
|
|||
return source
|
||||
except:
|
||||
return source
|
||||
return translate(cr, None, 'code', lang, source) or source
|
||||
|
||||
cr.execute('select value from ir_translation where lang=%s and type=%s and src=%s', (lang, 'code', source))
|
||||
res_trans = cr.fetchone()
|
||||
return res_trans and res_trans[0] or source
|
||||
_ = GettextAlias()
|
||||
|
||||
|
||||
|
@ -570,7 +572,6 @@ def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=
|
|||
line += 1
|
||||
# skip empty rows and rows where the translation field (=last fiefd) is empty
|
||||
if (not row) or (not row[-1]):
|
||||
#print "translate: skip %s" % repr(row)
|
||||
continue
|
||||
|
||||
# dictionary which holds values for this line of the csv file
|
||||
|
|
|
@ -59,7 +59,7 @@ def upgrade():
|
|||
for module_id,name,url in cr.fetchall():
|
||||
print '\tremoving module %s' % name
|
||||
remove(name)
|
||||
cr.execute('update ir_module_module set state=%s where id=%d', ('uninstalled', module_id))
|
||||
cr.execute('update ir_module_module set state=%s where id=%s', ('uninstalled', module_id))
|
||||
cr.commit()
|
||||
|
||||
print 'Check for modules to upgrade...'
|
||||
|
@ -68,7 +68,7 @@ def upgrade():
|
|||
print '\tupgrading module %s' % name
|
||||
remove(name)
|
||||
install(name, url)
|
||||
cr.execute('update ir_module_module set state=%s where id=%d', ('installed', module_id))
|
||||
cr.execute('update ir_module_module set state=%s where id=%s', ('installed', module_id))
|
||||
cr.commit()
|
||||
toupdate.append(name)
|
||||
|
||||
|
@ -77,7 +77,7 @@ def upgrade():
|
|||
for module_id,name,url in cr.fetchall():
|
||||
print '\tinstalling module %s' % name
|
||||
install(name, url)
|
||||
cr.execute('update ir_module_module set state=%s where id=%d', ('installed', module_id))
|
||||
cr.execute('update ir_module_module set state=%s where id=%s', ('installed', module_id))
|
||||
cr.commit()
|
||||
toinit.append(name)
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class interface(netsvc.Service):
|
|||
if node.hasAttribute('string') and node.getAttribute('string'):
|
||||
trans = translate(cr, self.wiz_name+','+state, 'wizard_view', lang, node.getAttribute('string').encode('utf8'))
|
||||
if trans:
|
||||
node.setAttribute('string', trans.decode('utf8'))
|
||||
node.setAttribute('string', trans)
|
||||
for n in node.childNodes:
|
||||
self.translate_view(cr, n, state, lang)
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ def create(cr, ident, wkf_id):
|
|||
(uid,res_type,res_id) = ident
|
||||
cr.execute("select nextval('wkf_instance_id_seq')")
|
||||
id_new = cr.fetchone()[0]
|
||||
cr.execute('insert into wkf_instance (id,res_type,res_id,uid,wkf_id) values (%d,%s,%s,%s,%s)', (id_new,res_type,res_id,uid,wkf_id))
|
||||
cr.execute('select * from wkf_activity where flow_start=True and wkf_id=%d', (wkf_id,))
|
||||
cr.execute('insert into wkf_instance (id,res_type,res_id,uid,wkf_id) values (%s,%s,%s,%s,%s)', (id_new,res_type,res_id,uid,wkf_id))
|
||||
cr.execute('select * from wkf_activity where flow_start=True and wkf_id=%s', (wkf_id,))
|
||||
res = cr.dictfetchall()
|
||||
stack = []
|
||||
workitem.create(cr, res, id_new, ident, stack=stack)
|
||||
|
@ -40,10 +40,10 @@ def create(cr, ident, wkf_id):
|
|||
|
||||
def delete(cr, ident):
|
||||
(uid,res_type,res_id) = ident
|
||||
cr.execute('delete from wkf_instance where res_id=%d and res_type=%s', (res_id,res_type))
|
||||
cr.execute('delete from wkf_instance where res_id=%s and res_type=%s', (res_id,res_type))
|
||||
|
||||
def validate(cr, inst_id, ident, signal, force_running=False):
|
||||
cr.execute("select * from wkf_workitem where inst_id=%d", (inst_id,))
|
||||
cr.execute("select * from wkf_workitem where inst_id=%s", (inst_id,))
|
||||
for witem in cr.dictfetchall():
|
||||
stack = []
|
||||
workitem.process(cr, witem, ident, signal, force_running, stack=stack)
|
||||
|
@ -52,27 +52,27 @@ def validate(cr, inst_id, ident, signal, force_running=False):
|
|||
return stack and stack[0] or False
|
||||
|
||||
def update(cr, inst_id, ident):
|
||||
cr.execute("select * from wkf_workitem where inst_id=%d", (inst_id,))
|
||||
cr.execute("select * from wkf_workitem where inst_id=%s", (inst_id,))
|
||||
for witem in cr.dictfetchall():
|
||||
stack = []
|
||||
workitem.process(cr, witem, ident, stack=stack)
|
||||
return _update_end(cr, inst_id, ident)
|
||||
|
||||
def _update_end(cr, inst_id, ident):
|
||||
cr.execute('select wkf_id from wkf_instance where id=%d', (inst_id,))
|
||||
cr.execute('select wkf_id from wkf_instance where id=%s', (inst_id,))
|
||||
wkf_id = cr.fetchone()[0]
|
||||
cr.execute('select state,flow_stop from wkf_workitem w left join wkf_activity a on (a.id=w.act_id) where w.inst_id=%d', (inst_id,))
|
||||
cr.execute('select state,flow_stop from wkf_workitem w left join wkf_activity a on (a.id=w.act_id) where w.inst_id=%s', (inst_id,))
|
||||
ok=True
|
||||
for r in cr.fetchall():
|
||||
if (r[0]<>'complete') or not r[1]:
|
||||
ok=False
|
||||
break
|
||||
if ok:
|
||||
cr.execute('select distinct a.name from wkf_activity a left join wkf_workitem w on (a.id=w.act_id) where w.inst_id=%d', (inst_id,))
|
||||
cr.execute('select distinct a.name from wkf_activity a left join wkf_workitem w on (a.id=w.act_id) where w.inst_id=%s', (inst_id,))
|
||||
act_names = cr.fetchall()
|
||||
cr.execute("update wkf_instance set state='complete' where id=%d", (inst_id,))
|
||||
cr.execute("update wkf_workitem set state='complete' where subflow_id=%d", (inst_id,))
|
||||
cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id in (select inst_id from wkf_workitem where subflow_id=%d)", (inst_id,))
|
||||
cr.execute("update wkf_instance set state='complete' where id=%s", (inst_id,))
|
||||
cr.execute("update wkf_workitem set state='complete' where subflow_id=%s", (inst_id,))
|
||||
cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id in (select inst_id from wkf_workitem where subflow_id=%s)", (inst_id,))
|
||||
for i in cr.fetchall():
|
||||
for act_name in act_names:
|
||||
validate(cr, i[0], (ident[0],i[1],i[2]), 'subflow.'+act_name[0])
|
||||
|
|
|
@ -66,7 +66,7 @@ def _eval_expr(cr, ident, workitem, action):
|
|||
ret=False
|
||||
assert action, 'You used a NULL action in a workflow, use dummy node instead.'
|
||||
for line in action.split('\n'):
|
||||
line = line.replace(chr(13),'')
|
||||
line = line.strip()
|
||||
uid=ident[0]
|
||||
model=ident[1]
|
||||
ids=[ident[2]]
|
||||
|
|
|
@ -23,10 +23,19 @@
|
|||
#
|
||||
# May be uncommented to logs workflows modifications
|
||||
#
|
||||
import netsvc
|
||||
|
||||
def log(cr,ident,act_id,info=''):
|
||||
pass
|
||||
#cr.execute('insert into wkf_logs (res_type, res_id, uid, act_id, time, info) values (%s,%d,%d,%d,current_time,%s)', (ident[1],int(ident[2]),int(ident[0]),int(act_id),info))
|
||||
msg = """
|
||||
res_type: %r
|
||||
res_id: %d
|
||||
uid: %d
|
||||
act_id: %d
|
||||
info: %s
|
||||
""" % (ident[1], ident[2], ident[0], act_id, info)
|
||||
netsvc.Logger().notifyChannel('wkf_log', netsvc.LOG_DEBUG, msg)
|
||||
|
||||
#cr.execute('insert into wkf_logs (res_type, res_id, uid, act_id, time, info) values (%s,%s,%s,%s,current_time,%s)', (ident[1],int(ident[2]),int(ident[0]),int(act_id),info))
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -44,15 +44,15 @@ class workflow_service(netsvc.Service):
|
|||
|
||||
def trg_write(self, uid, res_type, res_id, cr):
|
||||
ident = (uid,res_type,res_id)
|
||||
cr.execute('select id from wkf_instance where res_id=%d and res_type=%s and state=%s', (res_id,res_type, 'active'))
|
||||
cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id or None,res_type or None, 'active'))
|
||||
for (id,) in cr.fetchall():
|
||||
instance.update(cr, id, ident)
|
||||
|
||||
def trg_trigger(self, uid, res_type, res_id, cr):
|
||||
cr.execute('select instance_id from wkf_triggers where res_id=%d and model=%s', (res_id,res_type))
|
||||
cr.execute('select instance_id from wkf_triggers where res_id=%s and model=%s', (res_id,res_type))
|
||||
res = cr.fetchall()
|
||||
for (instance_id,) in res:
|
||||
cr.execute('select uid,res_type,res_id from wkf_instance where id=%d', (instance_id,))
|
||||
cr.execute('select uid,res_type,res_id from wkf_instance where id=%s', (instance_id,))
|
||||
ident = cr.fetchone()
|
||||
instance.update(cr, instance_id, ident)
|
||||
|
||||
|
@ -76,7 +76,7 @@ class workflow_service(netsvc.Service):
|
|||
result = False
|
||||
ident = (uid,res_type,res_id)
|
||||
# ids of all active workflow instances for a corresponding resource (id, model_nam)
|
||||
cr.execute('select id from wkf_instance where res_id=%d and res_type=%s and state=%s', (res_id, res_type, 'active'))
|
||||
cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id, res_type, 'active'))
|
||||
for (id,) in cr.fetchall():
|
||||
res2 = instance.validate(cr, id, ident, signal)
|
||||
result = result or res2
|
||||
|
@ -88,21 +88,21 @@ class workflow_service(netsvc.Service):
|
|||
def trg_redirect(self, uid, res_type, res_id, new_rid, cr):
|
||||
# get ids of wkf instances for the old resource (res_id)
|
||||
#CHECKME: shouldn't we get only active instances?
|
||||
cr.execute('select id, wkf_id from wkf_instance where res_id=%d and res_type=%s', (res_id, res_type))
|
||||
cr.execute('select id, wkf_id from wkf_instance where res_id=%s and res_type=%s', (res_id, res_type))
|
||||
for old_inst_id, wkf_id in cr.fetchall():
|
||||
# first active instance for new resource (new_rid), using same wkf
|
||||
cr.execute(
|
||||
'SELECT id '\
|
||||
'FROM wkf_instance '\
|
||||
'WHERE res_id=%d AND res_type=%s AND wkf_id=%d AND state=%s',
|
||||
'WHERE res_id=%s AND res_type=%s AND wkf_id=%s AND state=%s',
|
||||
(new_rid, res_type, wkf_id, 'active'))
|
||||
new_id = cr.fetchone()
|
||||
if new_id:
|
||||
# select all workitems which "wait" for the old instance
|
||||
cr.execute('select id from wkf_workitem where subflow_id=%d', (old_inst_id,))
|
||||
cr.execute('select id from wkf_workitem where subflow_id=%s', (old_inst_id,))
|
||||
for (item_id,) in cr.fetchall():
|
||||
# redirect all those workitems to the wkf instance of the new resource
|
||||
cr.execute('update wkf_workitem set subflow_id=%d where id=%d', (new_id[0], item_id))
|
||||
cr.execute('update wkf_workitem set subflow_id=%s where id=%s', (new_id[0], item_id))
|
||||
workflow_service()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#
|
||||
# TODO:
|
||||
# cr.execute('delete from wkf_triggers where model=%s and res_id=%d', (res_type,res_id))
|
||||
# cr.execute('delete from wkf_triggers where model=%s and res_id=%s', (res_type,res_id))
|
||||
#
|
||||
|
||||
import netsvc
|
||||
|
@ -35,8 +35,8 @@ def create(cr, act_datas, inst_id, ident, stack):
|
|||
for act in act_datas:
|
||||
cr.execute("select nextval('wkf_workitem_id_seq')")
|
||||
id_new = cr.fetchone()[0]
|
||||
cr.execute("insert into wkf_workitem (id,act_id,inst_id,state) values (%d,%s,%s,'active')", (id_new, act['id'], inst_id))
|
||||
cr.execute('select * from wkf_workitem where id=%d',(id_new,))
|
||||
cr.execute("insert into wkf_workitem (id,act_id,inst_id,state) values (%s,%s,%s,'active')", (id_new, act['id'], inst_id))
|
||||
cr.execute('select * from wkf_workitem where id=%s',(id_new,))
|
||||
res = cr.dictfetchone()
|
||||
wkf_logs.log(cr,ident,act['id'],'active')
|
||||
process(cr, res, ident, stack=stack)
|
||||
|
@ -45,7 +45,7 @@ def process(cr, workitem, ident, signal=None, force_running=False, stack=None):
|
|||
if stack is None:
|
||||
raise 'Error !!!'
|
||||
result = True
|
||||
cr.execute('select * from wkf_activity where id=%d', (workitem['act_id'],))
|
||||
cr.execute('select * from wkf_activity where id=%s', (workitem['act_id'],))
|
||||
activity = cr.dictfetchone()
|
||||
|
||||
triggers = False
|
||||
|
@ -63,7 +63,7 @@ def process(cr, workitem, ident, signal=None, force_running=False, stack=None):
|
|||
triggers = triggers and not ok
|
||||
|
||||
if triggers:
|
||||
cr.execute('select * from wkf_transition where act_from=%d', (workitem['act_id'],))
|
||||
cr.execute('select * from wkf_transition where act_from=%s', (workitem['act_id'],))
|
||||
alltrans = cr.dictfetchall()
|
||||
for trans in alltrans:
|
||||
if trans['trigger_model']:
|
||||
|
@ -71,7 +71,7 @@ def process(cr, workitem, ident, signal=None, force_running=False, stack=None):
|
|||
for res_id in ids:
|
||||
cr.execute('select nextval(\'wkf_triggers_id_seq\')')
|
||||
id =cr.fetchone()[0]
|
||||
cr.execute('insert into wkf_triggers (model,res_id,instance_id,workitem_id,id) values (%s,%d,%d,%d,%d)', (trans['trigger_model'],res_id,workitem['inst_id'], workitem['id'], id))
|
||||
cr.execute('insert into wkf_triggers (model,res_id,instance_id,workitem_id,id) values (%s,%s,%s,%s,%s)', (trans['trigger_model'],res_id,workitem['inst_id'], workitem['id'], id))
|
||||
|
||||
return result
|
||||
|
||||
|
@ -79,7 +79,7 @@ def process(cr, workitem, ident, signal=None, force_running=False, stack=None):
|
|||
# ---------------------- PRIVATE FUNCS --------------------------------
|
||||
|
||||
def _state_set(cr, workitem, activity, state, ident):
|
||||
cr.execute('update wkf_workitem set state=%s where id=%d', (state,workitem['id']))
|
||||
cr.execute('update wkf_workitem set state=%s where id=%s', (state,workitem['id']))
|
||||
workitem['state'] = state
|
||||
wkf_logs.log(cr,ident,activity['id'],state)
|
||||
|
||||
|
@ -89,7 +89,7 @@ def _execute(cr, workitem, activity, ident, stack):
|
|||
# send a signal to parent workflow (signal: subflow.signal_name)
|
||||
#
|
||||
if (workitem['state']=='active') and activity['signal_send']:
|
||||
cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id in (select inst_id from wkf_workitem where subflow_id=%d)", (workitem['inst_id'],))
|
||||
cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id in (select inst_id from wkf_workitem where subflow_id=%s)", (workitem['inst_id'],))
|
||||
for i in cr.fetchall():
|
||||
instance.validate(cr, i[0], (ident[0],i[1],i[2]), activity['signal_send'], force_running=True)
|
||||
|
||||
|
@ -97,7 +97,6 @@ def _execute(cr, workitem, activity, ident, stack):
|
|||
if workitem['state']=='active':
|
||||
_state_set(cr, workitem, activity, 'complete', ident)
|
||||
if activity['action_id']:
|
||||
print 'ICI'
|
||||
res2 = wkf_expr.execute_action(cr, ident, workitem, activity)
|
||||
if res2:
|
||||
stack.append(res2)
|
||||
|
@ -116,7 +115,7 @@ def _execute(cr, workitem, activity, ident, stack):
|
|||
elif activity['kind']=='stopall':
|
||||
if workitem['state']=='active':
|
||||
_state_set(cr, workitem, activity, 'running', ident)
|
||||
cr.execute('delete from wkf_workitem where inst_id=%d and id<>%d', (workitem['inst_id'], workitem['id']))
|
||||
cr.execute('delete from wkf_workitem where inst_id=%s and id<>%s', (workitem['inst_id'], workitem['id']))
|
||||
if activity['action']:
|
||||
wkf_expr.execute(cr, ident, workitem, activity)
|
||||
_state_set(cr, workitem, activity, 'complete', ident)
|
||||
|
@ -129,14 +128,14 @@ def _execute(cr, workitem, activity, ident, stack):
|
|||
cr.execute('delete from wkf_workitem where id=%s', (workitem['id'],))
|
||||
return False
|
||||
assert type(id_new)==type(1) or type(id_new)==type(1L), 'Wrong return value: '+str(id_new)+' '+str(type(id_new))
|
||||
cr.execute('select id from wkf_instance where res_id=%d and wkf_id=%d', (id_new,activity['subflow_id']))
|
||||
cr.execute('select id from wkf_instance where res_id=%s and wkf_id=%s', (id_new,activity['subflow_id']))
|
||||
id_new = cr.fetchone()[0]
|
||||
else:
|
||||
id_new = instance.create(cr, ident, activity['subflow_id'])
|
||||
cr.execute('update wkf_workitem set subflow_id=%d where id=%s', (id_new, workitem['id']))
|
||||
cr.execute('update wkf_workitem set subflow_id=%s where id=%s', (id_new, workitem['id']))
|
||||
workitem['subflow_id'] = id_new
|
||||
if workitem['state']=='running':
|
||||
cr.execute("select state from wkf_instance where id=%d", (workitem['subflow_id'],))
|
||||
cr.execute("select state from wkf_instance where id=%s", (workitem['subflow_id'],))
|
||||
state= cr.fetchone()[0]
|
||||
if state=='complete':
|
||||
_state_set(cr, workitem, activity, 'complete', ident)
|
||||
|
@ -145,7 +144,7 @@ def _execute(cr, workitem, activity, ident, stack):
|
|||
def _split_test(cr, workitem, split_mode, ident, signal=None, stack=None):
|
||||
if stack is None:
|
||||
raise 'Error !!!'
|
||||
cr.execute('select * from wkf_transition where act_from=%d', (workitem['act_id'],))
|
||||
cr.execute('select * from wkf_transition where act_from=%s', (workitem['act_id'],))
|
||||
test = False
|
||||
transitions = []
|
||||
alltrans = cr.dictfetchall()
|
||||
|
@ -162,36 +161,36 @@ def _split_test(cr, workitem, split_mode, ident, signal=None, stack=None):
|
|||
if not wkf_expr.check(cr, workitem, ident, transition,signal):
|
||||
test = False
|
||||
break
|
||||
cr.execute('select count(*) from wkf_witm_trans where trans_id=%d and inst_id=%d', (transition['id'], workitem['inst_id']))
|
||||
cr.execute('select count(*) from wkf_witm_trans where trans_id=%s and inst_id=%s', (transition['id'], workitem['inst_id']))
|
||||
if not cr.fetchone()[0]:
|
||||
transitions.append((transition['id'], workitem['inst_id']))
|
||||
if test and len(transitions):
|
||||
cr.executemany('insert into wkf_witm_trans (trans_id,inst_id) values (%d,%d)', transitions)
|
||||
cr.execute('delete from wkf_workitem where id=%d', (workitem['id'],))
|
||||
cr.executemany('insert into wkf_witm_trans (trans_id,inst_id) values (%s,%s)', transitions)
|
||||
cr.execute('delete from wkf_workitem where id=%s', (workitem['id'],))
|
||||
for t in transitions:
|
||||
_join_test(cr, t[0], t[1], ident, stack)
|
||||
return True
|
||||
return False
|
||||
|
||||
def _join_test(cr, trans_id, inst_id, ident, stack):
|
||||
cr.execute('select * from wkf_activity where id=(select act_to from wkf_transition where id=%d)', (trans_id,))
|
||||
cr.execute('select * from wkf_activity where id=(select act_to from wkf_transition where id=%s)', (trans_id,))
|
||||
activity = cr.dictfetchone()
|
||||
if activity['join_mode']=='XOR':
|
||||
create(cr,[activity], inst_id, ident, stack)
|
||||
cr.execute('delete from wkf_witm_trans where inst_id=%d and trans_id=%d', (inst_id,trans_id))
|
||||
cr.execute('delete from wkf_witm_trans where inst_id=%s and trans_id=%s', (inst_id,trans_id))
|
||||
else:
|
||||
cr.execute('select id from wkf_transition where act_to=%d', (activity['id'],))
|
||||
cr.execute('select id from wkf_transition where act_to=%s', (activity['id'],))
|
||||
trans_ids = cr.fetchall()
|
||||
ok = True
|
||||
for (id,) in trans_ids:
|
||||
cr.execute('select count(*) from wkf_witm_trans where trans_id=%d and inst_id=%d', (id,inst_id))
|
||||
cr.execute('select count(*) from wkf_witm_trans where trans_id=%s and inst_id=%s', (id,inst_id))
|
||||
res = cr.fetchone()[0]
|
||||
if not res:
|
||||
ok = False
|
||||
break
|
||||
if ok:
|
||||
for (id,) in trans_ids:
|
||||
cr.execute('delete from wkf_witm_trans where trans_id=%d and inst_id=%d', (id,inst_id))
|
||||
cr.execute('delete from wkf_witm_trans where trans_id=%s and inst_id=%s', (id,inst_id))
|
||||
create(cr, [activity], inst_id, ident, stack)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
2
setup.py
2
setup.py
|
@ -54,7 +54,7 @@ execfile(opj('bin', 'release.py'))
|
|||
py_short_version = '%s.%s' % sys.version_info[:2]
|
||||
|
||||
required_modules = [
|
||||
('psycopg', 'PostgreSQL module'),
|
||||
('psycopg2', 'PostgreSQL module'),
|
||||
('xml', 'XML Tools for python'),
|
||||
('libxml2', 'libxml2 python bindings'),
|
||||
('libxslt', 'libxslt python bindings'),
|
||||
|
|
Loading…
Reference in New Issue