[merge] merge from lp:~openerp/openobject-server/5.0/

bzr revid: hmo@tinyerp.com-20091128104436-nryf42nmutq0s2ig
This commit is contained in:
Harry (Open ERP) 2009-11-28 16:14:36 +05:30
commit 3ac7d15820
15 changed files with 341 additions and 261 deletions

View File

@ -11298,3 +11298,63 @@ msgstr ""
msgid "Russian / русский язык"
msgstr ""
#. module: base
#: sql_constraint:res.user:0
msgid "You cannot have two users with the same login !"
msgstr ""
#. module: base
#: sql_constraint:ir.model.data:0
msgid "You cannot have multiple records with the same id for the same module"
msgstr ""
#. module: base
#: sql_constraint:maintenance.contract:0
msgid "Your maintenance contract is already subscribed in the system !"
msgstr ""
#. module: base
#: sql_constraint:ir.module.module:0
msgid "The name of the module must be unique !"
msgstr ""
#. module: base
#: sql_constraint:res.partner.function:0
msgid "The Code of the Partner Function must be unique !"
msgstr ""
#. module: base
#: sql_constraint:res.partner:0
msgid "The name of the Partner must be unique !"
msgstr ""
#. module: base
#: sql_constraint:res.country:0
msgid "The name of the country must be unique !"
msgstr ""
#. module: base
#: sql_constraint:res.country:0
msgid "The code of the country must be unique !"
msgstr ""
#. module: base
#: sql_constraint:res.lang:0
msgid "The name of the language must be unique !"
msgstr ""
#. module: base
#: sql_constraint:res.lang:0
msgid "The code of the language must be unique !"
msgstr ""
#. module: base
#: code:addons/osv/osv.py:0
#, python-format
msgid "Constraint Error"
msgstr ""
#. module: base
#: selection:ir.translation,type:0
msgid "SQL Constraint"
msgstr ""

View File

@ -1031,6 +1031,7 @@
<tree string="Scheduled Actions">
<field name="nextcall"/>
<field name="name"/>
<field name="active"/>
<field name="interval_number"/>
<field name="interval_type"/>
<field name="numbercall"/>

View File

@ -429,8 +429,8 @@ class actions_server(osv.osv):
def _select_signals(self, cr, uid, context={}):
cr.execute("select distinct t.signal as key, t.signal || ' - [ ' || w.osv || ' ] ' as val from wkf w, wkf_activity a, wkf_transition t "\
" where w.id = a.wkf_id " \
" and t.act_from = a.wkf_id " \
" or t.act_to = a.wkf_id and t.signal not in (null, NULL)")
" and t.act_from = a.id " \
" or t.act_to = a.id and t.signal not in (null, NULL)")
result = cr.fetchall() or []
res = []
for rs in result:

View File

@ -28,7 +28,7 @@ import pooler
from osv import fields, osv
def str2tuple(s):
return eval('tuple(%s)' % s)
return eval('tuple(%s)' % (s or ''))
_intervalTypes = {
'work_days': lambda interval: DateTime.RelativeDateTime(days=interval),

View File

@ -425,7 +425,7 @@ class ir_model_data(osv.osv):
'module': lambda *a: ''
}
_sql_constraints = [
('module_name_uniq', 'unique(name, module)', 'You can not have multiple records with the same id for the same module'),
('module_name_uniq', 'unique(name, module)', 'You cannot have multiple records with the same id for the same module'),
]
def __init__(self, pool, cr):

View File

@ -35,6 +35,7 @@ TRANSLATION_TYPE = [
('help', 'Help'),
('code', 'Code'),
('constraint', 'Constraint'),
('sql_constraint', 'SQL Constraint')
]
class ir_translation(osv.osv):
@ -131,14 +132,14 @@ class ir_translation(osv.osv):
'and type=%s ' \
'and name=%s ' \
'and src=%s',
(lang, tt, str(name), source))
(lang, tt, tools.ustr(name), source))
else:
cr.execute('select value ' \
'from ir_translation ' \
'where lang=%s ' \
'and type=%s ' \
'and name=%s',
(lang, tt, str(name)))
(lang, tt, tools.ustr(name)))
res = cr.fetchone()
trad = res and res[0] or ''
return trad

View File

@ -140,6 +140,12 @@ class expression(object):
if field._type == 'many2one':
right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context)
self.__exp[i] = (fargs[0], 'in', right)
# Making search easier when there is a left operand as field.o2m or field.m2m
if field._type in ['many2many','one2many']:
right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context)
right1 = table.search(cr, uid, [(fargs[0],'in', right)], context=context)
self.__exp[i] = ('id', 'in', right1)
continue
if field._properties:
@ -162,32 +168,45 @@ class expression(object):
elif field._type == 'one2many':
call_null = True
if right:
# Applying recursivity on field(one2many)
if operator == 'child_of':
if isinstance(right, basestring):
ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None)]
operator = 'in'
ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], 'like', limit=None)]
else:
if not isinstance(right,list):
ids2 = [right]
else:
ids2 = right
if not ids2:
call_null = True
operator = 'in' # operator changed because ids are directly related to main object
ids2 = list(right)
if field._obj != working_table._name:
dom = _rec_get(ids2, field_obj, left=left, prefix=field._obj)
else:
call_null = False
o2m_op = 'in'
if operator in ['not like','not ilike','not in','<>','!=']:
o2m_op = 'not in'
self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2, operator, field._type))
dom = _rec_get(ids2, working_table, parent=left)
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
if call_null:
o2m_op = 'not in'
if operator in ['not like','not ilike','not in','<>','!=']:
o2m_op = 'in'
self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0])
else:
call_null = True
if right:
if isinstance(right, basestring):
ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None)]
operator = 'in'
else:
if not isinstance(right,list):
ids2 = [right]
else:
ids2 = right
if not ids2:
call_null = True
operator = 'in' # operator changed because ids are directly related to main object
else:
call_null = False
o2m_op = 'in'
if operator in ['not like','not ilike','not in','<>','!=']:
o2m_op = 'not in'
self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2, operator, field._type))
if call_null:
o2m_op = 'not in'
if operator in ['not like','not ilike','not in','<>','!=']:
o2m_op = 'in'
self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0])
elif field._type == 'many2many':
#FIXME

View File

@ -527,6 +527,8 @@ class many2many(_column):
return
obj = obj.pool.get(self._obj)
for act in values:
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
continue
if act[0] == 0:
idnew = obj.create(cr, user, act[2])
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, idnew))

View File

@ -52,6 +52,7 @@ import fields
import tools
from tools.translate import _
import copy
import sys
import copy
@ -62,6 +63,7 @@ except ImportError:
sys.stderr.write("ERROR: Try to install the python-lxml package\n")
sys.exit(2)
from tools.config import config
regex_order = re.compile('^([a-z0-9_]+( *desc| *asc)?( *, *|))+$', re.I)
@ -534,7 +536,9 @@ class orm_template(object):
for rr in r :
if isinstance(rr.name, browse_record):
rr = rr.name
dt += rr.name or '' + ','
rr_name = self.pool.get(rr._table_name).name_get(cr, uid, [rr.id])
rr_name = rr_name and rr_name[0] and rr_name[0][1] or ''
dt += tools.ustr(rr_name or '') + ','
data[fpos] = dt[:-1]
break
lines += lines2[1:]
@ -545,7 +549,8 @@ class orm_template(object):
i += 1
if i == len(f):
if isinstance(r, browse_record):
r = r.name
r = self.pool.get(r._table_name).name_get(cr, uid, [r.id])
r = r and r[0] and r[0][1] or ''
data[fpos] = tools.ustr(r or '')
return [data] + lines
@ -854,14 +859,17 @@ class orm_template(object):
noupdate=noupdate, res_id=res_id, context=context)
except Exception, e:
import psycopg2
import osv
if isinstance(e,psycopg2.IntegrityError):
msg= _('Insertion Failed!')
msg= _('Insertion Failed! ')
for key in self.pool._sql_error.keys():
if key in e[0]:
msg = self.pool._sql_error[key]
break
return (-1, res,'Line ' + str(counter) +' : ' + msg,'' )
return (-1, res, 'Line ' + str(counter) +' : ' + msg, '' )
if isinstance(e, osv.orm.except_orm ):
msg = _('Insertion Failed! ' + e[1])
return (-1, res, 'Line ' + str(counter) +' : ' + msg, '' )
for lang in translate:
context2 = context.copy()
context2['lang'] = lang
@ -1041,10 +1049,9 @@ class orm_template(object):
attrs = {'views': views}
if node.get('widget') and node.get('widget') == 'selection':
# We can not use the 'string' domain has it is defined according to the record !
dom = []
dom = None
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.get('required') and not int(node.get('required'))) or not column.required:
attrs['selection'].append((False,''))
@ -1120,8 +1127,7 @@ class orm_template(object):
# running -> done = signal_next (role Z)
# running -> cancel = signal_cancel (role Z)
# As we don't know the object state, in this scenario,
# As we don't know the object state, in this scenario,
# the button "signal_cancel" will be always shown as there is no restriction to cancel in draft
# the button "signal_next" will be show if the user has any of the roles (X Y or Z)
# The verification will be made later in workflow process...
@ -1238,7 +1244,7 @@ class orm_template(object):
while len(toparse):
node2 = toparse.pop(0)
if node2.tag == 'data':
toparse += node2.getchildren()
toparse += [ c for c in doc_dest ]
continue
node = _find(src, node2)
if node is not None:
@ -1379,7 +1385,7 @@ class orm_template(object):
result['name'] = 'default'
result['field_parent'] = False
result['view_id'] = 0
xarch, xfields = self.__view_look_dom_arch(cr, user, result['arch'], view_id, context=context)
result['arch'] = xarch
result['fields'] = xfields
@ -1997,12 +2003,23 @@ class orm(orm_template):
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" VARCHAR(%d)' % (self._table, k, f.size))
cr.execute('UPDATE "%s" SET "%s"=temp_change_size::VARCHAR(%d)' % (self._table, k, f.size))
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size' % (self._table,))
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
cr.commit()
for c in casts:
if (f_pg_type==c[0]) and (f._type==c[1]):
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]))
# Adding upcoming 6 lines to check whether only the size of the fields got changed or not.E.g. :(16,3) to (16,4)
field_size_change = False
if f_pg_type in ['int4','numeric','float8']:
if f.digits:
field_size = (65535 * f.digits[0]) + f.digits[0] + f.digits[1]
if field_size != f_pg_size:
field_size_change = True
if f_pg_type != f_obj_type or field_size_change:
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]))
if field_size_change:
logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed in the size." % (k, self._table))
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]))
@ -2140,7 +2157,8 @@ class orm(orm_template):
ok = True
for x,y,z,e,f,l in self.pool._store_function[object]:
if (x==self._name) and (y==store_field) and (e==fields2):
ok = False
if f==order:
ok = False
if ok:
self.pool._store_function[object].append( (self._name, store_field, fnct, fields2, order, length))
self.pool._store_function[object].sort(lambda x,y: cmp(x[4],y[4]))
@ -2306,7 +2324,21 @@ class orm(orm_template):
for key, v in r.items():
if v == None:
r[key] = False
if key in self._columns.keys():
type = self._columns[key]._type
elif key in self._inherit_fields.keys():
type = self._inherit_fields[key][2]._type
else:
continue
if type == 'reference' and v:
model,ref_id = v.split(',')
table = self.pool.get(model)._table
cr.execute('select id from "%s" where id=%s' % (table,ref_id))
id_exist = cr.fetchone()
if not id_exist:
cr.execute('update "'+self._table+'" set "'+key+'"=NULL where "%s"=%s' %(key,''.join("'"+str(v)+"'")))
r[key] = ''
if isinstance(ids, (int, long, dict)):
return result and result[0] or False
return result
@ -3272,6 +3304,4 @@ class orm(orm_template):
return False
return True
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -33,6 +33,8 @@ from psycopg2 import IntegrityError
from netsvc import Logger, LOG_ERROR
from tools.misc import UpdateableDict
from tools.translate import _
module_list = []
module_class_list = {}
class_pool = {}
@ -63,7 +65,7 @@ class osv_pool(netsvc.Service):
except IntegrityError, inst:
for key in self._sql_error.keys():
if key in inst[0]:
self.abortResponse(1, 'Constraint Error', 'warning', self._sql_error[key])
self.abortResponse(1, _('Constraint Error'), 'warning', _(self._sql_error[key]))
self.abortResponse(1, 'Integrity Error', 'warning', inst[0])
except Exception, e:
import traceback, sys

