diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index cb242942656..719a4fe8a4d 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -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: diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index d6ad6efdd90..fc5d5aa1188 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -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, } diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index df4cff03fb0..630c33971fa 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -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 = "" % (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): diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index 6347e22d576..c7b4b369b17 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -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 diff --git a/addons/project/project.py b/addons/project/project.py index 0f5c8dbef50..40c239a42fa 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -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): diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 4451a2589b2..eeb23330e91 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2013 OpenERP S.A. +# Copyright (C) 2004-2014 OpenERP S.A. # # 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] + [('', '')] diff --git a/openerp/addons/base/ir/ir_attachment.py b/openerp/addons/base/ir/ir_attachment.py index f6bb00fed5f..52b5d4ab8cc 100644 --- a/openerp/addons/base/ir/ir_attachment.py +++ b/openerp/addons/base/ir/ir_attachment.py @@ -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 diff --git a/openerp/addons/base/res/res_country.py b/openerp/addons/base/res/res_country.py index 63fcf967630..df68d211a97 100644 --- a/openerp/addons/base/res/res_country.py +++ b/openerp/addons/base/res/res_country.py @@ -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) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 1c26b120bfe..37b6493e081 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -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 diff --git a/openerp/addons/base/test/test_osv_expression.yml b/openerp/addons/base/test/test_osv_expression.yml index 111ce40f2ce..e0061135d85 100644 --- a/openerp/addons/base/test/test_osv_expression.yml +++ b/openerp/addons/base/test/test_osv_expression.yml @@ -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)" diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index 18a1e9508f5..4eb6ad192a7 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -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. diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index a9498b1ff71..49c436c69d4 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -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) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 610d0a5d503..9bf216f30d3 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -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 diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index f82fa4b87ad..c14244abd56 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -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: