[MERGE] Forward-port of latest 7.0 bugfixes, up to rev. 9743 revid:qdp-launchpad@openerp.com-20140108160719-9i8xhrat49cn9l5e
bzr revid: chs@openerp.com-20140107141524-xzz39a2ym66swr0t bzr revid: chs@openerp.com-20140107172248-zic9mqg0rigy2czb bzr revid: chs@openerp.com-20140108160418-ph17jgy5hlejj9hr bzr revid: dle@openerp.com-20140108171400-8r0fwv3wi36w2im0
This commit is contained in:
commit
05aab83eb1
|
@ -1199,7 +1199,7 @@ class account_move_line(osv.osv):
|
|||
break
|
||||
# Automatically convert in the account's secondary currency if there is one and
|
||||
# the provided values were not already multi-currency
|
||||
if account.currency_id and (vals.get('amount_currency', False) is False) and account.currency_id.id != account.company_id.currency_id.id:
|
||||
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
|
||||
vals['currency_id'] = account.currency_id.id
|
||||
ctx = {}
|
||||
if 'date' in vals:
|
||||
|
|
|
@ -1329,7 +1329,7 @@ class account_voucher(osv.osv):
|
|||
'date': voucher.date,
|
||||
'credit': diff > 0 and diff or 0.0,
|
||||
'debit': diff < 0 and -diff or 0.0,
|
||||
'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or False,
|
||||
'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or 0.0,
|
||||
'currency_id': company_currency <> current_currency and current_currency or False,
|
||||
'analytic_account_id': voucher.analytic_id and voucher.analytic_id.id or False,
|
||||
}
|
||||
|
|
|
@ -1048,11 +1048,13 @@ class crm_lead(format_address, osv.osv):
|
|||
def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None):
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0]
|
||||
if action == 'log':
|
||||
prefix = 'Logged'
|
||||
message = _('Logged a call for %(date)s. %(description)s')
|
||||
else:
|
||||
prefix = 'Scheduled'
|
||||
suffix = ' %s' % phonecall.description
|
||||
message = _("%s a call for %s.%s") % (prefix, phonecall.date, suffix)
|
||||
message = _('Scheduled a call for %(date)s. %(description)s')
|
||||
phonecall_date = datetime.strptime(phonecall.date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
phonecall_usertime = fields.datetime.context_timestamp(cr, uid, phonecall_date, context=context).strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
html_time = "<time datetime='%s+00:00'>%s</time>" % (phonecall.date, phonecall_usertime)
|
||||
message = message % dict(date=html_time, description=phonecall.description)
|
||||
return self.message_post(cr, uid, ids, body=message, context=context)
|
||||
|
||||
def log_meeting(self, cr, uid, ids, meeting_subject, meeting_date, duration, context=None):
|
||||
|
|
|
@ -33,11 +33,6 @@ class procurement_order(osv.osv):
|
|||
'production_id': fields.many2one('mrp.production', 'Manufacturing Order'),
|
||||
}
|
||||
|
||||
def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
|
||||
result = super(procurement_order, self)._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, context)
|
||||
result['property_ids'] = [(6, 0, [x.id for x in line.property_ids])]
|
||||
return result
|
||||
|
||||
def check_produce_product(self, cr, uid, procurement, context=None):
|
||||
''' Depict the capacity of the procurement workflow to produce products (not services)'''
|
||||
return True
|
||||
|
@ -128,4 +123,10 @@ class procurement_order(osv.osv):
|
|||
self.message_post(cr, uid, [procurement.id], body=body, context=context)
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
class sale_order(osv.Model):
|
||||
_inherit ='sale.order'
|
||||
|
||||
def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
|
||||
result = super(sale_order, self)._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, context)
|
||||
result['property_ids'] = [(6, 0, [x.id for x in line.property_ids])]
|
||||
return result
|
||||
|
|
|
@ -64,7 +64,7 @@ class project(osv.osv):
|
|||
""" Installation hook: aliases, project.project """
|
||||
# create aliases for all projects and avoid constraint errors
|
||||
alias_context = dict(context, alias_model_name='project.task')
|
||||
self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(project, self)._auto_init,
|
||||
return self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(project, self)._auto_init,
|
||||
'project.task', self._columns['alias_id'], 'id', alias_prefix='project+', alias_defaults={'project_id':'id'}, context=alias_context)
|
||||
|
||||
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2013 OpenERP S.A. <http://www.openerp.com>
|
||||
# Copyright (C) 2004-2014 OpenERP S.A. <http://www.openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -478,7 +478,7 @@ class actions_server(osv.osv):
|
|||
|
||||
def _select_objects(self, cr, uid, context=None):
|
||||
model_pool = self.pool.get('ir.model')
|
||||
ids = model_pool.search(cr, uid, [('name', 'not ilike', '.')])
|
||||
ids = model_pool.search(cr, uid, [], limit=None)
|
||||
res = model_pool.read(cr, uid, ids, ['model', 'name'])
|
||||
return [(r['model'], r['name']) for r in res] + [('', '')]
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ class ir_attachment(osv.osv):
|
|||
# performed in batch as much as possible.
|
||||
ima = self.pool.get('ir.model.access')
|
||||
for model, targets in model_attachments.iteritems():
|
||||
if model not in self.pool:
|
||||
if not self.pool.get(model):
|
||||
continue
|
||||
if not ima.check(cr, uid, model, 'read', False):
|
||||
# remove all corresponding attachment ids
|
||||
|
|
|
@ -77,7 +77,7 @@ addresses belonging to this country.\n\nYou can use the python-style string pate
|
|||
context=context)
|
||||
|
||||
def write(self, cursor, user, ids, vals, context=None):
|
||||
if vals.get('code', False):
|
||||
if vals.get('code'):
|
||||
vals['code'] = vals['code'].upper()
|
||||
return super(Country, self).write(cursor, user, ids, vals,
|
||||
context=context)
|
||||
|
|
|
@ -830,7 +830,7 @@ class users_view(osv.osv):
|
|||
fields.append('groups_id')
|
||||
res = super(users_view, self).read(cr, uid, ids, fields, context=context, load=load)
|
||||
|
||||
if group_fields:
|
||||
if res and group_fields:
|
||||
for values in (res if isinstance(res, list) else [res]):
|
||||
self._get_reified_groups(group_fields, values)
|
||||
if inject_groups_id:
|
||||
|
@ -862,6 +862,7 @@ class users_view(osv.osv):
|
|||
'selection': [(False, '')] + [(g.id, g.name) for g in gs],
|
||||
'help': '\n'.join(tips),
|
||||
'exportable': False,
|
||||
'selectable': False,
|
||||
}
|
||||
else:
|
||||
# boolean group fields
|
||||
|
@ -871,6 +872,7 @@ class users_view(osv.osv):
|
|||
'string': g.name,
|
||||
'help': g.comment,
|
||||
'exportable': False,
|
||||
'selectable': False,
|
||||
}
|
||||
return res
|
||||
|
||||
|
|
|
@ -530,4 +530,34 @@
|
|||
!python {model: res.partner }: |
|
||||
res_ids = self.search(cr, uid, [('child_ids.country_id','=','Belgium'),('active','=',False)])
|
||||
assert len(res_ids) != 0, "Record not Found with country Belgium and active False."
|
||||
-
|
||||
Check that we can exclude translated fields (bug lp:1071710)
|
||||
-
|
||||
!python {model: res.country}: |
|
||||
# first install french language
|
||||
Modules = self.pool.get('ir.module.module')
|
||||
base = Modules.browse(cr, uid, Modules.search(cr, uid, [('name', '=', 'base')])[0])
|
||||
|
||||
# hack: mark module as installed to allow install of the translation
|
||||
base_state = base.state
|
||||
base.write({'state': 'installed'})
|
||||
base.update_translations('fr_FR')
|
||||
base.write({'state': base_state})
|
||||
|
||||
# tests
|
||||
be_id = self.search(cr, uid, [('name', '=', 'Belgium')])[0]
|
||||
|
||||
ctx = {'lang': 'fr_FR'}
|
||||
not_be = self.search(cr, uid, [('name', '!=', 'Belgique')], context=ctx)
|
||||
|
||||
assert be_id not in not_be, "Search match failed"
|
||||
|
||||
# indirect search via m2o
|
||||
Partners = self.pool.get('res.partner')
|
||||
agrolait = Partners.search(cr, uid, [('name', '=', 'Agrolait')])[0]
|
||||
|
||||
not_be = Partners.search(cr, uid, [('country_id', '!=', 'Belgium')])
|
||||
assert agrolait not in not_be, "Search match failed (m2o)"
|
||||
|
||||
not_be = Partners.search(cr, uid, [('country_id', '!=', 'Belgique')], context=ctx)
|
||||
assert agrolait not in not_be, "Search match failed (m2o)"
|
||||
|
|
|
@ -152,8 +152,8 @@ DOMAIN_OPERATORS = (NOT_OPERATOR, OR_OPERATOR, AND_OPERATOR)
|
|||
# for consistency. This list doesn't contain '<>' as it is simpified to '!='
|
||||
# by the normalize_operator() function (so later part of the code deals with
|
||||
# only one representation).
|
||||
# An internal (i.e. not available to the user) 'inselect' operator is also
|
||||
# used. In this case its right operand has the form (subselect, params).
|
||||
# Internals (i.e. not available to the user) 'inselect' and 'not inselect'
|
||||
# operators are also used. In this case its right operand has the form (subselect, params).
|
||||
TERM_OPERATORS = ('=', '!=', '<=', '<', '>', '>=', '=?', '=like', '=ilike',
|
||||
'like', 'not like', 'ilike', 'not ilike', 'in', 'not in',
|
||||
'child_of')
|
||||
|
@ -395,7 +395,7 @@ def is_leaf(element, internal=False):
|
|||
"""
|
||||
INTERNAL_OPS = TERM_OPERATORS + ('<>',)
|
||||
if internal:
|
||||
INTERNAL_OPS += ('inselect',)
|
||||
INTERNAL_OPS += ('inselect', 'not inselect')
|
||||
return (isinstance(element, tuple) or isinstance(element, list)) \
|
||||
and len(element) == 3 \
|
||||
and element[1] in INTERNAL_OPS \
|
||||
|
@ -1024,6 +1024,12 @@ class expression(object):
|
|||
if need_wildcard:
|
||||
right = '%%%s%%' % right
|
||||
|
||||
inselect_operator = 'inselect'
|
||||
if sql_operator in NEGATIVE_TERM_OPERATORS:
|
||||
# negate operator (fix lp:1071710)
|
||||
sql_operator = sql_operator[4:] if sql_operator[:3] == 'not' else '='
|
||||
inselect_operator = 'not inselect'
|
||||
|
||||
subselect = '( SELECT res_id' \
|
||||
' FROM ir_translation' \
|
||||
' WHERE name = %s' \
|
||||
|
@ -1031,7 +1037,7 @@ class expression(object):
|
|||
' AND type = %s'
|
||||
instr = ' %s'
|
||||
#Covering in,not in operators with operands (%s,%s) ,etc.
|
||||
if sql_operator in ['in', 'not in']:
|
||||
if sql_operator == 'in':
|
||||
instr = ','.join(['%s'] * len(right))
|
||||
subselect += ' AND value ' + sql_operator + ' ' + " (" + instr + ")" \
|
||||
') UNION (' \
|
||||
|
@ -1051,7 +1057,7 @@ class expression(object):
|
|||
right,
|
||||
right,
|
||||
]
|
||||
push(create_substitution_leaf(leaf, ('id', 'inselect', (subselect, params)), working_model))
|
||||
push(create_substitution_leaf(leaf, ('id', inselect_operator, (subselect, params)), working_model))
|
||||
|
||||
else:
|
||||
push_result(leaf)
|
||||
|
@ -1072,7 +1078,7 @@ class expression(object):
|
|||
left, operator, right = leaf
|
||||
|
||||
# final sanity checks - should never fail
|
||||
assert operator in (TERM_OPERATORS + ('inselect',)), \
|
||||
assert operator in (TERM_OPERATORS + ('inselect', 'not inselect')), \
|
||||
"Invalid operator %r in domain term %r" % (operator, leaf)
|
||||
assert leaf in (TRUE_LEAF, FALSE_LEAF) or left in model._all_columns \
|
||||
or left in MAGIC_COLUMNS, "Invalid field %r in domain term %r" % (left, leaf)
|
||||
|
@ -1091,6 +1097,10 @@ class expression(object):
|
|||
query = '(%s."%s" in (%s))' % (table_alias, left, right[0])
|
||||
params = right[1]
|
||||
|
||||
elif operator == 'not inselect':
|
||||
query = '(%s."%s" not in (%s))' % (table_alias, left, right[0])
|
||||
params = right[1]
|
||||
|
||||
elif operator in ['in', 'not in']:
|
||||
# Two cases: right is a boolean or a list. The boolean case is an
|
||||
# abuse and handled for backward compatibility.
|
||||
|
|
|
@ -203,7 +203,8 @@ class reference(_column):
|
|||
model_name, res_id = value.split(',')
|
||||
if model_name in obj.pool and res_id:
|
||||
model = obj.pool[model_name]
|
||||
return model.name_get(cr, uid, [int(res_id)], context=context)[0][1]
|
||||
names = model.name_get(cr, uid, [int(res_id)], context=context)
|
||||
return names[0][1] if names else False
|
||||
return tools.ustr(value)
|
||||
|
||||
# takes a string (encoded in utf8) and returns a string (encoded in utf8)
|
||||
|
|
|
@ -77,6 +77,9 @@ from openerp.tools import SKIPPED_ELEMENT_TYPES
|
|||
regex_order = re.compile('^(([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
|
||||
regex_object_name = re.compile(r'^[a-z0-9_.]+$')
|
||||
|
||||
# TODO for trunk, raise the value to 1000
|
||||
AUTOINIT_RECALCULATE_STORED_FIELDS = 40
|
||||
|
||||
def transfer_field_to_modifiers(field, modifiers):
|
||||
default_values = {}
|
||||
state_exceptions = {}
|
||||
|
@ -2838,8 +2841,8 @@ class BaseModel(object):
|
|||
cr.execute('select id from '+self._table)
|
||||
ids_lst = map(lambda x: x[0], cr.fetchall())
|
||||
while ids_lst:
|
||||
iids = ids_lst[:40]
|
||||
ids_lst = ids_lst[40:]
|
||||
iids = ids_lst[:AUTOINIT_RECALCULATE_STORED_FIELDS]
|
||||
ids_lst = ids_lst[AUTOINIT_RECALCULATE_STORED_FIELDS:]
|
||||
res = f.get(cr, self, iids, k, SUPERUSER_ID, {})
|
||||
for key, val in res.items():
|
||||
if f._multi:
|
||||
|
@ -4560,7 +4563,9 @@ class BaseModel(object):
|
|||
self._validate(cr, user, [id_new], context)
|
||||
|
||||
if not context.get('no_store_function', False):
|
||||
result += self._store_get_values(cr, user, [id_new], vals.keys(), context)
|
||||
result += self._store_get_values(cr, user, [id_new],
|
||||
list(set(vals.keys() + self._inherits.values())),
|
||||
context)
|
||||
result.sort()
|
||||
done = []
|
||||
for order, model_name, ids, fields2 in result:
|
||||
|
@ -4785,6 +4790,9 @@ class BaseModel(object):
|
|||
|
||||
:param query: the current query object
|
||||
"""
|
||||
if uid == SUPERUSER_ID:
|
||||
return
|
||||
|
||||
def apply_rule(added_clause, added_params, added_tables, parent_model=None, child_object=None):
|
||||
""" :param string parent_model: string of the parent model
|
||||
:param model child_object: model object, base of the rule application
|
||||
|
|
|
@ -961,6 +961,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True,
|
|||
irt_cursor.push(dic)
|
||||
|
||||
irt_cursor.finish()
|
||||
trans_obj.clear_caches()
|
||||
if verbose:
|
||||
_logger.info("translation file loaded succesfully")
|
||||
except IOError:
|
||||
|
|
Loading…
Reference in New Issue