View File

@ -23,147 +23,128 @@
# French
#-------------------------------------------------------------
unites = {
0: '', 1:'un', 2:'deux', 3:'trois', 4:'quatre', 5:'cinq', 6:'six', 7:'sept', 8:'huit', 9:'neuf',
10:'dix', 11:'onze', 12:'douze', 13:'treize', 14:'quatorze', 15:'quinze', 16:'seize',
21:'vingt et un', 31:'trente et un', 41:'quarante et un', 51:'cinquante et un', 61:'soixante et un',
71:'septante et un', 91:'nonante et un', 80:'quatre-vingts'
}
dizaine = {
1: 'dix', 2:'vingt', 3:'trente',4:'quarante', 5:'cinquante', 6:'soixante', 7:'septante', 8:'quatre-vingt', 9:'nonante'
}
to_19_fr = ( 'zéro', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six',
'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize',
'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf' )
tens_fr = ( 'vingt', 'trente', 'quarante', 'Cinquante', 'Soixante', 'Soixante-dix', 'Quatre-vingts', 'Quatre-vingt Dix')
denom_fr = ( '',
'Mille', 'Millions', 'Milliards', 'Billions', 'Quadrillions',
'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
'Décillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion' )
centaine = {
0:'', 1: 'cent', 2:'deux cent', 3:'trois cent',4:'quatre cent', 5:'cinq cent', 6:'six cent', 7:'sept cent', 8:'huit cent', 9:'neuf cent'
}
# convert a value < 100 to French.
def _convert_nn_fr(val):
if val < 20:
return to_19_fr[val]
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_fr)):
if dval + 10 > val:
if val % 10:
return dcap + '-' + to_19_fr[val % 10]
return dcap
mille = {
0:'', 1:'mille'
}
# convert a value < 1000 to french, special cased because it is the level that kicks
# off the < 100 special case. The rest are more general. This also allows you to
# get strings in the form of 'forty-five hundred' if called directly.
def _convert_nnn_fr(val):
word = ''
(mod, rem) = (val % 100, val // 100)
if rem > 0:
word = to_19_fr[rem] + ' Cent'
if mod > 0:
word = word + ' '
if mod > 0:
word = word + _convert_nn_fr(mod)
return word
def _100_to_text_fr(chiffre):
if chiffre in unites:
return unites[chiffre]
else:
if chiffre%10>0:
return dizaine[chiffre / 10]+'-'+unites[chiffre % 10]
else:
return dizaine[chiffre / 10]
def french_number(val):
if val < 100:
return _convert_nn_fr(val)
if val < 1000:
return _convert_nnn_fr(val)
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_fr))):
if dval > val:
mod = 1000 ** didx
l = val // mod
r = val - (l * mod)
ret = _convert_nnn_fr(l) + ' ' + denom_fr[didx]
if r > 0:
ret = ret + ', ' + french_number(r)
return ret
def _1000_to_text_fr(chiffre):
d = _100_to_text_fr(chiffre % 100)
d2 = chiffre/100
if d2>0 and d:
return centaine[d2]+' '+d
elif d2>1 and not(d):
return centaine[d2]+'s'
else:
return centaine[d2] or d
def _10000_to_text_fr(chiffre):
if chiffre==0:
return 'zero'
part1 = _1000_to_text_fr(chiffre % 1000)
part2 = mille.get(chiffre / 1000, _1000_to_text_fr(chiffre / 1000)+' mille')
if part2 and part1:
part1 = ' '+part1
return part2+part1
def amount_to_text_fr(number, currency):
units_number = int(number)
units_name = currency
if units_number > 1:
units_name += 's'
units = _10000_to_text_fr(units_number)
units = units_number and '%s %s' % (units, units_name) or ''
cents_number = int(number * 100) % 100
cents_name = (cents_number > 1) and 'cents' or 'cent'
cents = _100_to_text_fr(cents_number)
cents = cents_number and '%s %s' % (cents, cents_name) or ''
if units and cents:
cents = ' '+cents
return units + cents
list = str(number).split('.')
start_word = french_number(abs(int(list[0])))
end_word = french_number(int(list[1]))
cents_number = int(list[1])
cents_name = (cents_number > 1) and ' Cents' or ' Cent'
final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
return final_result
#-------------------------------------------------------------
# Dutch
#-------------------------------------------------------------
units_nl = {
0:'', 1:'een', 2:'twee', 3:'drie', 4:'vier', 5:'vijf', 6:'zes', 7:'zeven', 8:'acht', 9:'negen',
10:'tien', 11:'elf', 12:'twaalf', 13:'dertien', 14:'veertien'
}
to_19_nl = ( 'Nul', 'Een', 'Twee', 'Drie', 'Vier', 'Vijf', 'Zes',
'Zeven', 'Acht', 'Negen', 'Tien', 'Elf', 'Twaalf', 'Dertien',
'Veertien', 'Vijftien', 'Zestien', 'Zeventien', 'Achttien', 'Negentien' )
tens_nl = ( 'Twintig', 'Dertig', 'Veertig', 'Vijftig', 'Zestig', 'Zeventig', 'Tachtig', 'Negentig')
denom_nl = ( '',
'Duizend', 'Miljoen', 'Miljard', 'Triljoen', 'Quadriljoen',
'Quintillion', 'Sextiljoen', 'Septillion', 'Octillion', 'Nonillion',
'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' )
tens_nl = {
1: 'tien', 2:'twintig', 3:'dertig',4:'veertig', 5:'vijftig', 6:'zestig', 7:'zeventig', 8:'tachtig', 9:'negentig'
}
# convert a value < 100 to Dutch.
def _convert_nn_nl(val):
if val < 20:
return to_19_nl[val]
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_nl)):
if dval + 10 > val:
if val % 10:
return dcap + '-' + to_19_nl[val % 10]
return dcap
hundreds_nl = {
0:'', 1: 'honderd',
}
# convert a value < 1000 to Dutch, special cased because it is the level that kicks
# off the < 100 special case. The rest are more general. This also allows you to
# get strings in the form of 'forty-five hundred' if called directly.
def _convert_nnn_nl(val):
word = ''
(mod, rem) = (val % 100, val // 100)
if rem > 0:
word = to_19_nl[rem] + ' Honderd'
if mod > 0:
word = word + ' '
if mod > 0:
word = word + _convert_nn_nl(mod)
return word
thousands_nl = {
0:'', 1:'duizend'
}
def dutch_number(val):
if val < 100:
return _convert_nn_nl(val)
if val < 1000:
return _convert_nnn_nl(val)
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_nl))):
if dval > val:
mod = 1000 ** didx
l = val // mod
r = val - (l * mod)
ret = _convert_nnn_nl(l) + ' ' + denom_nl[didx]
if r > 0:
ret = ret + ', ' + dutch_number(r)
return ret
def _100_to_text_nl(number):
if number in units_nl:
return units_nl[number]
else:
if number%10 > 0:
if number>10 and number<20:
return units_nl[number % 10]+tens_nl[number / 10]
else:
units = units_nl[number % 10]
if units[-1] == 'e':
joinword = 'ën'
else:
joinword = 'en'
return units+joinword+tens_nl[number / 10]
else:
return tens_nl[number / 10]
def _1000_to_text_nl(number):
part1 = _100_to_text_nl(number % 100)
part2 = hundreds_nl.get(number / 100, units_nl[number/100] + hundreds_nl[1])
if part2 and part1:
part1 = ' ' + part1
return part2 + part1
def _10000_to_text_nl(number):
if number==0:
return 'nul'
part1 = _1000_to_text_nl(number % 1000)
if thousands_nl.has_key(number / 1000):
part2 = thousands_nl[number / 1000]
else:
if (number / 1000 % 100 > 0) and (number / 1000 > 100):
space = ' '
else:
space = ''
part2 = _1000_to_text_nl(number / 1000) + space + thousands_nl[1]
if part2 and part1:
part1 = ' ' + part1
return part2 + part1
def amount_to_text_nl(number, currency):
units_number = int(number)
units_name = currency
units = _10000_to_text_nl(units_number)
units = units_number and '%s %s' % (units, units_name) or ''
cents_number = int(number * 100) % 100
cents_name = 'cent'
cents = _100_to_text_nl(cents_number)
cents = cents_number and '%s %s' % (cents, cents_name) or ''
if units and cents:
cents = ' ' + cents
return units + cents
list = str(number).split('.')
start_word = dutch_number(int(list[0]))
end_word = dutch_number(int(list[1]))
cents_number = int(list[1])
cents_name = (cents_number > 1) and 'cent' or 'cent'
final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
return final_result
#-------------------------------------------------------------
# Generic functions
@ -182,17 +163,17 @@ def amount_to_text(nbr, lang='fr', currency='euro'):
Example:
1654: mille six cent cinquante-quatre.
"""
if nbr > 1000000:
#TODO: use logger
print "WARNING: number too large '%d', can't translate it!" % (nbr,)
return str(nbr)
# if nbr > 1000000:
##TODO: use logger
# print "WARNING: number too large '%d', can't translate it!" % (nbr,)
# return str(nbr)
if not _translate_funcs.has_key(lang):
#TODO: use logger
print "WARNING: no translation function found for lang: '%s'" % (lang,)
#TODO: (default should be en) same as above
lang = 'fr'
return _translate_funcs[lang](nbr, currency)
return _translate_funcs[lang](abs(nbr), currency)
if __name__=='__main__':
from sys import argv

View File

@ -22,85 +22,66 @@
#-------------------------------------------------------------
#ENGLISH
#-------------------------------------------------------------
from tools.translate import _
ones = {
0: '', 1:'One', 2:'Two', 3:'Three', 4:'Four', 5:'Five', 6:'Six', 7:'Seven', 8:'Eight', 9:'Nine',
10:'Ten', 11:'Eleven', 12:'Twelve', 13:'Thirteen', 14:'Forteen', 15:'Fifteen', 16:'Sixteen', 17:"Seventeen",18:"Eighteen",19:"Nineteen",
}
to_19 = ( 'Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six',
'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen',
'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen' )
tens = ( 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety')
denom = ( '',
'Thousand', 'Million', 'Billion', 'Trillion', 'Quadrillion',
'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' )
tens = {
1: 'Ten', 2: 'Twenty ', 3:'Thirty', 4:'Forty', 5:'Fifty', 6: 'Sixty', 7 : 'Seventy', 8:'Eighty' ,9: 'Ninety'}
# convert a value < 100 to English.
def _convert_nn(val):
if val < 20:
return to_19[val]
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)):
if dval + 10 > val:
if val % 10:
return dcap + '-' + to_19[val % 10]
return dcap
hundred = {
0:'',1: 'One Hundred', 2: 'Two Hundred', 3: 'Three Hundred', 4 :'Four Hundred', 5: 'Five Hundred', 6: 'Six Hundred', 7 :'Seven Hundred', 8:' Eight Hundred ', 9:'Nine Hundred '
}
thousands ={
0:'',1: 'One Thousand'
}
lacs = {
0:'',1: 'Lac'
}
def _100_to_text(number):
if number in ones:
return ones[number]
else:
if number%10>0:
return tens[number / 10]+'-'+ones[number % 10]
else:
return tens[number / 10]
def _1000_to_text(number):
d = _100_to_text(number % 100)
d2 = number/100
if d2>0 and d:
return hundred[d2]+' '+d
elif d2>1 and not(d):
return hundred[d2]+'s'
else:
return hundred[d2] or d
def _10000_to_text(number):
if number==0:
return 'zero'
part1 = _1000_to_text(number % 1000)
part2 = thousands.get(number / 1000, _1000_to_text(number / 1000)+' Thousands')
if part2 and part1:
part1 = ' '+part1
return part2+part1
def _1000000_to_text(number):
if number==0:
return 'zero'
part1 = _10000_to_text(number % 100000)
part2 = lacs.get(number / 100000, _10000_to_text(number / 100000)+' Lacs')
if part2 and part1:
part1 = ' '+part1
return part2+part1
# convert a value < 1000 to english, special cased because it is the level that kicks
# off the < 100 special case. The rest are more general. This also allows you to
# get strings in the form of 'forty-five hundred' if called directly.
def _convert_nnn(val):
word = ''
(mod, rem) = (val % 100, val // 100)
if rem > 0:
word = to_19[rem] + ' Hundred'
if mod > 0:
word = word + ' '
if mod > 0:
word = word + _convert_nn(mod)
return word
def english_number(val):
if val < 100:
return _convert_nn(val)
if val < 1000:
return _convert_nnn(val)
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))):
if dval > val:
mod = 1000 ** didx
l = val // mod
r = val - (l * mod)
ret = _convert_nnn(l) + ' ' + denom[didx]
if r > 0:
ret = ret + ', ' + english_number(r)
return ret
def amount_to_text(number, currency):
lacs_number = int(number)
units_name = currency
if lacs_number > 1:
units_name += 's'
lacs = _1000000_to_text(lacs_number)
lacs = lacs_number and '%s %s' % (lacs, units_name) or ''
units_number = int(number * 10000) % 10000
units = _10000_to_text(units_number)
units = units_number and '%s %s' % (units, units_name) or ''
cents_number = int(number * 100) % 100
cents_name = (cents_number > 1) and 'cents' or 'cent'
cents = _100_to_text(cents_number)
cents = cents_number and '%s %s' % (cents.lower(), cents_name) or ''
if cents:
lacs += ' and %s' % (cents, )
return lacs
list = str(number).split('.')
start_word = english_number(int(list[0]))
end_word = english_number(int(list[1]))
cents_number = int(list[1])
cents_name = (cents_number > 1) and 'Cents' or 'Cent'
final_result = start_word +' '+units_name+' and ' + end_word +' '+cents_name
return final_result
#-------------------------------------------------------------
@ -118,15 +99,15 @@ def amount_to_text(nbr, lang='en', currency='euro'):
1654: thousands six cent cinquante-quatre.
"""
import netsvc
if nbr > 10000000:
netsvc.Logger().notifyChannel('translate', netsvc.LOG_WARNING, _("Number too large '%d', can not translate it"))
return str(nbr)
# if nbr > 10000000:
# netsvc.Logger().notifyChannel('translate', netsvc.LOG_WARNING, _("Number too large '%d', can not translate it"))
# return str(nbr)
if not _translate_funcs.has_key(lang):
netsvc.Logger().notifyChannel('translate', netsvc.LOG_WARNING, _("no translation function found for lang: '%s'" % (lang,)))
#TODO: (default should be en) same as above
lang = 'en'
return _translate_funcs[lang](nbr, currency)
return _translate_funcs[lang](abs(nbr), currency)
if __name__=='__main__':
from sys import argv

