diff --git a/Makefile b/Makefile index 39ab146c13a..7b410d19dee 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ # -*- makefile -*- addons-path := bin/addons/ +extra-addons:= '' root-path := bin/ port := 8069 net_port := 8070 @@ -22,7 +23,7 @@ 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) + python $(interrogation_file) install-module --modules=$(module) --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --extra-addons=$(extra-addons) --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) diff --git a/bin/addons/base/base_data.xml b/bin/addons/base/base_data.xml index 03869ec8a21..710bddeb73d 100644 --- a/bin/addons/base/base_data.xml +++ b/bin/addons/base/base_data.xml @@ -1212,6 +1212,12 @@ 0.01 4 + + + 5.6 + + + INR diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index e1730b5d4c4..4c938c5210c 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -285,57 +285,57 @@ class ir_model_fields(osv.osv): 'complete_name': fields.char('Complete Name', size=64, select=1), } - def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=800): - def get_fields(cr, uid, field, rel): - result = [] - mobj = self.pool.get('ir.model') - id = mobj.search(cr, uid, [('model','=',rel)]) + def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80): + return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) +# def get_fields(cr, uid, field, rel): +# result = [] +# mobj = self.pool.get('ir.model') +# id = mobj.search(cr, uid, [('model','=',rel)]) - obj = self.pool.get('ir.model.fields') - ids = obj.search(cr, uid, [('model_id','in',id)]) - records = obj.read(cr, uid, ids) - for record in records: - id = record['id'] - fld = field + '/' + record['name'] +# obj = self.pool.get('ir.model.fields') +# ids = obj.search(cr, uid, [('model_id','in',id)]) +# records = obj.read(cr, uid, ids) +# for record in records: +# id = record['id'] +# fld = field + '/' + record['name'] - result.append((id, fld)) - return result +# result.append((id, fld)) +# return result - if not args: - args=[] - if not context: - context={} - return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) +# if not args: +# args=[] +# if not context: +# context={} +# return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) - if context.get('key') != 'server_action': - return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) +# if context.get('key') != 'server_action': +# return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) +# result = [] +# obj = self.pool.get('ir.model.fields') +# ids = obj.search(cr, uid, args) +# records = obj.read(cr, uid, ids) +# for record in records: +# id = record['id'] +# field = record['name'] - result = [] - obj = self.pool.get('ir.model.fields') - ids = obj.search(cr, uid, args) - records = obj.read(cr, uid, ids) - for record in records: - id = record['id'] - field = record['name'] +# if record['ttype'] == 'many2one': +# rel = record['relation'] +# res = get_fields(cr, uid, field, record['relation']) +# for rs in res: +# result.append(rs) - if record['ttype'] == 'many2one': - rel = record['relation'] - res = get_fields(cr, uid, field, record['relation']) - for rs in res: - result.append(rs) +# result.append((id, field)) - result.append((id, field)) +# for rs in result: +# obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]}) - for rs in result: - obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]}) +# iids = [] +# for rs in result: +# iids.append(rs[0]) - iids = [] - for rs in result: - iids.append(rs[0]) +# result = super(ir_model_fields, self).name_search(cr, uid, name, [('complete_name','ilike',name), ('id','in',iids)], operator, context, limit) - result = super(ir_model_fields, self).name_search(cr, uid, name, [('complete_name','ilike',name), ('id','in',iids)], operator, context, limit) - - return result +# return result ir_model_fields() diff --git a/bin/addons/base/ir/ir_cron.py b/bin/addons/base/ir/ir_cron.py index c3e327b9f82..c9288bee07c 100644 --- a/bin/addons/base/ir/ir_cron.py +++ b/bin/addons/base/ir/ir_cron.py @@ -27,8 +27,6 @@ import tools import pooler from osv import fields,osv -next_wait = 60 - _intervalTypes = { 'work_days': lambda interval: DateTime.RelativeDateTime(days=interval), 'days': lambda interval: DateTime.RelativeDateTime(days=interval), @@ -74,20 +72,18 @@ class ir_cron(osv.osv, netsvc.Agent): f = getattr(m, func) f(cr, uid, *args) - def _poolJobs(self, db_name, check=False): + def _poolJobs(self, db_name, check=False): try: db, pool = pooler.get_db_and_pool(db_name) except: - return False - + return False if pool._init: # retry in a few minutes - next_call = 600 + next_call = 600 else: - next_call = next_wait - cr = db.cursor() now = DateTime.now() try: + cr = db.cursor() cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority') for job in cr.dictfetchall(): nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S') @@ -119,10 +115,32 @@ class ir_cron(osv.osv, netsvc.Agent): # Can be improved to do at the min(min(nextcalls), time()+next_call) # But is this an improvement ? # + cr = db.cursor() + cr.execute('select min(nextcall) as min_next_call from ir_cron where numbercall<>0 and active and nextcall>=now()') + next_call = cr.dictfetchone()['min_next_call'] + cr.close() + if next_call: + next_call = time.mktime(time.strptime(next_call, '%Y-%m-%d %H:%M:%S')) + else: + next_call = int(time.time()) + 3600 # if do not find active cron job from database, it will run again after 1 day if not check: - self.setAlarm(self._poolJobs, int(time.time()) + next_call, db_name, db_name) - return None - + self.setAlarm(self._poolJobs, next_call, db_name, db_name) + + def create(self, cr, uid, vals, context=None): + res = super(ir_cron, self).create(cr, uid, vals, context=context) + cr.commit() + self._poolJobs(cr.dbname) + return res + def write(self, cr, user, ids, vals, context=None): + res = super(ir_cron, self).write(cr, user, ids, vals, context=context) + cr.commit() + self._poolJobs(cr.dbname) + return res + def unlink(self, cr, uid, ids, context=None): + res = super(ir_cron, self).unlink(cr, uid, ids, context=context) + cr.commit() + self._poolJobs(cr.dbname) + return res ir_cron() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/addons/base/ir/ir_translation.py b/bin/addons/base/ir/ir_translation.py index 68e9138479e..9bf6e0ae776 100644 --- a/bin/addons/base/ir/ir_translation.py +++ b/bin/addons/base/ir/ir_translation.py @@ -143,6 +143,33 @@ class ir_translation(osv.osv): res = cr.fetchone() trad = res and res[0] or '' return trad + + def create(self, cursor, user, vals, context=None): + if not context: + context = {} + ids = super(ir_translation, self).create(cursor, user, vals, context=context) + for trans_obj in self.read(cursor, user, [ids], ['name','type','res_id'], context=context): + self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], lang=context.get('lang','en_US')) + self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], context.get('lang','en_US'), [trans_obj['res_id']]) + return ids + + def write(self, cursor, user, ids, vals, context=None): + if not context: + context = {} + result = super(ir_translation, self).write(cursor, user, ids, vals, context=context) + for trans_obj in self.read(cursor, user, ids, ['name','type','res_id'], context=context): + self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], lang=context.get('lang','en_US')) + self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], context.get('lang','en_US'), [trans_obj['res_id']]) + return result + + def unlink(self, cursor, user, ids, context=None): + if not context: + context = {} + for trans_obj in self.read(cursor, user, ids, ['name','type','res_id'], context=context): + self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], lang=context.get('lang','en_US')) + self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], context.get('lang','en_US'), [trans_obj['res_id']]) + result = super(ir_translation, self).unlink(cursor, user, ids, context=context) + return result ir_translation() diff --git a/bin/addons/base/res/partner/partner_view.xml b/bin/addons/base/res/partner/partner_view.xml index 127a44e4549..6ed8118ab93 100644 --- a/bin/addons/base/res/partner/partner_view.xml +++ b/bin/addons/base/res/partner/partner_view.xml @@ -325,6 +325,7 @@ res.partner form [('supplier','=',1)] + {'default_customer':0} diff --git a/bin/addons/base/res/res_currency.py b/bin/addons/base/res/res_currency.py index 7033abe7ec6..0ce4cbb3254 100644 --- a/bin/addons/base/res/res_currency.py +++ b/bin/addons/base/res/res_currency.py @@ -26,6 +26,7 @@ import ir from tools.misc import currency from tools.translate import _ +from tools import config import mx.DateTime from mx.DateTime import RelativeDateTime, now, DateTime, localtime @@ -67,7 +68,7 @@ class res_currency(osv.osv): if currency.rounding == 0: return 0.0 else: - return round(amount / currency.rounding) * currency.rounding + return round(amount / currency.rounding, int(config['price_accuracy'])) * currency.rounding def is_zero(self, cr, uid, currency, amount): return abs(self.round(cr, uid, currency, amount)) < currency.rounding diff --git a/bin/addons/base/rng/view.rng b/bin/addons/base/rng/view.rng index 78bef8172f7..025e461cade 100644 --- a/bin/addons/base/rng/view.rng +++ b/bin/addons/base/rng/view.rng @@ -384,6 +384,7 @@ + diff --git a/bin/addons/quality_integration_server/base_quality_interrogation.py b/bin/addons/quality_integration_server/base_quality_interrogation.py index 2df0af247c7..3f3010350f3 100755 --- a/bin/addons/quality_integration_server/base_quality_interrogation.py +++ b/bin/addons/quality_integration_server/base_quality_interrogation.py @@ -34,11 +34,11 @@ import socket admin_passwd = 'admin' waittime = 10 +wait_count = 0 +wait_limit = 12 -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 start_server(root_path, port, addons_path): + os.system('python2.5 %sopenerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(root_path, str(port), addons_path)) def clean(): if os.path.isfile('openerp.pid'): ps = open('openerp.pid') @@ -49,17 +49,24 @@ def clean(): os.kill(pid,9) def execute(connector, method, *args): + global wait_count res = False try: res = getattr(connector,method)(*args) except socket.error,e: - if e.args[0] == 111: + if e.args[0] == 111: + if wait_count > wait_limit: + print "Server is taking too long to start, it has exceeded the maximum limit of %d seconds."%(wait_limit) + clean() + sys.exit(1) print 'Please wait %d sec to start server....'%(waittime) + wait_count += 1 time.sleep(waittime) res = execute(connector, method, *args) else: raise e - return res + wait_count = 0 + return res def login(uri, dbname, user, pwd): conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common') @@ -94,40 +101,51 @@ def import_translate(uri, user, pwd, dbname, translate_in): state = res['state'] -def check_quality(uri, user, pwd, dbname, modules): +def check_quality(uri, user, pwd, dbname, modules, quality_logs): uid = login(uri, dbname, user, pwd) + quality_logs += 'quality-logs' if uid: conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') - qualityresult = {} final = {} - test_detail = {} - for module in modules: + for module in modules: + qualityresult = {} + test_detail = {} quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module) detail_html = '' - html = '''''' + html = '''''' html +="

