Merge commit 'origin/master' into xrg (5.0.3 official)
Conflicts: bin/netsvc.py bin/tools/config.py bin/workflow/instance.py bzr revid: p_christ@hol.gr-20090823100210-2py390qp3hym8jlp
This commit is contained in:
commit
8cbe393b52
|
@ -0,0 +1,43 @@
|
|||
# -*- makefile -*-
|
||||
|
||||
addons-path := bin/addons/
|
||||
root-path := bin/
|
||||
port := 8069
|
||||
net_port := 8070
|
||||
module := base
|
||||
database := terp
|
||||
language := fr_FR
|
||||
i18n-import := bin/addons/base/i18n/fr_FR.po
|
||||
interrogation_file := bin/addons/quality_integration_server/base_quality_interrogation.py
|
||||
login := admin
|
||||
password := admin
|
||||
|
||||
start:
|
||||
python $(interrogation_file) start-server --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port)
|
||||
|
||||
create-db:
|
||||
python $(interrogation_file) create-db --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
|
||||
|
||||
drop-db:
|
||||
python $(interrogation_file) drop-db --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port)
|
||||
|
||||
install-module:
|
||||
python $(interrogation_file) install-module --modules=$(module) --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
|
||||
|
||||
upgrade-module:
|
||||
python $(interrogation_file) upgrade-module --modules=$(module) --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
|
||||
|
||||
|
||||
install-translation:
|
||||
python $(interrogation_file) install-translation --database=$(database) --translate-in=$(i18n-import) --port=$(port) --login=$(login) --password=$(password) --root-path=$(root-path) --addons-path=$(addons-path)
|
||||
|
||||
|
||||
version:
|
||||
python bin/openerp-server.py --version
|
||||
|
||||
check-quality:
|
||||
python $(interrogation_file) check-quality --database=$(database) --modules=$(module) --port=$(port) --login=$(login) --password=$(password) --addons-path=$(addons-path) --root-path=$(root-path)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
Metadata-Version: 1.1
|
||||
Name: OpenERP
|
||||
Version: 5.0.1
|
||||
Version: 5.0.3
|
||||
Author: Tiny.be
|
||||
Author-email: fp at tiny be
|
||||
Maintainer: Tiny.be
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
import time
|
||||
from osv import fields,osv
|
||||
import pooler
|
||||
|
||||
class ir_sequence_type(osv.osv):
|
||||
_name = 'ir.sequence.type'
|
||||
|
@ -69,13 +70,12 @@ class ir_sequence(osv.osv):
|
|||
'sec': time.strftime('%S'),
|
||||
}
|
||||
|
||||
def get_id(self, cr, uid, sequence_id, test='id=%s', context={}):
|
||||
def get_id(self, cr, uid, sequence_id, test='id=%s', context=None):
|
||||
try:
|
||||
cr.execute('lock table ir_sequence')
|
||||
cr.execute('select id,number_next,number_increment,prefix,suffix,padding from ir_sequence where '+test+' and active=True', (sequence_id,))
|
||||
cr.execute('SELECT id, number_next, prefix, suffix, padding FROM ir_sequence WHERE '+test+' AND active=%s FOR UPDATE', (sequence_id, True))
|
||||
res = cr.dictfetchone()
|
||||
if res:
|
||||
cr.execute('update ir_sequence set number_next=number_next+number_increment where id=%s and active=True', (res['id'],))
|
||||
cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True))
|
||||
if res['number_next']:
|
||||
return self._process(res['prefix']) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix'])
|
||||
else:
|
||||
|
|
|
@ -325,7 +325,10 @@ class res_partner_address(osv.osv):
|
|||
if context.get('contact_display', 'contact')=='partner':
|
||||
ids = self.search(cr, user, [('partner_id',operator,name)], limit=limit, context=context)
|
||||
else:
|
||||
ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context)
|
||||
if not name:
|
||||
ids = self.search(cr, user, args, limit=limit, context=context)
|
||||
else:
|
||||
ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context)
|
||||
if not ids:
|
||||
ids = self.search(cr, user, [('city',operator,name)] + args, limit=limit, context=context)
|
||||
if name:
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import xmlrpclib
|
||||
import ConfigParser
|
||||
import optparse
|
||||
import sys
|
||||
import thread
|
||||
import threading
|
||||
import os
|
||||
import time
|
||||
import pickle
|
||||
import base64
|
||||
import socket
|
||||
|
||||
admin_passwd = 'admin'
|
||||
waittime = 10
|
||||
|
||||
def start_server(root_path, port, addons_path):
|
||||
if root_path:
|
||||
root_path += '/'
|
||||
os.system('python2.5 '+root_path+'openerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(str(port),addons_path))
|
||||
def clean():
|
||||
if os.path.isfile('openerp.pid'):
|
||||
ps = open('openerp.pid')
|
||||
if ps:
|
||||
pid = int(ps.read())
|
||||
ps.close()
|
||||
if pid:
|
||||
os.kill(pid,9)
|
||||
|
||||
def execute(connector, method, *args):
|
||||
res = False
|
||||
try:
|
||||
res = getattr(connector,method)(*args)
|
||||
except socket.error,e:
|
||||
if e.args[0] == 111:
|
||||
print 'Please wait %d sec to start server....'%(waittime)
|
||||
time.sleep(waittime)
|
||||
res = execute(connector, method, *args)
|
||||
else:
|
||||
raise e
|
||||
return res
|
||||
|
||||
def login(uri, dbname, user, pwd):
|
||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
|
||||
uid = execute(conn,'login',dbname, user, pwd)
|
||||
return uid
|
||||
|
||||
def import_translate(uri, user, pwd, dbname, translate_in):
|
||||
uid = login(uri, dbname, user, pwd)
|
||||
if uid:
|
||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
|
||||
wiz_id = execute(conn,'create',dbname, uid, pwd, 'module.lang.import')
|
||||
for trans_in in translate_in:
|
||||
lang,ext = os.path.splitext(trans_in.split('/')[-1])
|
||||
state = 'init'
|
||||
datas = {'form':{}}
|
||||
while state!='end':
|
||||
res = execute(conn,'execute',dbname, uid, pwd, wiz_id, datas, state, {})
|
||||
if 'datas' in res:
|
||||
datas['form'].update( res['datas'].get('form',{}) )
|
||||
if res['type']=='form':
|
||||
for field in res['fields'].keys():
|
||||
datas['form'][field] = res['fields'][field].get('value', False)
|
||||
state = res['state'][-1][0]
|
||||
trans_obj = open(trans_in)
|
||||
datas['form'].update({
|
||||
'name': lang,
|
||||
'code': lang,
|
||||
'data' : base64.encodestring(trans_obj.read())
|
||||
})
|
||||
trans_obj.close()
|
||||
elif res['type']=='action':
|
||||
state = res['state']
|
||||
|
||||
|
||||
def check_quality(uri, user, pwd, dbname, modules):
|
||||
uid = login(uri, dbname, user, pwd)
|
||||
if uid:
|
||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
||||
qualityresult = {}
|
||||
final = {}
|
||||
test_detail = {}
|
||||
for module in modules:
|
||||
quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module)
|
||||
detail_html = ''
|
||||
html = '''<html><html><html><html><body><a name="TOP"></a>'''
|
||||
html +="<h1> Module : %s </h1>"%(quality_result['name'])
|
||||
html += "<h2> Final score : %s</h2>"%(quality_result['final_score'])
|
||||
html += "<oi>"
|
||||
for x,y,detail in quality_result['check_detail_ids']:
|
||||
if detail.get('detail') != '':
|
||||
test = detail.get('name')
|
||||
score = round(float(detail.get('score',0)),2)
|
||||
html += "<li><a href=\"#%s\">%s (%.2f)</a></li>"%(test,test,score)
|
||||
detail_html +="<a name=\"%s\"><h3>%s (Score : %s)</h3>%s</a>"%(test,test,score,detail.get('detail'))
|
||||
detail_html +='''<a href="#TOP">Go to Top</a>'''
|
||||
test_detail[test] = (score,detail.get('detail',''))
|
||||
html += "</oi>%s</body></html></html></html></html></html>"%(detail_html)
|
||||
final[quality_result['name']] = (quality_result['final_score'],html,test_detail)
|
||||
|
||||
fp = open('quality_log.pck','wb')
|
||||
pck_obj = pickle.dump(final,fp)
|
||||
fp.close()
|
||||
print "LOG PATH%s"%(os.path.realpath('quality_log.pck'))
|
||||
return final
|
||||
else:
|
||||
print 'Login Failed...'
|
||||
clean()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def wait(id,url=''):
|
||||
progress=0.0
|
||||
sock2 = xmlrpclib.ServerProxy(url+'/db')
|
||||
while not progress==1.0:
|
||||
progress,users = execute(sock2,'get_progress',admin_passwd, id)
|
||||
return True
|
||||
|
||||
|
||||
def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'):
|
||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
|
||||
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
||||
wiz_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
|
||||
login_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
|
||||
db_list = execute(conn, 'list')
|
||||
if dbname not in db_list:
|
||||
id = execute(conn,'create',admin_passwd, dbname, True, lang)
|
||||
wait(id,uri)
|
||||
uid = login_conn.login(dbname, user, pwd)
|
||||
|
||||
wiz_id = execute(wiz_conn,'create', dbname, uid, user, 'base_setup.base_setup')
|
||||
|
||||
state = 'init'
|
||||
datas = {'form':{}}
|
||||
|
||||
while state!='config':
|
||||
res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
|
||||
if state=='init':
|
||||
datas['form'].update( res['datas'] )
|
||||
if res['type']=='form':
|
||||
for field in res['fields'].keys():
|
||||
datas['form'][field] = datas['form'].get(field,False)
|
||||
state = res['state'][-1][0]
|
||||
datas['form'].update({
|
||||
'profile': -1
|
||||
})
|
||||
elif res['type']=='state':
|
||||
state = res['state']
|
||||
res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
|
||||
install_module(uri, dbname, ['base_module_quality'],user,pwd)
|
||||
return True
|
||||
|
||||
def drop_db(uri, dbname):
|
||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
|
||||
db_list = execute(conn,'list')
|
||||
if dbname in db_list:
|
||||
execute(conn, 'drop', admin_passwd, dbname)
|
||||
return True
|
||||
|
||||
def install_module(uri, dbname, modules, user='admin', pwd='admin'):
|
||||
uid = login(uri, dbname, user, pwd)
|
||||
if uid:
|
||||
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
||||
wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
|
||||
module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
|
||||
execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_install', module_ids)
|
||||
wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
|
||||
state = 'init'
|
||||
datas = {}
|
||||
#while state!='menu':
|
||||
while state!='end':
|
||||
res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
|
||||
if state == 'init':
|
||||
state = 'start'
|
||||
elif state == 'start':
|
||||
state = 'end'
|
||||
return True
|
||||
|
||||
def upgrade_module(uri, dbname, modules, user='admin', pwd='admin'):
|
||||
uid = login(uri, dbname, user, pwd)
|
||||
if uid:
|
||||
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
||||
wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
|
||||
module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
|
||||
execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_upgrade', module_ids)
|
||||
wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
|
||||
state = 'init'
|
||||
datas = {}
|
||||
#while state!='menu':
|
||||
while state!='end':
|
||||
res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
|
||||
if state == 'init':
|
||||
state = 'start'
|
||||
elif state == 'start':
|
||||
state = 'end'
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
usage = """%prog command [options]
|
||||
|
||||
Basic Commands:
|
||||
start-server Start Server
|
||||
create-db Create new database
|
||||
drop-db Drop database
|
||||
install-module Install module
|
||||
upgrade-module Upgrade module
|
||||
install-translation Install translation file
|
||||
check-quality Calculate quality and dump quality result into quality_log.pck using pickle
|
||||
"""
|
||||
parser = optparse.OptionParser(usage)
|
||||
parser.add_option("--modules", dest="modules",
|
||||
help="specify modules to install or check quality")
|
||||
parser.add_option("--addons-path", dest="addons_path", help="specify the addons path")
|
||||
parser.add_option("--root-path", dest="root_path", help="specify the root path")
|
||||
parser.add_option("-p", "--port", dest="port", help="specify the TCP port", type="int")
|
||||
parser.add_option("-d", "--database", dest="db_name", help="specify the database name")
|
||||
parser.add_option("--login", dest="login", help="specify the User Login")
|
||||
parser.add_option("--password", dest="pwd", help="specify the User Password")
|
||||
parser.add_option("--translate-in", dest="translate_in",
|
||||
help="specify .po files to import translation terms")
|
||||
(opt, args) = parser.parse_args()
|
||||
if len(args) != 1:
|
||||
parser.error("incorrect number of arguments")
|
||||
command = args[0]
|
||||
if command not in ('start-server','create-db','drop-db','install-module','upgrade-module','check-quality','install-translation'):
|
||||
parser.error("incorrect command")
|
||||
|
||||
def die(cond, msg):
|
||||
if cond:
|
||||
print msg
|
||||
sys.exit(1)
|
||||
|
||||
die(opt.modules and (not opt.db_name),
|
||||
"the modules option cannot be used without the database (-d) option")
|
||||
|
||||
die(opt.translate_in and (not opt.db_name),
|
||||
"the translate-in option cannot be used without the database (-d) option")
|
||||
|
||||
options = {
|
||||
'addons-path' : opt.addons_path or 'addons',
|
||||
'root-path' : opt.root_path or '',
|
||||
'translate-in': opt.translate_in,
|
||||
'port' : opt.port or 8069,
|
||||
'database': opt.db_name or 'terp',
|
||||
'modules' : opt.modules or [],
|
||||
'login' : opt.login or 'admin',
|
||||
'pwd' : opt.pwd or '',
|
||||
}
|
||||
|
||||
options['modules'] = opt.modules and map(lambda m: m.strip(), opt.modules.split(',')) or []
|
||||
options['translate_in'] = opt.translate_in and map(lambda m: m.strip(), opt.translate_in.split(',')) or []
|
||||
uri = 'http://localhost:' + str(options['port'])
|
||||
|
||||
server_thread = threading.Thread(target=start_server,
|
||||
args=(options['root-path'], options['port'], options['addons-path']))
|
||||
try:
|
||||
server_thread.start()
|
||||
if command == 'create-db':
|
||||
create_db(uri, options['database'], options['login'], options['pwd'])
|
||||
if command == 'drop-db':
|
||||
drop_db(uri, options['database'])
|
||||
if command == 'install-module':
|
||||
install_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
|
||||
if command == 'upgrade-module':
|
||||
upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
|
||||
if command == 'check-quality':
|
||||
check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'])
|
||||
if command == 'install-translation':
|
||||
import_translate(uri, options['login'], options['pwd'], options['database'], options['translate_in'])
|
||||
clean()
|
||||
sys.exit(0)
|
||||
|
||||
except xmlrpclib.Fault, e:
|
||||
print e.faultString
|
||||
clean()
|
||||
sys.exit(1)
|
||||
except Exception, e:
|
||||
print e
|
||||
clean()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -180,10 +180,11 @@ class Logger(object):
|
|||
msg = tools.exception_to_unicode(msg)
|
||||
|
||||
try:
|
||||
msg = tools.ustr(msg).strip()
|
||||
if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True):
|
||||
msg = common().get_server_environment() + msg
|
||||
|
||||
result = tools.ustr(msg).strip().split('\n')
|
||||
result = msg.split('\n')
|
||||
except UnicodeDecodeError:
|
||||
result = msg.strip().split('\n')
|
||||
try:
|
||||
|
|
|
@ -103,14 +103,23 @@ class expression(object):
|
|||
left, operator, right = e
|
||||
|
||||
working_table = table
|
||||
if left in table._inherit_fields:
|
||||
working_table = table.pool.get(table._inherit_fields[left][0])
|
||||
if working_table not in self.__tables.values():
|
||||
self.__joins.append(('%s.%s=%s.%s' % (working_table._table, 'id', table._table, table._inherits[working_table._name]), working_table._table))
|
||||
|
||||
self.__tables[i] = working_table
|
||||
|
||||
main_table = table
|
||||
fargs = left.split('.', 1)
|
||||
index = i
|
||||
if left in table._inherit_fields:
|
||||
while True:
|
||||
field = main_table._columns.get(fargs[0], False)
|
||||
if field:
|
||||
working_table = main_table
|
||||
self.__tables[i] = working_table
|
||||
break
|
||||
working_table = main_table.pool.get(main_table._inherit_fields[left][0])
|
||||
if working_table not in self.__tables.values():
|
||||
self.__joins.append(('%s.%s=%s.%s' % (working_table._table, 'id', main_table._table, main_table._inherits[working_table._name]), working_table._table))
|
||||
self.__tables[index] = working_table
|
||||
index += 1
|
||||
main_table = working_table
|
||||
|
||||
field = working_table._columns.get(fargs[0], False)
|
||||
if not field:
|
||||
if left == 'id' and operator == 'child_of':
|
||||
|
|
|
@ -53,6 +53,7 @@ def _symbol_set(symb):
|
|||
class _column(object):
|
||||
_classic_read = True
|
||||
_classic_write = True
|
||||
_prefetch = True
|
||||
_properties = False
|
||||
_type = 'unknown'
|
||||
_obj = None
|
||||
|
@ -196,6 +197,7 @@ class binary(_column):
|
|||
_symbol_get = lambda self, x: x and str(x)
|
||||
|
||||
_classic_read = False
|
||||
_prefetch = False
|
||||
|
||||
def __init__(self, string='unknown', filters=None, **args):
|
||||
_column.__init__(self, string=string, **args)
|
||||
|
@ -350,6 +352,7 @@ class many2one(_column):
|
|||
class one2many(_column):
|
||||
_classic_read = False
|
||||
_classic_write = False
|
||||
_prefetch = False
|
||||
_type = 'one2many'
|
||||
|
||||
def __init__(self, obj, fields_id, string='unknown', limit=None, **args):
|
||||
|
@ -426,11 +429,13 @@ class one2many(_column):
|
|||
return res
|
||||
|
||||
def set(self, cr, obj, id, field, values, user=None, context=None):
|
||||
result = []
|
||||
if not context:
|
||||
context = {}
|
||||
if self._context:
|
||||
context = context.copy()
|
||||
context.update(self._context)
|
||||
context['no_store_function'] = True
|
||||
if not values:
|
||||
return
|
||||
_table = obj.pool.get(self._obj)._table
|
||||
|
@ -438,7 +443,8 @@ class one2many(_column):
|
|||
for act in values:
|
||||
if act[0] == 0:
|
||||
act[2][self._fields_id] = id
|
||||
obj.create(cr, user, act[2], context=context)
|
||||
id_new = obj.create(cr, user, act[2], context=context)
|
||||
result += obj._store_get_values(cr, user, [id_new], act[2].keys(), context)
|
||||
elif act[0] == 1:
|
||||
obj.write(cr, user, [act[1]], act[2], context=context)
|
||||
elif act[0] == 2:
|
||||
|
@ -455,6 +461,7 @@ class one2many(_column):
|
|||
cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id not in ('+','.join(map(str, ids2))+')', (id,))
|
||||
ids3 = map(lambda x:x[0], cr.fetchall())
|
||||
obj.write(cr, user, ids3, {self._fields_id:False}, context=context or {})
|
||||
return result
|
||||
|
||||
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
|
||||
return obj.pool.get(self._obj).name_search(cr, uid, value, self._domain, offset, limit)
|
||||
|
@ -472,6 +479,7 @@ class one2many(_column):
|
|||
class many2many(_column):
|
||||
_classic_read = False
|
||||
_classic_write = False
|
||||
_prefetch = False
|
||||
_type = 'many2many'
|
||||
|
||||
def __init__(self, obj, rel, id1, id2, string='unknown', limit=None, **args):
|
||||
|
@ -582,6 +590,7 @@ class many2many(_column):
|
|||
class function(_column):
|
||||
_classic_read = False
|
||||
_classic_write = False
|
||||
_prefetch = False
|
||||
_type = 'function'
|
||||
_properties = True
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ class browse_record(object):
|
|||
return None
|
||||
|
||||
# if the field is a classic one or a many2one, we'll fetch all classic and many2one fields
|
||||
if col._classic_write:
|
||||
if col._prefetch:
|
||||
# gen the list of "local" (ie not inherited) fields which are classic or many2one
|
||||
ffields = filter(lambda x: x[1]._classic_write, self._table._columns.items())
|
||||
# gen the list of inherited fields
|
||||
|
@ -673,7 +673,7 @@ class orm_template(object):
|
|||
if fields_def[field[len(prefix)]]['type'] == 'integer':
|
||||
res = line[i] and int(line[i])
|
||||
elif fields_def[field[len(prefix)]]['type'] == 'boolean':
|
||||
res = line[i] and bool(line[i])
|
||||
res = line[i].lower() not in ('0', 'false', 'off')
|
||||
elif fields_def[field[len(prefix)]]['type'] == 'float':
|
||||
res = line[i] and float(line[i])
|
||||
elif fields_def[field[len(prefix)]]['type'] == 'selection':
|
||||
|
@ -1444,10 +1444,10 @@ class orm_memory(orm_template):
|
|||
self._validate(cr, user, [id_new], context)
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_write(user, self._name, id_new, cr)
|
||||
self.vaccum(cr, user)
|
||||
return id_new
|
||||
|
||||
def create(self, cr, user, vals, context=None):
|
||||
self.vaccum(cr, user)
|
||||
self.next_id += 1
|
||||
id_new = self.next_id
|
||||
default = []
|
||||
|
@ -1471,7 +1471,6 @@ class orm_memory(orm_template):
|
|||
self._validate(cr, user, [id_new], context)
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_create(user, self._name, id_new, cr)
|
||||
self.vaccum(cr, user)
|
||||
return id_new
|
||||
|
||||
def default_get(self, cr, uid, fields_list, context=None):
|
||||
|
@ -2056,7 +2055,9 @@ class orm(orm_template):
|
|||
self._inherits_reload_src()
|
||||
|
||||
def fields_get(self, cr, user, fields=None, context=None):
|
||||
read_access = self.pool.get('ir.model.access').check(cr, user, self._name, 'write', raise_exception=False, context=context)
|
||||
ira = self.pool.get('ir.model.access')
|
||||
read_access = ira.check(cr, user, self._name, 'write', raise_exception=False, context=context) or \
|
||||
ira.check(cr, user, self._name, 'create', raise_exception=False, context=context)
|
||||
return super(orm, self).fields_get(cr, user, fields, context, read_access)
|
||||
|
||||
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
|
||||
|
@ -2361,6 +2362,7 @@ class orm(orm_template):
|
|||
if not edit:
|
||||
vals.pop(field)
|
||||
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
if not ids:
|
||||
|
@ -2372,6 +2374,7 @@ class orm(orm_template):
|
|||
|
||||
self.pool.get('ir.model.access').check(cr, user, self._name, 'write', context=context)
|
||||
|
||||
|
||||
upd0 = []
|
||||
upd1 = []
|
||||
upd_todo = []
|
||||
|
@ -2448,6 +2451,7 @@ class orm(orm_template):
|
|||
src_trans = self.pool.get(self._name).read(cr,user,ids,[f])
|
||||
self.pool.get('ir.translation')._set_ids(cr, user, self._name+','+f, 'model', context['lang'], ids, vals[f], src_trans[0][f])
|
||||
|
||||
|
||||
# call the 'set' method of fields which are not classic_write
|
||||
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
|
||||
|
||||
|
@ -2549,12 +2553,12 @@ class orm(orm_template):
|
|||
for (t, c) in self._inherits.items():
|
||||
if c in vals:
|
||||
avoid_table.append(t)
|
||||
for f in self._columns.keys(): # + self._inherit_fields.keys():
|
||||
if not f in vals:
|
||||
for f in self._columns.keys():
|
||||
if (not f in vals) and (not isinstance(self._columns[f], fields.property)):
|
||||
default.append(f)
|
||||
|
||||
for f in self._inherit_fields.keys():
|
||||
if (not f in vals) and (self._inherit_fields[f][0] not in avoid_table):
|
||||
if (not f in vals) and (self._inherit_fields[f][0] not in avoid_table) and (not isinstance(self._inherit_fields[f][2], fields.property)):
|
||||
default.append(f)
|
||||
|
||||
if len(default):
|
||||
|
@ -2563,7 +2567,6 @@ class orm(orm_template):
|
|||
if dv in self._columns and self._columns[dv]._type == 'many2many':
|
||||
if default_values[dv] and isinstance(default_values[dv][0], (int, long)):
|
||||
default_values[dv] = [(6, 0, default_values[dv])]
|
||||
|
||||
vals.update(default_values)
|
||||
|
||||
tocreate = {}
|
||||
|
@ -2666,13 +2669,19 @@ class orm(orm_template):
|
|||
if c[0].startswith('default_'):
|
||||
del rel_context[c[0]]
|
||||
|
||||
result = []
|
||||
for field in upd_todo:
|
||||
self._columns[field].set(cr, self, id_new, field, vals[field], user, rel_context)
|
||||
result += self._columns[field].set(cr, self, id_new, field, vals[field], user, rel_context) or []
|
||||
self._validate(cr, user, [id_new], context)
|
||||
|
||||
result = self._store_get_values(cr, user, [id_new], vals.keys(), context)
|
||||
for order, object, ids, fields in result:
|
||||
self.pool.get(object)._store_set_values(cr, user, ids, fields, context)
|
||||
if not context.get('no_store_function', False):
|
||||
result += self._store_get_values(cr, user, [id_new], vals.keys(), context)
|
||||
result.sort()
|
||||
done = []
|
||||
for order, object, ids, fields2 in result:
|
||||
if not (object, ids, fields2) in done:
|
||||
self.pool.get(object)._store_set_values(cr, user, ids, fields2, context)
|
||||
done.append((object, ids, fields2))
|
||||
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_create(user, self._name, id_new, cr)
|
||||
|
@ -2682,6 +2691,15 @@ class orm(orm_template):
|
|||
result = {}
|
||||
fncts = self.pool._store_function.get(self._name, [])
|
||||
for fnct in range(len(fncts)):
|
||||
if fncts[fnct][3]:
|
||||
ok = False
|
||||
for f in (fields or []):
|
||||
if f in fncts[fnct][3]:
|
||||
ok = True
|
||||
break
|
||||
if not ok:
|
||||
continue
|
||||
|
||||
result.setdefault(fncts[fnct][0], {})
|
||||
ids2 = fncts[fnct][2](self,cr, uid, ids, context)
|
||||
for id in filter(None, ids2):
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
##############################################################################
|
||||
|
||||
name = 'openerp-server'
|
||||
version = '5.0.3-bzr'
|
||||
version = '5.0.3'
|
||||
major_version = '5.0'
|
||||
description = 'OpenERP Server'
|
||||
long_desc = '''\
|
||||
|
|
|
@ -240,7 +240,7 @@ class document(object):
|
|||
txt = str(datas[atr['value']])
|
||||
else:
|
||||
txt = datas[atr['value']]
|
||||
el.append(txt)
|
||||
el.text = txt
|
||||
else:
|
||||
for el_cld in node:
|
||||
parse_result_tree(el_cld, el, datas)
|
||||
|
|
|
@ -51,7 +51,7 @@ class report_printscreen_list(report_int):
|
|||
return result
|
||||
|
||||
def _parse_string(self, view):
|
||||
dom = etree.XML(unicode(view, 'utf-8').encode('utf-8'))
|
||||
dom = etree.XML(view)
|
||||
return self._parse_node(dom)
|
||||
|
||||
def create(self, cr, uid, ids, datas, context=None):
|
||||
|
@ -139,7 +139,7 @@ class report_printscreen_list(report_int):
|
|||
|
||||
for f in fields_order:
|
||||
field = etree.Element("field")
|
||||
field.text = fields[f]['string'] or ''
|
||||
field.text = tools.ustr(fields[f]['string'] or '')
|
||||
header.append(field)
|
||||
|
||||
new_doc.append(header)
|
||||
|
@ -153,7 +153,7 @@ class report_printscreen_list(report_int):
|
|||
node_line = etree.Element("row")
|
||||
count = -1
|
||||
for f in fields_order:
|
||||
|
||||
float_flag = 0
|
||||
count += 1
|
||||
|
||||
if fields[f]['type']=='many2one' and line[f]:
|
||||
|
@ -170,7 +170,9 @@ class report_printscreen_list(report_int):
|
|||
|
||||
if fields[f]['type'] == 'float' and line[f]:
|
||||
precision=(('digits' in fields[f]) and fields[f]['digits'][1]) or 2
|
||||
line[f]='%.2f'%(line[f])
|
||||
prec ='%.' + str(precision) +'f'
|
||||
line[f]=prec%(line[f])
|
||||
float_flag = 1
|
||||
|
||||
if fields[f]['type'] == 'date' and line[f]:
|
||||
format = str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))
|
||||
|
@ -195,8 +197,12 @@ class report_printscreen_list(report_int):
|
|||
col.set('tree','no')
|
||||
if line[f] != None:
|
||||
col.text = tools.ustr(line[f] or '')
|
||||
if float_flag:
|
||||
col.set('tree','float')
|
||||
if temp[count] == 1:
|
||||
tsum[count] = float(tsum[count]) + float(line[f]);
|
||||
|
||||
|
||||
else:
|
||||
col.text = '/'
|
||||
node_line.append(col)
|
||||
|
@ -210,16 +216,18 @@ class report_printscreen_list(report_int):
|
|||
col.set('tree','no')
|
||||
if tsum[f] != None:
|
||||
if tsum[f] >= 0.01 :
|
||||
total = '%.2f'%(tsum[f])
|
||||
txt = str(total or '')
|
||||
else :
|
||||
txt = str(tsum[f] or '')
|
||||
prec = '%.' + str(tools.config['price_accuracy']) + 'f'
|
||||
total = prec%(tsum[f])
|
||||
txt = str(total or '')
|
||||
col.set('tree','float')
|
||||
else:
|
||||
txt = str(tsum[f] or '')
|
||||
else:
|
||||
txt = '/'
|
||||
if f == 0:
|
||||
txt ='Total'
|
||||
|
||||
col.text = txt
|
||||
col.text = tools.ustr(txt or '')
|
||||
node_line.append(col)
|
||||
|
||||
lines.append(node_line)
|
||||
|
|
|
@ -236,7 +236,8 @@ class _rml_canvas(object):
|
|||
self.canvas.setTitle(self.title)
|
||||
|
||||
def _textual(self, node, x=0, y=0):
|
||||
rc = utils._process_text(self, node.text.encode('utf-8') or '')
|
||||
text = node.text and node.text.encode('utf-8') or ''
|
||||
rc = utils._process_text(self, text)
|
||||
for n in node:
|
||||
if n.tag == 'seq':
|
||||
from reportlab.lib.sequencer import getSequencer
|
||||
|
|
|
@ -189,7 +189,7 @@ class rml_parse(object):
|
|||
return newtag, attrs
|
||||
|
||||
def format(self, text, oldtag=None):
|
||||
return text
|
||||
return text.strip()
|
||||
|
||||
def removeParentNode(self, tag=None):
|
||||
raise Exception('Skip')
|
||||
|
@ -420,12 +420,14 @@ class report_sxw(report_rml, preprocess.report):
|
|||
return s.getvalue(), results[0][1]
|
||||
return self.create_single_pdf(cr, uid, ids, data, report_xml, context)
|
||||
|
||||
def create_single_pdf(self, cr, uid, ids, data, report_xml, context={}):
|
||||
def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
logo = None
|
||||
context = context.copy()
|
||||
title = report_xml.name
|
||||
rml = report_xml.report_rml_content
|
||||
rml_parser = self.parser(cr, uid, self.name2, context)
|
||||
rml_parser = self.parser(cr, uid, self.name2, context=context)
|
||||
objs = self.getObjects(cr, uid, ids, context)
|
||||
rml_parser.set_context(objs, data, ids, report_xml.report_type)
|
||||
processed_rml = self.preprocess_rml(etree.XML(rml),report_xml.report_type)
|
||||
|
@ -437,7 +439,9 @@ class report_sxw(report_rml, preprocess.report):
|
|||
pdf = create_doc(etree.tostring(processed_rml),rml_parser.localcontext,logo,title.encode('utf8'))
|
||||
return (pdf, report_xml.report_type)
|
||||
|
||||
def create_single_odt(self, cr, uid, ids, data, report_xml, context={}):
|
||||
def create_single_odt(self, cr, uid, ids, data, report_xml, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
context = context.copy()
|
||||
report_type = report_xml.report_type
|
||||
context['parents'] = sxw_parents
|
||||
|
@ -447,7 +451,7 @@ class report_sxw(report_rml, preprocess.report):
|
|||
meta = sxw_z.read('meta.xml')
|
||||
sxw_z.close()
|
||||
|
||||
rml_parser = self.parser(cr, uid, self.name2, context)
|
||||
rml_parser = self.parser(cr, uid, self.name2, context=context)
|
||||
rml_parser.parents = sxw_parents
|
||||
rml_parser.tag = sxw_tag
|
||||
objs = self.getObjects(cr, uid, ids, context)
|
||||
|
@ -514,7 +518,7 @@ class report_sxw(report_rml, preprocess.report):
|
|||
if report_xml.header:
|
||||
#Add corporate header/footer
|
||||
rml = tools.file_open(os.path.join('base', 'report', 'corporate_%s_header.xml' % report_type)).read()
|
||||
rml_parser = self.parser(cr, uid, self.name2, context)
|
||||
rml_parser = self.parser(cr, uid, self.name2, context=context)
|
||||
rml_parser.parents = sxw_parents
|
||||
rml_parser.tag = sxw_tag
|
||||
objs = self.getObjects(cr, uid, ids, context)
|
||||
|
@ -532,13 +536,15 @@ class report_sxw(report_rml, preprocess.report):
|
|||
sxw_io.close()
|
||||
return (final_op, report_type)
|
||||
|
||||
def create_single_html2html(self, cr, uid, ids, data, report_xml, context={}):
|
||||
def create_single_html2html(self, cr, uid, ids, data, report_xml, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
context = context.copy()
|
||||
report_type = 'html'
|
||||
context['parents'] = html_parents
|
||||
|
||||
html = report_xml.report_rml_content
|
||||
html_parser = self.parser(cr, uid, self.name2, context)
|
||||
html_parser = self.parser(cr, uid, self.name2, context=context)
|
||||
html_parser.parents = html_parents
|
||||
html_parser.tag = sxw_tag
|
||||
objs = self.getObjects(cr, uid, ids, context)
|
||||
|
|
|
@ -612,9 +612,16 @@ class cache(object):
|
|||
"""
|
||||
|
||||
def to_tuple(d):
|
||||
i = d.items()
|
||||
i.sort(key=lambda (x,y): x)
|
||||
return tuple(i)
|
||||
pairs = d.items()
|
||||
pairs.sort(key=lambda (k,v): k)
|
||||
for i, (k, v) in enumerate(pairs):
|
||||
if isinstance(v, dict):
|
||||
pairs[i] = (k, to_tuple(v))
|
||||
if isinstance(v, (list, set)):
|
||||
pairs[i] = (k, tuple(v))
|
||||
elif not is_hashable(v):
|
||||
pairs[i] = (k, repr(v))
|
||||
return tuple(pairs)
|
||||
|
||||
if not self.multi:
|
||||
key = (('dbname', dbname),) + to_tuple(kwargs2)
|
||||
|
@ -631,12 +638,6 @@ class cache(object):
|
|||
kwargs2 = self.fun_default_values.copy()
|
||||
kwargs2.update(kwargs)
|
||||
kwargs2.update(dict(zip(self.fun_arg_names, args[self.skiparg-2:])))
|
||||
for k in kwargs2:
|
||||
if isinstance(kwargs2[k], (list, dict, set)):
|
||||
kwargs2[k] = tuple(kwargs2[k])
|
||||
elif not is_hashable(kwargs2[k]):
|
||||
kwargs2[k] = repr(kwargs2[k])
|
||||
|
||||
return kwargs2
|
||||
|
||||
def clear(self, dbname, *args, **kwargs):
|
||||
|
|
|
@ -344,8 +344,9 @@ def trans_export(lang, modules, buffer, format, dbname=None):
|
|||
tmpmoddir = join(tmpdir, mod, 'i18n')
|
||||
os.makedirs(tmpmoddir)
|
||||
pofilename = (newlang and mod or lang) + ".po" + (newlang and 't' or '')
|
||||
buf = open(join(tmpmoddir, pofilename), 'w')
|
||||
buf = file(join(tmpmoddir, pofilename), 'w')
|
||||
_process('po', [mod], modrows, buf, lang, newlang)
|
||||
buf.close()
|
||||
|
||||
tar = tarfile.open(fileobj=buffer, mode='w|gz')
|
||||
tar.add(tmpdir, '')
|
||||
|
|
|
@ -43,7 +43,7 @@ def delete(cr, ident):
|
|||
|
||||
def validate(cr, inst_id, ident, signal, force_running=False):
|
||||
cr.execute("select * from wkf_workitem where inst_id=%s", (inst_id,))
|
||||
stack = None
|
||||
stack = []
|
||||
for witem in cr.dictfetchall():
|
||||
stack = []
|
||||
workitem.process(cr, witem, ident, signal, force_running, stack=stack)
|
||||
|
|
|
@ -1,8 +1,85 @@
|
|||
2009-08-21: 5.0.2
|
||||
=================
|
||||
|
||||
Bugfixes (server)
|
||||
-----------------
|
||||
|
||||
* Not linked to a bug report:
|
||||
* set_alarm: removed unwanted comment
|
||||
* report engine: context argument was passed at a wrong position. Now it's passed as a named argument.
|
||||
* fields_get check access aginst write or create access
|
||||
* Not allowing only white spaces text to be printed
|
||||
* sequences: avoid an sql error when locking table...
|
||||
* report engine: fixed a bug when the xml tag is empty
|
||||
* bin/workflow: 'stack' variable was not initialized when sql query returned an empty set.
|
||||
* security issue: avoid access to inactive users
|
||||
* security issue: avoid access with 'None' password (Thanks to P. Christeas for the bug report)
|
||||
* avoid a bug when look in stack when translate code strings
|
||||
|
||||
* https://launchpad.net/bugs/415257
|
||||
* import of boolean fields in csv files.
|
||||
* https://launchpad.net/bugs/415014
|
||||
* correct translation tgz archive creation
|
||||
* https://launchpad.net/bugs/362280
|
||||
* https://launchpad.net/bugs/416883
|
||||
* Print screen unicode-decode error solved
|
||||
* https://launchpad.net/bugs/400378
|
||||
* partner address search
|
||||
* https://launchpad.net/bugs/415972
|
||||
* do not get next sequence in its own cursor
|
||||
* https://launchpad.net/bugs/413484
|
||||
* Print Screen : was not considering field names with superscripted,subscripted characters(ex.m²)
|
||||
* https://launchpad.net/bugs/406945
|
||||
* import of boolean fields in csv files.
|
||||
* https://launchpad.net/bugs/413586
|
||||
* bug in cache system that altered some arguments passed to cached function
|
||||
* https://launchpad.net/bugs/413594
|
||||
* logger: convert the message in unicode before concatenate it with server environment
|
||||
* https://launchpad.net/bugs/348217
|
||||
* Secure option on config file
|
||||
|
||||
|
||||
Improvements (server)
|
||||
---------------------
|
||||
|
||||
* Makefile and quality_integration_server module for Integration server
|
||||
* Speed impprovement: 2x faster for flow: sale -> invoice -> payment
|
||||
* Speed improvement in creation of records (4 time faster on partners)
|
||||
|
||||
|
||||
Bugfixes (addons)
|
||||
-----------------
|
||||
|
||||
* Not linked to a bug report:
|
||||
* Purchase :copy method was not setting stock moves to be null for PO lines
|
||||
* Module:account Fix keyerror in general_ledger report
|
||||
* Access rules stock / worker
|
||||
* mrp: fr_FR.po file had a duplicate message definition
|
||||
|
||||
* https://launchpad.net/bugs/413699
|
||||
* https://launchpad.net/bugs/415014
|
||||
* report_task: regenerate translations files
|
||||
* https://launchpad.net/bugs/397100
|
||||
* improving commit on report
|
||||
* https://launchpad.net/bugs/416296
|
||||
* Base_setup : Country passed in values only if filled
|
||||
* https://launchpad.net/bugs/415218
|
||||
* report_task : report_task_user_pipeline_open was having no uniqueness
|
||||
|
||||
|
||||
Improvements (addons)
|
||||
---------------------
|
||||
|
||||
* POS: improved the point_of_sale receipt
|
||||
|
||||
|
||||
|
||||
2009-08-12: 5.0.2
|
||||
=================
|
||||
|
||||
Bugfixes (server)
|
||||
-----------------
|
||||
|
||||
* Not Linked to a bug report:
|
||||
* ensure sys is imported
|
||||
* pass the context to check method of 'ir.model.access'
|
||||
|
@ -130,6 +207,7 @@ Bugfixes (server)
|
|||
|
||||
Improvements (server)
|
||||
---------------------
|
||||
|
||||
* Logger notification improved
|
||||
* update po(t) files
|
||||
* new method that allow the server to return a message that will be display on login page
|
||||
|
@ -146,6 +224,7 @@ Improvements (server)
|
|||
|
||||
Bugfixes (addons)
|
||||
-----------------
|
||||
|
||||
* Not linked to a bug report:
|
||||
* DMS directory not translatable + translations improvement
|
||||
* Project : Searching active=no was failing, corrected
|
||||
|
@ -339,6 +418,7 @@ Bugfixes (addons)
|
|||
|
||||
Improvements (addons)
|
||||
---------------------
|
||||
|
||||
* update po(t) files
|
||||
* Module:account Api changes def _refund_cleanup_lines(self, lines): added cr,uid arguments
|
||||
* pyflakes test display result improve on base_module_quality
|
||||
|
@ -381,37 +461,46 @@ Improvements (addons)
|
|||
|
||||
2009-05-26: 5.0.1
|
||||
=================
|
||||
|
||||
TODO
|
||||
|
||||
2009-02-12: 5.0.0-3
|
||||
===================
|
||||
|
||||
TODO
|
||||
|
||||
2009-02-08: 5.0.0-2
|
||||
===================
|
||||
|
||||
TODO
|
||||
|
||||
2009-02-06: 5.0.0
|
||||
=================
|
||||
|
||||
TODO
|
||||
|
||||
2009-01-03: 5.0.0-rc3
|
||||
=====================
|
||||
|
||||
TODO
|
||||
|
||||
2008-12-22: 5.0.0-rc2
|
||||
=====================
|
||||
|
||||
TODO
|
||||
|
||||
2008-12-01: 5.0.0-rc1.1
|
||||
=======================
|
||||
|
||||
TODO
|
||||
|
||||
2008-11-28: 5.0.0-rc1
|
||||
=====================
|
||||
|
||||
TODO
|
||||
|
||||
2008-11-03: 5.0.0-alpha
|
||||
=======================
|
||||
|
||||
TODO
|
||||
|
||||
|
|
Loading…
Reference in New Issue