View File

@ -21,7 +21,7 @@
import re
import cStringIO
import xml.dom.minidom
from lxml import etree
import osv
import ir
import pooler
@ -119,7 +119,6 @@ def _eval_xml(self,node, pool, cr, uid, idref, context=None):
idref[id]=self.id_get(cr, False, id)
return s % idref
txt = '<?xml version="1.0"?>\n'+_process("".join([etree.tostring(i).encode("utf8") for i in node.getchildren()]), idref)
return txt
if t in ('char', 'int', 'float'):
d = node.text
@ -281,9 +280,10 @@ form: module.record_id""" % (xml_id,)
res['header'] = eval(rec.get('header',''))
if rec.get('report_type'):
res['report_type'] = rec.get('report_type','')
res['multi'] = rec.get('multi','') and eval(rec.get('multi',''))
xml_id = rec.get('id','').encode('utf8')
xml_id = rec.get('id','').encode('utf8')
self._test_xml_id(xml_id)
if rec.get('groups'):
@ -302,7 +302,6 @@ form: module.record_id""" % (xml_id,)
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
self.idref[xml_id] = int(id)
if not rec.get('menu') or eval(rec.get('menu','')):
keyword = str(rec.get('keyword','') or 'client_print_multi')
keys = [('action',keyword),('res_model',res['model'])]
@ -380,7 +379,7 @@ form: module.record_id""" % (xml_id,)
view_id = False
if rec.get('view'):
view_id = self.id_get(cr, 'ir.actions.act_window', rec.get('view','').encode('utf-8'))
domain = rec.get('domain','').encode('utf-8')
domain = rec.get('domain','').encode('utf-8') or '{}'
context = rec.get('context','').encode('utf-8') or '{}'
res_model = rec.get('res_model','').encode('utf-8')
src_model = rec.get('src_model','').encode('utf-8')
@ -675,7 +674,6 @@ form: module.record_id""" % (xml_id,)
if rec_context:
rec_context = eval(rec_context)
self._test_xml_id(rec_id)
if self.isnoupdate(data_node) and self.mode != 'init':
# check if the xml record has an id string
if rec_id:
@ -701,7 +699,6 @@ form: module.record_id""" % (xml_id,)
else:
# otherwise it is skipped
return None
res = {}
for field in [i for i in rec.getchildren() if (i.tag == "field")]:
#TODO: most of this code is duplicated above (in _eval_xml)...
@ -895,7 +892,6 @@ def convert_xml_export(res):
data = etree.SubElement ( page, 'data' )
text_node = etree.SubElement ( page, 'text' )
text_node.text = 'Some textual content.'
cr.commit()
cr.close()

View File

@ -134,12 +134,18 @@ class GettextAlias(object):
cr = frame.f_locals.get('cr')
try:
lang = (frame.f_locals.get('context') or {}).get('lang', False)
if not (cr and lang):
args = frame.f_locals.get('args',False)
if args:
lang = args[-1].get('lang',False)
if frame.f_globals.get('pooler',False):
cr = pooler.get_db(frame.f_globals['pooler'].pool_dic.keys()[0]).cursor()
if not (lang and cr):
return source
except:
return source
cr.execute('select value from ir_translation where lang=%s and type=%s and src=%s', (lang, 'code', source))
cr.execute('select value from ir_translation where lang=%s and type in (%s,%s) and src=%s', (lang, 'code','sql_constraint', source))
res_trans = cr.fetchone()
return res_trans and res_trans[0] or source
_ = GettextAlias()

View File

@ -59,6 +59,7 @@ required_modules = [
('reportlab', 'reportlab module'),
('pychart', 'pychart module'),
('pydot', 'pydot module'),
('lxml', 'lxml module: pythonic libxml2 and libxslt bindings'),
]
def check_modules():