Module : %s

"%(quality_result['name']) html += "

Final score : %s

"%(quality_result['final_score']) - html += "" - 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 += "
  • %s (%.2f)
  • "%(test,test,score) - detail_html +="

    %s (Score : %s)

    %s
    "%(test,test,score,detail.get('detail')) - detail_html +='''Go to Top''' - test_detail[test] = (score,detail.get('detail','')) - html += "
    %s"%(detail_html) - final[quality_result['name']] = (quality_result['final_score'],html,test_detail) + html += "
    " + html += "
      " + for x,y,detail in quality_result['check_detail_ids']: + test = detail.get('name') + msg = detail.get('message','') + score = round(float(detail.get('score',0)),2) + html += "
    • %s
    • "%(test.replace(' ','-'),test) + if test == 'Unit Test': + if not detail.get('detail',''): + detail['detail'] = '''%s'''%(detail.get('summary','')) + detail_html +="

      %s (Score : %s)

      %s
      "%(test.replace(' ','-'),test,score,detail.get('detail','')) + test_detail[test] = (score,msg,detail.get('detail','')) + html += "
    " + html += "%s"%(detail_html) + html += "
    " + if not os.path.isdir(quality_logs): + os.mkdir(quality_logs) + fp = open('%s/%s.html'%(quality_logs,module),'wb') + fp.write(str(html)) + fp.close() + #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 + #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 True else: print 'Login Failed...' clean() - sys.exit(1) + sys.exit(1) @@ -169,7 +187,7 @@ def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'): 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) + install_module(uri, dbname, ['base_module_quality'],user=user,pwd=pwd) return True def drop_db(uri, dbname): @@ -178,13 +196,38 @@ def drop_db(uri, dbname): if dbname in db_list: execute(conn, 'drop', admin_passwd, dbname) return True + +def make_links(uri, uid, dbname, source, destination, module, user, pwd): + if module in ('base','quality_integration_server'): + return True + if not os.path.islink(destination + '/' + module): + if not os.path.isdir(destination + '/' + module): + for path in source: + if os.path.isdir(path + '/' + module): + os.symlink(path + '/' + module, destination + '/' + module) + obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') + execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'update_list') + module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','=',module)]) + if len(module_ids): + data = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'read', module_ids[0],['name','dependencies_id']) + dep_datas = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module.dependency', 'read', data['dependencies_id'],['name']) + for dep_data in dep_datas: + make_links(uri, uid, dbname, source, destination, dep_data['name'], user, pwd) + return True + return False -def install_module(uri, dbname, modules, user='admin', pwd='admin'): +def install_module(uri, dbname, modules, addons='', extra_addons='', user='admin', pwd='admin'): uid = login(uri, dbname, user, pwd) + if extra_addons: + extra_addons = extra_addons.split(',') if uid: + if addons and extra_addons: + for module in modules: + make_links(uri, uid, dbname, extra_addons, addons, module, user, pwd) + 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)]) + 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' @@ -237,6 +280,7 @@ 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("--quality-logs", dest="quality_logs", help="specify the path of quality logs files which has to stores") 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") @@ -244,6 +288,9 @@ 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") +parser.add_option("--extra-addons", dest="extra_addons", + help="specify extra_addons and trunkCommunity modules path ") + (opt, args) = parser.parse_args() if len(args) != 1: parser.error("incorrect number of arguments") @@ -264,17 +311,26 @@ die(opt.translate_in and (not opt.db_name), options = { 'addons-path' : opt.addons_path or 'addons', + 'quality-logs' : opt.quality_logs or '', 'root-path' : opt.root_path or '', - 'translate-in': opt.translate_in, + '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 '', + 'extra-addons':opt.extra_addons 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 [] +# Hint:i18n-import=purchase:ar_AR.po+sale:fr_FR.po,nl_BE.po +if opt.translate_in: + translate = opt.translate_in + for module_name,po_files in map(lambda x:tuple(x.split(':')),translate.split('+')): + for po_file in po_files.split(','): + po_link = '%s/%s/i18n/%s'%(options['addons-path'], module_name, po_file) + options['translate-in'].append(po_link) + uri = 'http://localhost:' + str(options['port']) server_thread = threading.Thread(target=start_server, @@ -286,13 +342,13 @@ try: if command == 'drop-db': drop_db(uri, options['database']) if command == 'install-module': - install_module(uri, options['database'], options['modules'], options['login'], options['pwd']) + install_module(uri, options['database'], options['modules'],options['addons-path'],options['extra-addons'],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']) + check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'], options['quality-logs']) if command == 'install-translation': - import_translate(uri, options['login'], options['pwd'], options['database'], options['translate_in']) + import_translate(uri, options['login'], options['pwd'], options['database'], options['translate-in']) clean() sys.exit(0) diff --git a/bin/netsvc.py b/bin/netsvc.py index 5254d3ceb80..c45ed5c5d65 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -227,7 +227,7 @@ class Logger(object): try: msg = tools.ustr(msg).strip() if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True): - msg = common().exp_get_server_environment() + msg + msg = common().exp_get_server_environment() + "\n" + msg result = msg.split('\n') except UnicodeDecodeError: diff --git a/bin/osv/fields.py b/bin/osv/fields.py index 0ca657e0ce7..2be9e32c2f0 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -616,6 +616,12 @@ class function(_column): self._multi = multi if 'relation' in args: self._obj = args['relation'] + + if 'digits' in args: + self.digits = args['digits'] + else: + self.digits = (16,2) + self._fnct_inv_arg = fnct_inv_arg if not fnct_inv: self.readonly = 1 diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 312bdc70fee..6b2bc56a673 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -308,7 +308,10 @@ def get_pg_type(f): t = eval('fields.'+(f._type)) f_type = (type_dict[t], type_dict[t]) elif isinstance(f, fields.function) and f._type == 'float': - f_type = ('float8', 'DOUBLE PRECISION') + if f.digits: + f_type = ('numeric', 'NUMERIC(%d,%d)' % (f.digits[0], f.digits[1])) + else: + f_type = ('float8', 'DOUBLE PRECISION') elif isinstance(f, fields.function) and f._type == 'selection': f_type = ('text', 'text') elif isinstance(f, fields.function) and f._type == 'char': @@ -506,7 +509,7 @@ class orm_template(object): for rr in r : if isinstance(rr.name, browse_record): rr = rr.name - dt+=rr.name+',' + dt += rr.name or '' + ',' data[fpos] = dt[:-1] break lines += lines2[1:] @@ -1009,9 +1012,10 @@ class orm_template(object): attrs = {'views': views} if node.hasAttribute('widget') and node.getAttribute('widget')=='selection': # We can not use the 'string' domain has it is defined according to the record ! - dom = None + dom = [] if column._domain and not isinstance(column._domain, (str, unicode)): dom = column._domain + attrs['selection'] = self.pool.get(relation).name_search(cr, user, '', dom, context=context) if (node.hasAttribute('required') and not int(node.getAttribute('required'))) or not column.required: attrs['selection'].append((False,'')) @@ -1816,6 +1820,8 @@ class orm(orm_template): ('varchar', 'text', 'TEXT', ''), ('int4', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ('date', 'datetime', 'TIMESTAMP', '::TIMESTAMP'), + ('numeric', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), + ('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ] # !!! Avoid reduction of varchar field !!! if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size < f.size: @@ -1828,13 +1834,15 @@ class orm(orm_template): cr.commit() for c in casts: if (f_pg_type==c[0]) and (f._type==c[1]): - logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1])) - ok = True - cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) - cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2])) - cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k)) - cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,)) - cr.commit() + if f_pg_type != f_obj_type: + logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1])) + ok = True + cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) + cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2])) + cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k)) + cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,)) + cr.commit() + break if f_pg_type != f_obj_type: if not ok: @@ -2504,9 +2512,10 @@ class orm(orm_template): if c[0].startswith('default_'): del rel_context[c[0]] + result = [] for field in upd_todo: for id in ids: - self._columns[field].set(cr, self, id, field, vals[field], user, context=rel_context) + result += self._columns[field].set(cr, self, id, field, vals[field], user, context=rel_context) or [] for table in self._inherits: col = self._inherits[table] @@ -2568,7 +2577,7 @@ class orm(orm_template): cr.execute('update '+self._table+' set parent_right=parent_right+%s where parent_right>=%s', (distance, position)) cr.execute('update '+self._table+' set parent_left=parent_left-%s, parent_right=parent_right-%s where parent_left>=%s and parent_left<%s', (pleft-position+distance,pleft-position+distance, pleft+distance, pright+distance)) - result = self._store_get_values(cr, user, ids, vals.keys(), context) + result += self._store_get_values(cr, user, ids, vals.keys(), context) for order, object, ids, fields in result: self.pool.get(object)._store_set_values(cr, user, ids, fields, context) diff --git a/bin/release.py b/bin/release.py index e5d56c92854..935d2136460 100644 --- a/bin/release.py +++ b/bin/release.py @@ -22,7 +22,7 @@ ############################################################################## name = 'openerp-server' -version = '5.0.4' +version = '5.0.6' major_version = '5.0' description = 'OpenERP Server' long_desc = '''\ diff --git a/bin/report/printscreen/ps_list.py b/bin/report/printscreen/ps_list.py index 8534fd5c887..d2f946e6715 100644 --- a/bin/report/printscreen/ps_list.py +++ b/bin/report/printscreen/ps_list.py @@ -51,7 +51,10 @@ class report_printscreen_list(report_int): return result def _parse_string(self, view): - dom = etree.XML(view) + try: + dom = etree.XML(view.encode('utf-8')) + except: + dom = etree.XML(view) return self._parse_node(dom) def create(self, cr, uid, ids, datas, context=None): diff --git a/bin/report/report_sxw.py b/bin/report/report_sxw.py index d8e3570454b..5f648b71eb8 100644 --- a/bin/report/report_sxw.py +++ b/bin/report/report_sxw.py @@ -156,7 +156,7 @@ class rml_parse(object): self.cr = cr self.uid = uid self.pool = pooler.get_pool(cr.dbname) - user = self.pool.get('res.users').browse(cr, uid, uid) + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) self.localcontext = { 'user': user, 'company': user.company_id, diff --git a/bin/tools/misc.py b/bin/tools/misc.py index 349085e13b6..25375037bdf 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -332,7 +332,10 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non email_bcc = [] if not attach: - msg = MIMEText(body or '',_subtype=subtype,_charset='utf-8') + try: + msg = MIMEText(body.encode('utf8') or '',_subtype=subtype,_charset='utf-8') + except: + msg = MIMEText(body or '',_subtype=subtype,_charset='utf-8') else: msg = MIMEMultipart() @@ -363,8 +366,10 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non msg['Message-Id'] = "<%s-tinycrm-%s@%s>" % (time.time(), tinycrm, socket.gethostname()) if attach: - msg.attach( MIMEText(body or '', _charset='utf-8', _subtype=subtype) ) - + try: + msg.attach(MIMEText(body.encode('utf8') or '',_subtype=subtype,_charset='utf-8')) + except: + msg.attach(MIMEText(body or '', _charset='utf-8', _subtype=subtype) ) for (fname,fcontent) in attach: part = MIMEBase('application', "octet-stream") part.set_payload( fcontent ) diff --git a/bin/tools/translate.py b/bin/tools/translate.py index 05c44ab6bc3..c91857fe52e 100644 --- a/bin/tools/translate.py +++ b/bin/tools/translate.py @@ -607,10 +607,12 @@ def trans_generate(lang, modules, dbname=None): installed_modids = modobj.search(cr, uid, [('state', '=', 'installed')]) installed_modules = map(lambda m: m['name'], modobj.read(cr, uid, installed_modids, ['name'])) - if tools.config['root_path'] in tools.config['addons_path'] : - path_list = [tools.config['root_path']] + root_path = os.path.join(tools.config['root_path'], 'addons') + + if root_path in tools.config['addons_path'] : + path_list = [root_path] else : - path_list = [tools.config['root_path'],tools.config['addons_path']] + path_list = [root_path,tools.config['addons_path']] for path in path_list: for root, dirs, files in tools.osutil.walksymlinks(path): diff --git a/doc/Changelog b/doc/Changelog index 577dfc5a651..e8866ff37b1 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,179 @@ + +2009-09-22: 5.0.6 +================= + +Bugfixes (server) +----------------- + + * https://launchpad.net/bugs/421904 + * Fields.function : Store value computation corrected + * https://launchpad.net/bugs/407332 + * Price Accuracy : rounding made to be based on --price_accuracy option + +Bugfixes (addons) +----------------- + + * Not linked to a bug report: + * fixed an "unsupported operand type(s) for +: 'bool' and 'str'" error. + * Sale_delivery_report : Delivery order report should take shipping address from picking itself + * account: bugfixed the fiscalyear closing wizard: + * Purchase_manual : certificate on terp displayed wrong value + * https://launchpad.net/bugs/431864 + * hr_timesheet_sheet : casting correction for a view + * https://launchpad.net/bugs/431871 + * Account : Move line creation was giving encoding error while automated entries were inserted,corrected + * https://launchpad.net/bugs/433979 + * [CRITICAL]document: crash list of directory after rev:hmo@tinyerp.com-20090916110722-4kl5t5q71im6c76i + * https://launchpad.net/bugs/407332 + * Account : Rounding problem based on price_accuracy + * https://launchpad.net/bugs/419720 + * Sale : Delivery Date delay computation made corrected when days are passed with fractions + * https://launchpad.net/bugs/423726 + * Sale : SO Boolean field picked behavior corrected + * https://launchpad.net/bugs/431821 + * Account_followup : Sending email while sending follow up corrected. + + +Improvements (addons) +--------------------- + + * purchase_manual: do not redefine view: add fields by inheritance... + * purchase: improve views to be directly usable in portals... + + +2009-09-17: 5.0.5 +================= + +Bugfixes (server) +----------------- + + * Not linked to a bug report: + * quality_integration_server: fixe problem on make link of extra-module in addons + * quality_integration_server : quality log : reduce overwrite last test log in other test logs + * base : ir_cron : take minimun next_call from database for job waiting. if database does not has any job, it will take 1 day for job waiting + * quality_integration_server: get message from base_quality_module if module can not success to reach minimun score + * regression in fields.function computation + * better log error, new line + * Report: context was missing while printing any report with header in a non-English Language + * quality_integration_server: fixe problem on make link of extra-module in addons + * https://launchpad.net/bugs/425131 + * Better translation exportation. + * https://launchpad.net/bugs/379645 + * Print screen : Correction when text for report is already encoded + * https://launchpad.net/bugs/421162 + * Send Mail : Unicode error handled + * Send mail : Non-English characters were throwing error. + * https://launchpad.net/bugs/421137 + * Base : 'Supplier Partners' menu will open new record with supplier=1,customer=0 + * https://launchpad.net/bugs/425430 + * Export : Error solved while Exporting O2M records with None value of any field + * https://launchpad.net/bugs/399208 + * Translation issue with cache: it needed to restart server,SOLVED + * https://launchpad.net/bugs/422563 + * Security Loophole corrected + + +Improvements (server) +--------------------- + + * quality_integration_server: make link of extra-addons module in addons module automatic on install-module command + * quality_integration_server: get message from base_quality_module if module can not success to reach minimun score + * Rng : Accepting Groups under/after/replacing Buttons + * quality_integration_server : quality html log + * quality_integration_server: put max_limit in server connection + * Base : Rate for ARS Added + * cchange version number + + +Bugfixes (addons) +----------------- + + * Not linked to a bug report: + * Purchase_manual : certificate on terp displayed wrong value + * fix the problem of message depending on the partner language + * fix a problem for the overdue payment message + * fix problem to get the detault message + * #416908 computation of invoice lines + * Project : Taks hours computed accurately. + * base_module_record: avoid duplications + * document: do not try to index binary documents + * +1 on the lengthmonth returns was too much, removed it + * Problem when using hr_holidays Summary Report when entering date 1 jan 2009 for example. + * multi currency reconciliations on bank statements weren't properly displayed + * multi currency payments weren't correctly computed on invoice's residual amount + * Project_gtd : Demo data defined for tasks(inboxes) + * Module:product Added report tag for product pricelist reportso that it can be modified using OODesigner + * Document : error on create if attachment not specified + * https://launchpad.net/bugs/422401 + * project_gtd : timebox field re-arranged + * https://launchpad.net/bugs/421907 + * Account : Aged Partner Balance report for Future analysis corrected + * https://launchpad.net/bugs/427388 + * Project : task work behavior towards task hours corrected + * https://launchpad.net/bugs/422408 + * Project_gtd : Hierarchical timeboxes allowed to open + * https://launchpad.net/bugs/403972 + * Account : Reports from Chart of Accounts were not considering contextual value of MOVE(draft,posted) + * https://launchpad.net/bugs/430577 + * Sale : Order Lines switches view from tree,form and view + * https://launchpad.net/bugs/425257 + * Project_gtd : improved menuitems names to avoid user confusion,domain improved + * https://launchpad.net/bugs/422078 + * Account_tax_include : floatdivision error corrected + * https://launchpad.net/bugs/423585 + * https://launchpad.net/bugs/423581 + * https://launchpad.net/bugs/416807 + * report_document : Dashboard should not display partner with no files + * https://launchpad.net/bugs/430522 + * https://launchpad.net/bugs/424214 + * Account :Residual amount unclear when used with partial payments. + * https://launchpad.net/bugs/424177 + * hr_timesheet_sheet : Rounding value problem in float_time widget + * https://launchpad.net/bugs/415056 + * https://launchpad.net/bugs/421636 + * added tooltip on tax and payment term + * https://launchpad.net/bugs/407290 + * https://launchpad.net/bugs/407293 + * Account : Making account.invoice.tax field language-depenant from account.tax + * https://launchpad.net/bugs/430043 + * Hr_timesheet_invoice : Query calculation corrected + * https://launchpad.net/bugs/379645 + * Base_report_creator : Print screen report is now available for custom reports + * https://launchpad.net/bugs/423260 + * Account : Title of of Move Line widnows renamed + * https://launchpad.net/bugs/427982 + * hr_timesheet_invoice : Invoicing analytic entries wizard corrected for product + * https://launchpad.net/bugs/426243 + * Account : Context was missing in report + * https://launchpad.net/bugs/426831 + * l10n_ch : default_value() of res.partner.bank corrected + * https://launchpad.net/bugs/430098 + * Hr_holidays : Workflow actions validations corrected + * https://launchpad.net/bugs/430516 + * https://launchpad.net/bugs/379191 + * its better to aply the patch + * fix the problem for related fields, related fields act as a many2one fields + * https://launchpad.net/bugs/429203 + * CRM : Mailgate script used default uid=3 instead of 1 + * https://launchpad.net/bugs/399817 + * Fixed Partial deliveries problem + + +Improvements (addons) +--------------------- + + * Invoice Supplier Control per line/manual + * add missing file for the followup date + * changed interval CRM calls to 4 hours instead of one -> efficient connection pooling with cron + * add inherited view for company + * add new filed to company object which will store the mesages + * add new data file which will add over due payment message to company + * Account : Analytic Account report following parental relationship approach(account with all its children + * hr_timesheet_invoice : Misleading string on invoice analytic entries' wizard + * base_module_quality: remove certificate tag from terp test + * report_dcoument : changed the misleading name of action + + 2009-08-28: 5.0.4 =================