Merge remote branch 'origin/master', v5.0.6 into optimize
Conflicts: bin/addons/base/ir/ir_cron.py bin/netsvc.py bin/osv/orm.py bzr revid: p_christ@hol.gr-20090925204745-352t3ngsltr4cj8a
This commit is contained in:
commit
71d5ee956a
3
Makefile
3
Makefile
|
@ -1,6 +1,7 @@
|
||||||
# -*- makefile -*-
|
# -*- makefile -*-
|
||||||
|
|
||||||
addons-path := bin/addons/
|
addons-path := bin/addons/
|
||||||
|
extra-addons:= ''
|
||||||
root-path := bin/
|
root-path := bin/
|
||||||
port := 8069
|
port := 8069
|
||||||
net_port := 8070
|
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)
|
python $(interrogation_file) drop-db --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port)
|
||||||
|
|
||||||
install-module:
|
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:
|
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)
|
python $(interrogation_file) upgrade-module --modules=$(module) --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
|
||||||
|
|
|
@ -1212,6 +1212,12 @@
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="rateARS" model="res.currency.rate">
|
||||||
|
<field name="rate">5.6</field>
|
||||||
|
<field name="currency_id" ref="ARS"/>
|
||||||
|
<field eval="time.strftime('%Y-01-01')" name="name"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record id="INR" model="res.currency">
|
<record id="INR" model="res.currency">
|
||||||
<field name="name">INR</field>
|
<field name="name">INR</field>
|
||||||
|
|
|
@ -285,57 +285,57 @@ class ir_model_fields(osv.osv):
|
||||||
'complete_name': fields.char('Complete Name', 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=800):
|
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80):
|
||||||
def get_fields(cr, uid, field, rel):
|
return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
|
||||||
result = []
|
# def get_fields(cr, uid, field, rel):
|
||||||
mobj = self.pool.get('ir.model')
|
# result = []
|
||||||
id = mobj.search(cr, uid, [('model','=',rel)])
|
# mobj = self.pool.get('ir.model')
|
||||||
|
# id = mobj.search(cr, uid, [('model','=',rel)])
|
||||||
|
|
||||||
obj = self.pool.get('ir.model.fields')
|
# obj = self.pool.get('ir.model.fields')
|
||||||
ids = obj.search(cr, uid, [('model_id','in',id)])
|
# ids = obj.search(cr, uid, [('model_id','in',id)])
|
||||||
records = obj.read(cr, uid, ids)
|
# records = obj.read(cr, uid, ids)
|
||||||
for record in records:
|
# for record in records:
|
||||||
id = record['id']
|
# id = record['id']
|
||||||
fld = field + '/' + record['name']
|
# fld = field + '/' + record['name']
|
||||||
|
|
||||||
result.append((id, fld))
|
# result.append((id, fld))
|
||||||
return result
|
# return result
|
||||||
|
|
||||||
if not args:
|
# if not args:
|
||||||
args=[]
|
# args=[]
|
||||||
if not context:
|
# if not context:
|
||||||
context={}
|
# context={}
|
||||||
return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
|
# return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
|
||||||
|
|
||||||
if context.get('key') != 'server_action':
|
# if context.get('key') != 'server_action':
|
||||||
return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
|
# 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 = []
|
# if record['ttype'] == 'many2one':
|
||||||
obj = self.pool.get('ir.model.fields')
|
# rel = record['relation']
|
||||||
ids = obj.search(cr, uid, args)
|
# res = get_fields(cr, uid, field, record['relation'])
|
||||||
records = obj.read(cr, uid, ids)
|
# for rs in res:
|
||||||
for record in records:
|
# result.append(rs)
|
||||||
id = record['id']
|
|
||||||
field = record['name']
|
|
||||||
|
|
||||||
if record['ttype'] == 'many2one':
|
# result.append((id, field))
|
||||||
rel = record['relation']
|
|
||||||
res = get_fields(cr, uid, field, record['relation'])
|
|
||||||
for rs in res:
|
|
||||||
result.append(rs)
|
|
||||||
|
|
||||||
result.append((id, field))
|
# for rs in result:
|
||||||
|
# obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]})
|
||||||
|
|
||||||
for rs in result:
|
# iids = []
|
||||||
obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]})
|
# for rs in result:
|
||||||
|
# iids.append(rs[0])
|
||||||
|
|
||||||
iids = []
|
# result = super(ir_model_fields, self).name_search(cr, uid, name, [('complete_name','ilike',name), ('id','in',iids)], operator, context, limit)
|
||||||
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)
|
# return result
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
ir_model_fields()
|
ir_model_fields()
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,6 @@ import tools
|
||||||
import pooler
|
import pooler
|
||||||
from osv import fields,osv
|
from osv import fields,osv
|
||||||
|
|
||||||
next_wait = 60
|
|
||||||
|
|
||||||
_intervalTypes = {
|
_intervalTypes = {
|
||||||
'work_days': lambda interval: DateTime.RelativeDateTime(days=interval),
|
'work_days': lambda interval: DateTime.RelativeDateTime(days=interval),
|
||||||
'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 = getattr(m, func)
|
||||||
f(cr, uid, *args)
|
f(cr, uid, *args)
|
||||||
|
|
||||||
def _poolJobs(self, db_name, check=False):
|
def _poolJobs(self, db_name, check=False):
|
||||||
try:
|
try:
|
||||||
db, pool = pooler.get_db_and_pool(db_name)
|
db, pool = pooler.get_db_and_pool(db_name)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if pool._init:
|
if pool._init:
|
||||||
# retry in a few minutes
|
# retry in a few minutes
|
||||||
next_call = 600
|
next_call = 600
|
||||||
else:
|
else:
|
||||||
next_call = next_wait
|
|
||||||
cr = db.cursor()
|
|
||||||
now = DateTime.now()
|
now = DateTime.now()
|
||||||
try:
|
try:
|
||||||
|
cr = db.cursor()
|
||||||
cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority')
|
cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority')
|
||||||
for job in cr.dictfetchall():
|
for job in cr.dictfetchall():
|
||||||
nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S')
|
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)
|
# Can be improved to do at the min(min(nextcalls), time()+next_call)
|
||||||
# But is this an improvement ?
|
# 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:
|
if not check:
|
||||||
self.setAlarm(self._poolJobs, int(time.time()) + next_call, db_name, db_name)
|
self.setAlarm(self._poolJobs, next_call, db_name, db_name)
|
||||||
return None
|
|
||||||
|
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()
|
ir_cron()
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -143,6 +143,33 @@ class ir_translation(osv.osv):
|
||||||
res = cr.fetchone()
|
res = cr.fetchone()
|
||||||
trad = res and res[0] or ''
|
trad = res and res[0] or ''
|
||||||
return trad
|
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()
|
ir_translation()
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,7 @@
|
||||||
<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="domain">[('supplier','=',1)]</field>
|
<field name="domain">[('supplier','=',1)]</field>
|
||||||
|
<field name="context">{'default_customer':0}</field>
|
||||||
</record>
|
</record>
|
||||||
<menuitem action="action_partner_supplier_form" id="menu_partner_supplier_form" parent="menu_partner_form"/>
|
<menuitem action="action_partner_supplier_form" id="menu_partner_supplier_form" parent="menu_partner_form"/>
|
||||||
<record id="action_partner_other_form" model="ir.actions.act_window">
|
<record id="action_partner_other_form" model="ir.actions.act_window">
|
||||||
|
|
|
@ -26,6 +26,7 @@ import ir
|
||||||
|
|
||||||
from tools.misc import currency
|
from tools.misc import currency
|
||||||
from tools.translate import _
|
from tools.translate import _
|
||||||
|
from tools import config
|
||||||
|
|
||||||
import mx.DateTime
|
import mx.DateTime
|
||||||
from mx.DateTime import RelativeDateTime, now, DateTime, localtime
|
from mx.DateTime import RelativeDateTime, now, DateTime, localtime
|
||||||
|
@ -67,7 +68,7 @@ class res_currency(osv.osv):
|
||||||
if currency.rounding == 0:
|
if currency.rounding == 0:
|
||||||
return 0.0
|
return 0.0
|
||||||
else:
|
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):
|
def is_zero(self, cr, uid, currency, amount):
|
||||||
return abs(self.round(cr, uid, currency, amount)) < currency.rounding
|
return abs(self.round(cr, uid, currency, amount)) < currency.rounding
|
||||||
|
|
|
@ -384,6 +384,7 @@
|
||||||
<rng:ref name="page" />
|
<rng:ref name="page" />
|
||||||
<rng:ref name="separator"/>
|
<rng:ref name="separator"/>
|
||||||
<rng:ref name="button"/>
|
<rng:ref name="button"/>
|
||||||
|
<rng:ref name="group"/>
|
||||||
<rng:element name="properties"><rng:empty/></rng:element>
|
<rng:element name="properties"><rng:empty/></rng:element>
|
||||||
<rng:element name="newline"><rng:empty/></rng:element>
|
<rng:element name="newline"><rng:empty/></rng:element>
|
||||||
</rng:choice>
|
</rng:choice>
|
||||||
|
|
|
@ -34,11 +34,11 @@ import socket
|
||||||
|
|
||||||
admin_passwd = 'admin'
|
admin_passwd = 'admin'
|
||||||
waittime = 10
|
waittime = 10
|
||||||
|
wait_count = 0
|
||||||
|
wait_limit = 12
|
||||||
|
|
||||||
def start_server(root_path, port, addons_path):
|
def start_server(root_path, port, addons_path):
|
||||||
if root_path:
|
os.system('python2.5 %sopenerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(root_path, str(port), addons_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():
|
def clean():
|
||||||
if os.path.isfile('openerp.pid'):
|
if os.path.isfile('openerp.pid'):
|
||||||
ps = open('openerp.pid')
|
ps = open('openerp.pid')
|
||||||
|
@ -49,17 +49,24 @@ def clean():
|
||||||
os.kill(pid,9)
|
os.kill(pid,9)
|
||||||
|
|
||||||
def execute(connector, method, *args):
|
def execute(connector, method, *args):
|
||||||
|
global wait_count
|
||||||
res = False
|
res = False
|
||||||
try:
|
try:
|
||||||
res = getattr(connector,method)(*args)
|
res = getattr(connector,method)(*args)
|
||||||
except socket.error,e:
|
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)
|
print 'Please wait %d sec to start server....'%(waittime)
|
||||||
|
wait_count += 1
|
||||||
time.sleep(waittime)
|
time.sleep(waittime)
|
||||||
res = execute(connector, method, *args)
|
res = execute(connector, method, *args)
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
return res
|
wait_count = 0
|
||||||
|
return res
|
||||||
|
|
||||||
def login(uri, dbname, user, pwd):
|
def login(uri, dbname, user, pwd):
|
||||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
|
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
|
||||||
|
@ -94,40 +101,51 @@ def import_translate(uri, user, pwd, dbname, translate_in):
|
||||||
state = res['state']
|
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)
|
uid = login(uri, dbname, user, pwd)
|
||||||
|
quality_logs += 'quality-logs'
|
||||||
if uid:
|
if uid:
|
||||||
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
||||||
qualityresult = {}
|
|
||||||
final = {}
|
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)
|
quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module)
|
||||||
detail_html = ''
|
detail_html = ''
|
||||||
html = '''<html><html><html><html><body><a name="TOP"></a>'''
|
html = '''<html><body><a name="TOP"></a>'''
|
||||||
html +="<h1> Module : %s </h1>"%(quality_result['name'])
|
html +="<h1> Module : %s </h1>"%(quality_result['name'])
|
||||||
html += "<h2> Final score : %s</h2>"%(quality_result['final_score'])
|
html += "<h2> Final score : %s</h2>"%(quality_result['final_score'])
|
||||||
html += "<oi>"
|
html += "<div id='tabs'>"
|
||||||
for x,y,detail in quality_result['check_detail_ids']:
|
html += "<ul>"
|
||||||
if detail.get('detail') != '':
|
for x,y,detail in quality_result['check_detail_ids']:
|
||||||
test = detail.get('name')
|
test = detail.get('name')
|
||||||
score = round(float(detail.get('score',0)),2)
|
msg = detail.get('message','')
|
||||||
html += "<li><a href=\"#%s\">%s (%.2f)</a></li>"%(test,test,score)
|
score = round(float(detail.get('score',0)),2)
|
||||||
detail_html +="<a name=\"%s\"><h3>%s (Score : %s)</h3>%s</a>"%(test,test,score,detail.get('detail'))
|
html += "<li><a href=\"#%s\">%s</a></li>"%(test.replace(' ','-'),test)
|
||||||
detail_html +='''<a href="#TOP">Go to Top</a>'''
|
if test == 'Unit Test':
|
||||||
test_detail[test] = (score,detail.get('detail',''))
|
if not detail.get('detail',''):
|
||||||
html += "</oi>%s</body></html></html></html></html></html>"%(detail_html)
|
detail['detail'] = '''<html><body><b>%s</b></body></html>'''%(detail.get('summary',''))
|
||||||
final[quality_result['name']] = (quality_result['final_score'],html,test_detail)
|
detail_html +="<div id=\"%s\"><h3>%s (Score : %s)</h3>%s</div>"%(test.replace(' ','-'),test,score,detail.get('detail',''))
|
||||||
|
test_detail[test] = (score,msg,detail.get('detail',''))
|
||||||
|
html += "</ul>"
|
||||||
|
html += "%s"%(detail_html)
|
||||||
|
html += "</div></body></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')
|
#fp = open('quality_log.pck','wb')
|
||||||
pck_obj = pickle.dump(final,fp)
|
#pck_obj = pickle.dump(final,fp)
|
||||||
fp.close()
|
#fp.close()
|
||||||
print "LOG PATH%s"%(os.path.realpath('quality_log.pck'))
|
#print "LOG PATH%s"%(os.path.realpath('quality_log.pck'))
|
||||||
return final
|
return True
|
||||||
else:
|
else:
|
||||||
print 'Login Failed...'
|
print 'Login Failed...'
|
||||||
clean()
|
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':
|
elif res['type']=='state':
|
||||||
state = res['state']
|
state = res['state']
|
||||||
res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, 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
|
return True
|
||||||
|
|
||||||
def drop_db(uri, dbname):
|
def drop_db(uri, dbname):
|
||||||
|
@ -178,13 +196,38 @@ def drop_db(uri, dbname):
|
||||||
if dbname in db_list:
|
if dbname in db_list:
|
||||||
execute(conn, 'drop', admin_passwd, dbname)
|
execute(conn, 'drop', admin_passwd, dbname)
|
||||||
return True
|
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)
|
uid = login(uri, dbname, user, pwd)
|
||||||
|
if extra_addons:
|
||||||
|
extra_addons = extra_addons.split(',')
|
||||||
if uid:
|
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')
|
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
|
||||||
wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
|
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)
|
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')
|
wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
|
||||||
state = 'init'
|
state = 'init'
|
||||||
|
@ -237,6 +280,7 @@ parser = optparse.OptionParser(usage)
|
||||||
parser.add_option("--modules", dest="modules",
|
parser.add_option("--modules", dest="modules",
|
||||||
help="specify modules to install or check quality")
|
help="specify modules to install or check quality")
|
||||||
parser.add_option("--addons-path", dest="addons_path", help="specify the addons path")
|
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("--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("-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("-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("--password", dest="pwd", help="specify the User Password")
|
||||||
parser.add_option("--translate-in", dest="translate_in",
|
parser.add_option("--translate-in", dest="translate_in",
|
||||||
help="specify .po files to import translation terms")
|
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()
|
(opt, args) = parser.parse_args()
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
parser.error("incorrect number of arguments")
|
parser.error("incorrect number of arguments")
|
||||||
|
@ -264,17 +311,26 @@ die(opt.translate_in and (not opt.db_name),
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
'addons-path' : opt.addons_path or 'addons',
|
'addons-path' : opt.addons_path or 'addons',
|
||||||
|
'quality-logs' : opt.quality_logs or '',
|
||||||
'root-path' : opt.root_path or '',
|
'root-path' : opt.root_path or '',
|
||||||
'translate-in': opt.translate_in,
|
'translate-in': [],
|
||||||
'port' : opt.port or 8069,
|
'port' : opt.port or 8069,
|
||||||
'database': opt.db_name or 'terp',
|
'database': opt.db_name or 'terp',
|
||||||
'modules' : opt.modules or [],
|
'modules' : opt.modules or [],
|
||||||
'login' : opt.login or 'admin',
|
'login' : opt.login or 'admin',
|
||||||
'pwd' : opt.pwd or '',
|
'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['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'])
|
uri = 'http://localhost:' + str(options['port'])
|
||||||
|
|
||||||
server_thread = threading.Thread(target=start_server,
|
server_thread = threading.Thread(target=start_server,
|
||||||
|
@ -286,13 +342,13 @@ try:
|
||||||
if command == 'drop-db':
|
if command == 'drop-db':
|
||||||
drop_db(uri, options['database'])
|
drop_db(uri, options['database'])
|
||||||
if command == 'install-module':
|
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':
|
if command == 'upgrade-module':
|
||||||
upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
|
upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
|
||||||
if command == 'check-quality':
|
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':
|
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()
|
clean()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ class Logger(object):
|
||||||
try:
|
try:
|
||||||
msg = tools.ustr(msg).strip()
|
msg = tools.ustr(msg).strip()
|
||||||
if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True):
|
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')
|
result = msg.split('\n')
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
|
|
|
@ -616,6 +616,12 @@ class function(_column):
|
||||||
self._multi = multi
|
self._multi = multi
|
||||||
if 'relation' in args:
|
if 'relation' in args:
|
||||||
self._obj = args['relation']
|
self._obj = args['relation']
|
||||||
|
|
||||||
|
if 'digits' in args:
|
||||||
|
self.digits = args['digits']
|
||||||
|
else:
|
||||||
|
self.digits = (16,2)
|
||||||
|
|
||||||
self._fnct_inv_arg = fnct_inv_arg
|
self._fnct_inv_arg = fnct_inv_arg
|
||||||
if not fnct_inv:
|
if not fnct_inv:
|
||||||
self.readonly = 1
|
self.readonly = 1
|
||||||
|
|
|
@ -308,7 +308,10 @@ def get_pg_type(f):
|
||||||
t = eval('fields.'+(f._type))
|
t = eval('fields.'+(f._type))
|
||||||
f_type = (type_dict[t], type_dict[t])
|
f_type = (type_dict[t], type_dict[t])
|
||||||
elif isinstance(f, fields.function) and f._type == 'float':
|
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':
|
elif isinstance(f, fields.function) and f._type == 'selection':
|
||||||
f_type = ('text', 'text')
|
f_type = ('text', 'text')
|
||||||
elif isinstance(f, fields.function) and f._type == 'char':
|
elif isinstance(f, fields.function) and f._type == 'char':
|
||||||
|
@ -506,7 +509,7 @@ class orm_template(object):
|
||||||
for rr in r :
|
for rr in r :
|
||||||
if isinstance(rr.name, browse_record):
|
if isinstance(rr.name, browse_record):
|
||||||
rr = rr.name
|
rr = rr.name
|
||||||
dt+=rr.name+','
|
dt += rr.name or '' + ','
|
||||||
data[fpos] = dt[:-1]
|
data[fpos] = dt[:-1]
|
||||||
break
|
break
|
||||||
lines += lines2[1:]
|
lines += lines2[1:]
|
||||||
|
@ -1009,9 +1012,10 @@ class orm_template(object):
|
||||||
attrs = {'views': views}
|
attrs = {'views': views}
|
||||||
if node.hasAttribute('widget') and node.getAttribute('widget')=='selection':
|
if node.hasAttribute('widget') and node.getAttribute('widget')=='selection':
|
||||||
# We can not use the 'string' domain has it is defined according to the record !
|
# 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)):
|
if column._domain and not isinstance(column._domain, (str, unicode)):
|
||||||
dom = column._domain
|
dom = column._domain
|
||||||
|
|
||||||
attrs['selection'] = self.pool.get(relation).name_search(cr, user, '', dom, context=context)
|
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:
|
if (node.hasAttribute('required') and not int(node.getAttribute('required'))) or not column.required:
|
||||||
attrs['selection'].append((False,''))
|
attrs['selection'].append((False,''))
|
||||||
|
@ -1816,6 +1820,8 @@ class orm(orm_template):
|
||||||
('varchar', 'text', 'TEXT', ''),
|
('varchar', 'text', 'TEXT', ''),
|
||||||
('int4', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
|
('int4', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
|
||||||
('date', 'datetime', 'TIMESTAMP', '::TIMESTAMP'),
|
('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 !!!
|
# !!! Avoid reduction of varchar field !!!
|
||||||
if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size < f.size:
|
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()
|
cr.commit()
|
||||||
for c in casts:
|
for c in casts:
|
||||||
if (f_pg_type==c[0]) and (f._type==c[1]):
|
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]))
|
if f_pg_type != f_obj_type:
|
||||||
ok = True
|
logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1]))
|
||||||
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
|
ok = True
|
||||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2]))
|
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
|
||||||
cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k))
|
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2]))
|
||||||
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
|
cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k))
|
||||||
cr.commit()
|
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
|
||||||
|
cr.commit()
|
||||||
|
break
|
||||||
|
|
||||||
if f_pg_type != f_obj_type:
|
if f_pg_type != f_obj_type:
|
||||||
if not ok:
|
if not ok:
|
||||||
|
@ -2504,9 +2512,10 @@ class orm(orm_template):
|
||||||
if c[0].startswith('default_'):
|
if c[0].startswith('default_'):
|
||||||
del rel_context[c[0]]
|
del rel_context[c[0]]
|
||||||
|
|
||||||
|
result = []
|
||||||
for field in upd_todo:
|
for field in upd_todo:
|
||||||
for id in ids:
|
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:
|
for table in self._inherits:
|
||||||
col = self._inherits[table]
|
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_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))
|
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:
|
for order, object, ids, fields in result:
|
||||||
self.pool.get(object)._store_set_values(cr, user, ids, fields, context)
|
self.pool.get(object)._store_set_values(cr, user, ids, fields, context)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
name = 'openerp-server'
|
name = 'openerp-server'
|
||||||
version = '5.0.4'
|
version = '5.0.6'
|
||||||
major_version = '5.0'
|
major_version = '5.0'
|
||||||
description = 'OpenERP Server'
|
description = 'OpenERP Server'
|
||||||
long_desc = '''\
|
long_desc = '''\
|
||||||
|
|
|
@ -51,7 +51,10 @@ class report_printscreen_list(report_int):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _parse_string(self, view):
|
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)
|
return self._parse_node(dom)
|
||||||
|
|
||||||
def create(self, cr, uid, ids, datas, context=None):
|
def create(self, cr, uid, ids, datas, context=None):
|
||||||
|
|
|
@ -156,7 +156,7 @@ class rml_parse(object):
|
||||||
self.cr = cr
|
self.cr = cr
|
||||||
self.uid = uid
|
self.uid = uid
|
||||||
self.pool = pooler.get_pool(cr.dbname)
|
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 = {
|
self.localcontext = {
|
||||||
'user': user,
|
'user': user,
|
||||||
'company': user.company_id,
|
'company': user.company_id,
|
||||||
|
|
|
@ -332,7 +332,10 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||||
email_bcc = []
|
email_bcc = []
|
||||||
|
|
||||||
if not attach:
|
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:
|
else:
|
||||||
msg = MIMEMultipart()
|
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())
|
msg['Message-Id'] = "<%s-tinycrm-%s@%s>" % (time.time(), tinycrm, socket.gethostname())
|
||||||
|
|
||||||
if attach:
|
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:
|
for (fname,fcontent) in attach:
|
||||||
part = MIMEBase('application', "octet-stream")
|
part = MIMEBase('application', "octet-stream")
|
||||||
part.set_payload( fcontent )
|
part.set_payload( fcontent )
|
||||||
|
|
|
@ -607,10 +607,12 @@ 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']))
|
||||||
|
|
||||||
if tools.config['root_path'] in tools.config['addons_path'] :
|
root_path = os.path.join(tools.config['root_path'], 'addons')
|
||||||
path_list = [tools.config['root_path']]
|
|
||||||
|
if root_path in tools.config['addons_path'] :
|
||||||
|
path_list = [root_path]
|
||||||
else :
|
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 path in path_list:
|
||||||
for root, dirs, files in tools.osutil.walksymlinks(path):
|
for root, dirs, files in tools.osutil.walksymlinks(path):
|
||||||
|
|
176
doc/Changelog
176
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
|
2009-08-28: 5.0.4
|
||||||
=================
|
=================
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue