Merge commit 'origin/master' into mdv-gpl3
bzr revid: p_christ@hol.gr-20081207195509-2tb8fb3d7qr2xigt bzr revid: p_christ@hol.gr-20081210075901-97mt6chs3ljokpsx
This commit is contained in:
commit
281c7c980a
|
@ -1,6 +1,6 @@
|
||||||
Metadata-Version: 1.1
|
Metadata-Version: 1.1
|
||||||
Name: OpenERP
|
Name: OpenERP
|
||||||
Version: 5.0.0-alpha
|
Version: 5.0.0-rc1
|
||||||
Author: Tiny.be
|
Author: Tiny.be
|
||||||
Author-email: fp at tiny be
|
Author-email: fp at tiny be
|
||||||
Maintainer: Tiny.be
|
Maintainer: Tiny.be
|
||||||
|
|
|
@ -21,11 +21,13 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import os, sys, imp
|
import os, sys, imp
|
||||||
|
from os.path import join as opj
|
||||||
import itertools
|
import itertools
|
||||||
from sets import Set
|
from sets import Set
|
||||||
|
|
||||||
import osv
|
import osv
|
||||||
import tools
|
import tools
|
||||||
|
import tools.osutil
|
||||||
import pooler
|
import pooler
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,11 +35,10 @@ import netsvc
|
||||||
from osv import fields
|
from osv import fields
|
||||||
|
|
||||||
import zipfile
|
import zipfile
|
||||||
|
import release
|
||||||
|
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
|
|
||||||
opj = os.path.join
|
|
||||||
|
|
||||||
_ad = os.path.abspath(opj(tools.config['root_path'], 'addons')) # default addons path (base)
|
_ad = os.path.abspath(opj(tools.config['root_path'], 'addons')) # default addons path (base)
|
||||||
ad = os.path.abspath(tools.config['addons_path']) # alternate addons path
|
ad = os.path.abspath(tools.config['addons_path']) # alternate addons path
|
||||||
|
|
||||||
|
@ -137,10 +138,41 @@ def get_module_path(module):
|
||||||
if os.path.exists(opj(_ad, module)) or os.path.exists(opj(_ad, '%s.zip' % module)):
|
if os.path.exists(opj(_ad, module)) or os.path.exists(opj(_ad, '%s.zip' % module)):
|
||||||
return opj(_ad, module)
|
return opj(_ad, module)
|
||||||
|
|
||||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon:%s:module not found' % (module,))
|
logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon %s: module not found' % (module,))
|
||||||
return False
|
return False
|
||||||
raise IOError, 'Module not found : %s' % module
|
raise IOError, 'Module not found : %s' % module
|
||||||
|
|
||||||
|
|
||||||
|
def get_module_filetree(module, dir='.'):
|
||||||
|
path = get_module_path(module)
|
||||||
|
if not path:
|
||||||
|
return False
|
||||||
|
|
||||||
|
dir = os.path.normpath(dir)
|
||||||
|
if dir == '.': dir = ''
|
||||||
|
if dir.startswith('..') or dir[0] == '/':
|
||||||
|
raise Exception('Cannot access file outside the module')
|
||||||
|
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
# zipmodule
|
||||||
|
zip = zipfile.ZipFile(path + ".zip")
|
||||||
|
files = ['/'.join(f.split('/')[1:]) for f in zip.namelist()]
|
||||||
|
else:
|
||||||
|
files = tools.osutil.listdir(path, True)
|
||||||
|
|
||||||
|
tree = {}
|
||||||
|
for f in files:
|
||||||
|
if not f.startswith(dir):
|
||||||
|
continue
|
||||||
|
f = f[len(dir)+int(not dir.endswith('/')):]
|
||||||
|
lst = f.split(os.sep)
|
||||||
|
current = tree
|
||||||
|
while len(lst) != 1:
|
||||||
|
current = current.setdefault(lst.pop(0), {})
|
||||||
|
current[lst.pop(0)] = None
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
def get_module_resource(module, *args):
|
def get_module_resource(module, *args):
|
||||||
"""Return the full path of a resource of the given module.
|
"""Return the full path of a resource of the given module.
|
||||||
|
|
||||||
|
@ -184,7 +216,7 @@ def create_graph(module_list, force=None):
|
||||||
try:
|
try:
|
||||||
info = eval(tools.file_open(terp_file).read())
|
info = eval(tools.file_open(terp_file).read())
|
||||||
except:
|
except:
|
||||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon:%s:eval file %s' % (module, terp_file))
|
logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon %s: eval file %s' % (module, terp_file))
|
||||||
raise
|
raise
|
||||||
if info.get('installable', True):
|
if info.get('installable', True):
|
||||||
packages.append((module, info.get('depends', []), info))
|
packages.append((module, info.get('depends', []), info))
|
||||||
|
@ -192,7 +224,7 @@ def create_graph(module_list, force=None):
|
||||||
dependencies = dict([(p, deps) for p, deps, data in packages])
|
dependencies = dict([(p, deps) for p, deps, data in packages])
|
||||||
current, later = Set([p for p, dep, data in packages]), Set()
|
current, later = Set([p for p, dep, data in packages]), Set()
|
||||||
while packages and current > later:
|
while packages and current > later:
|
||||||
package, deps, datas = packages[0]
|
package, deps, data = packages[0]
|
||||||
|
|
||||||
# if all dependencies of 'package' are already in the graph, add 'package' in the graph
|
# if all dependencies of 'package' are already in the graph, add 'package' in the graph
|
||||||
if reduce(lambda x,y: x and y in graph, deps, True):
|
if reduce(lambda x,y: x and y in graph, deps, True):
|
||||||
|
@ -203,24 +235,24 @@ def create_graph(module_list, force=None):
|
||||||
current.remove(package)
|
current.remove(package)
|
||||||
graph.addNode(package, deps)
|
graph.addNode(package, deps)
|
||||||
node = Node(package, graph)
|
node = Node(package, graph)
|
||||||
node.datas = datas
|
node.data = data
|
||||||
for kind in ('init', 'demo', 'update'):
|
for kind in ('init', 'demo', 'update'):
|
||||||
if package in tools.config[kind] or 'all' in tools.config[kind] or kind in force:
|
if package in tools.config[kind] or 'all' in tools.config[kind] or kind in force:
|
||||||
setattr(node, kind, True)
|
setattr(node, kind, True)
|
||||||
else:
|
else:
|
||||||
later.add(package)
|
later.add(package)
|
||||||
packages.append((package, deps, datas))
|
packages.append((package, deps, data))
|
||||||
packages.pop(0)
|
packages.pop(0)
|
||||||
|
|
||||||
for package in later:
|
for package in later:
|
||||||
unmet_deps = filter(lambda p: p not in graph, dependencies[package])
|
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, 'addon %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps)))
|
||||||
|
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
def init_module_objects(cr, module_name, obj_list):
|
def init_module_objects(cr, module_name, obj_list):
|
||||||
pool = pooler.get_pool(cr.dbname)
|
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, 'addon %s: creating or updating database tables' % module_name)
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
if hasattr(obj, 'init'):
|
if hasattr(obj, 'init'):
|
||||||
obj.init(cr)
|
obj.init(cr)
|
||||||
|
@ -234,12 +266,11 @@ def register_class(m):
|
||||||
global loaded
|
global loaded
|
||||||
if m in loaded:
|
if m in loaded:
|
||||||
return
|
return
|
||||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:registering classes' % m)
|
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: registering classes' % m)
|
||||||
sys.stdout.flush()
|
|
||||||
loaded.append(m)
|
loaded.append(m)
|
||||||
mod_path = get_module_path(m)
|
mod_path = get_module_path(m)
|
||||||
if not os.path.isfile(mod_path+'.zip'):
|
if not os.path.isfile(mod_path+'.zip'):
|
||||||
imp.load_module(m, *imp.find_module(m))
|
imp.load_module(m, *imp.find_module(m, [ad, _ad]))
|
||||||
else:
|
else:
|
||||||
import zipimport
|
import zipimport
|
||||||
try:
|
try:
|
||||||
|
@ -248,14 +279,140 @@ def register_class(m):
|
||||||
except zipimport.ZipImportError:
|
except zipimport.ZipImportError:
|
||||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m)
|
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m)
|
||||||
|
|
||||||
def register_classes():
|
|
||||||
return
|
class MigrationManager(object):
|
||||||
module_list = get_modules()
|
"""
|
||||||
for package in create_graph(module_list):
|
This class manage the migration of modules
|
||||||
m = package.name
|
Migrations files must be python files containing a "migrate(cr, installed_version)" function.
|
||||||
register_class(m)
|
Theses files must respect a directory tree structure: A 'migrations' folder which containt a
|
||||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:registering classes' % m)
|
folder by version. Version can be 'module' version or 'server.module' version (in this case,
|
||||||
sys.stdout.flush()
|
the files will only be processed by this version of the server). Python file names must start
|
||||||
|
by 'pre' or 'post' and will be executed, respectively, before and after the module initialisation
|
||||||
|
Example:
|
||||||
|
|
||||||
|
<moduledir>
|
||||||
|
`-- migrations
|
||||||
|
|-- 1.0
|
||||||
|
| |-- pre-update_table_x.py
|
||||||
|
| |-- pre-update_table_y.py
|
||||||
|
| |-- post-clean-data.py
|
||||||
|
| `-- README.txt # not processed
|
||||||
|
|-- 5.0.1.1 # files in this folder will be executed only on a 5.0 server
|
||||||
|
| |-- pre-delete_table_z.py
|
||||||
|
| `-- post-clean-data.py
|
||||||
|
`-- foo.py # not processed
|
||||||
|
|
||||||
|
This similar structure is generated by the maintenance module with the migrations files get by
|
||||||
|
the maintenance contract
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, cr, graph):
|
||||||
|
self.cr = cr
|
||||||
|
self.graph = graph
|
||||||
|
self.migrations = {}
|
||||||
|
self._get_files()
|
||||||
|
|
||||||
|
def _get_files(self):
|
||||||
|
|
||||||
|
"""
|
||||||
|
import addons.base.maintenance.utils as maintenance_utils
|
||||||
|
maintenance_utils.update_migrations_files(self.cr)
|
||||||
|
#"""
|
||||||
|
|
||||||
|
for pkg in self.graph:
|
||||||
|
self.migrations[pkg.name] = {}
|
||||||
|
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.migrations[pkg.name]['module'] = get_module_filetree(pkg.name, 'migrations') or {}
|
||||||
|
self.migrations[pkg.name]['maintenance'] = get_module_filetree('base', 'maintenance/migrations/' + pkg.name) or {}
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_module(self, pkg, stage):
|
||||||
|
assert stage in ('pre', 'post')
|
||||||
|
stageformat = {'pre': '[>%s]',
|
||||||
|
'post': '[%s>]',
|
||||||
|
}
|
||||||
|
|
||||||
|
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'):
|
||||||
|
return
|
||||||
|
|
||||||
|
def convert_version(version):
|
||||||
|
if version.startswith(release.major_version) and version != release.major_version:
|
||||||
|
return version # the version number already containt the server version
|
||||||
|
return "%s.%s" % (release.major_version, version)
|
||||||
|
|
||||||
|
def _get_migration_versions(pkg):
|
||||||
|
def __get_dir(tree):
|
||||||
|
return [d for d in tree if tree[d] is not None]
|
||||||
|
|
||||||
|
versions = list(set(
|
||||||
|
__get_dir(self.migrations[pkg.name]['module']) +
|
||||||
|
__get_dir(self.migrations[pkg.name]['maintenance'])
|
||||||
|
))
|
||||||
|
versions.sort(key=lambda k: parse_version(convert_version(k)))
|
||||||
|
return versions
|
||||||
|
|
||||||
|
def _get_migration_files(pkg, version, stage):
|
||||||
|
""" return a list of tuple (module, file)
|
||||||
|
"""
|
||||||
|
m = self.migrations[pkg.name]
|
||||||
|
lst = []
|
||||||
|
|
||||||
|
mapping = {'module': {'module': pkg.name, 'rootdir': opj('migrations')},
|
||||||
|
'maintenance': {'module': 'base', 'rootdir': opj('maintenance', 'migrations', pkg.name)},
|
||||||
|
}
|
||||||
|
|
||||||
|
for x in mapping.keys():
|
||||||
|
if version in m[x]:
|
||||||
|
for f in m[x][version]:
|
||||||
|
if m[x][version][f] is not None:
|
||||||
|
continue
|
||||||
|
if not f.startswith(stage + '-'):
|
||||||
|
continue
|
||||||
|
lst.append((mapping[x]['module'], opj(mapping[x]['rootdir'], version, f)))
|
||||||
|
return lst
|
||||||
|
|
||||||
|
def mergedict(a,b):
|
||||||
|
a = a.copy()
|
||||||
|
a.update(b)
|
||||||
|
return a
|
||||||
|
|
||||||
|
from tools.parse_version import parse_version
|
||||||
|
|
||||||
|
parsed_installed_version = parse_version(pkg.latest_version)
|
||||||
|
current_version = parse_version(convert_version(pkg.data.get('version', '0')))
|
||||||
|
|
||||||
|
versions = _get_migration_versions(pkg)
|
||||||
|
|
||||||
|
for version in versions:
|
||||||
|
if parsed_installed_version < parse_version(convert_version(version)) <= current_version:
|
||||||
|
|
||||||
|
strfmt = {'addon': pkg.name,
|
||||||
|
'stage': stage,
|
||||||
|
'version': stageformat[stage] % version,
|
||||||
|
}
|
||||||
|
|
||||||
|
for modulename, pyfile in _get_migration_files(pkg, version, stage):
|
||||||
|
name, ext = os.path.splitext(os.path.basename(pyfile))
|
||||||
|
if ext.lower() != '.py':
|
||||||
|
continue
|
||||||
|
fp = tools.file_open(opj(modulename, pyfile))
|
||||||
|
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)
|
||||||
|
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))
|
||||||
|
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)
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
fp.close()
|
||||||
|
del mod
|
||||||
|
|
||||||
|
|
||||||
def load_module_graph(cr, graph, status=None, **kwargs):
|
def load_module_graph(cr, graph, status=None, **kwargs):
|
||||||
# **kwargs is passed directly to convert_xml_import
|
# **kwargs is passed directly to convert_xml_import
|
||||||
|
@ -265,67 +422,94 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
||||||
status = status.copy()
|
status = status.copy()
|
||||||
package_todo = []
|
package_todo = []
|
||||||
statusi = 0
|
statusi = 0
|
||||||
|
pool = pooler.get_pool(cr.dbname)
|
||||||
|
|
||||||
|
|
||||||
|
# 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})
|
||||||
|
## Then we get the values from the database
|
||||||
|
cr.execute('SELECT name, id, state, demo AS dbdemo, latest_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()]))
|
||||||
|
|
||||||
|
for package in graph:
|
||||||
|
for k, v in additional_data[package.name].items():
|
||||||
|
setattr(package, k, v)
|
||||||
|
|
||||||
|
migrations = MigrationManager(cr, graph)
|
||||||
|
|
||||||
for package in graph:
|
for package in graph:
|
||||||
status['progress'] = (float(statusi)+0.1)/len(graph)
|
status['progress'] = (float(statusi)+0.1)/len(graph)
|
||||||
m = package.name
|
m = package.name
|
||||||
|
mid = package.id
|
||||||
|
|
||||||
|
migrations.migrate_module(package, 'pre')
|
||||||
|
|
||||||
register_class(m)
|
register_class(m)
|
||||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s' % m)
|
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s' % m)
|
||||||
sys.stdout.flush()
|
|
||||||
pool = pooler.get_pool(cr.dbname)
|
|
||||||
modules = pool.instanciate(m, cr)
|
modules = pool.instanciate(m, cr)
|
||||||
|
|
||||||
cr.execute('select id from ir_module_module where name=%s', (m,))
|
|
||||||
mid = int(cr.rowcount and cr.fetchone()[0] or 0)
|
|
||||||
|
|
||||||
cr.execute('select state, demo from ir_module_module where id=%d', (mid,))
|
|
||||||
(package_state, package_demo) = (cr.rowcount and cr.fetchone()) or ('uninstalled', False)
|
|
||||||
idref = {}
|
idref = {}
|
||||||
status['progress'] = (float(statusi)+0.4)/len(graph)
|
status['progress'] = (float(statusi)+0.4)/len(graph)
|
||||||
if hasattr(package, 'init') or hasattr(package, 'update') or package_state in ('to install', 'to upgrade'):
|
if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'):
|
||||||
init_module_objects(cr, m, modules)
|
init_module_objects(cr, m, modules)
|
||||||
for kind in ('init', 'update'):
|
for kind in ('init', 'update'):
|
||||||
for filename in package.datas.get('%s_xml' % kind, []):
|
for filename in package.data.get('%s_xml' % kind, []):
|
||||||
mode = 'update'
|
mode = 'update'
|
||||||
if hasattr(package, 'init') or package_state=='to install':
|
if hasattr(package, 'init') or package.state=='to install':
|
||||||
mode = 'init'
|
mode = 'init'
|
||||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:loading %s' % (m, filename))
|
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon %s: loading %s' % (m, filename))
|
||||||
name, ext = os.path.splitext(filename)
|
name, ext = os.path.splitext(filename)
|
||||||
|
fp = tools.file_open(opj(m, filename))
|
||||||
if ext == '.csv':
|
if ext == '.csv':
|
||||||
tools.convert_csv_import(cr, m, os.path.basename(filename), tools.file_open(opj(m, filename)).read(), idref, mode=mode)
|
tools.convert_csv_import(cr, m, os.path.basename(filename), fp.read(), idref, mode=mode)
|
||||||
elif ext == '.sql':
|
elif ext == '.sql':
|
||||||
queries = tools.file_open(opj(m, filename)).read().split(';')
|
queries = fp.read().split(';')
|
||||||
for query in queries:
|
for query in queries:
|
||||||
new_query = ' '.join(query.split())
|
new_query = ' '.join(query.split())
|
||||||
if new_query:
|
if new_query:
|
||||||
cr.execute(new_query)
|
cr.execute(new_query)
|
||||||
else:
|
else:
|
||||||
tools.convert_xml_import(cr, m, tools.file_open(opj(m, filename)), idref, mode=mode, **kwargs)
|
tools.convert_xml_import(cr, m, fp, idref, mode=mode, **kwargs)
|
||||||
if hasattr(package, 'demo') or (package_demo and package_state != 'installed'):
|
fp.close()
|
||||||
|
if hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed'):
|
||||||
status['progress'] = (float(statusi)+0.75)/len(graph)
|
status['progress'] = (float(statusi)+0.75)/len(graph)
|
||||||
for xml in package.datas.get('demo_xml', []):
|
for xml in package.data.get('demo_xml', []):
|
||||||
name, ext = os.path.splitext(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, 'addon %s: loading %s' % (m, xml))
|
||||||
|
fp = tools.file_open(opj(m, xml))
|
||||||
if ext == '.csv':
|
if ext == '.csv':
|
||||||
tools.convert_csv_import(cr, m, os.path.basename(xml), tools.file_open(opj(m, xml)).read(), idref, noupdate=True)
|
tools.convert_csv_import(cr, m, os.path.basename(xml), fp.read(), idref, noupdate=True)
|
||||||
else:
|
else:
|
||||||
tools.convert_xml_import(cr, m, tools.file_open(opj(m, xml)), idref, noupdate=True, **kwargs)
|
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=%d', (True, mid))
|
||||||
package_todo.append(package.name)
|
package_todo.append(package.name)
|
||||||
cr.execute("update ir_module_module set state='installed' where state in ('to upgrade', 'to install') and id=%d", (mid,))
|
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,))
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
# Update translations for all installed languages
|
# Set new modules and dependencies
|
||||||
modobj = pool.get('ir.module.module')
|
modobj = pool.get('ir.module.module')
|
||||||
|
|
||||||
|
# Update translations for all installed languages
|
||||||
if modobj:
|
if modobj:
|
||||||
modobj.update_translations(cr, 1, [mid], None)
|
modobj.update_translations(cr, 1, [mid], None)
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
|
|
||||||
|
migrations.migrate_module(package, 'post')
|
||||||
|
|
||||||
statusi+=1
|
statusi+=1
|
||||||
|
|
||||||
cr.execute("""select model,name from ir_model where id not in (select model_id from ir_model_access)""")
|
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():
|
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, 'addon object %s (%s) has no access rules!' % (model,name))
|
||||||
|
|
||||||
pool = pooler.get_pool(cr.dbname)
|
pool = pooler.get_pool(cr.dbname)
|
||||||
cr.execute('select * from ir_model where state=%s', ('manual',))
|
cr.execute('select * from ir_model where state=%s', ('manual',))
|
||||||
|
@ -342,10 +526,23 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
||||||
force = []
|
force = []
|
||||||
if force_demo:
|
if force_demo:
|
||||||
force.append('demo')
|
force.append('demo')
|
||||||
|
pool = pooler.get_pool(cr.dbname)
|
||||||
if update_module:
|
if update_module:
|
||||||
for module in tools.config['init']:
|
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.execute('update ir_module_module set state=%s where state=%s and name=%s', ('to install', 'uninstalled', module))
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
|
register_class('base')
|
||||||
|
pool.instanciate('base', cr)
|
||||||
|
modobj = pool.get('ir.module.module')
|
||||||
|
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])
|
||||||
|
|
||||||
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade','to remove')")
|
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade','to remove')")
|
||||||
else:
|
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', 'to remove')")
|
||||||
|
@ -354,7 +551,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
||||||
report = tools.assertion_report()
|
report = tools.assertion_report()
|
||||||
load_module_graph(cr, graph, status, report=report)
|
load_module_graph(cr, graph, status, report=report)
|
||||||
if report.get_report():
|
if report.get_report():
|
||||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'assert:%s' % report)
|
logger.notifyChannel('init', netsvc.LOG_INFO, 'assert: %s' % report)
|
||||||
|
|
||||||
for kind in ('init', 'demo', 'update'):
|
for kind in ('init', 'demo', 'update'):
|
||||||
tools.config[kind]={}
|
tools.config[kind]={}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
import ir
|
import ir
|
||||||
import module
|
import module
|
||||||
import res
|
import res
|
||||||
|
import maintenance
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
"base_menu.xml",
|
"base_menu.xml",
|
||||||
"security/base_security.xml",
|
"security/base_security.xml",
|
||||||
"res/res_security.xml",
|
"res/res_security.xml",
|
||||||
|
"maintenance/maintenance_security.xml",
|
||||||
],
|
],
|
||||||
"demo_xml" : [
|
"demo_xml" : [
|
||||||
"base_demo.xml",
|
"base_demo.xml",
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
"res/partner/partner_data.xml",
|
"res/partner/partner_data.xml",
|
||||||
"res/ir_property_view.xml",
|
"res/ir_property_view.xml",
|
||||||
"security/base_security.xml",
|
"security/base_security.xml",
|
||||||
|
"maintenance/maintenance_view.xml",
|
||||||
"security/ir.model.access.csv",
|
"security/ir.model.access.csv",
|
||||||
],
|
],
|
||||||
"active": True,
|
"active": True,
|
||||||
|
|
|
@ -27,6 +27,7 @@ CREATE TABLE ir_model (
|
||||||
id serial,
|
id serial,
|
||||||
model varchar(64) DEFAULT ''::varchar NOT NULL,
|
model varchar(64) DEFAULT ''::varchar NOT NULL,
|
||||||
name varchar(64),
|
name varchar(64),
|
||||||
|
state varchar(16),
|
||||||
info text,
|
info text,
|
||||||
primary key(id)
|
primary key(id)
|
||||||
);
|
);
|
||||||
|
@ -196,7 +197,7 @@ create table wkf_activity
|
||||||
signal_send varchar(32) default null,
|
signal_send varchar(32) default null,
|
||||||
flow_start boolean default False,
|
flow_start boolean default False,
|
||||||
flow_stop boolean default False,
|
flow_stop boolean default False,
|
||||||
action varchar(64) default null,
|
action text default null,
|
||||||
primary key(id)
|
primary key(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -505,8 +505,8 @@
|
||||||
<form string="Attachments">
|
<form string="Attachments">
|
||||||
<group colspan="4" col="6">
|
<group colspan="4" col="6">
|
||||||
<field name="name" select="1" />
|
<field name="name" select="1" />
|
||||||
<field name="create_uid" select="1"/>
|
<field name="create_uid" select="2"/>
|
||||||
<field name="create_date" select="1"/>
|
<field name="create_date" select="2"/>
|
||||||
</group>
|
</group>
|
||||||
<notebook colspan="4">
|
<notebook colspan="4">
|
||||||
<page string="Attachment">
|
<page string="Attachment">
|
||||||
|
@ -517,7 +517,7 @@
|
||||||
</group>
|
</group>
|
||||||
<group col="2" colspan="2">
|
<group col="2" colspan="2">
|
||||||
<separator string="Attached To" colspan="2"/>
|
<separator string="Attached To" colspan="2"/>
|
||||||
<field name="res_model" select="1"/>
|
<field name="res_model" select="2"/>
|
||||||
<field name="res_id"/>
|
<field name="res_id"/>
|
||||||
</group>
|
</group>
|
||||||
<separator string="Preview" colspan="4"/>
|
<separator string="Preview" colspan="4"/>
|
||||||
|
@ -1155,19 +1155,23 @@
|
||||||
<field name="trigger_name" select="2"/>
|
<field name="trigger_name" select="2"/>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
<page string="Email / SMS" attrs="{'invisible':[('state','=','python'),('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','client_action'), ('state','=','other')]}">
|
<page string="Action to Launch" attrs="{'invisible':[('state','!=','client_action')]}">
|
||||||
<separator colspan="4" string="Email Configuration"/>
|
<field name="action_id" select="2" colspan="4"/>
|
||||||
<field name="address" domain="[('model_id','=',model_id)]"/>
|
|
||||||
<field name="sms" colspan="4" attrs="{'readonly':[('state','=','python'), ('state','=','email'), ('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','client_action'), ('state','=','other')]}"/>
|
|
||||||
<field name="message" select="2" colspan="4" attrs="{'readonly':[('state','=','python'), ('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','sms'), ('state','=','client_action'), ('state','=','other')]}" />
|
|
||||||
<newline/>
|
|
||||||
<label colspan="4" string="Access all the fields related to the current object easily just by defining name of the attribute, i.e. [[partner_id.name]] for Invoice Object"/>
|
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
<page string="Create / Write" attrs="{'invisible':[('state','=','python'),('state','=','dummy'),('state','=','trigger'), ('state','=','sms'), ('state','=','email'), ('state','=','client_action'), ('state','=','other')]}">
|
<page string="Email / SMS" attrs="{'invisible':[('state','!=','sms'),('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')]}" />
|
||||||
|
<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"/>
|
<separator colspan="4" string="Fields Mapping"/>
|
||||||
<field name="otype"/>
|
<field name="otype"/>
|
||||||
<field name="srcmodel_id" select="2" attrs="{'readonly':[('type','=','copy'),('state','=','write_create')]}"/>
|
<field name="srcmodel_id" select="2"/>
|
||||||
<field name="fields_lines" nolabel="1" select="2" colspan="4">
|
<field name="fields_lines" nolabel="1" select="2" colspan="4">
|
||||||
<tree string="Field Mappings" editable="top">
|
<tree string="Field Mappings" editable="top">
|
||||||
<field name="col1" domain="[('model_id','=',parent.srcmodel_id or parent.model_id)]"/>
|
<field name="col1" domain="[('model_id','=',parent.srcmodel_id or parent.model_id)]"/>
|
||||||
|
@ -1180,6 +1184,7 @@
|
||||||
<field name="value" colsapan="4"/>
|
<field name="value" colsapan="4"/>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
<label colspan="4" string="If you use a formula type, use a python expression using the variable 'object'." align="0.0"/>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
<page string="Other Actions" attrs="{'invisible':[('state','!=','other')]}">
|
<page string="Other Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||||
|
@ -1290,7 +1295,7 @@
|
||||||
<separator colspan="4" string=""/>
|
<separator colspan="4" string=""/>
|
||||||
<label string="" colspan="2"/>
|
<label string="" colspan="2"/>
|
||||||
<group colspan="2" col="2">
|
<group colspan="2" col="2">
|
||||||
<button icon="gtk-cancel" special="cancel" string="Skip Step"/>
|
<button icon="gtk-cancel" name="button_skip" string="Skip Step" type="object"/>
|
||||||
<button icon="gtk-go-forward" name="button_continue" string="Continue" type="object"/>
|
<button icon="gtk-go-forward" name="button_continue" string="Continue" type="object"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
|
@ -287,7 +287,7 @@ class ir_model_fields(osv.osv):
|
||||||
_inherit = 'ir.model.fields'
|
_inherit = 'ir.model.fields'
|
||||||
_rec_name = 'field_description'
|
_rec_name = 'field_description'
|
||||||
_columns = {
|
_columns = {
|
||||||
'complete_name': fields.char('Complete Name', required=True, size=64, select=1),
|
'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=80):
|
||||||
|
@ -371,6 +371,7 @@ class actions_server(osv.osv):
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Action Name', required=True, size=64),
|
'name': fields.char('Action Name', required=True, size=64),
|
||||||
'state': fields.selection([
|
'state': fields.selection([
|
||||||
|
('client_action','Client Action'),
|
||||||
('python','Python Code'),
|
('python','Python Code'),
|
||||||
('dummy','Dummy'),
|
('dummy','Dummy'),
|
||||||
('trigger','Trigger'),
|
('trigger','Trigger'),
|
||||||
|
@ -378,12 +379,12 @@ class actions_server(osv.osv):
|
||||||
('sms','SMS'),
|
('sms','SMS'),
|
||||||
('object_create','Create Object'),
|
('object_create','Create Object'),
|
||||||
('object_write','Write Object'),
|
('object_write','Write Object'),
|
||||||
('client_action','Client Action'),
|
|
||||||
('other','Others Actions'),
|
('other','Others Actions'),
|
||||||
], 'Action State', required=True, size=32, change_default=True),
|
], 'Action State', required=True, size=32),
|
||||||
'code': fields.text('Python Code'),
|
'code': fields.text('Python Code'),
|
||||||
'sequence': fields.integer('Sequence'),
|
'sequence': fields.integer('Sequence'),
|
||||||
'model_id': fields.many2one('ir.model', 'Object', required=True),
|
'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_name': fields.char('Trigger Name', size=128),
|
||||||
'trigger_obj_id': fields.reference('Trigger On', selection=model_get, size=128),
|
'trigger_obj_id': fields.reference('Trigger On', selection=model_get, size=128),
|
||||||
'message': fields.text('Message', translate=True),
|
'message': fields.text('Message', translate=True),
|
||||||
|
@ -438,26 +439,12 @@ class actions_server(osv.osv):
|
||||||
def merge_message(self, cr, uid, keystr, action, context):
|
def merge_message(self, cr, uid, keystr, action, context):
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
def merge(match):
|
def merge(match):
|
||||||
|
|
||||||
obj_pool = self.pool.get(action.model_id.model)
|
obj_pool = self.pool.get(action.model_id.model)
|
||||||
id = context.get('active_id')
|
id = context.get('active_id')
|
||||||
obj = obj_pool.browse(cr, uid, id)
|
obj = obj_pool.browse(cr, uid, id)
|
||||||
|
return eval(match[2:-2], {'object':obj, 'context': context,'time':time})
|
||||||
|
|
||||||
field = match.group()
|
com = re.compile('(\[\[.+?\]\])')
|
||||||
field = field.replace('[','')
|
|
||||||
field = field.replace(']','')
|
|
||||||
field = field.strip()
|
|
||||||
|
|
||||||
fields = field.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()))
|
|
||||||
|
|
||||||
return str(obj)
|
|
||||||
|
|
||||||
com = re.compile('\[\[(.+?)\]\]')
|
|
||||||
message = com.sub(merge, keystr)
|
message = com.sub(merge, keystr)
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
@ -471,6 +458,10 @@ class actions_server(osv.osv):
|
||||||
def run(self, cr, uid, ids, context={}):
|
def run(self, cr, uid, ids, context={}):
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
for action in self.browse(cr, uid, ids, context):
|
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':
|
if action.state=='python':
|
||||||
localdict = {
|
localdict = {
|
||||||
'self': self.pool.get(action.model_id.model),
|
'self': self.pool.get(action.model_id.model),
|
||||||
|
@ -490,9 +481,7 @@ class actions_server(osv.osv):
|
||||||
address = self.get_field_value(cr, uid, action, context)
|
address = self.get_field_value(cr, uid, action, context)
|
||||||
if not address:
|
if not address:
|
||||||
raise osv.except_osv(_('Error'), _("Please specify the Partner Email address !"))
|
raise osv.except_osv(_('Error'), _("Please specify the Partner Email address !"))
|
||||||
|
|
||||||
body = self.merge_message(cr, uid, str(action.message), action, context)
|
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_attach(user, address, subject, body, debug=False) == True:
|
||||||
logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address))
|
logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address))
|
||||||
else:
|
else:
|
||||||
|
@ -537,8 +526,9 @@ class actions_server(osv.osv):
|
||||||
for exp in action.fields_lines:
|
for exp in action.fields_lines:
|
||||||
euq = exp.value
|
euq = exp.value
|
||||||
if exp.type == 'equation':
|
if exp.type == 'equation':
|
||||||
expr = self.merge_message(cr, uid, euq, action, context)
|
obj_pool = self.pool.get(action.model_id.model)
|
||||||
expr = eval(expr)
|
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
|
||||||
|
expr = eval(euq, {'context':context, 'object': obj})
|
||||||
else:
|
else:
|
||||||
expr = exp.value
|
expr = exp.value
|
||||||
res[exp.col1.name] = expr
|
res[exp.col1.name] = expr
|
||||||
|
@ -550,8 +540,9 @@ class actions_server(osv.osv):
|
||||||
for exp in action.fields_lines:
|
for exp in action.fields_lines:
|
||||||
euq = exp.value
|
euq = exp.value
|
||||||
if exp.type == 'equation':
|
if exp.type == 'equation':
|
||||||
expr = self.merge_message(cr, uid, euq, action, context)
|
obj_pool = self.pool.get(action.model_id.model)
|
||||||
expr = eval(expr)
|
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
|
||||||
|
expr = eval(euq, {'context':context, 'object': obj})
|
||||||
else:
|
else:
|
||||||
expr = exp.value
|
expr = exp.value
|
||||||
res[exp.col1.name] = expr
|
res[exp.col1.name] = expr
|
||||||
|
@ -591,7 +582,7 @@ class ir_actions_todo(osv.osv):
|
||||||
_name = 'ir.actions.todo'
|
_name = 'ir.actions.todo'
|
||||||
_columns={
|
_columns={
|
||||||
'name':fields.char('Name',size=64,required=True, select=True),
|
'name':fields.char('Name',size=64,required=True, select=True),
|
||||||
'note':fields.text('Text'),
|
'note':fields.text('Text', translate=True),
|
||||||
'start_date': fields.datetime('Start Date'),
|
'start_date': fields.datetime('Start Date'),
|
||||||
'end_date': fields.datetime('End Date'),
|
'end_date': fields.datetime('End Date'),
|
||||||
'action_id':fields.many2one('ir.actions.act_window', 'Action', select=True,required=True, ondelete='cascade'),
|
'action_id':fields.many2one('ir.actions.act_window', 'Action', select=True,required=True, ondelete='cascade'),
|
||||||
|
@ -651,6 +642,21 @@ class ir_actions_configuration_wizard(osv.osv_memory):
|
||||||
'item_id':_get_action,
|
'item_id':_get_action,
|
||||||
'name':_get_action_name,
|
'name':_get_action_name,
|
||||||
}
|
}
|
||||||
|
def button_next(self,cr,uid,ids,context=None):
|
||||||
|
user_action=self.pool.get('res.users').browse(cr,uid,uid)
|
||||||
|
act_obj=self.pool.get(user_action.menu_id.type)
|
||||||
|
action_ids=act_obj.search(cr,uid,[('name','=',user_action.menu_id.name)])
|
||||||
|
action_open=act_obj.browse(cr,uid,action_ids)[0]
|
||||||
|
if context.get('menu',False):
|
||||||
|
return{
|
||||||
|
'view_type': action_open.view_type,
|
||||||
|
'view_id':action_open.view_id and [action_open.view_id.id] or False,
|
||||||
|
'res_model': action_open.res_model,
|
||||||
|
'type': action_open.type,
|
||||||
|
'domain':action_open.domain
|
||||||
|
}
|
||||||
|
return {'type':'ir.actions.act_window_close'}
|
||||||
|
|
||||||
def button_skip(self,cr,uid,ids,context=None):
|
def button_skip(self,cr,uid,ids,context=None):
|
||||||
item_obj = self.pool.get('ir.actions.todo')
|
item_obj = self.pool.get('ir.actions.todo')
|
||||||
item_id=self.read(cr,uid,ids)[0]['item_id']
|
item_id=self.read(cr,uid,ids)[0]['item_id']
|
||||||
|
@ -666,7 +672,7 @@ class ir_actions_configuration_wizard(osv.osv_memory):
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'target':'new',
|
'target':'new',
|
||||||
}
|
}
|
||||||
return {'type':'ir.actions.act_window_close'}
|
return self.button_next(cr, uid, ids, context)
|
||||||
|
|
||||||
def button_continue(self, cr, uid, ids, context=None):
|
def button_continue(self, cr, uid, ids, context=None):
|
||||||
item_obj = self.pool.get('ir.actions.todo')
|
item_obj = self.pool.get('ir.actions.todo')
|
||||||
|
@ -684,19 +690,7 @@ class ir_actions_configuration_wizard(osv.osv_memory):
|
||||||
'type': item.action_id.type,
|
'type': item.action_id.type,
|
||||||
'target':item.action_id.target,
|
'target':item.action_id.target,
|
||||||
}
|
}
|
||||||
user_action=self.pool.get('res.users').browse(cr,uid,uid)
|
return self.button_next(cr, uid, ids, context)
|
||||||
act_obj=self.pool.get(user_action.menu_id.type)
|
|
||||||
action_ids=act_obj.search(cr,uid,[('name','=',user_action.menu_id.name)])
|
|
||||||
action_open=act_obj.browse(cr,uid,action_ids)[0]
|
|
||||||
if context.get('menu',False):
|
|
||||||
return{
|
|
||||||
'view_type': action_open.view_type,
|
|
||||||
'view_id':action_open.view_id and [action_open.view_id.id] or False,
|
|
||||||
'res_model': action_open.res_model,
|
|
||||||
'type': action_open.type,
|
|
||||||
'domain':action_open.domain
|
|
||||||
}
|
|
||||||
return {'type':'ir.actions.act_window_close' }
|
|
||||||
ir_actions_configuration_wizard()
|
ir_actions_configuration_wizard()
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -52,12 +52,11 @@ class ir_attachment(osv.osv):
|
||||||
cache = {}
|
cache = {}
|
||||||
ima = self.pool.get('ir.model.access')
|
ima = self.pool.get('ir.model.access')
|
||||||
for m in models:
|
for m in models:
|
||||||
if m['res_model'] in cache:
|
if m['res_model'] not in cache:
|
||||||
if not cache[m['res_model']]:
|
cache[m['res_model']] = ima.check(cr, uid, m['res_model'], 'read',
|
||||||
ids.remove(m['id'])
|
raise_exception=False)
|
||||||
continue
|
if not cache[m['res_model']]:
|
||||||
cache[m['res_model']] = ima.check(cr, uid, m['res_model'], 'read',
|
ids.remove(m['id'])
|
||||||
raise_exception=False)
|
|
||||||
|
|
||||||
if count:
|
if count:
|
||||||
return len(ids)
|
return len(ids)
|
||||||
|
|
|
@ -27,6 +27,7 @@ from osv.orm import except_orm, browse_record
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import tools
|
import tools
|
||||||
|
from tools import config
|
||||||
import pooler
|
import pooler
|
||||||
|
|
||||||
def _get_fields_type(self, cr, uid, context=None):
|
def _get_fields_type(self, cr, uid, context=None):
|
||||||
|
@ -74,7 +75,10 @@ class ir_model(osv.osv):
|
||||||
vals['state']='manual'
|
vals['state']='manual'
|
||||||
res = super(ir_model,self).create(cr, user, vals, context)
|
res = super(ir_model,self).create(cr, user, vals, context)
|
||||||
if vals.get('state','base')=='manual':
|
if vals.get('state','base')=='manual':
|
||||||
pooler.restart_pool(cr.dbname)
|
self.instanciate(cr, user, vals['model'], context)
|
||||||
|
self.pool.get(vals['model']).__init__(self.pool, cr)
|
||||||
|
self.pool.get(vals['model'])._auto_init(cr,{})
|
||||||
|
#pooler.restart_pool(cr.dbname)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def instanciate(self, cr, user, model, context={}):
|
def instanciate(self, cr, user, model, context={}):
|
||||||
|
@ -83,10 +87,7 @@ class ir_model(osv.osv):
|
||||||
x_custom_model._name = model
|
x_custom_model._name = model
|
||||||
x_custom_model._module = False
|
x_custom_model._module = False
|
||||||
x_custom_model.createInstance(self.pool, '', cr)
|
x_custom_model.createInstance(self.pool, '', cr)
|
||||||
if 'x_name' in x_custom_model._columns:
|
x_custom_model._rec_name = 'x_name'
|
||||||
x_custom_model._rec_name = 'x_name'
|
|
||||||
else:
|
|
||||||
x_custom_model._rec_name = x_custom_model._columns.keys()[0]
|
|
||||||
ir_model()
|
ir_model()
|
||||||
|
|
||||||
|
|
||||||
|
@ -561,18 +562,19 @@ class ir_model_data(osv.osv):
|
||||||
wf_service.trg_write(uid, model, id, cr)
|
wf_service.trg_write(uid, model, id, cr)
|
||||||
|
|
||||||
cr.commit()
|
cr.commit()
|
||||||
for (model,id) in self.unlink_mark.keys():
|
if not config.get('import_partial', False):
|
||||||
if self.pool.get(model):
|
for (model,id) in self.unlink_mark.keys():
|
||||||
logger = netsvc.Logger()
|
if self.pool.get(model):
|
||||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (id, model))
|
logger = netsvc.Logger()
|
||||||
try:
|
logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (id, model))
|
||||||
self.pool.get(model).unlink(cr, uid, [id])
|
try:
|
||||||
if self.unlink_mark[(model,id)]:
|
self.pool.get(model).unlink(cr, uid, [id])
|
||||||
self.unlink(cr, uid, [self.unlink_mark[(model,id)]])
|
if self.unlink_mark[(model,id)]:
|
||||||
cr.execute('DELETE FROM ir_values WHERE value=%s', (model+','+str(id),))
|
self.unlink(cr, uid, [self.unlink_mark[(model,id)]])
|
||||||
cr.commit()
|
cr.execute('DELETE FROM ir_values WHERE value=%s', (model+','+str(id),))
|
||||||
except:
|
cr.commit()
|
||||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\tThere should be some relation that points to this resource\tYou should manually fix this and restart --update=module' % (id, model))
|
except:
|
||||||
|
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\tThere should be some relation that points to this resource\tYou should manually fix this and restart --update=module' % (id, model))
|
||||||
return True
|
return True
|
||||||
ir_model_data()
|
ir_model_data()
|
||||||
|
|
||||||
|
|
|
@ -166,14 +166,19 @@ class ir_values(osv.osv):
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
ok = True
|
ok = True
|
||||||
|
result_ids = {}
|
||||||
while ok:
|
while ok:
|
||||||
if not where_opt:
|
if not where_opt:
|
||||||
cr.execute('select id from ir_values where ' +\
|
cr.execute('select id,name,value,object,meta, key from ir_values where ' +\
|
||||||
' and '.join(where1)+' and user_id is null', where2)
|
' and '.join(where1)+' and user_id is null', where2)
|
||||||
else:
|
else:
|
||||||
cr.execute('select id from ir_values where ' +\
|
cr.execute('select id,name,value,object,meta, key from ir_values where ' +\
|
||||||
' and '.join(where1+where_opt), where2)
|
' and '.join(where1+where_opt), where2)
|
||||||
result.extend([x[0] for x in cr.fetchall()])
|
for rec in cr.fetchall():
|
||||||
|
if rec[0] in result_ids:
|
||||||
|
continue
|
||||||
|
result.append(rec)
|
||||||
|
result_ids[rec[0]] = True
|
||||||
if len(where_opt):
|
if len(where_opt):
|
||||||
where_opt.pop()
|
where_opt.pop()
|
||||||
else:
|
else:
|
||||||
|
@ -184,13 +189,6 @@ class ir_values(osv.osv):
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
return []
|
return []
|
||||||
cid = self.pool.get('res.users').browse(cr, uid, uid, context={}).company_id.id
|
|
||||||
cr.execute('select id,name,value,object,meta, key ' \
|
|
||||||
'from ir_values ' \
|
|
||||||
'where id in ('+','.join(map(str,result))+') ' \
|
|
||||||
'and (company_id is null or company_id = %d) '\
|
|
||||||
'ORDER BY user_id', (cid,))
|
|
||||||
result = cr.fetchall()
|
|
||||||
|
|
||||||
def _result_get(x, keys):
|
def _result_get(x, keys):
|
||||||
if x[1] in keys:
|
if x[1] in keys:
|
||||||
|
@ -199,18 +197,19 @@ class ir_values(osv.osv):
|
||||||
if x[3]:
|
if x[3]:
|
||||||
model,id = x[2].split(',')
|
model,id = x[2].split(',')
|
||||||
id = int(id)
|
id = int(id)
|
||||||
datas = self.pool.get(model).read(cr, uid, id, False, context)
|
fields = self.pool.get(model).fields_get_keys(cr, uid)
|
||||||
|
pos = 0
|
||||||
|
while pos<len(fields):
|
||||||
|
if fields[pos] in ('report_sxw_content', 'report_rml_content',
|
||||||
|
'report_sxw', 'report_rml', 'report_sxw_content_data',
|
||||||
|
'report_rml_content_data'):
|
||||||
|
del fields[pos]
|
||||||
|
else:
|
||||||
|
pos+=1
|
||||||
|
datas = self.pool.get(model).read(cr, uid, [id], fields, context)[0]
|
||||||
if not datas:
|
if not datas:
|
||||||
#ir_del(cr, uid, x[0])
|
#ir_del(cr, uid, x[0])
|
||||||
return False
|
return False
|
||||||
def clean(x):
|
|
||||||
for key in ('report_sxw_content', 'report_rml_content',
|
|
||||||
'report_sxw', 'report_rml', 'report_sxw_content_data',
|
|
||||||
'report_rml_content_data'):
|
|
||||||
if key in x:
|
|
||||||
del x[key]
|
|
||||||
return x
|
|
||||||
datas = clean(datas)
|
|
||||||
else:
|
else:
|
||||||
datas = pickle.loads(x[2])
|
datas = pickle.loads(x[2])
|
||||||
if meta:
|
if meta:
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
</field>
|
</field>
|
||||||
<label colspan="2" string=""/>
|
<label colspan="2" string=""/>
|
||||||
<group col="2" colspan="2">
|
<group col="2" colspan="2">
|
||||||
<button special="cancel" string="Cancel"/>
|
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
|
||||||
<button name="menu_create" string="Create Menu" type="object"/>
|
<button name="menu_create" string="Create Menu" type="object" icon="gtk-ok"/>
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
|
|
@ -38,7 +38,7 @@ def graph_get(cr, graph, wkf_id, nested=False, workitem={}):
|
||||||
if n['subflow_id'] and nested:
|
if n['subflow_id'] and nested:
|
||||||
cr.execute('select * from wkf where id=%d', (n['subflow_id'],))
|
cr.execute('select * from wkf where id=%d', (n['subflow_id'],))
|
||||||
wkfinfo = cr.dictfetchone()
|
wkfinfo = cr.dictfetchone()
|
||||||
graph2 = pydot.Cluster('subflow'+str(n['subflow_id']), fontsize='12', label = "Subflow: "+n['name']+'\\nOSV: '+wkfinfo['osv'])
|
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)
|
(s1,s2) = graph_get(cr, graph2, n['subflow_id'], nested,workitem)
|
||||||
graph.add_subgraph(graph2)
|
graph.add_subgraph(graph2)
|
||||||
actfrom[n['id']] = s2
|
actfrom[n['id']] = s2
|
||||||
|
@ -143,12 +143,9 @@ showpage'''
|
||||||
showpage'''
|
showpage'''
|
||||||
else:
|
else:
|
||||||
inst_id = inst_id[0]
|
inst_id = inst_id[0]
|
||||||
graph = pydot.Dot(fontsize='16', label="""\\\n\\nWorkflow: %s\\n OSV: %s""" % (wkfinfo['name'],wkfinfo['osv']))
|
graph = pydot.Dot(fontsize='16', label="""\\\n\\nWorkflow: %s\\n OSV: %s""" % (wkfinfo['name'],wkfinfo['osv']),
|
||||||
graph.set('size', '10.7,7.3')
|
size='10.7, 7.3', center='1', ratio='auto', rotate='90', rankdir='LR'
|
||||||
graph.set('center', '1')
|
)
|
||||||
graph.set('ratio', 'auto')
|
|
||||||
graph.set('rotate', '90')
|
|
||||||
graph.set('rankdir', 'LR')
|
|
||||||
graph_instance_get(cr, graph, inst_id, data.get('nested', False))
|
graph_instance_get(cr, graph, inst_id, data.get('nested', False))
|
||||||
ps_string = graph.create(prog='dot', format='ps')
|
ps_string = graph.create(prog='dot', format='ps')
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
@ -27,7 +27,7 @@ import netsvc
|
||||||
class workflow(osv.osv):
|
class workflow(osv.osv):
|
||||||
_name = "workflow"
|
_name = "workflow"
|
||||||
_table = "wkf"
|
_table = "wkf"
|
||||||
_log_access = False
|
# _log_access = False
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Name', size=64, required=True),
|
'name': fields.char('Name', size=64, required=True),
|
||||||
'osv': fields.char('Resource Object', size=64, required=True,select=True),
|
'osv': fields.char('Resource Object', size=64, required=True,select=True),
|
||||||
|
@ -49,7 +49,7 @@ class workflow(osv.osv):
|
||||||
# scale = (vertical-distance, horizontal-distance, min-node-width(optional), min-node-height(optional), margin(default=20))
|
# scale = (vertical-distance, horizontal-distance, min-node-width(optional), min-node-height(optional), margin(default=20))
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def graph_get(self, cr, uid, id, scale, context={}):
|
def graph_get(self, cr, uid, id, scale, context={}):
|
||||||
|
|
||||||
nodes= []
|
nodes= []
|
||||||
|
@ -67,24 +67,24 @@ class workflow(osv.osv):
|
||||||
else:
|
else:
|
||||||
if not a.in_transitions:
|
if not a.in_transitions:
|
||||||
no_ancester.append(a.id)
|
no_ancester.append(a.id)
|
||||||
|
|
||||||
for t in a.out_transitions:
|
for t in a.out_transitions:
|
||||||
transitions.append((a.id, t.act_to.id))
|
transitions.append((a.id, t.act_to.id))
|
||||||
tres[t.id] = (a.id, t.act_to.id)
|
tres[t.id] = (a.id, t.act_to.id)
|
||||||
|
|
||||||
|
|
||||||
g = graph(nodes, transitions, no_ancester)
|
g = graph(nodes, transitions, no_ancester)
|
||||||
g.process(start)
|
g.process(start)
|
||||||
g.scale(*scale)
|
g.scale(*scale)
|
||||||
result = g.result_get()
|
result = g.result_get()
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
for node in nodes_name:
|
for node in nodes_name:
|
||||||
results[str(node[0])] = result[node[0]]
|
results[str(node[0])] = result[node[0]]
|
||||||
results[str(node[0])]['name'] = node[1]
|
results[str(node[0])]['name'] = node[1]
|
||||||
|
|
||||||
return {'nodes': results, 'transitions': tres}
|
return {'nodes': results, 'transitions': tres}
|
||||||
|
|
||||||
|
|
||||||
def create(self, cr, user, vals, context=None):
|
def create(self, cr, user, vals, context=None):
|
||||||
if not context:
|
if not context:
|
||||||
|
@ -97,7 +97,7 @@ workflow()
|
||||||
class wkf_activity(osv.osv):
|
class wkf_activity(osv.osv):
|
||||||
_name = "workflow.activity"
|
_name = "workflow.activity"
|
||||||
_table = "wkf_activity"
|
_table = "wkf_activity"
|
||||||
_log_access = False
|
# _log_access = False
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Name', size=64, required=True),
|
'name': fields.char('Name', size=64, required=True),
|
||||||
'wkf_id': fields.many2one('workflow', 'Workflow', required=True, select=True, ondelete='cascade'),
|
'wkf_id': fields.many2one('workflow', 'Workflow', required=True, select=True, ondelete='cascade'),
|
||||||
|
@ -123,7 +123,7 @@ wkf_activity()
|
||||||
class wkf_transition(osv.osv):
|
class wkf_transition(osv.osv):
|
||||||
_table = "wkf_transition"
|
_table = "wkf_transition"
|
||||||
_name = "workflow.transition"
|
_name = "workflow.transition"
|
||||||
_log_access = False
|
# _log_access = False
|
||||||
_rec_name = 'signal'
|
_rec_name = 'signal'
|
||||||
_columns = {
|
_columns = {
|
||||||
'trigger_model': fields.char('Trigger Object', size=128),
|
'trigger_model': fields.char('Trigger Object', size=128),
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2004-2008 Tiny SPRL (http://tiny.be) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# WARNING: This program as such is intended to be used by professional
|
||||||
|
# programmers who take the whole responsability of assessing all potential
|
||||||
|
# consequences resulting from its eventual inadequacies and bugs
|
||||||
|
# End users who are looking for a ready-to-use solution with commercial
|
||||||
|
# garantees and support are strongly adviced to contract a Free Software
|
||||||
|
# Service Company
|
||||||
|
#
|
||||||
|
# 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 2
|
||||||
|
# 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
import maintenance
|
||||||
|
|
||||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# WARNING: This program as such is intended to be used by professional
|
||||||
|
# programmers who take the whole responsability of assessing all potential
|
||||||
|
# consequences resulting from its eventual inadequacies and bugs
|
||||||
|
# End users who are looking for a ready-to-use solution with commercial
|
||||||
|
# garantees and support are strongly adviced to contract a Free Software
|
||||||
|
# Service Company
|
||||||
|
#
|
||||||
|
# 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 2
|
||||||
|
# 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
from osv import osv, fields
|
||||||
|
import pooler
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
|
||||||
|
from tools import config
|
||||||
|
import xmlrpclib
|
||||||
|
|
||||||
|
class maintenance_contract(osv.osv):
|
||||||
|
_name = "maintenance.contract"
|
||||||
|
_description = "Maintenance Contract"
|
||||||
|
_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')
|
||||||
|
}
|
||||||
|
_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
|
||||||
|
|
||||||
|
maintenance_contract()
|
||||||
|
|
||||||
|
|
||||||
|
class maintenance_contract_wizard(osv.osv_memory):
|
||||||
|
_name = 'maintenance.contract.wizard'
|
||||||
|
|
||||||
|
_columns = {
|
||||||
|
'name' : fields.char('Contract ID', size=256, required=True ),
|
||||||
|
'password' : fields.char('Password', size=64, required=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
def validate_cb(self, cr, uid, ids, context):
|
||||||
|
print "Validate_cb"
|
||||||
|
return False
|
||||||
|
|
||||||
|
maintenance_contract_wizard()
|
||||||
|
|
||||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<openerp>
|
||||||
|
<data noupdate="0">
|
||||||
|
|
||||||
|
<record model="res.groups" id="group_maintenance_manager">
|
||||||
|
<field name="name">Maintenance Manager</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu" id="menu_maintenance_contract">
|
||||||
|
<field eval="[(6,0,[ref('group_maintenance_manager')])]" name="groups_id"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</openerp>
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<openerp>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="maintenance_contract_tree_view" model="ir.ui.view">
|
||||||
|
<field name="name">maintenance.contract.tree</field>
|
||||||
|
<field name="model">maintenance.contract</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Maintenance Contract">
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="date_start"/>
|
||||||
|
<field name="date_stop"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="maintenance_contract_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">maintenance.contract.form</field>
|
||||||
|
<field name="model">maintenance.contract</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Maintenance Contract">
|
||||||
|
<separator string="Information" colspan="4"/>
|
||||||
|
<field name="name" select="1" colspan="4"/>
|
||||||
|
<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"/>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_maintenance_contract_form" model="ir.actions.act_window">
|
||||||
|
<field name="name">Your Maintenance Contracts</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">maintenance.contract</field>
|
||||||
|
<field name="view_type">form</field>
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
name="Maintenance"
|
||||||
|
id="maintenance"
|
||||||
|
parent="base.menu_administration"/>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
action="action_maintenance_contract_form"
|
||||||
|
id="menu_maintenance_contract"
|
||||||
|
parent="maintenance"/>
|
||||||
|
|
||||||
|
<record id="maintenance_contract_add_wizard" model="ir.ui.view">
|
||||||
|
<field name="name">maintenance.contract.add.wizard</field>
|
||||||
|
<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" />
|
||||||
|
<newline />
|
||||||
|
<field name="password" password="True" />
|
||||||
|
<newline />
|
||||||
|
<label string="" /><button name="validate_cb" type="object" string="Validate" />
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_maintenance_contract_add_wizard" model="ir.actions.act_window">
|
||||||
|
<field name="name">Add Maintenance Contract</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">maintenance.contract.wizard</field>
|
||||||
|
<field name="view_type">form</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
action="action_maintenance_contract_add_wizard"
|
||||||
|
id="menu_maintenance_contract_add"
|
||||||
|
parent="maintenance" />
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</openerp>
|
|
@ -35,111 +35,7 @@ import addons
|
||||||
import pooler
|
import pooler
|
||||||
import netsvc
|
import netsvc
|
||||||
|
|
||||||
ver_regexp = re.compile("^(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?$")
|
from tools.parse_version import parse_version
|
||||||
suffix_regexp = re.compile("^(alpha|beta|rc|pre|p)(\\d*)$")
|
|
||||||
|
|
||||||
def vercmp(ver1, ver2):
|
|
||||||
"""
|
|
||||||
Compare two versions
|
|
||||||
Take from portage_versions.py
|
|
||||||
@param ver1: version to compare with
|
|
||||||
@type ver1: string (example "1.2-r3")
|
|
||||||
@param ver2: version to compare again
|
|
||||||
@type ver2: string (example "2.1-r1")
|
|
||||||
@rtype: None or float
|
|
||||||
@return:
|
|
||||||
1. position if ver1 is greater than ver2
|
|
||||||
2. negative if ver1 is less than ver2
|
|
||||||
3. 0 if ver1 equals ver2
|
|
||||||
4. None if ver1 or ver2 are invalid
|
|
||||||
"""
|
|
||||||
|
|
||||||
match1 = ver_regexp.match(ver1)
|
|
||||||
match2 = ver_regexp.match(ver2)
|
|
||||||
|
|
||||||
if not match1 or not match1.groups():
|
|
||||||
return None
|
|
||||||
if not match2 or not match2.groups():
|
|
||||||
return None
|
|
||||||
|
|
||||||
list1 = [int(match1.group(1))]
|
|
||||||
list2 = [int(match2.group(1))]
|
|
||||||
|
|
||||||
if len(match1.group(2)) or len(match2.group(2)):
|
|
||||||
vlist1 = match1.group(2)[1:].split(".")
|
|
||||||
vlist2 = match2.group(2)[1:].split(".")
|
|
||||||
for i in range(0, max(len(vlist1), len(vlist2))):
|
|
||||||
# Implicit .0 is given -1, so 1.0.0 > 1.0
|
|
||||||
# would be ambiguous if two versions that aren't literally equal
|
|
||||||
# are given the same value (in sorting, for example).
|
|
||||||
if len(vlist1) <= i or len(vlist1[i]) == 0:
|
|
||||||
list1.append(-1)
|
|
||||||
list2.append(int(vlist2[i]))
|
|
||||||
elif len(vlist2) <= i or len(vlist2[i]) == 0:
|
|
||||||
list1.append(int(vlist1[i]))
|
|
||||||
list2.append(-1)
|
|
||||||
# Let's make life easy and use integers unless we're forced to use floats
|
|
||||||
elif (vlist1[i][0] != "0" and vlist2[i][0] != "0"):
|
|
||||||
list1.append(int(vlist1[i]))
|
|
||||||
list2.append(int(vlist2[i]))
|
|
||||||
# now we have to use floats so 1.02 compares correctly against 1.1
|
|
||||||
else:
|
|
||||||
list1.append(float("0."+vlist1[i]))
|
|
||||||
list2.append(float("0."+vlist2[i]))
|
|
||||||
# and now the final letter
|
|
||||||
if len(match1.group(4)):
|
|
||||||
list1.append(ord(match1.group(4)))
|
|
||||||
if len(match2.group(4)):
|
|
||||||
list2.append(ord(match2.group(4)))
|
|
||||||
|
|
||||||
for i in range(0, max(len(list1), len(list2))):
|
|
||||||
if len(list1) <= i:
|
|
||||||
return -1
|
|
||||||
elif len(list2) <= i:
|
|
||||||
return 1
|
|
||||||
elif list1[i] != list2[i]:
|
|
||||||
return list1[i] - list2[i]
|
|
||||||
|
|
||||||
# main version is equal, so now compare the _suffix part
|
|
||||||
list1 = match1.group(5).split("_")[1:]
|
|
||||||
list2 = match2.group(5).split("_")[1:]
|
|
||||||
|
|
||||||
for i in range(0, max(len(list1), len(list2))):
|
|
||||||
# Implicit _p0 is given a value of -1, so that 1 < 1_p0
|
|
||||||
if len(list1) <= i:
|
|
||||||
s1 = ("p","-1")
|
|
||||||
else:
|
|
||||||
s1 = suffix_regexp.match(list1[i]).groups()
|
|
||||||
if len(list2) <= i:
|
|
||||||
s2 = ("p","-1")
|
|
||||||
else:
|
|
||||||
s2 = suffix_regexp.match(list2[i]).groups()
|
|
||||||
if s1[0] != s2[0]:
|
|
||||||
return suffix_value[s1[0]] - suffix_value[s2[0]]
|
|
||||||
if s1[1] != s2[1]:
|
|
||||||
# it's possible that the s(1|2)[1] == ''
|
|
||||||
# in such a case, fudge it.
|
|
||||||
try:
|
|
||||||
r1 = int(s1[1])
|
|
||||||
except ValueError:
|
|
||||||
r1 = 0
|
|
||||||
try:
|
|
||||||
r2 = int(s2[1])
|
|
||||||
except ValueError:
|
|
||||||
r2 = 0
|
|
||||||
if r1 - r2:
|
|
||||||
return r1 - r2
|
|
||||||
|
|
||||||
# the suffix part is equal to, so finally check the revision
|
|
||||||
if match1.group(9):
|
|
||||||
r1 = int(match1.group(9))
|
|
||||||
else:
|
|
||||||
r1 = 0
|
|
||||||
if match2.group(9):
|
|
||||||
r2 = int(match2.group(9))
|
|
||||||
else:
|
|
||||||
r2 = 0
|
|
||||||
return r1 - r2
|
|
||||||
|
|
||||||
|
|
||||||
class module_repository(osv.osv):
|
class module_repository(osv.osv):
|
||||||
|
@ -158,7 +54,7 @@ class module_repository(osv.osv):
|
||||||
}
|
}
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'sequence': lambda *a: 5,
|
'sequence': lambda *a: 5,
|
||||||
'filter': lambda *a: 'href="([a-zA-Z0-9_]+)-('+release.version.rsplit('.', 1)[0]+'.(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?)(\.zip)"',
|
'filter': lambda *a: 'href="([a-zA-Z0-9_]+)-('+release.major_version+'.(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?)(\.zip)"',
|
||||||
'active': lambda *a: 1,
|
'active': lambda *a: 1,
|
||||||
}
|
}
|
||||||
_order = "sequence"
|
_order = "sequence"
|
||||||
|
@ -196,7 +92,7 @@ class module(osv.osv):
|
||||||
data = f.read()
|
data = f.read()
|
||||||
info = eval(data)
|
info = eval(data)
|
||||||
if 'version' in info:
|
if 'version' in info:
|
||||||
info['version'] = release.version.rsplit('.', 1)[0] + '.' + info['version']
|
info['version'] = release.major_version + '.' + info['version']
|
||||||
f.close()
|
f.close()
|
||||||
except:
|
except:
|
||||||
return {}
|
return {}
|
||||||
|
@ -313,7 +209,7 @@ class module(osv.osv):
|
||||||
_('You try to remove a module that is installed or will be installed'))
|
_('You try to remove a module that is installed or will be installed'))
|
||||||
return super(module, self).unlink(cr, uid, ids, context=context)
|
return super(module, self).unlink(cr, uid, ids, context=context)
|
||||||
|
|
||||||
def state_update(self, cr, uid, ids, newstate, states_to_update, context={}, level=50):
|
def state_update(self, cr, uid, ids, newstate, states_to_update, context={}, level=100):
|
||||||
if level<1:
|
if level<1:
|
||||||
raise orm.except_orm(_('Error'), _('Recursion error in modules dependencies !'))
|
raise orm.except_orm(_('Error'), _('Recursion error in modules dependencies !'))
|
||||||
demo = False
|
demo = False
|
||||||
|
@ -403,7 +299,7 @@ class module(osv.osv):
|
||||||
terp = self.get_module_info(mod_name)
|
terp = self.get_module_info(mod_name)
|
||||||
if terp.get('installable', True) and mod.state == 'uninstallable':
|
if terp.get('installable', True) and mod.state == 'uninstallable':
|
||||||
self.write(cr, uid, id, {'state': 'uninstalled'})
|
self.write(cr, uid, id, {'state': 'uninstalled'})
|
||||||
if vercmp(terp.get('version', ''), mod.latest_version or '0') > 0:
|
if parse_version(terp.get('version', '')) > parse_version(mod.latest_version or ''):
|
||||||
self.write(cr, uid, id, {
|
self.write(cr, uid, id, {
|
||||||
'latest_version': terp.get('version'),
|
'latest_version': terp.get('version'),
|
||||||
'url': ''})
|
'url': ''})
|
||||||
|
@ -429,15 +325,14 @@ class module(osv.osv):
|
||||||
if not terp or not terp.get('installable', True):
|
if not terp or not terp.get('installable', True):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not os.path.isfile( mod_path ):
|
#if not os.path.isfile( mod_path ):
|
||||||
import imp
|
# import imp
|
||||||
# XXX must restrict to only addons paths
|
# path = imp.find_module(mod_name, [addons.ad, addons._ad])
|
||||||
path = imp.find_module(mod_name)
|
# imp.load_module(name, *path)
|
||||||
imp.load_module(name, *path)
|
#else:
|
||||||
else:
|
# import zipimport
|
||||||
import zipimport
|
# zimp = zipimport.zipimporter(mod_path)
|
||||||
zimp = zipimport.zipimporter(mod_path)
|
# zimp.load_module(mod_name)
|
||||||
zimp.load_module(mod_name)
|
|
||||||
id = self.create(cr, uid, {
|
id = self.create(cr, uid, {
|
||||||
'name': mod_name,
|
'name': mod_name,
|
||||||
'state': 'uninstalled',
|
'state': 'uninstalled',
|
||||||
|
@ -452,8 +347,8 @@ class module(osv.osv):
|
||||||
self._update_dependencies(cr, uid, id, terp.get('depends', []))
|
self._update_dependencies(cr, uid, id, terp.get('depends', []))
|
||||||
self._update_category(cr, uid, id, terp.get('category', 'Uncategorized'))
|
self._update_category(cr, uid, id, terp.get('category', 'Uncategorized'))
|
||||||
|
|
||||||
import socket
|
#import socket
|
||||||
socket.setdefaulttimeout(10)
|
#socket.setdefaulttimeout(10)
|
||||||
for repository in robj.browse(cr, uid, robj.search(cr, uid, [])):
|
for repository in robj.browse(cr, uid, robj.search(cr, uid, [])):
|
||||||
try:
|
try:
|
||||||
index_page = urllib.urlopen(repository.url).read()
|
index_page = urllib.urlopen(repository.url).read()
|
||||||
|
@ -472,7 +367,7 @@ class module(osv.osv):
|
||||||
if version == 'x': # 'x' version was a mistake
|
if version == 'x': # 'x' version was a mistake
|
||||||
version = '0'
|
version = '0'
|
||||||
if name in mod_sort:
|
if name in mod_sort:
|
||||||
if vercmp(version, mod_sort[name][0]) <= 0:
|
if parse_version(version) <= parse_version(mod_sort[name][0]):
|
||||||
continue
|
continue
|
||||||
mod_sort[name] = [version, extension]
|
mod_sort[name] = [version, extension]
|
||||||
for name in mod_sort.keys():
|
for name in mod_sort.keys():
|
||||||
|
@ -494,8 +389,7 @@ class module(osv.osv):
|
||||||
['latest_version']
|
['latest_version']
|
||||||
if latest_version == 'x': # 'x' version was a mistake
|
if latest_version == 'x': # 'x' version was a mistake
|
||||||
latest_version = '0'
|
latest_version = '0'
|
||||||
c = vercmp(version, latest_version)
|
if parse_version(version) > parse_version(latest_version):
|
||||||
if c > 0:
|
|
||||||
self.write(cr, uid, id,
|
self.write(cr, uid, id,
|
||||||
{'latest_version': version, 'url': url})
|
{'latest_version': version, 'url': url})
|
||||||
res[0] += 1
|
res[0] += 1
|
||||||
|
@ -503,8 +397,7 @@ class module(osv.osv):
|
||||||
['published_version']
|
['published_version']
|
||||||
if published_version == 'x' or not published_version:
|
if published_version == 'x' or not published_version:
|
||||||
published_version = '0'
|
published_version = '0'
|
||||||
c = vercmp(version, published_version)
|
if parse_version(version) > parse_version(published_version):
|
||||||
if c > 0:
|
|
||||||
self.write(cr, uid, id,
|
self.write(cr, uid, id,
|
||||||
{'published_version': version})
|
{'published_version': version})
|
||||||
return res
|
return res
|
||||||
|
@ -518,7 +411,7 @@ class module(osv.osv):
|
||||||
version = '0'
|
version = '0'
|
||||||
if match:
|
if match:
|
||||||
version = match.group(1)
|
version = match.group(1)
|
||||||
if vercmp(mod.installed_version or '0', version) >= 0:
|
if parse_version(mod.installed_version or '0') >= parse_version(version):
|
||||||
continue
|
continue
|
||||||
res.append(mod.url)
|
res.append(mod.url)
|
||||||
if not download:
|
if not download:
|
||||||
|
|
|
@ -334,7 +334,7 @@ class res_partner_bank_type(osv.osv):
|
||||||
_description='Bank Account Type'
|
_description='Bank Account Type'
|
||||||
_name = 'res.partner.bank.type'
|
_name = 'res.partner.bank.type'
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Name', size=64, required=True),
|
'name': fields.char('Name', size=64, required=True, translate=True),
|
||||||
'code': fields.char('Code', size=64, required=True),
|
'code': fields.char('Code', size=64, required=True),
|
||||||
'field_ids': fields.one2many('res.partner.bank.type.field', 'bank_type_id', 'Type fields'),
|
'field_ids': fields.one2many('res.partner.bank.type.field', 'bank_type_id', 'Type fields'),
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ class res_partner_bank_type_fields(osv.osv):
|
||||||
_description='Bank type fields'
|
_description='Bank type fields'
|
||||||
_name = 'res.partner.bank.type.field'
|
_name = 'res.partner.bank.type.field'
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Field name', size=64, required=True),
|
'name': fields.char('Field name', size=64, required=True, translate=True),
|
||||||
'bank_type_id': fields.many2one('res.partner.bank.type', 'Bank type', required=True, ondelete='cascade'),
|
'bank_type_id': fields.many2one('res.partner.bank.type', 'Bank type', required=True, ondelete='cascade'),
|
||||||
'required': fields.boolean('Required'),
|
'required': fields.boolean('Required'),
|
||||||
'readonly': fields.boolean('Readonly'),
|
'readonly': fields.boolean('Readonly'),
|
||||||
|
|
|
@ -202,6 +202,16 @@
|
||||||
<field name="type">default</field>
|
<field name="type">default</field>
|
||||||
<field name="partner_id" ref="res_partner_10"/>
|
<field name="partner_id" ref="res_partner_10"/>
|
||||||
</record>
|
</record>
|
||||||
|
<record id="res_partner_address_3000" model="res.partner.address">
|
||||||
|
<field name="city">Champs sur Marne</field>
|
||||||
|
<field name="name">Laith Jubair</field>
|
||||||
|
<field name="zip">77420</field>
|
||||||
|
<field model="res.country" name="country_id" search="[('name','=','France')]"/>
|
||||||
|
<field name="email">info@axelor.com</field>
|
||||||
|
<field name="phone">+33 1 64 61 04 01</field>
|
||||||
|
<field name="street">12 rue Albert Einstein</field>
|
||||||
|
<field name="partner_id" ref="res_partner_desertic_hispafuentes"/>
|
||||||
|
</record>
|
||||||
<record id="res_partner_address_3" model="res.partner.address">
|
<record id="res_partner_address_3" model="res.partner.address">
|
||||||
<field name="city">Louvain-la-Neuve</field>
|
<field name="city">Louvain-la-Neuve</field>
|
||||||
<field name="name">Thomas Passot</field>
|
<field name="name">Thomas Passot</field>
|
||||||
|
|
|
@ -508,7 +508,7 @@
|
||||||
<menuitem action="action_partner_category" id="menu_partner_category_main" parent="base.menu_partner_form" sequence="1"/>
|
<menuitem action="action_partner_category" id="menu_partner_category_main" parent="base.menu_partner_form" sequence="1"/>
|
||||||
|
|
||||||
<record id="action_partner_by_category" model="ir.actions.act_window">
|
<record id="action_partner_by_category" model="ir.actions.act_window">
|
||||||
<field name="name" eval="False"/>
|
<field name="name">Partner Categories</field>
|
||||||
<field name="res_model">res.partner</field>
|
<field name="res_model">res.partner</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
|
|
|
@ -92,7 +92,7 @@ def _tz_get(self,cr,uid, context={}):
|
||||||
|
|
||||||
class users(osv.osv):
|
class users(osv.osv):
|
||||||
_name = "res.users"
|
_name = "res.users"
|
||||||
_log_access = False
|
#_log_access = False
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Name', size=64, required=True, select=True),
|
'name': fields.char('Name', size=64, required=True, select=True),
|
||||||
'login': fields.char('Login', size=64, required=True),
|
'login': fields.char('Login', size=64, required=True),
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"access_ir_module_module_dependency_group_system","ir_module_module_dependency group_system","model_ir_module_module_dependency","group_system",1,1,1,1
|
"access_ir_module_module_dependency_group_system","ir_module_module_dependency group_system","model_ir_module_module_dependency","group_system",1,1,1,1
|
||||||
"access_ir_module_repository_group_system","ir_module_repository group_system","model_ir_module_repository","group_system",1,1,1,1
|
"access_ir_module_repository_group_system","ir_module_repository group_system","model_ir_module_repository","group_system",1,1,1,1
|
||||||
"access_ir_property_group_user","ir_property group_user","model_ir_property",,1,0,0,0
|
"access_ir_property_group_user","ir_property group_user","model_ir_property",,1,0,0,0
|
||||||
|
"access_ir_property_group_user_manager","ir_property group_manager","model_ir_property",base.group_partner_manager,1,1,1,1
|
||||||
"access_ir_report_custom_group_system","ir_report_custom group_system","model_ir_report_custom",,1,0,0,0
|
"access_ir_report_custom_group_system","ir_report_custom group_system","model_ir_report_custom",,1,0,0,0
|
||||||
"access_ir_report_custom_fields_group_system","ir_report_custom_fields group_system","model_ir_report_custom_fields",,1,0,0,0
|
"access_ir_report_custom_fields_group_system","ir_report_custom_fields group_system","model_ir_report_custom_fields",,1,0,0,0
|
||||||
"access_ir_rule_group_user","ir_rule group_user","model_ir_rule",,1,0,0,0
|
"access_ir_rule_group_user","ir_rule group_user","model_ir_rule",,1,0,0,0
|
||||||
|
@ -38,7 +39,8 @@
|
||||||
"access_ir_ui_view_custom_group_user","ir_ui_view_custom_group_user","model_ir_ui_view_custom",,1,0,0,0
|
"access_ir_ui_view_custom_group_user","ir_ui_view_custom_group_user","model_ir_ui_view_custom",,1,0,0,0
|
||||||
"access_ir_ui_view_custom_group_system","ir_ui_view_custom_group_system","model_ir_ui_view_custom","group_system",1,1,1,1
|
"access_ir_ui_view_custom_group_system","ir_ui_view_custom_group_system","model_ir_ui_view_custom","group_system",1,1,1,1
|
||||||
"access_ir_ui_view_sc_group_user","ir_ui_view_sc group_user","model_ir_ui_view_sc",,1,1,1,1
|
"access_ir_ui_view_sc_group_user","ir_ui_view_sc group_user","model_ir_ui_view_sc",,1,1,1,1
|
||||||
"access_ir_values_group_erp_manager","ir_values group_erp_manager","model_ir_values",,1,1,1,1
|
"access_ir_values_group_erp_manager","ir_values group_erp_manager","model_ir_values",group_erp_manager,1,1,1,1
|
||||||
|
"access_ir_values_group_all","ir_values group_all","model_ir_values",,1,0,0,0
|
||||||
"access_wizard_ir_model_menu_create_group_system","wizard_ir_model_menu_create group_system","model_wizard_ir_model_menu_create","group_system",1,1,1,1
|
"access_wizard_ir_model_menu_create_group_system","wizard_ir_model_menu_create group_system","model_wizard_ir_model_menu_create","group_system",1,1,1,1
|
||||||
"access_wizard_ir_model_menu_create_line_group_system","wizard_ir_model_menu_create_line group_system","model_wizard_ir_model_menu_create_line","group_system",1,1,1,1
|
"access_wizard_ir_model_menu_create_line_group_system","wizard_ir_model_menu_create_line group_system","model_wizard_ir_model_menu_create_line","group_system",1,1,1,1
|
||||||
"access_wizard_module_lang_export_group_system","wizard_module_lang_export group_system","model_wizard_module_lang_export","group_system",1,1,1,1
|
"access_wizard_module_lang_export_group_system","wizard_module_lang_export group_system","model_wizard_module_lang_export","group_system",1,1,1,1
|
||||||
|
@ -127,3 +129,4 @@
|
||||||
"access_res_config_view_all","res_config_view_all","model_res_config_view",,1,0,0,0
|
"access_res_config_view_all","res_config_view_all","model_res_config_view",,1,0,0,0
|
||||||
"access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1
|
"access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1
|
||||||
"access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0
|
"access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0
|
||||||
|
"access_maintenance_group_user","maintenance_contract group_user","model_maintenance_contract","group_maintenance_manager",1,1,1,1
|
||||||
|
|
|
|
@ -135,9 +135,9 @@
|
||||||
<rng:optional><rng:attribute name="id" /> </rng:optional>
|
<rng:optional><rng:attribute name="id" /> </rng:optional>
|
||||||
<rng:attribute name="model" />
|
<rng:attribute name="model" />
|
||||||
<rng:optional><rng:attribute name="forcecreate" /></rng:optional>
|
<rng:optional><rng:attribute name="forcecreate" /></rng:optional>
|
||||||
<rng:oneOrMore>
|
<rng:zeroOrMore>
|
||||||
<rng:ref name="field" />
|
<rng:ref name="field" />
|
||||||
</rng:oneOrMore>
|
</rng:zeroOrMore>
|
||||||
</rng:element>
|
</rng:element>
|
||||||
</rng:define>
|
</rng:define>
|
||||||
|
|
||||||
|
|
|
@ -122,10 +122,15 @@ class Service(object):
|
||||||
class LocalService(Service):
|
class LocalService(Service):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.__name = name
|
self.__name = name
|
||||||
s = _service[name]
|
try:
|
||||||
self._service = s
|
s = _service[name]
|
||||||
for m in s._method:
|
self._service = s
|
||||||
setattr(self, m, s._method[m])
|
for m in s._method:
|
||||||
|
setattr(self, m, s._method[m])
|
||||||
|
except KeyError, keyError:
|
||||||
|
Logger().notifyChannel('module', LOG_ERROR, 'This service does not exists: %s' % (str(keyError),) )
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceUnavailable(Exception):
|
class ServiceUnavailable(Exception):
|
||||||
|
@ -154,6 +159,9 @@ def init_logger():
|
||||||
logf = config['logfile']
|
logf = config['logfile']
|
||||||
# test if the directories exist, else create them
|
# test if the directories exist, else create them
|
||||||
try:
|
try:
|
||||||
|
dirname = os.path.dirname(logf)
|
||||||
|
if not os.path.isdir(dirname):
|
||||||
|
res = os.makedirs(dirname)
|
||||||
handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
|
handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
|
||||||
except:
|
except:
|
||||||
sys.stderr.write("ERROR: couldn't create the logfile directory\n")
|
sys.stderr.write("ERROR: couldn't create the logfile directory\n")
|
||||||
|
@ -272,24 +280,19 @@ class GenericXMLRPCRequestHandler:
|
||||||
raise xmlrpclib.Fault(s, tb_s)
|
raise xmlrpclib.Fault(s, tb_s)
|
||||||
|
|
||||||
|
|
||||||
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler,
|
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
|
||||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||||
|
|
||||||
|
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
|
||||||
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn,
|
|
||||||
SimpleXMLRPCServer.SimpleXMLRPCServer):
|
|
||||||
|
|
||||||
def server_bind(self):
|
def server_bind(self):
|
||||||
try:
|
try:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
socket.SO_REUSEADDR, 1)
|
|
||||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||||
except:
|
except:
|
||||||
sys.stderr.write("ERROR: address already in use\n")
|
Logger().notifyChannel('init', LOG_ERROR, 'Address already in use')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
class HttpDaemon(threading.Thread):
|
class HttpDaemon(threading.Thread):
|
||||||
|
|
||||||
def __init__(self, interface, port, secure=False):
|
def __init__(self, interface, port, secure=False):
|
||||||
|
@ -299,22 +302,19 @@ class HttpDaemon(threading.Thread):
|
||||||
self.secure = secure
|
self.secure = secure
|
||||||
if secure:
|
if secure:
|
||||||
from ssl import SecureXMLRPCServer
|
from ssl import SecureXMLRPCServer
|
||||||
class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler,
|
|
||||||
SecureXMLRPCServer.SecureXMLRPCRequestHandler):
|
|
||||||
SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
|
||||||
class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn,
|
|
||||||
SecureXMLRPCServer.SecureXMLRPCServer):
|
|
||||||
|
|
||||||
|
class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler):
|
||||||
|
SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||||
|
|
||||||
|
class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer):
|
||||||
def server_bind(self):
|
def server_bind(self):
|
||||||
try:
|
try:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
socket.SO_REUSEADDR, 1)
|
|
||||||
SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
|
SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
|
||||||
except:
|
except:
|
||||||
sys.stderr.write("ERROR: address already in use\n")
|
sys.stderr.write("ERROR: address already in use\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
self.server = SecureThreadedXMLRPCServer((interface, port),
|
self.server = SecureThreadedXMLRPCServer((interface, port),
|
||||||
SecureXMLRPCRequestHandler, 0)
|
SecureXMLRPCRequestHandler, 0)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from tools import flatten, reverse_enumerate
|
from tools import flatten, reverse_enumerate
|
||||||
|
import fields
|
||||||
|
|
||||||
|
|
||||||
class expression(object):
|
class expression(object):
|
||||||
|
@ -190,7 +191,7 @@ class expression(object):
|
||||||
dom = _rec_get(ids2, working_table, left)
|
dom = _rec_get(ids2, working_table, left)
|
||||||
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
|
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
|
||||||
else:
|
else:
|
||||||
if isinstance(right, basestring):
|
if isinstance(right, basestring): # and not isinstance(field, fields.related):
|
||||||
res_ids = field_obj.name_search(cr, uid, right, [], operator, limit=None)
|
res_ids = field_obj.name_search(cr, uid, right, [], operator, limit=None)
|
||||||
right = map(lambda x: x[0], res_ids)
|
right = map(lambda x: x[0], res_ids)
|
||||||
self.__exp[i] = (left, 'in', right)
|
self.__exp[i] = (left, 'in', right)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
@ -160,7 +160,7 @@ class char(_column):
|
||||||
u_symb = symb
|
u_symb = symb
|
||||||
else:
|
else:
|
||||||
u_symb = unicode(symb)
|
u_symb = unicode(symb)
|
||||||
return u_symb.encode('utf8')[:self.size]
|
return u_symb[:self.size].encode('utf8')
|
||||||
|
|
||||||
|
|
||||||
class text(_column):
|
class text(_column):
|
||||||
|
@ -597,6 +597,9 @@ class function(_column):
|
||||||
self._type = type
|
self._type = type
|
||||||
self._fnct_search = fnct_search
|
self._fnct_search = fnct_search
|
||||||
self.store = store
|
self.store = store
|
||||||
|
if store:
|
||||||
|
self._classic_read = True
|
||||||
|
self._classic_write = True
|
||||||
if type == 'float':
|
if type == 'float':
|
||||||
self._symbol_c = '%f'
|
self._symbol_c = '%f'
|
||||||
self._symbol_f = lambda x: __builtin__.float(x or 0.0)
|
self._symbol_f = lambda x: __builtin__.float(x or 0.0)
|
||||||
|
@ -636,60 +639,27 @@ class function(_column):
|
||||||
|
|
||||||
class related(function):
|
class related(function):
|
||||||
|
|
||||||
def _fnct_search(self, tobj, cr, uid, obj=None, name=None, context=None):
|
def _fnct_search(self, tobj, cr, uid, obj=None, name=None, domain=None, context={}):
|
||||||
where_flag = 0
|
self._field_get2(cr, uid, obj, context)
|
||||||
where = " where"
|
i = len(self._arg)-1
|
||||||
query = "select %s.id from %s" % (obj._table, obj._table)
|
sarg = name
|
||||||
relation_child = obj._name
|
while i>0:
|
||||||
relation = obj._name
|
if type(sarg) in [type([]), type( (1,) )]:
|
||||||
for i in range(len(self._arg)):
|
where = [(self._arg[i], 'in', sarg)]
|
||||||
field_detail = self._field_get(cr, uid, obj, relation, self._arg[i])
|
|
||||||
relation = field_detail[0]
|
|
||||||
if field_detail[1] in ('one2many', 'many2many'):
|
|
||||||
obj_child = obj.pool.get(field_detail[2][self._arg[i]]['relation'])
|
|
||||||
field_detail_child = obj_child.fields_get(cr, uid,)
|
|
||||||
|
|
||||||
fields_filter = dict(filter(lambda x: x[1].get('relation', False)
|
|
||||||
and x[1].get('relation') == relation_child
|
|
||||||
and x[1].get('type')=='many2one', field_detail_child.items()))
|
|
||||||
query += " inner join %s on %s.id = %s.%s" % (obj_child._table, obj._table, obj_child._table, fields_filter.keys()[0])
|
|
||||||
relation_child = relation
|
|
||||||
elif field_detail[1] in ('many2one'):
|
|
||||||
obj_child = obj.pool.get(field_detail[2][self._arg[i]]['relation'])
|
|
||||||
obj_child2 = obj.pool.get(relation_child)
|
|
||||||
if obj_child._name == obj_child2._name:
|
|
||||||
# select res_partner.id from res_partner where res_partner.parent_id in(select id from res_partner where res_partner.date >= '2008-10-01');
|
|
||||||
# where +=" %s.id = %s.%s in (select id from %s where %s.%s %s %s"%(obj_child._table,obj_child2._table,self._arg[i])
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
query += " inner join %s on %s.id = %s.%s" % (obj_child._table, obj_child._table, obj_child2._table, self._arg[i])
|
|
||||||
relation_child = field_detail[0]
|
|
||||||
if i == (len(self._arg)-1):
|
|
||||||
if obj_child._inherits:
|
|
||||||
obj_child_inherits = obj.pool.get(obj_child._inherits.keys()[0])
|
|
||||||
query += " inner join %s on %s.id = %s.%s" % (obj_child_inherits._table, obj_child_inherits._table, obj_child._table, obj_child._inherits.values()[0])
|
|
||||||
obj_child = obj_child_inherits
|
|
||||||
where += " %s.%s %s '%%%s%%' and" % (obj_child._table, obj_child._rec_name, context[0][1], context[0][2])
|
|
||||||
else:
|
else:
|
||||||
obj_child = obj.pool.get(relation_child)
|
where = [(self._arg[i], '=', sarg)]
|
||||||
if field_detail[1] in ('char'):
|
if domain:
|
||||||
where += " %s.%s %s '%%%s%%' and" % (obj_child._table, self._arg[i], context[0][1], context[0][2])
|
where = map(lambda x: (self._arg[i],x[1], x[2]), domain)
|
||||||
if field_detail[1] in ('date'):
|
domain = []
|
||||||
where += " %s.%s %s '%s' and" % (obj_child._table, self._arg[i], context[0][1], context[0][2])
|
sarg = obj.pool.get(self._relations[i]['object']).search(cr, uid, where, context=context)
|
||||||
if field_detail[1] in ['integer', 'long', 'float','integer_big']:
|
i -= 1
|
||||||
where += " %s.%s %s '%d' and" % (obj_child._table, self._arg[i], context[0][1], context[0][2])
|
return [(self._arg[0], 'in', sarg)]
|
||||||
if len(where)>10:
|
|
||||||
query += where.rstrip('and')
|
|
||||||
cr.execute(query)
|
|
||||||
ids = []
|
|
||||||
for id in cr.fetchall():
|
|
||||||
ids.append(id[0])
|
|
||||||
return [('id', 'in', ids)]
|
|
||||||
|
|
||||||
# def _fnct_write(self,obj,cr, uid, ids,values, field_name, args, context=None):
|
def _fnct_write(self,obj,cr, uid, ids,values, field_name, args, context=None):
|
||||||
# raise 'Not Implemented Yet'
|
raise 'Not Implemented Yet'
|
||||||
|
|
||||||
def _fnct_read(self, obj, cr, uid, ids, field_name, args, context=None):
|
def _fnct_read(self, obj, cr, uid, ids, field_name, args, context=None):
|
||||||
|
self._field_get2(cr, uid, obj, context)
|
||||||
if not ids: return {}
|
if not ids: return {}
|
||||||
relation = obj._name
|
relation = obj._name
|
||||||
res = {}
|
res = {}
|
||||||
|
@ -698,33 +668,40 @@ class related(function):
|
||||||
t_data = data
|
t_data = data
|
||||||
relation = obj._name
|
relation = obj._name
|
||||||
for i in range(len(self.arg)):
|
for i in range(len(self.arg)):
|
||||||
field_detail = self._field_get(cr, uid, obj, relation, self.arg[i])
|
field_detail = self._relations[i]
|
||||||
relation = field_detail[0]
|
relation = field_detail['object']
|
||||||
if not t_data[self.arg[i]]:
|
if not t_data[self.arg[i]]:
|
||||||
t_data = False
|
t_data = False
|
||||||
break
|
break
|
||||||
if field_detail[1] in ('one2many', 'many2many'):
|
if field_detail['type'] in ('one2many', 'many2many'):
|
||||||
t_data = t_data[self.arg[i]][0]
|
t_data = t_data[self.arg[i]][0]
|
||||||
else:
|
else:
|
||||||
t_data = t_data[self.arg[i]]
|
t_data = t_data[self.arg[i]]
|
||||||
if type(t_data) == type(objlst[0]):
|
if type(t_data) == type(objlst[0]):
|
||||||
res[data.id] = t_data.id
|
res[data.id] = (t_data.id,t_data.name)
|
||||||
else:
|
else:
|
||||||
res[data.id] = t_data
|
res[data.id] = t_data
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def __init__(self, *arg, **args):
|
def __init__(self, *arg, **args):
|
||||||
self.arg = arg
|
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, fnct_inv_arg=arg, method=True, fnct_search=self._fnct_search, **args)
|
||||||
|
|
||||||
# TODO: call field_get on the object, not in the DB
|
def _field_get2(self, cr, uid, obj, context={}):
|
||||||
def _field_get(self, cr, uid, obj, model_name, prop):
|
if self._relations:
|
||||||
fields = obj.pool.get(model_name).fields_get(cr, uid,)
|
return
|
||||||
if fields.get(prop, False):
|
obj_name = obj._name
|
||||||
return(fields[prop].get('relation', False), fields[prop].get('type', False), fields)
|
for i in range(len(self._arg)):
|
||||||
else:
|
f = obj.pool.get(obj_name).fields_get(cr, uid, [self._arg[i]], context=context)[self._arg[i]]
|
||||||
raise 'Field %s not exist in %s' % (prop, model_name)
|
self._relations.append({
|
||||||
|
'object': obj_name,
|
||||||
|
'type': f['type']
|
||||||
|
|
||||||
|
})
|
||||||
|
if f.get('relation',False):
|
||||||
|
obj_name = f['relation']
|
||||||
|
self._relations[-1]['relation'] = f['relation']
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
# Serialized fields
|
# Serialized fields
|
||||||
|
|
326
bin/osv/orm.py
326
bin/osv/orm.py
|
@ -303,18 +303,24 @@ class orm_template(object):
|
||||||
_description = None
|
_description = None
|
||||||
_inherits = {}
|
_inherits = {}
|
||||||
_table = None
|
_table = None
|
||||||
_invalids=[]
|
_invalids = set()
|
||||||
|
|
||||||
def _field_create(self, cr, context={}):
|
def _field_create(self, cr, context={}):
|
||||||
cr.execute("SELECT id FROM ir_model_data WHERE name='%s'" % ('model_'+self._name.replace('.','_'),))
|
cr.execute("SELECT id FROM ir_model WHERE model='%s'" % self._name)
|
||||||
if not cr.rowcount:
|
if not cr.rowcount:
|
||||||
cr.execute('SELECT nextval(%s)', ('ir_model_id_seq',))
|
cr.execute('SELECT nextval(%s)', ('ir_model_id_seq',))
|
||||||
id = cr.fetchone()[0]
|
model_id = cr.fetchone()[0]
|
||||||
cr.execute("INSERT INTO ir_model (id,model, name, info) VALUES (%s, %s, %s, %s)", (id, self._name, self._description, self.__doc__))
|
cr.execute("INSERT INTO ir_model (id,model, name, info,state) VALUES (%s, %s, %s, %s,%s)", (model_id, self._name, self._description, self.__doc__, 'base'))
|
||||||
if 'module' in context:
|
else:
|
||||||
|
model_id = cr.fetchone()[0]
|
||||||
|
if 'module' in context:
|
||||||
|
name_id = 'model_'+self._name.replace('.','_')
|
||||||
|
cr.execute('select * from ir_model_data where name=%s and res_id=%s', (name_id,model_id))
|
||||||
|
if not cr.rowcount:
|
||||||
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, now(), now(), %s, %s, %s)", \
|
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, now(), now(), %s, %s, %s)", \
|
||||||
('model_'+self._name.replace('.','_'), context['module'], 'ir.model', id)
|
(name_id, context['module'], 'ir.model', model_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
cr.execute("SELECT * FROM ir_model_fields WHERE model=%s", (self._name,))
|
cr.execute("SELECT * FROM ir_model_fields WHERE model=%s", (self._name,))
|
||||||
|
@ -322,9 +328,6 @@ class orm_template(object):
|
||||||
for rec in cr.dictfetchall():
|
for rec in cr.dictfetchall():
|
||||||
cols[rec['name']] = rec
|
cols[rec['name']] = rec
|
||||||
|
|
||||||
cr.execute("SELECT id FROM ir_model WHERE model='%s'" % self._name)
|
|
||||||
model_id = cr.fetchone()[0]
|
|
||||||
|
|
||||||
for (k, f) in self._columns.items():
|
for (k, f) in self._columns.items():
|
||||||
vals = {
|
vals = {
|
||||||
'model_id': model_id,
|
'model_id': model_id,
|
||||||
|
@ -656,7 +659,7 @@ class orm_template(object):
|
||||||
raise _('The read method is not implemented on this object !')
|
raise _('The read method is not implemented on this object !')
|
||||||
|
|
||||||
def get_invalid_fields(self,cr,uid):
|
def get_invalid_fields(self,cr,uid):
|
||||||
return self._invalids.__str__()
|
return list(self._invalids)
|
||||||
|
|
||||||
def _validate(self, cr, uid, ids, context=None):
|
def _validate(self, cr, uid, ids, context=None):
|
||||||
context = context or {}
|
context = context or {}
|
||||||
|
@ -670,12 +673,12 @@ class orm_template(object):
|
||||||
error_msgs.append(
|
error_msgs.append(
|
||||||
_("Error occured while validating the field(s) %s: %s") % (','.join(fields), translated_msg)
|
_("Error occured while validating the field(s) %s: %s") % (','.join(fields), translated_msg)
|
||||||
)
|
)
|
||||||
self._invalids.extend(fields)
|
self._invalids.update(fields)
|
||||||
if error_msgs:
|
if error_msgs:
|
||||||
cr.rollback()
|
cr.rollback()
|
||||||
raise except_orm('ValidateError', '\n'.join(error_msgs))
|
raise except_orm('ValidateError', '\n'.join(error_msgs))
|
||||||
else:
|
else:
|
||||||
self._invalids=[]
|
self._invalids.clear()
|
||||||
|
|
||||||
def default_get(self, cr, uid, fields_list, context=None):
|
def default_get(self, cr, uid, fields_list, context=None):
|
||||||
return {}
|
return {}
|
||||||
|
@ -694,6 +697,14 @@ class orm_template(object):
|
||||||
|
|
||||||
# returns the definition of each field in the object
|
# returns the definition of each field in the object
|
||||||
# the optional fields parameter can limit the result to some fields
|
# the optional fields parameter can limit the result to some fields
|
||||||
|
def fields_get_keys(self, cr, user, context=None, read_access=True):
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
res = self._columns.keys()
|
||||||
|
for parent in self._inherits:
|
||||||
|
res.extend(self.pool.get(parent).fields_get_keys(cr, user, fields, context))
|
||||||
|
return res
|
||||||
|
|
||||||
def fields_get(self, cr, user, fields=None, context=None, read_access=True):
|
def fields_get(self, cr, user, fields=None, context=None, read_access=True):
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
|
@ -790,7 +801,9 @@ class orm_template(object):
|
||||||
for f in node.childNodes:
|
for f in node.childNodes:
|
||||||
if f.nodeType == f.ELEMENT_NODE and f.localName in ('form', 'tree', 'graph'):
|
if f.nodeType == f.ELEMENT_NODE and f.localName in ('form', 'tree', 'graph'):
|
||||||
node.removeChild(f)
|
node.removeChild(f)
|
||||||
xarch, xfields = self.pool.get(relation).__view_look_dom_arch(cr, user, f, context)
|
ctx = context.copy()
|
||||||
|
ctx['base_model_name'] = self._name
|
||||||
|
xarch, xfields = self.pool.get(relation).__view_look_dom_arch(cr, user, f, ctx)
|
||||||
views[str(f.localName)] = {
|
views[str(f.localName)] = {
|
||||||
'arch': xarch,
|
'arch': xarch,
|
||||||
'fields': xfields
|
'fields': xfields
|
||||||
|
@ -829,6 +842,8 @@ class orm_template(object):
|
||||||
if ('lang' in context) and not result:
|
if ('lang' in context) and not result:
|
||||||
if node.hasAttribute('string') and node.getAttribute('string'):
|
if node.hasAttribute('string') and node.getAttribute('string'):
|
||||||
trans = tools.translate(cr, self._name, 'view', context['lang'], node.getAttribute('string').encode('utf8'))
|
trans = tools.translate(cr, 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'))
|
||||||
if trans:
|
if trans:
|
||||||
node.setAttribute('string', trans.decode('utf8'))
|
node.setAttribute('string', trans.decode('utf8'))
|
||||||
if node.hasAttribute('sum') and node.getAttribute('sum'):
|
if node.hasAttribute('sum') and node.getAttribute('sum'):
|
||||||
|
@ -839,11 +854,13 @@ class orm_template(object):
|
||||||
if childs:
|
if childs:
|
||||||
for f in node.childNodes:
|
for f in node.childNodes:
|
||||||
fields.update(self.__view_look_dom(cr, user, f, context))
|
fields.update(self.__view_look_dom(cr, user, f, context))
|
||||||
|
|
||||||
|
if ('state' not in fields) and (('state' in self._columns) or ('state' in self._inherit_fields)):
|
||||||
|
fields['state'] = {}
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def __view_look_dom_arch(self, cr, user, node, context=None):
|
def __view_look_dom_arch(self, cr, user, node, context=None):
|
||||||
if not context:
|
|
||||||
context = {}
|
|
||||||
fields_def = self.__view_look_dom(cr, user, node, context=context)
|
fields_def = self.__view_look_dom(cr, user, node, context=context)
|
||||||
|
|
||||||
buttons = xpath.Evaluate('//button', node)
|
buttons = xpath.Evaluate('//button', node)
|
||||||
|
@ -1035,6 +1052,9 @@ class orm_template(object):
|
||||||
xml += "<newline/>"
|
xml += "<newline/>"
|
||||||
xml += "</form>"
|
xml += "</form>"
|
||||||
elif view_type == 'tree':
|
elif view_type == 'tree':
|
||||||
|
_rec_name = self._rec_name
|
||||||
|
if _rec_name not in self._columns:
|
||||||
|
_rec_name = self._columns.keys()[0]
|
||||||
xml = '''<?xml version="1.0" encoding="utf-8"?>''' \
|
xml = '''<?xml version="1.0" encoding="utf-8"?>''' \
|
||||||
'''<tree string="%s"><field name="%s"/></tree>''' \
|
'''<tree string="%s"><field name="%s"/></tree>''' \
|
||||||
% (self._description, self._rec_name)
|
% (self._description, self._rec_name)
|
||||||
|
@ -1110,6 +1130,47 @@ class orm_template(object):
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
raise _('The copy method is not implemented on this object !')
|
raise _('The copy method is not implemented on this object !')
|
||||||
|
|
||||||
|
def read_string(self, cr, uid, id, langs, fields=None, context=None):
|
||||||
|
if not context:
|
||||||
|
context = {}
|
||||||
|
res = {}
|
||||||
|
res2 = {}
|
||||||
|
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'read')
|
||||||
|
if not fields:
|
||||||
|
fields = self._columns.keys() + self._inherit_fields.keys()
|
||||||
|
for lang in langs:
|
||||||
|
res[lang] = {'code': lang}
|
||||||
|
for f in fields:
|
||||||
|
if f in self._columns:
|
||||||
|
res_trans = self.pool.get('ir.translation')._get_source(cr, uid, self._name+','+f, 'field', lang)
|
||||||
|
if res_trans:
|
||||||
|
res[lang][f] = res_trans
|
||||||
|
else:
|
||||||
|
res[lang][f] = self._columns[f].string
|
||||||
|
for table in self._inherits:
|
||||||
|
cols = intersect(self._inherit_fields.keys(), fields)
|
||||||
|
res2 = self.pool.get(table).read_string(cr, uid, id, langs, cols, context)
|
||||||
|
for lang in res2:
|
||||||
|
if lang in res:
|
||||||
|
res[lang] = {'code': lang}
|
||||||
|
for f in res2[lang]:
|
||||||
|
res[lang][f] = res2[lang][f]
|
||||||
|
return res
|
||||||
|
|
||||||
|
def write_string(self, cr, uid, id, langs, vals, context=None):
|
||||||
|
if not context:
|
||||||
|
context = {}
|
||||||
|
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'write')
|
||||||
|
for lang in langs:
|
||||||
|
for field in vals:
|
||||||
|
if field in self._columns:
|
||||||
|
self.pool.get('ir.translation')._set_ids(cr, uid, self._name+','+field, 'field', lang, [0], vals[field])
|
||||||
|
for table in self._inherits:
|
||||||
|
cols = intersect(self._inherit_fields.keys(), vals)
|
||||||
|
if cols:
|
||||||
|
self.pool.get(table).write_string(cr, uid, id, langs, vals, context)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class orm_memory(orm_template):
|
class orm_memory(orm_template):
|
||||||
_protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count']
|
_protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count']
|
||||||
|
@ -1379,6 +1440,7 @@ class orm(orm_template):
|
||||||
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"
|
# iterate on the "object columns"
|
||||||
|
todo_update_store = []
|
||||||
for k in self._columns:
|
for k in self._columns:
|
||||||
if k in ('id', 'write_uid', 'write_date', 'create_uid', 'create_date'):
|
if k in ('id', 'write_uid', 'write_date', 'create_uid', 'create_date'):
|
||||||
continue
|
continue
|
||||||
|
@ -1420,20 +1482,9 @@ class orm(orm_template):
|
||||||
cr.execute("UPDATE \"%s\" SET \"%s\"=NULL" % (self._table, k))
|
cr.execute("UPDATE \"%s\" SET \"%s\"=NULL" % (self._table, k))
|
||||||
else:
|
else:
|
||||||
cr.execute("UPDATE \"%s\" SET \"%s\"='%s'" % (self._table, k, default))
|
cr.execute("UPDATE \"%s\" SET \"%s\"='%s'" % (self._table, k, default))
|
||||||
|
|
||||||
if isinstance(f, fields.function):
|
if isinstance(f, fields.function):
|
||||||
cr.execute('select id from '+self._table)
|
todo_update_store.append((f,k))
|
||||||
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))
|
|
||||||
|
|
||||||
# and add constraints if needed
|
# and add constraints if needed
|
||||||
if isinstance(f, fields.many2one):
|
if isinstance(f, fields.many2one):
|
||||||
|
@ -1547,6 +1598,21 @@ class orm(orm_template):
|
||||||
cr.commit()
|
cr.commit()
|
||||||
else:
|
else:
|
||||||
print "ERROR"
|
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))
|
||||||
|
|
||||||
else:
|
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())
|
create = not bool(cr.fetchone())
|
||||||
|
@ -1573,29 +1639,33 @@ class orm(orm_template):
|
||||||
def __init__(self, cr):
|
def __init__(self, cr):
|
||||||
super(orm, self).__init__(cr)
|
super(orm, self).__init__(cr)
|
||||||
self._columns = self._columns.copy()
|
self._columns = self._columns.copy()
|
||||||
f = filter(lambda a: isinstance(self._columns[a], fields.function) and self._columns[a].store, self._columns)
|
for store_field in self._columns:
|
||||||
if f:
|
f = self._columns[store_field]
|
||||||
list_store = []
|
if not isinstance(f, fields.function):
|
||||||
tuple_store = ()
|
continue
|
||||||
tuple_fn = ()
|
if not f.store:
|
||||||
for store_field in f:
|
continue
|
||||||
if not self._columns[store_field].store == True:
|
if self._columns[store_field].store is True:
|
||||||
dict_store = self._columns[store_field].store
|
sm = {self._name:(lambda self,cr, uid, ids, c={}: ids, None)}
|
||||||
key = dict_store.keys()
|
else:
|
||||||
list_data = []
|
sm = self._columns[store_field].store
|
||||||
for i in key:
|
for object, aa in sm.items():
|
||||||
tuple_store = self._name, store_field, self._columns[store_field]._fnct.__name__, tuple(dict_store[i][0]), dict_store[i][1], i
|
if len(aa)==2:
|
||||||
list_data.append(tuple_store)
|
(fnct,fields2)=aa
|
||||||
#tuple_store=self._name,store_field,self._columns[store_field]._fnct.__name__,tuple(dict_store[key[0]][0]),dict_store[key[0]][1]
|
order = 1
|
||||||
for l in list_data:
|
elif len(aa)==3:
|
||||||
list_store = []
|
(fnct,fields2,order)=aa
|
||||||
if l[5] in self.pool._store_function.keys():
|
else:
|
||||||
self.pool._store_function[l[5]].append(l)
|
raise except_orm(_('Error'),
|
||||||
temp_list = list(set(self.pool._store_function[l[5]]))
|
_('Invalid function definition %s in object %s !' % (store_field, self._name)))
|
||||||
self.pool._store_function[l[5]] = temp_list
|
self.pool._store_function.setdefault(object, [])
|
||||||
else:
|
ok = True
|
||||||
list_store.append(l)
|
for x,y,z,e,f in self.pool._store_function[object]:
|
||||||
self.pool._store_function[l[5]] = list_store
|
if (x==self._name) and (y==store_field) and (e==fields2):
|
||||||
|
ok = False
|
||||||
|
if ok:
|
||||||
|
self.pool._store_function[object].append( (self._name, store_field, fnct, fields2, order))
|
||||||
|
self.pool._store_function[object].sort(lambda x,y: cmp(x[4],y[4]))
|
||||||
|
|
||||||
for (key, _, msg) in self._sql_constraints:
|
for (key, _, msg) in self._sql_constraints:
|
||||||
self.pool._sql_error[self._table+'_'+key] = msg
|
self.pool._sql_error[self._table+'_'+key] = msg
|
||||||
|
@ -1747,7 +1817,7 @@ class orm(orm_template):
|
||||||
if v == None:
|
if v == None:
|
||||||
r[key] = False
|
r[key] = False
|
||||||
if isinstance(ids, (int, long)):
|
if isinstance(ids, (int, long)):
|
||||||
return result[0]
|
return result and result[0] or False
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _read_flat(self, cr, user, ids, fields_to_read, context=None, load='_classic_read'):
|
def _read_flat(self, cr, user, ids, fields_to_read, context=None, load='_classic_read'):
|
||||||
|
@ -1924,15 +1994,10 @@ class orm(orm_template):
|
||||||
ids = [ids]
|
ids = [ids]
|
||||||
|
|
||||||
fn_list = []
|
fn_list = []
|
||||||
if self._name in self.pool._store_function.keys():
|
for fnct in self.pool._store_function.get(self._name, []):
|
||||||
list_store = self.pool._store_function[self._name]
|
ids2 = filter(None, fnct[2](self,cr, uid, ids, context))
|
||||||
fn_data = ()
|
if ids2:
|
||||||
id_change = []
|
fn_list.append( (fnct[0], fnct[1], ids2) )
|
||||||
for tuple_fn in list_store:
|
|
||||||
for id in ids:
|
|
||||||
id_change.append(self._store_get_ids(cr, uid, id, tuple_fn, context)[0])
|
|
||||||
fn_data = id_change, tuple_fn
|
|
||||||
fn_list.append(fn_data)
|
|
||||||
|
|
||||||
delta = context.get('read_delta', False)
|
delta = context.get('read_delta', False)
|
||||||
if delta and self._log_access:
|
if delta and self._log_access:
|
||||||
|
@ -1979,10 +2044,11 @@ class orm(orm_template):
|
||||||
else:
|
else:
|
||||||
cr.execute('delete from "'+self._table+'" ' \
|
cr.execute('delete from "'+self._table+'" ' \
|
||||||
'where id in ('+str_d+')', sub_ids)
|
'where id in ('+str_d+')', sub_ids)
|
||||||
if fn_list:
|
|
||||||
for ids, tuple_fn in fn_list:
|
|
||||||
self._store_set_values(cr, uid, ids, tuple_fn, id_change, context)
|
|
||||||
|
|
||||||
|
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)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -2193,22 +2259,17 @@ class orm(orm_template):
|
||||||
wf_service = netsvc.LocalService("workflow")
|
wf_service = netsvc.LocalService("workflow")
|
||||||
for id in ids:
|
for id in ids:
|
||||||
wf_service.trg_write(user, self._name, id, cr)
|
wf_service.trg_write(user, self._name, id, cr)
|
||||||
self._update_function_stored(cr, user, ids, context=context)
|
|
||||||
|
|
||||||
if self._name in self.pool._store_function.keys():
|
|
||||||
list_store = self.pool._store_function[self._name]
|
|
||||||
for tuple_fn in list_store:
|
|
||||||
flag = False
|
|
||||||
if not tuple_fn[3]:
|
|
||||||
flag = True
|
|
||||||
for field in tuple_fn[3]:
|
|
||||||
if field in vals.keys():
|
|
||||||
flag = True
|
|
||||||
break
|
|
||||||
if flag:
|
|
||||||
id_change = self._store_get_ids(cr, user, ids[0], tuple_fn, context)
|
|
||||||
self._store_set_values(cr, user, ids[0], tuple_fn, id_change, context)
|
|
||||||
|
|
||||||
|
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
|
return True
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -2315,54 +2376,32 @@ class orm(orm_template):
|
||||||
|
|
||||||
wf_service = netsvc.LocalService("workflow")
|
wf_service = netsvc.LocalService("workflow")
|
||||||
wf_service.trg_create(user, self._name, id_new, cr)
|
wf_service.trg_create(user, self._name, id_new, cr)
|
||||||
self._update_function_stored(cr, user, [id_new], context=context)
|
|
||||||
if self._name in self.pool._store_function.keys():
|
|
||||||
list_store = self.pool._store_function[self._name]
|
|
||||||
for tuple_fn in list_store:
|
|
||||||
id_change = self._store_get_ids(cr, user, id_new, tuple_fn, context)
|
|
||||||
self._store_set_values(cr, user, id_new, tuple_fn, id_change, context)
|
|
||||||
|
|
||||||
|
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
|
return id_new
|
||||||
|
|
||||||
def _store_get_ids(self, cr, uid, ids, tuple_fn, context):
|
def _store_set_values(self, cr, uid, ids, field, context):
|
||||||
parent_id = getattr(self.pool.get(tuple_fn[0]), tuple_fn[4].func_name)(cr, uid, [ids])
|
|
||||||
return parent_id
|
|
||||||
|
|
||||||
def _store_set_values(self, cr, uid, ids, tuple_fn, parent_id, context):
|
|
||||||
name = tuple_fn[1]
|
|
||||||
table = tuple_fn[0]
|
|
||||||
args = {}
|
args = {}
|
||||||
vals_tot = getattr(self.pool.get(table), tuple_fn[2])(cr, uid, parent_id, name, args, context)
|
result = self._columns[field].get(cr, self, ids, field, uid, context=context)
|
||||||
write_dict = {}
|
for id,value in result.items():
|
||||||
for id in vals_tot.keys():
|
upd0 = []
|
||||||
write_dict[name] = vals_tot[id]
|
upd1 = []
|
||||||
self.pool.get(table).write(cr, uid, [id], write_dict)
|
if self._columns[field]._multi:
|
||||||
return True
|
value = value[field]
|
||||||
|
if self._columns[field]._type in ('many2one', 'one2one'):
|
||||||
def _update_function_stored(self, cr, user, ids, context=None):
|
try:
|
||||||
if not context:
|
value = value[0]
|
||||||
context = {}
|
except:
|
||||||
f = filter(lambda a: isinstance(self._columns[a], fields.function) \
|
pass
|
||||||
and self._columns[a].store, self._columns)
|
upd0.append('"'+field+'"='+self._columns[field]._symbol_set[0])
|
||||||
if f:
|
upd1.append(self._columns[field]._symbol_set[1](value))
|
||||||
result = self.read(cr, user, ids, fields=f, context=context)
|
upd1.append(id)
|
||||||
for res in result:
|
cr.execute('update "' + self._table + '" set ' + \
|
||||||
upd0 = []
|
string.join(upd0, ',') + ' where id = %d', upd1)
|
||||||
upd1 = []
|
|
||||||
for field in res:
|
|
||||||
if field not in f:
|
|
||||||
continue
|
|
||||||
value = res[field]
|
|
||||||
if self._columns[field]._type in ('many2one', 'one2one'):
|
|
||||||
try:
|
|
||||||
value = res[field][0]
|
|
||||||
except:
|
|
||||||
value = res[field]
|
|
||||||
upd0.append('"'+field+'"='+self._columns[field]._symbol_set[0])
|
|
||||||
upd1.append(self._columns[field]._symbol_set[1](value))
|
|
||||||
upd1.append(res['id'])
|
|
||||||
cr.execute('update "' + self._table + '" set ' + \
|
|
||||||
string.join(upd0, ',') + ' where id = %d', upd1)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -2546,47 +2585,6 @@ class orm(orm_template):
|
||||||
|
|
||||||
return new_id
|
return new_id
|
||||||
|
|
||||||
def read_string(self, cr, uid, id, langs, fields=None, context=None):
|
|
||||||
if not context:
|
|
||||||
context = {}
|
|
||||||
res = {}
|
|
||||||
res2 = {}
|
|
||||||
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'read')
|
|
||||||
if not fields:
|
|
||||||
fields = self._columns.keys() + self._inherit_fields.keys()
|
|
||||||
for lang in langs:
|
|
||||||
res[lang] = {'code': lang}
|
|
||||||
for f in fields:
|
|
||||||
if f in self._columns:
|
|
||||||
res_trans = self.pool.get('ir.translation')._get_source(cr, uid, self._name+','+f, 'field', lang)
|
|
||||||
if res_trans:
|
|
||||||
res[lang][f] = res_trans
|
|
||||||
else:
|
|
||||||
res[lang][f] = self._columns[f].string
|
|
||||||
for table in self._inherits:
|
|
||||||
cols = intersect(self._inherit_fields.keys(), fields)
|
|
||||||
res2 = self.pool.get(table).read_string(cr, uid, id, langs, cols, context)
|
|
||||||
for lang in res2:
|
|
||||||
if lang in res:
|
|
||||||
res[lang] = {'code': lang}
|
|
||||||
for f in res2[lang]:
|
|
||||||
res[lang][f] = res2[lang][f]
|
|
||||||
return res
|
|
||||||
|
|
||||||
def write_string(self, cr, uid, id, langs, vals, context=None):
|
|
||||||
if not context:
|
|
||||||
context = {}
|
|
||||||
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'write')
|
|
||||||
for lang in langs:
|
|
||||||
for field in vals:
|
|
||||||
if field in self._columns:
|
|
||||||
self.pool.get('ir.translation')._set_ids(cr, uid, self._name+','+field, 'field', lang, [0], vals[field])
|
|
||||||
for table in self._inherits:
|
|
||||||
cols = intersect(self._inherit_fields.keys(), vals)
|
|
||||||
if cols:
|
|
||||||
self.pool.get(table).write_string(cr, uid, id, langs, vals, context)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def check_recursion(self, cr, uid, ids, parent=None):
|
def check_recursion(self, cr, uid, ids, parent=None):
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = self._parent_name
|
parent = self._parent_name
|
||||||
|
|
|
@ -90,16 +90,14 @@ class osv_pool(netsvc.Service):
|
||||||
except psycopg.IntegrityError, inst:
|
except psycopg.IntegrityError, inst:
|
||||||
for key in self._sql_error.keys():
|
for key in self._sql_error.keys():
|
||||||
if key in inst[0]:
|
if key in inst[0]:
|
||||||
self.abortResponse(1, 'Constraint Error', 'warning',
|
self.abortResponse(1, 'Constraint Error', 'warning', self._sql_error[key])
|
||||||
self._sql_error[key])
|
|
||||||
self.abortResponse(1, 'Integrity Error', 'warning', inst[0])
|
self.abortResponse(1, 'Integrity Error', 'warning', inst[0])
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
import traceback
|
import traceback
|
||||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
|
tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||||
sys.exc_type, sys.exc_value, sys.exc_traceback))
|
|
||||||
logger = Logger()
|
logger = Logger()
|
||||||
logger.notifyChannel("web-services", LOG_ERROR,
|
for idx, s in enumerate(tb_s.split('\n')):
|
||||||
'Exception in call: ' + tb_s)
|
logger.notifyChannel("web-services", LOG_ERROR, '[%2d]: %s' % (idx, s,))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def execute(self, db, uid, obj, method, *args, **kw):
|
def execute(self, db, uid, obj, method, *args, **kw):
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
name = 'openerp-server'
|
name = 'openerp-server'
|
||||||
version = '5.0.0-alpha'
|
version = '5.0.0-rc1'
|
||||||
|
major_version = version.rsplit('.', 1)[0]
|
||||||
description = 'OpenERP Server'
|
description = 'OpenERP Server'
|
||||||
long_desc = '''\
|
long_desc = '''\
|
||||||
OpenERP is a complete ERP and CRM. The main features are accounting (analytic
|
OpenERP is a complete ERP and CRM. The main features are accounting (analytic
|
||||||
|
@ -33,7 +34,7 @@ customizable reports, and SOAP and XML-RPC interfaces.
|
||||||
'''
|
'''
|
||||||
classifiers = """\
|
classifiers = """\
|
||||||
Development Status :: 5 - Production/Stable
|
Development Status :: 5 - Production/Stable
|
||||||
License :: OSI Approved :: GNU General Public License Version 2 (GPL-2)
|
License :: OSI Approved :: GNU General Public License Version 3 (GPL-3)
|
||||||
Programming Language :: Python
|
Programming Language :: Python
|
||||||
"""
|
"""
|
||||||
url = 'http://www.openerp.com'
|
url = 'http://www.openerp.com'
|
||||||
|
|
|
@ -121,7 +121,7 @@ class document(object):
|
||||||
#Pinky: Why not this ? eval(expr, browser) ?
|
#Pinky: Why not this ? eval(expr, browser) ?
|
||||||
# name = browser.name
|
# name = browser.name
|
||||||
# data_dict = browser._data[self.get_value(browser, 'id')]
|
# data_dict = browser._data[self.get_value(browser, 'id')]
|
||||||
return eval(expr)
|
return eval(expr, {}, {'obj': record})
|
||||||
|
|
||||||
def parse_node(self, node, parent, browser, datas=None):
|
def parse_node(self, node, parent, browser, datas=None):
|
||||||
# node is the node of the xml template to be parsed
|
# node is the node of the xml template to be parsed
|
||||||
|
|
|
@ -67,6 +67,7 @@ class db(netsvc.Service):
|
||||||
db = sql_db.db_connect('template1', serialize=1)
|
db = sql_db.db_connect('template1', serialize=1)
|
||||||
db.truedb.autocommit()
|
db.truedb.autocommit()
|
||||||
cr = db.cursor()
|
cr = db.cursor()
|
||||||
|
time.sleep(0.2)
|
||||||
cr.execute('CREATE DATABASE ' + db_name + ' ENCODING \'unicode\'')
|
cr.execute('CREATE DATABASE ' + db_name + ' ENCODING \'unicode\'')
|
||||||
cr.close()
|
cr.close()
|
||||||
class DBInitialize(object):
|
class DBInitialize(object):
|
||||||
|
@ -149,7 +150,7 @@ class db(netsvc.Service):
|
||||||
try:
|
try:
|
||||||
cr.execute('DROP DATABASE ' + db_name)
|
cr.execute('DROP DATABASE ' + db_name)
|
||||||
except:
|
except:
|
||||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
logger.notifyChannel("web-services", netsvc.LOG_ERROR,
|
||||||
'DROP DB: %s failed' % (db_name,))
|
'DROP DB: %s failed' % (db_name,))
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
|
@ -163,11 +164,6 @@ class db(netsvc.Service):
|
||||||
security.check_super(password)
|
security.check_super(password)
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
|
|
||||||
if tools.config['db_password']:
|
|
||||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
|
||||||
'DUMP DB: %s doesn\'t work with password' % (db_name,))
|
|
||||||
raise Exception, "Couldn't dump database with password"
|
|
||||||
|
|
||||||
cmd = ['pg_dump', '--format=c']
|
cmd = ['pg_dump', '--format=c']
|
||||||
if tools.config['db_user']:
|
if tools.config['db_user']:
|
||||||
cmd.append('--username=' + tools.config['db_user'])
|
cmd.append('--username=' + tools.config['db_user'])
|
||||||
|
@ -182,7 +178,7 @@ class db(netsvc.Service):
|
||||||
data = stdout.read()
|
data = stdout.read()
|
||||||
res = stdout.close()
|
res = stdout.close()
|
||||||
if res:
|
if res:
|
||||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
logger.notifyChannel("web-services", netsvc.LOG_ERROR,
|
||||||
'DUMP DB: %s failed\n%s' % (db_name, data))
|
'DUMP DB: %s failed\n%s' % (db_name, data))
|
||||||
raise Exception, "Couldn't dump database"
|
raise Exception, "Couldn't dump database"
|
||||||
logger.notifyChannel("web-services", netsvc.LOG_INFO,
|
logger.notifyChannel("web-services", netsvc.LOG_INFO,
|
||||||
|
@ -194,15 +190,10 @@ class db(netsvc.Service):
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
|
|
||||||
if self.db_exist(db_name):
|
if self.db_exist(db_name):
|
||||||
logger.notifyChannel("web-service", netsvc.LOG_WARNING,
|
logger.notifyChannel("web-services", netsvc.LOG_WARNING,
|
||||||
'RESTORE DB: %s already exists' % (db_name,))
|
'RESTORE DB: %s already exists' % (db_name,))
|
||||||
raise Exception, "Database already exists"
|
raise Exception, "Database already exists"
|
||||||
|
|
||||||
if tools.config['db_password']:
|
|
||||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
|
||||||
'RESTORE DB: %s doesn\'t work with password' % (db_name,))
|
|
||||||
raise Exception, "Couldn't restore database with password"
|
|
||||||
|
|
||||||
db = sql_db.db_connect('template1', serialize=1)
|
db = sql_db.db_connect('template1', serialize=1)
|
||||||
db.truedb.autocommit()
|
db.truedb.autocommit()
|
||||||
cr = db.cursor()
|
cr = db.cursor()
|
||||||
|
@ -328,7 +319,7 @@ class common(netsvc.Service):
|
||||||
res = security.login(db, login, password)
|
res = security.login(db, login, password)
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
msg = res and 'successful login' or 'bad login or password'
|
msg = res and 'successful login' or 'bad login or password'
|
||||||
logger.notifyChannel("web-service", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, login, db.lower()))
|
logger.notifyChannel("web-services", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, login, db.lower()))
|
||||||
return res or False
|
return res or False
|
||||||
|
|
||||||
def about(self, extended=False):
|
def about(self, extended=False):
|
||||||
|
@ -480,7 +471,7 @@ class report_spool(netsvc.Service):
|
||||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
|
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
|
||||||
sys.exc_type, sys.exc_value, sys.exc_traceback))
|
sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||||
logger = netsvc.Logger()
|
logger = netsvc.Logger()
|
||||||
logger.notifyChannel('web-service', netsvc.LOG_ERROR,
|
logger.notifyChannel('web-services', netsvc.LOG_ERROR,
|
||||||
'Exception: %s\n%s' % (str(exception), tb_s))
|
'Exception: %s\n%s' % (str(exception), tb_s))
|
||||||
self._reports[id]['exception'] = exception
|
self._reports[id]['exception'] = exception
|
||||||
self._reports[id]['state'] = True
|
self._reports[id]['state'] = True
|
||||||
|
|
|
@ -171,6 +171,9 @@ def amount_to_text_nl(number, currency):
|
||||||
#-------------------------------------------------------------
|
#-------------------------------------------------------------
|
||||||
|
|
||||||
_translate_funcs = {'fr' : amount_to_text_fr, 'nl' : amount_to_text_nl}
|
_translate_funcs = {'fr' : amount_to_text_fr, 'nl' : amount_to_text_nl}
|
||||||
|
|
||||||
|
def add_amount_to_text_function(lang, func):
|
||||||
|
_translate_funcs[lang] = func
|
||||||
|
|
||||||
#TODO: we should use the country AND language (ex: septante VS soixante dix)
|
#TODO: we should use the country AND language (ex: septante VS soixante dix)
|
||||||
#TODO: we should use en by default, but the translation func is yet to be implemented
|
#TODO: we should use en by default, but the translation func is yet to be implemented
|
||||||
|
|
|
@ -92,7 +92,7 @@ def _eval_xml(self,node, pool, cr, uid, idref, context=None):
|
||||||
idref2['time'] = time
|
idref2['time'] = time
|
||||||
idref2['DateTime'] = DateTime
|
idref2['DateTime'] = DateTime
|
||||||
import release
|
import release
|
||||||
idref2['version'] = release.version.rsplit('.', 1)[0]
|
idref2['version'] = release.major_version
|
||||||
idref2['ref'] = lambda x: self.id_get(cr, False, x)
|
idref2['ref'] = lambda x: self.id_get(cr, False, x)
|
||||||
if len(f_model):
|
if len(f_model):
|
||||||
idref2['obj'] = _obj(self.pool, cr, uid, f_model, context=context)
|
idref2['obj'] = _obj(self.pool, cr, uid, f_model, context=context)
|
||||||
|
@ -287,7 +287,7 @@ form: module.record_id""" % (xml_id,)
|
||||||
groups_value.append((4, group_id))
|
groups_value.append((4, group_id))
|
||||||
res['groups_id'] = groups_value
|
res['groups_id'] = groups_value
|
||||||
|
|
||||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, mode=self.mode)
|
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||||
self.idref[xml_id] = int(id)
|
self.idref[xml_id] = int(id)
|
||||||
if not rec.hasAttribute('menu') or eval(rec.getAttribute('menu')):
|
if not rec.hasAttribute('menu') or eval(rec.getAttribute('menu')):
|
||||||
keyword = str(rec.getAttribute('keyword') or 'client_print_multi')
|
keyword = str(rec.getAttribute('keyword') or 'client_print_multi')
|
||||||
|
@ -327,7 +327,7 @@ form: module.record_id""" % (xml_id,)
|
||||||
groups_value.append((4, group_id))
|
groups_value.append((4, group_id))
|
||||||
res['groups_id'] = groups_value
|
res['groups_id'] = groups_value
|
||||||
|
|
||||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.wizard", self.module, res, xml_id, mode=self.mode)
|
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.wizard", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||||
self.idref[xml_id] = int(id)
|
self.idref[xml_id] = int(id)
|
||||||
# ir_set
|
# ir_set
|
||||||
if (not rec.hasAttribute('menu') or eval(rec.getAttribute('menu'))) and id:
|
if (not rec.hasAttribute('menu') or eval(rec.getAttribute('menu'))) and id:
|
||||||
|
@ -348,7 +348,7 @@ form: module.record_id""" % (xml_id,)
|
||||||
|
|
||||||
res = {'name': name, 'url': url, 'target':target}
|
res = {'name': name, 'url': url, 'target':target}
|
||||||
|
|
||||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.url", self.module, res, xml_id, mode=self.mode)
|
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.url", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||||
self.idref[xml_id] = int(id)
|
self.idref[xml_id] = int(id)
|
||||||
# ir_set
|
# ir_set
|
||||||
if (not rec.hasAttribute('menu') or eval(rec.getAttribute('menu'))) and id:
|
if (not rec.hasAttribute('menu') or eval(rec.getAttribute('menu'))) and id:
|
||||||
|
@ -419,7 +419,7 @@ form: module.record_id""" % (xml_id,)
|
||||||
|
|
||||||
if rec.hasAttribute('target'):
|
if rec.hasAttribute('target'):
|
||||||
res['target'] = rec.getAttribute('target')
|
res['target'] = rec.getAttribute('target')
|
||||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.actions.act_window', self.module, res, xml_id, mode=self.mode)
|
id = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.actions.act_window', self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||||
self.idref[xml_id] = int(id)
|
self.idref[xml_id] = int(id)
|
||||||
|
|
||||||
if src_model:
|
if src_model:
|
||||||
|
@ -567,7 +567,7 @@ form: module.record_id""" % (xml_id,)
|
||||||
|
|
||||||
xml_id = rec.getAttribute('id').encode('utf8')
|
xml_id = rec.getAttribute('id').encode('utf8')
|
||||||
self._test_xml_id(xml_id)
|
self._test_xml_id(xml_id)
|
||||||
pid = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.ui.menu', self.module, values, xml_id, True, mode=self.mode, res_id=res and res[0] or False)
|
pid = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.ui.menu', self.module, values, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode, res_id=res and res[0] or False)
|
||||||
|
|
||||||
if rec_id and pid:
|
if rec_id and pid:
|
||||||
self.idref[rec_id] = int(pid)
|
self.idref[rec_id] = int(pid)
|
||||||
|
@ -757,15 +757,17 @@ form: module.record_id""" % (xml_id,)
|
||||||
raise
|
raise
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __init__(self, cr, module, idref, mode, report=assertion_report(), noupdate = False):
|
def __init__(self, cr, module, idref, mode, report=None, noupdate=False):
|
||||||
|
|
||||||
self.logger = netsvc.Logger()
|
self.logger = netsvc.Logger()
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.module = module
|
self.module = module
|
||||||
self.cr = cr
|
self.cr = cr
|
||||||
self.idref = idref
|
self.idref = idref
|
||||||
self.pool = pooler.get_pool(cr.dbname)
|
self.pool = pooler.get_pool(cr.dbname)
|
||||||
# self.pool = osv.osv.FakePool(module)
|
|
||||||
self.uid = 1
|
self.uid = 1
|
||||||
|
if report is None:
|
||||||
|
report = assertion_report()
|
||||||
self.assert_report = report
|
self.assert_report = report
|
||||||
self.noupdate = noupdate
|
self.noupdate = noupdate
|
||||||
self._tags = {
|
self._tags = {
|
||||||
|
@ -835,7 +837,7 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
||||||
#
|
#
|
||||||
# xml import/export
|
# xml import/export
|
||||||
#
|
#
|
||||||
def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate = False, report=None):
|
def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate=False, report=None):
|
||||||
xmlstr = xmlfile.read()
|
xmlstr = xmlfile.read()
|
||||||
xmlfile.seek(0)
|
xmlfile.seek(0)
|
||||||
relaxng_doc = etree.parse(file(os.path.join( config['root_path'], 'import_xml.rng' )))
|
relaxng_doc = etree.parse(file(os.path.join( config['root_path'], 'import_xml.rng' )))
|
||||||
|
@ -852,9 +854,7 @@ def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate =
|
||||||
|
|
||||||
if idref is None:
|
if idref is None:
|
||||||
idref={}
|
idref={}
|
||||||
if report is None:
|
obj = xml_import(cr, module, idref, mode, report=report, noupdate=noupdate)
|
||||||
report=assertion_report()
|
|
||||||
obj = xml_import(cr, module, idref, mode, report=report, noupdate = noupdate)
|
|
||||||
obj.parse(xmlstr)
|
obj.parse(xmlstr)
|
||||||
del obj
|
del obj
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -104,7 +104,7 @@ def init_db(cr):
|
||||||
category_id, state) \
|
category_id, state) \
|
||||||
values (%d, %s, %s, %s, %s, %s, %s, %d, %s)', (
|
values (%d, %s, %s, %s, %s, %s, %s, %d, %s)', (
|
||||||
id, info.get('author', ''),
|
id, info.get('author', ''),
|
||||||
release.version.rsplit('.', 1)[0] + '.' + info.get('version', ''),
|
release.major_version + '.' + info.get('version', ''),
|
||||||
info.get('website', ''), i, info.get('name', False),
|
info.get('website', ''), i, info.get('name', False),
|
||||||
info.get('description', ''), p_id, state))
|
info.get('description', ''), p_id, state))
|
||||||
dependencies = info.get('depends', [])
|
dependencies = info.get('depends', [])
|
||||||
|
@ -252,23 +252,6 @@ def file_open(name, mode="r", subdir='addons', pathinfo=False):
|
||||||
raise IOError, 'File not found : '+str(name)
|
raise IOError, 'File not found : '+str(name)
|
||||||
|
|
||||||
|
|
||||||
def oswalksymlinks(top, topdown=True, onerror=None):
|
|
||||||
"""
|
|
||||||
same as os.walk but follow symlinks
|
|
||||||
attention: all symlinks are walked before all normals directories
|
|
||||||
"""
|
|
||||||
for dirpath, dirnames, filenames in os.walk(top, topdown, onerror):
|
|
||||||
if topdown:
|
|
||||||
yield dirpath, dirnames, filenames
|
|
||||||
|
|
||||||
symlinks = filter(lambda dirname: os.path.islink(os.path.join(dirpath, dirname)), dirnames)
|
|
||||||
for s in symlinks:
|
|
||||||
for x in oswalksymlinks(os.path.join(dirpath, s), topdown, onerror):
|
|
||||||
yield x
|
|
||||||
|
|
||||||
if not topdown:
|
|
||||||
yield dirpath, dirnames, filenames
|
|
||||||
|
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
# iterables
|
# iterables
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
# -*- 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/>.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
Some functions related to the os and os.path module
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from os.path import join as opj
|
||||||
|
|
||||||
|
def listdir(dir, recursive=False):
|
||||||
|
"""Allow to recursively get the file listing"""
|
||||||
|
dir = os.path.normpath(dir)
|
||||||
|
if not recursive:
|
||||||
|
return os.listdir(dir)
|
||||||
|
|
||||||
|
res = []
|
||||||
|
for root, dirs, files in os.walk(dir):
|
||||||
|
root = root[len(dir)+1:]
|
||||||
|
res.extend([opj(root, f) for f in files])
|
||||||
|
return res
|
||||||
|
|
||||||
|
def walksymlinks(top, topdown=True, onerror=None):
|
||||||
|
"""
|
||||||
|
same as os.walk but follow symlinks
|
||||||
|
attention: all symlinks are walked before all normals directories
|
||||||
|
"""
|
||||||
|
for dirpath, dirnames, filenames in os.walk(top, topdown, onerror):
|
||||||
|
if topdown:
|
||||||
|
yield dirpath, dirnames, filenames
|
||||||
|
|
||||||
|
symlinks = filter(lambda dirname: os.path.islink(os.path.join(dirpath, dirname)), dirnames)
|
||||||
|
for s in symlinks:
|
||||||
|
for x in walksymlinks(os.path.join(dirpath, s), topdown, onerror):
|
||||||
|
yield x
|
||||||
|
|
||||||
|
if not topdown:
|
||||||
|
yield dirpath, dirnames, filenames
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from pprint import pprint as pp
|
||||||
|
pp(listdir('../report', True))
|
|
@ -0,0 +1,96 @@
|
||||||
|
# -*- 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/>.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
## this functions are taken from the setuptools package (version 0.6c8)
|
||||||
|
## http://peak.telecommunity.com/DevCenter/PkgResources#parsing-utilities
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
|
||||||
|
replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c','dev':'@'}.get
|
||||||
|
|
||||||
|
def _parse_version_parts(s):
|
||||||
|
for part in component_re.split(s):
|
||||||
|
part = replace(part,part)
|
||||||
|
if not part or part=='.':
|
||||||
|
continue
|
||||||
|
if part[:1] in '0123456789':
|
||||||
|
yield part.zfill(8) # pad for numeric comparison
|
||||||
|
else:
|
||||||
|
yield '*'+part
|
||||||
|
|
||||||
|
yield '*final' # ensure that alpha/beta/candidate are before final
|
||||||
|
|
||||||
|
def parse_version(s):
|
||||||
|
"""Convert a version string to a chronologically-sortable key
|
||||||
|
|
||||||
|
This is a rough cross between distutils' StrictVersion and LooseVersion;
|
||||||
|
if you give it versions that would work with StrictVersion, then it behaves
|
||||||
|
the same; otherwise it acts like a slightly-smarter LooseVersion. It is
|
||||||
|
*possible* to create pathological version coding schemes that will fool
|
||||||
|
this parser, but they should be very rare in practice.
|
||||||
|
|
||||||
|
The returned value will be a tuple of strings. Numeric portions of the
|
||||||
|
version are padded to 8 digits so they will compare numerically, but
|
||||||
|
without relying on how numbers compare relative to strings. Dots are
|
||||||
|
dropped, but dashes are retained. Trailing zeros between alpha segments
|
||||||
|
or dashes are suppressed, so that e.g. "2.4.0" is considered the same as
|
||||||
|
"2.4". Alphanumeric parts are lower-cased.
|
||||||
|
|
||||||
|
The algorithm assumes that strings like "-" and any alpha string that
|
||||||
|
alphabetically follows "final" represents a "patch level". So, "2.4-1"
|
||||||
|
is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is
|
||||||
|
considered newer than "2.4-1", whic in turn is newer than "2.4".
|
||||||
|
|
||||||
|
Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that
|
||||||
|
come before "final" alphabetically) are assumed to be pre-release versions,
|
||||||
|
so that the version "2.4" is considered newer than "2.4a1".
|
||||||
|
|
||||||
|
Finally, to handle miscellaneous cases, the strings "pre", "preview", and
|
||||||
|
"rc" are treated as if they were "c", i.e. as though they were release
|
||||||
|
candidates, and therefore are not as new as a version string that does not
|
||||||
|
contain them.
|
||||||
|
"""
|
||||||
|
parts = []
|
||||||
|
for part in _parse_version_parts(s.lower()):
|
||||||
|
if part.startswith('*'):
|
||||||
|
if part<'*final': # remove '-' before a prerelease tag
|
||||||
|
while parts and parts[-1]=='*final-': parts.pop()
|
||||||
|
# remove trailing zeros from each series of numeric parts
|
||||||
|
while parts and parts[-1]=='00000000':
|
||||||
|
parts.pop()
|
||||||
|
parts.append(part)
|
||||||
|
return tuple(parts)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pvs = []
|
||||||
|
for v in ('0', '4.2', '4.2.3.4', '5.0.0-alpha', '5.0.0-rc1', '5.0.0-rc1.1', '5.0.0'):
|
||||||
|
pv = parse_version(v)
|
||||||
|
print v, pv
|
||||||
|
pvs.append(pv)
|
||||||
|
|
||||||
|
def cmp(a, b):
|
||||||
|
assert(a < b)
|
||||||
|
return b
|
||||||
|
|
||||||
|
reduce(cmp, pvs)
|
||||||
|
|
|
@ -190,13 +190,16 @@ class TinyPoFile(object):
|
||||||
plurial = len(modules) > 1 and 's' or ''
|
plurial = len(modules) > 1 and 's' or ''
|
||||||
self.buffer.write("#. module%s: %s\n" % (plurial, ', '.join(modules)))
|
self.buffer.write("#. module%s: %s\n" % (plurial, ', '.join(modules)))
|
||||||
|
|
||||||
if "code" in map(lambda e: e[0], tnrs):
|
|
||||||
# only strings in python code are python formated
|
|
||||||
self.buffer.write("#, python-format\n")
|
|
||||||
|
|
||||||
|
|
||||||
|
code = False
|
||||||
for typy, name, res_id in tnrs:
|
for typy, name, res_id in tnrs:
|
||||||
self.buffer.write("#: %s:%s:%s\n" % (typy, name, res_id))
|
self.buffer.write("#: %s:%s:%s\n" % (typy, name, res_id))
|
||||||
|
if typy == 'code':
|
||||||
|
code = True
|
||||||
|
|
||||||
|
if code:
|
||||||
|
# only strings in python code are python formated
|
||||||
|
self.buffer.write("#, python-format\n")
|
||||||
|
|
||||||
if not isinstance(trad, unicode):
|
if not isinstance(trad, unicode):
|
||||||
trad = unicode(trad, 'utf8')
|
trad = unicode(trad, 'utf8')
|
||||||
|
@ -373,10 +376,14 @@ def trans_generate(lang, modules, dbname=None):
|
||||||
|
|
||||||
# export fields
|
# export fields
|
||||||
for field_name, field_def in result['fields'].iteritems():
|
for field_name, field_def in result['fields'].iteritems():
|
||||||
|
res_name = name + ',' + field_name
|
||||||
if 'string' in field_def:
|
if 'string' in field_def:
|
||||||
source = field_def['string']
|
source = field_def['string']
|
||||||
res_name = name + ',' + field_name
|
push_translation(module, 'wizard_field', res_name, 0, source.encode('utf8'))
|
||||||
push_translation(module, 'wizard_field', res_name, 0, source)
|
|
||||||
|
if 'selection' in field_def:
|
||||||
|
for key, val in field_def['selection']:
|
||||||
|
push_translation(module, 'selection', res_name, 0, val.encode('utf8'))
|
||||||
|
|
||||||
# export arch
|
# export arch
|
||||||
arch = result['arch']
|
arch = result['arch']
|
||||||
|
@ -472,7 +479,7 @@ def trans_generate(lang, modules, dbname=None):
|
||||||
installed_modids = modobj.search(cr, uid, [('state', '=', 'installed')])
|
installed_modids = modobj.search(cr, uid, [('state', '=', 'installed')])
|
||||||
installed_modules = map(lambda m: m['name'], modobj.read(cr, uid, installed_modids, ['name']))
|
installed_modules = map(lambda m: m['name'], modobj.read(cr, uid, installed_modids, ['name']))
|
||||||
|
|
||||||
for root, dirs, files in tools.oswalksymlinks(tools.config['root_path']):
|
for root, dirs, files in tools.osutil.walksymlinks(tools.config['root_path']):
|
||||||
for fname in fnmatch.filter(files, '*.py'):
|
for fname in fnmatch.filter(files, '*.py'):
|
||||||
fabsolutepath = join(root, fname)
|
fabsolutepath = join(root, fname)
|
||||||
frelativepath = fabsolutepath[len(tools.config['root_path'])+1:]
|
frelativepath = fabsolutepath[len(tools.config['root_path'])+1:]
|
||||||
|
@ -506,7 +513,7 @@ def trans_load(db_name, filename, lang, strict=False, verbose=True):
|
||||||
return r
|
return r
|
||||||
except IOError:
|
except IOError:
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read file")
|
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,)) # FIXME translate message
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=None, verbose=True):
|
def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=None, verbose=True):
|
||||||
|
@ -627,7 +634,8 @@ def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=
|
||||||
logger.notifyChannel("init", netsvc.LOG_INFO,
|
logger.notifyChannel("init", netsvc.LOG_INFO,
|
||||||
"translation file loaded succesfully")
|
"translation file loaded succesfully")
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read file")
|
filename = '[lang: %s][format: %s]' % (lang or 'new', fileformat)
|
||||||
|
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
|
||||||
|
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -116,6 +116,11 @@ class interface(netsvc.Service):
|
||||||
trans = translate(cr, self.wiz_name+','+state+','+field, 'wizard_field', lang)
|
trans = translate(cr, self.wiz_name+','+state+','+field, 'wizard_field', lang)
|
||||||
if trans:
|
if trans:
|
||||||
fields[field]['string'] = trans
|
fields[field]['string'] = trans
|
||||||
|
|
||||||
|
if 'selection' in fields[field]:
|
||||||
|
trans = lambda x: translate(cr, self.wiz_name+','+state+','+field, 'selection', lang, x) or x
|
||||||
|
for idx, (key, val) in enumerate(fields[field]['selection']):
|
||||||
|
fields[field]['selection'][idx] = (key, trans(val))
|
||||||
|
|
||||||
# translate arch
|
# translate arch
|
||||||
if not isinstance(arch, UpdateableStr):
|
if not isinstance(arch, UpdateableStr):
|
||||||
|
|
|
@ -66,6 +66,7 @@ def _eval_expr(cr, ident, workitem, action):
|
||||||
ret=False
|
ret=False
|
||||||
assert action, 'You used a NULL action in a workflow, use dummy node instead.'
|
assert action, 'You used a NULL action in a workflow, use dummy node instead.'
|
||||||
for line in action.split('\n'):
|
for line in action.split('\n'):
|
||||||
|
line = line.replace(chr(13),'')
|
||||||
uid=ident[0]
|
uid=ident[0]
|
||||||
model=ident[1]
|
model=ident[1]
|
||||||
ids=[ident[2]]
|
ids=[ident[2]]
|
||||||
|
|
|
@ -96,6 +96,12 @@ def _execute(cr, workitem, activity, ident, stack):
|
||||||
if activity['kind']=='dummy':
|
if activity['kind']=='dummy':
|
||||||
if workitem['state']=='active':
|
if workitem['state']=='active':
|
||||||
_state_set(cr, workitem, activity, 'complete', ident)
|
_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)
|
||||||
|
result=res2
|
||||||
elif activity['kind']=='function':
|
elif activity['kind']=='function':
|
||||||
if workitem['state']=='active':
|
if workitem['state']=='active':
|
||||||
_state_set(cr, workitem, activity, 'running', ident)
|
_state_set(cr, workitem, activity, 'running', ident)
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
__author__ = 'Cédric Krier, <ced@tinyerp.com>'
|
|
||||||
__version__ = '0.1.0'
|
__version__ = '0.1.0'
|
||||||
|
|
||||||
import psycopg
|
import psycopg
|
||||||
|
|
73
setup.py
73
setup.py
|
@ -35,6 +35,9 @@ import glob
|
||||||
from stat import ST_MODE
|
from stat import ST_MODE
|
||||||
|
|
||||||
from distutils.core import setup, Command
|
from distutils.core import setup, Command
|
||||||
|
from distutils.command.install import install
|
||||||
|
from distutils.command.build import build
|
||||||
|
from distutils.command.build_scripts import build_scripts
|
||||||
from distutils.command.install_scripts import install_scripts
|
from distutils.command.install_scripts import install_scripts
|
||||||
from distutils.file_util import copy_file
|
from distutils.file_util import copy_file
|
||||||
|
|
||||||
|
@ -74,10 +77,9 @@ def check_modules():
|
||||||
|
|
||||||
def find_addons():
|
def find_addons():
|
||||||
for (dp, dn, names) in os.walk(opj('bin', 'addons')):
|
for (dp, dn, names) in os.walk(opj('bin', 'addons')):
|
||||||
for dirpath, dirnames, filenames in os.walk(dp):
|
if '__init__.py' in names:
|
||||||
if '__init__.py' in filenames:
|
modname = dp.replace(os.path.sep, '.').replace('bin', 'openerp-server', 1)
|
||||||
modname = dirpath.replace(os.path.sep, '.')
|
yield modname
|
||||||
yield modname.replace('bin', 'openerp-server', 1)
|
|
||||||
|
|
||||||
def data_files():
|
def data_files():
|
||||||
'''Build list of data files to be installed'''
|
'''Build list of data files to be installed'''
|
||||||
|
@ -86,12 +88,10 @@ def data_files():
|
||||||
os.chdir('bin')
|
os.chdir('bin')
|
||||||
for (dp,dn,names) in os.walk('addons'):
|
for (dp,dn,names) in os.walk('addons'):
|
||||||
files.append((dp, map(lambda x: opj('bin', dp, x), names)))
|
files.append((dp, map(lambda x: opj('bin', dp, x), names)))
|
||||||
for (dp,dn,names) in os.walk('i18n'):
|
|
||||||
files.append((dp, map(lambda x: opj('bin', dp, x), names)))
|
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
for (dp,dn,names) in os.walk('doc'):
|
for (dp,dn,names) in os.walk('doc'):
|
||||||
files.append((dp, map(lambda x: opj(dp, x), names)))
|
files.append((dp, map(lambda x: opj(dp, x), names)))
|
||||||
files.append(('.', [('bin/import_xml.rng')]))
|
files.append(('.', [(opj('bin', 'import_xml.rng'))]))
|
||||||
else:
|
else:
|
||||||
man_directory = opj('share', 'man')
|
man_directory = opj('share', 'man')
|
||||||
files.append((opj(man_directory, 'man1'), ['man/openerp-server.1']))
|
files.append((opj(man_directory, 'man1'), ['man/openerp-server.1']))
|
||||||
|
@ -104,59 +104,37 @@ def data_files():
|
||||||
|
|
||||||
openerp_site_packages = opj('lib', 'python%s' % py_short_version, 'site-packages', 'openerp-server')
|
openerp_site_packages = opj('lib', 'python%s' % py_short_version, 'site-packages', 'openerp-server')
|
||||||
|
|
||||||
files.append((opj(openerp_site_packages, 'i18n'), glob.glob('bin/i18n/*')))
|
|
||||||
files.append((opj(openerp_site_packages, 'addons', 'custom'),
|
|
||||||
glob.glob('bin/addons/custom/*xml') + glob.glob('bin/addons/custom/*rml') + glob.glob('bin/addons/custom/*xsl')))
|
|
||||||
|
|
||||||
files.append((openerp_site_packages, [('bin/import_xml.rng')]))
|
files.append((openerp_site_packages, [('bin/import_xml.rng')]))
|
||||||
|
|
||||||
for addon in find_addons():
|
for addon in find_addons():
|
||||||
add_path = addon.replace('.', os.path.sep).replace('openerp-server', 'bin', 1)
|
add_path = addon.replace('.', os.path.sep).replace('openerp-server', 'bin', 1)
|
||||||
addon_path = opj('lib', 'python%s' % py_short_version, 'site-packages', add_path.replace('bin', 'openerp-server', 1))
|
addon_path = opj('lib', 'python%s' % py_short_version, 'site-packages', add_path.replace('bin', 'openerp-server', 1))
|
||||||
|
|
||||||
pathfiles = [
|
pathfiles = []
|
||||||
(
|
for root, dirs, innerfiles in os.walk(add_path):
|
||||||
addon_path,
|
innerfiles = filter(lambda file: os.path.splitext(file)[1] not in ('.pyc', '.py', '.pyd', '.pyo'), innerfiles)
|
||||||
glob.glob(opj(add_path, '*xml')) +
|
if innerfiles:
|
||||||
glob.glob(opj(add_path, '*csv')) +
|
pathfiles.extend(((opj(addon_path, root.replace('bin/addons/', '')), map(lambda file: opj(root, file), innerfiles)),))
|
||||||
glob.glob(opj(add_path, '*sql'))
|
|
||||||
),
|
|
||||||
(
|
|
||||||
opj(addon_path, 'data'),
|
|
||||||
glob.glob(opj(add_path, 'data', '*xml'))
|
|
||||||
),
|
|
||||||
(
|
|
||||||
opj(addon_path, 'report'),
|
|
||||||
glob.glob(opj(add_path, 'report', '*xml')) +
|
|
||||||
glob.glob(opj(add_path, 'report', '*rml')) +
|
|
||||||
glob.glob(opj(add_path, 'report', '*sxw')) +
|
|
||||||
glob.glob(opj(add_path, 'report', '*xsl'))
|
|
||||||
),
|
|
||||||
(
|
|
||||||
opj(addon_path, 'security'),
|
|
||||||
glob.glob(opj(add_path, 'security', '*csv')) +
|
|
||||||
glob.glob(opj(add_path, 'security', '*xml'))
|
|
||||||
),
|
|
||||||
(
|
|
||||||
opj(addon_path, 'rng'),
|
|
||||||
glob.glob(opj(add_path, 'rng', '*rng'))
|
|
||||||
)
|
|
||||||
]
|
|
||||||
files.extend(pathfiles)
|
files.extend(pathfiles)
|
||||||
return files
|
return files
|
||||||
|
|
||||||
check_modules()
|
check_modules()
|
||||||
|
|
||||||
# create startup script
|
f = file('openerp-server','w')
|
||||||
start_script = \
|
start_script = """#!/bin/sh\necho "OpenERP Setup - The content of this file is generated at the install stage" """
|
||||||
"#!/bin/sh\n\
|
|
||||||
cd %s/lib/python%s/site-packages/openerp-server\n\
|
|
||||||
exec %s ./openerp-server.py $@\n" % (sys.prefix, py_short_version, sys.executable)
|
|
||||||
# write script
|
|
||||||
f = open('openerp-server', 'w')
|
|
||||||
f.write(start_script)
|
f.write(start_script)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
class openerp_server_install(install):
|
||||||
|
def run(self):
|
||||||
|
# create startup script
|
||||||
|
start_script = "#!/bin/sh\ncd %s\nexec %s ./openerp-server.py $@\n" % (opj(self.install_libbase, "openerp-server"), sys.executable)
|
||||||
|
# write script
|
||||||
|
f = open('openerp-server', 'w')
|
||||||
|
f.write(start_script)
|
||||||
|
f.close()
|
||||||
|
install.run(self)
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
"py2exe": {
|
"py2exe": {
|
||||||
"compressed": 1,
|
"compressed": 1,
|
||||||
|
@ -179,6 +157,9 @@ setup(name = name,
|
||||||
classifiers = filter(None, classifiers.split("\n")),
|
classifiers = filter(None, classifiers.split("\n")),
|
||||||
license = license,
|
license = license,
|
||||||
data_files = data_files(),
|
data_files = data_files(),
|
||||||
|
cmdclass = {
|
||||||
|
'install' : openerp_server_install,
|
||||||
|
},
|
||||||
scripts = ['openerp-server'],
|
scripts = ['openerp-server'],
|
||||||
packages = ['openerp-server',
|
packages = ['openerp-server',
|
||||||
'openerp-server.addons',
|
'openerp-server.addons',
|
||||||
|
|
Loading…
Reference in New Issue