From 539f0ebb452aba5edae77ad08f07c9640c4ab99b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 May 2012 11:06:37 +0200 Subject: [PATCH 1/8] [FIX] cleanup of ir.sequence tests to make them repeatable bzr revid: xmo@openerp.com-20120522090637-xty4p2jmo74wijcc --- openerp/tests/test_ir_sequence.py | 74 ++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/openerp/tests/test_ir_sequence.py b/openerp/tests/test_ir_sequence.py index fcc5888e47e..9db4ff4817e 100644 --- a/openerp/tests/test_ir_sequence.py +++ b/openerp/tests/test_ir_sequence.py @@ -22,18 +22,59 @@ def registry(model): def cursor(): return openerp.modules.registry.RegistryManager.get(DB).db.cursor() -class test_ir_sequence_standard(unittest2.TestCase): +class SequenceCase(unittest2.TestCase): + """ + Base case for stateful testing of sequence objects (until we have fixtures?) + + * Provides easy-to-call methods for creating new ir.sequence and + ir.sequence.type (``make_seq`` and ``make_typ``) + * Cleanup of all sequences and sequence types created via the two functions + above + """ + typ_ids = None + seq_ids = None + + @classmethod + def setUpClass(cls): + cls.typ_ids = [] + cls.seq_ids = [] + + @classmethod + def tearDownClass(cls): + cr = cursor() + + registry('ir.sequence.type').unlink(cr, ADMIN_USER_ID, cls.typ_ids) + registry('ir.sequence').unlink(cr, ADMIN_USER_ID, cls.seq_ids) + + cr.commit() + cr.close() + + @classmethod + def make_seq(cls, cr, vars): + seq = registry('ir.sequence').create(cr, ADMIN_USER_ID, vars, {}) + cls.seq_ids.append(seq) + return seq + + @classmethod + def make_typ(cls, cr, vars): + typ = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, vars, {}) + cls.typ_ids.append(typ) + return typ + +class test_ir_sequence_standard(SequenceCase): """ A few tests for a 'Standard' (i.e. PostgreSQL) sequence. """ def test_ir_sequence_create(self): """ Try to create a sequence object. """ cr = cursor() + d = dict(code='test_sequence_type', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_typ(cr, d) assert c d = dict(code='test_sequence_type', name='Test sequence') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_seq(cr, d) assert c + cr.commit() cr.close() @@ -66,18 +107,19 @@ class test_ir_sequence_standard(unittest2.TestCase): cr0.close() cr1.close() -class test_ir_sequence_no_gap(unittest2.TestCase): +class test_ir_sequence_no_gap(SequenceCase): """ Copy of the previous tests for a 'No gap' sequence. """ def test_ir_sequence_create_no_gap(self): """ Try to create a sequence object. """ cr = cursor() d = dict(code='test_sequence_type_2', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_typ(cr, d) assert c + d = dict(code='test_sequence_type_2', name='Test sequence', implementation='no_gap') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_seq(cr, d) assert c cr.commit() cr.close() @@ -105,24 +147,24 @@ class test_ir_sequence_no_gap(unittest2.TestCase): cr0.close() cr1.close() -class test_ir_sequence_change_implementation(unittest2.TestCase): +class test_ir_sequence_change_implementation(SequenceCase): """ Create sequence objects and change their ``implementation`` field. """ def test_ir_sequence_1_create(self): """ Try to create a sequence object. """ cr = cursor() d = dict(code='test_sequence_type_3', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_typ(cr, d) assert c d = dict(code='test_sequence_type_3', name='Test sequence') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_seq(cr, d) assert c d = dict(code='test_sequence_type_4', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_typ(cr, d) assert c d = dict(code='test_sequence_type_4', name='Test sequence', implementation='no_gap') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_seq(cr, d) assert c cr.commit() cr.close() @@ -146,17 +188,17 @@ class test_ir_sequence_change_implementation(unittest2.TestCase): cr.commit() cr.close() -class test_ir_sequence_generate(unittest2.TestCase): +class test_ir_sequence_generate(SequenceCase): """ Create sequence objects and generate some values. """ def test_ir_sequence_create(self): """ Try to create a sequence object. """ cr = cursor() d = dict(code='test_sequence_type_5', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_typ(cr, d) assert c d = dict(code='test_sequence_type_5', name='Test sequence') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_seq(cr, d) assert c cr.commit() cr.close() @@ -171,10 +213,10 @@ class test_ir_sequence_generate(unittest2.TestCase): """ Try to create a sequence object. """ cr = cursor() d = dict(code='test_sequence_type_6', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_typ(cr, d) assert c d = dict(code='test_sequence_type_6', name='Test sequence') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + c = self.make_seq(cr, d) assert c cr.commit() cr.close() From 33e585a607e733e1fa99f8f6eb50681ed902125b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 May 2012 13:00:31 +0200 Subject: [PATCH 2/8] [TEST] (ir.filters).get_filters bzr revid: xmo@openerp.com-20120522110031-pddbryncp07dwfjk --- openerp/tests/__init__.py | 4 +- openerp/tests/common.py | 2 +- openerp/tests/test_ir_filters.py | 82 ++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 openerp/tests/test_ir_filters.py diff --git a/openerp/tests/__init__.py b/openerp/tests/__init__.py index 5fccb07a082..c55647983ed 100644 --- a/openerp/tests/__init__.py +++ b/openerp/tests/__init__.py @@ -11,10 +11,12 @@ See the :ref:`test-framework` section in the :ref:`features` list. import test_expression import test_ir_sequence import test_orm +from . import test_ir_filters fast_suite = [ test_ir_sequence, - ] + test_ir_filters +] checks = [ test_expression, diff --git a/openerp/tests/common.py b/openerp/tests/common.py index ef5b0586136..49fecefc3c8 100644 --- a/openerp/tests/common.py +++ b/openerp/tests/common.py @@ -14,7 +14,7 @@ DB = openerp.tools.config['db_name'] HOST = '127.0.0.1' ADMIN_USER = 'admin' -ADMIN_USER_ID = 1 +ADMIN_USER_ID = openerp.SUPERUSER_ID ADMIN_PASSWORD = 'admin' def start_openerp(): diff --git a/openerp/tests/test_ir_filters.py b/openerp/tests/test_ir_filters.py new file mode 100644 index 00000000000..c27583f37e1 --- /dev/null +++ b/openerp/tests/test_ir_filters.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +import functools + +import openerp +import common + +class Fixtures(object): + def __init__(self, *args): + self.fixtures = args + + def __call__(self, fn): + @functools.wraps(fn) + def wrapper(case): + for model, vars in self.fixtures: + case.registry(model).create( + case.cr, common.ADMIN_USER_ID, vars, {}) + + fn(case) + return wrapper +def fixtures(*args): + return Fixtures(*args) + +def noid(d): + """ Removes `id` key from a dict so we don't have to keep these things + around when trying to match + """ + if 'id' in d: del d['id'] + return d + +class TestGetFilters(common.TransactionCase): + USER_ID = 3 + USER = (3, u'Demo User') + + @fixtures( + ('ir.filters', dict(name='a', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='b', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='c', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='d', user_id=USER_ID, model_id='ir.filters')), + ) + def test_own_filters(self): + filters = self.registry('ir.filters').get_filters( + self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=self.USER, domain='[]', context='{}'), + dict(name='b', user_id=self.USER, domain='[]', context='{}'), + dict(name='c', user_id=self.USER, domain='[]', context='{}'), + dict(name='d', user_id=self.USER, domain='[]', context='{}'), + ]) + + @fixtures( + ('ir.filters', dict(name='a', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='b', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='c', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='d', user_id=False, model_id='ir.filters')), + ) + def test_global_filters(self): + filters = self.registry('ir.filters').get_filters( + self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=False, domain='[]', context='{}'), + dict(name='b', user_id=False, domain='[]', context='{}'), + dict(name='c', user_id=False, domain='[]', context='{}'), + dict(name='d', user_id=False, domain='[]', context='{}'), + ]) + + @fixtures( + ('ir.filters', dict(name='a', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='b', user_id=common.ADMIN_USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='c', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='d', user_id=common.ADMIN_USER_ID, model_id='ir.filters')), + ) + def test_no_third_party_filters(self): + filters = self.registry('ir.filters').get_filters( + self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=False, domain='[]', context='{}'), + dict(name='c', user_id=self.USER, domain='[]', context='{}'), + ]) + From a90c8ff5ae71e6b0bcf768ac0ddb85b1d3533133 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 May 2012 13:53:30 +0200 Subject: [PATCH 3/8] [ADD] is_default handling on private filters bzr revid: xmo@openerp.com-20120522115330-xnr4pyfy9sh3oqtv --- openerp/addons/base/ir/ir_filters.py | 11 ++- openerp/tests/test_ir_filters.py | 113 ++++++++++++++++++++++++--- 2 files changed, 113 insertions(+), 11 deletions(-) diff --git a/openerp/addons/base/ir/ir_filters.py b/openerp/addons/base/ir/ir_filters.py index 02a723c116c..f716a4f8d43 100644 --- a/openerp/addons/base/ir/ir_filters.py +++ b/openerp/addons/base/ir/ir_filters.py @@ -46,7 +46,7 @@ class ir_filters(osv.osv): """ # available filters: private filters (user_id=uid) and public filters (uid=NULL) act_ids = self.search(cr, uid, [('model_id','=',model),('user_id','in',[uid, False])]) - my_acts = self.read(cr, uid, act_ids, ['name', 'domain', 'context', 'user_id']) + my_acts = self.read(cr, uid, act_ids, ['name', 'is_default', 'domain', 'context', 'user_id']) return my_acts def create_or_replace(self, cr, uid, vals, context=None): @@ -57,6 +57,13 @@ class ir_filters(osv.osv): # f.user_id is False and vals.user_id is False or missing, # or f.user_id.id == vals.user_id if (f['user_id'] and f['user_id'][0]) == vals.get('user_id', False)] + + if 'user_id' in vals and vals.get('is_default'): + act_ids = self.search(cr, uid, [('model_id', '=', vals['model_id']), + ('user_id', '=', vals['user_id'])], + context=context) + self.write(cr, uid, act_ids, {'is_default': False}, context=context) + # When a filter exists for the same (name, model, user) triple, we simply # replace its definition. if matching_filters: @@ -87,11 +94,13 @@ class ir_filters(osv.osv): 'domain': fields.text('Domain', required=True), 'context': fields.text('Context', required=True), 'model_id': fields.selection(_list_all_models, 'Model', required=True), + 'is_default': fields.boolean('Default filter') } _defaults = { 'domain': '[]', 'context':'{}', 'user_id': lambda self,cr,uid,context=None: uid, + 'is_default': False } ir_filters() diff --git a/openerp/tests/test_ir_filters.py b/openerp/tests/test_ir_filters.py index c27583f37e1..98714d7f46b 100644 --- a/openerp/tests/test_ir_filters.py +++ b/openerp/tests/test_ir_filters.py @@ -42,10 +42,10 @@ class TestGetFilters(common.TransactionCase): self.cr, self.USER_ID, 'ir.filters') self.assertItemsEqual(map(noid, filters), [ - dict(name='a', user_id=self.USER, domain='[]', context='{}'), - dict(name='b', user_id=self.USER, domain='[]', context='{}'), - dict(name='c', user_id=self.USER, domain='[]', context='{}'), - dict(name='d', user_id=self.USER, domain='[]', context='{}'), + dict(name='a', is_default=False, user_id=self.USER, domain='[]', context='{}'), + dict(name='b', is_default=False, user_id=self.USER, domain='[]', context='{}'), + dict(name='c', is_default=False, user_id=self.USER, domain='[]', context='{}'), + dict(name='d', is_default=False, user_id=self.USER, domain='[]', context='{}'), ]) @fixtures( @@ -59,10 +59,10 @@ class TestGetFilters(common.TransactionCase): self.cr, self.USER_ID, 'ir.filters') self.assertItemsEqual(map(noid, filters), [ - dict(name='a', user_id=False, domain='[]', context='{}'), - dict(name='b', user_id=False, domain='[]', context='{}'), - dict(name='c', user_id=False, domain='[]', context='{}'), - dict(name='d', user_id=False, domain='[]', context='{}'), + dict(name='a', is_default=False, user_id=False, domain='[]', context='{}'), + dict(name='b', is_default=False, user_id=False, domain='[]', context='{}'), + dict(name='c', is_default=False, user_id=False, domain='[]', context='{}'), + dict(name='d', is_default=False, user_id=False, domain='[]', context='{}'), ]) @fixtures( @@ -76,7 +76,100 @@ class TestGetFilters(common.TransactionCase): self.cr, self.USER_ID, 'ir.filters') self.assertItemsEqual(map(noid, filters), [ - dict(name='a', user_id=False, domain='[]', context='{}'), - dict(name='c', user_id=self.USER, domain='[]', context='{}'), + dict(name='a', is_default=False, user_id=False, domain='[]', context='{}'), + dict(name='c', is_default=False, user_id=self.USER, domain='[]', context='{}'), ]) +class TestOwnDefaults(common.TransactionCase): + USER_ID = 3 + USER = (3, u'Demo User') + + def test_new_no_filter(self): + """ + When creating a @is_default filter with no existing filter, that new + filter gets the default flag + """ + Filters = self.registry('ir.filters') + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'a', + 'model_id': 'ir.filters', + 'user_id': self.USER_ID, + 'is_default': True, + }) + filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=self.USER, is_default=True, + domain='[]', context='{}') + ]) + + @fixtures( + ('ir.filters', dict(name='a', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='b', user_id=USER_ID, model_id='ir.filters')), + ) + def test_new_filter_not_default(self): + """ + When creating a @is_default filter with existing non-default filters, + the new filter gets the flag + """ + Filters = self.registry('ir.filters') + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'c', + 'model_id': 'ir.filters', + 'user_id': self.USER_ID, + 'is_default': True, + }) + filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=self.USER, is_default=False, domain='[]', context='{}'), + dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}'), + dict(name='c', user_id=self.USER, is_default=True, domain='[]', context='{}'), + ]) + + @fixtures( + ('ir.filters', dict(name='a', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='b', is_default=True, user_id=USER_ID, model_id='ir.filters')), + ) + def test_new_filter_existing_default(self): + """ + When creating a @is_default filter where an existing filter is already + @is_default, the flag should be *moved* from the old to the new filter + """ + Filters = self.registry('ir.filters') + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'c', + 'model_id': 'ir.filters', + 'user_id': self.USER_ID, + 'is_default': True, + }) + filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=self.USER, is_default=False, domain='[]', context='{}'), + dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}'), + dict(name='c', user_id=self.USER, is_default=True, domain='[]', context='{}'), + ]) + + @fixtures( + ('ir.filters', dict(name='a', user_id=USER_ID, model_id='ir.filters')), + ('ir.filters', dict(name='b', is_default=True, user_id=USER_ID, model_id='ir.filters')), + ) + def test_update_filter_set_default(self): + """ + When updating an existing filter to @is_default, if an other filter + already has the flag the flag should be moved + """ + Filters = self.registry('ir.filters') + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'a', + 'model_id': 'ir.filters', + 'user_id': self.USER_ID, + 'is_default': True, + }) + filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=self.USER, is_default=True, domain='[]', context='{}'), + dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}'), + ]) From 415d91f924428941759d4f0b229e17cf30e41658 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 May 2012 14:55:00 +0200 Subject: [PATCH 4/8] [FIX] error out when trying to set a global default if there already is a global default set bzr revid: xmo@openerp.com-20120522125500-k4gxfa5ocmxk70us --- openerp/addons/base/ir/ir_filters.py | 48 +++++++++++++++++--- openerp/tests/test_ir_filters.py | 67 +++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/ir/ir_filters.py b/openerp/addons/base/ir/ir_filters.py index f716a4f8d43..40ef7d41a86 100644 --- a/openerp/addons/base/ir/ir_filters.py +++ b/openerp/addons/base/ir/ir_filters.py @@ -19,6 +19,7 @@ # ############################################################################## +from openerp import exceptions from osv import osv, fields from tools.translate import _ @@ -49,6 +50,37 @@ class ir_filters(osv.osv): my_acts = self.read(cr, uid, act_ids, ['name', 'is_default', 'domain', 'context', 'user_id']) return my_acts + def _check_global_default(self, cr, uid, vals, matching_filters, context=None): + """ _check_global_default(cursor, UID, dict, list(dict), dict) -> None + + Checks if there is a global default for the model_id requested. + + If there is, and the default is different than the record being written + (-> we're not updating the current global default), raise an error + to avoid users unknowingly overwriting existing global defaults (they + have to explicitly remove the current default before setting a new one) + + This method should only be called if ``vals`` is trying to set + ``is_default`` + + :raises openerp.exceptions.Warning: if there is an existing default and + we're not updating it + """ + existing_default = self.search(cr, uid, [ + ('model_id', '=', vals['model_id']), + ('user_id', '=', False), + ('is_default', '=', True)], context=context) + + if not existing_default: return + if matching_filters and \ + (matching_filters[0]['id'] == existing_default[0]): + return + + raise exceptions.Warning( + _("There is already a global filter set as default for %(model)s, delete or change it before setting a new default") % { + 'model': vals['model_id'] + }) + def create_or_replace(self, cr, uid, vals, context=None): lower_name = vals['name'].lower() matching_filters = [f for f in self.get_filters(cr, uid, vals['model_id']) @@ -58,17 +90,23 @@ class ir_filters(osv.osv): # or f.user_id.id == vals.user_id if (f['user_id'] and f['user_id'][0]) == vals.get('user_id', False)] - if 'user_id' in vals and vals.get('is_default'): - act_ids = self.search(cr, uid, [('model_id', '=', vals['model_id']), - ('user_id', '=', vals['user_id'])], - context=context) - self.write(cr, uid, act_ids, {'is_default': False}, context=context) + if vals.get('is_default'): + if vals.get('user_id'): + act_ids = self.search(cr, uid, [('model_id', '=', vals['model_id']), + ('user_id', '=', vals['user_id'])], + context=context) + self.write(cr, uid, act_ids, {'is_default': False}, context=context) + else: + self._check_global_default( + cr, uid, vals, matching_filters, context=None) + # When a filter exists for the same (name, model, user) triple, we simply # replace its definition. if matching_filters: self.write(cr, uid, matching_filters[0]['id'], vals, context) return matching_filters[0]['id'] + return self.create(cr, uid, vals, context) _sql_constraints = [ diff --git a/openerp/tests/test_ir_filters.py b/openerp/tests/test_ir_filters.py index 98714d7f46b..eaf5eb93d3c 100644 --- a/openerp/tests/test_ir_filters.py +++ b/openerp/tests/test_ir_filters.py @@ -2,7 +2,8 @@ import functools import openerp -import common +from openerp import exceptions +from . import common class Fixtures(object): def __init__(self, *args): @@ -173,3 +174,67 @@ class TestOwnDefaults(common.TransactionCase): dict(name='a', user_id=self.USER, is_default=True, domain='[]', context='{}'), dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}'), ]) + +class TestGlobalDefaults(common.TransactionCase): + USER_ID = 3 + + @fixtures( + ('ir.filters', dict(name='a', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='b', user_id=False, model_id='ir.filters')), + ) + def test_new_filter_not_default(self): + """ + When creating a @is_default filter with existing non-default filters, + the new filter gets the flag + """ + Filters = self.registry('ir.filters') + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'c', + 'model_id': 'ir.filters', + 'user_id': False, + 'is_default': True, + }) + filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=False, is_default=False, domain='[]', context='{}'), + dict(name='b', user_id=False, is_default=False, domain='[]', context='{}'), + dict(name='c', user_id=False, is_default=True, domain='[]', context='{}'), + ]) + + @fixtures( + ('ir.filters', dict(name='a', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='b', is_default=True, user_id=False, model_id='ir.filters')), + ) + def test_new_filter_existing_default(self): + """ + When creating a @is_default filter where an existing filter is already + @is_default, an error should be generated + """ + Filters = self.registry('ir.filters') + with self.assertRaises(exceptions.Warning): + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'c', + 'model_id': 'ir.filters', + 'user_id': False, + 'is_default': True, + }) + + @fixtures( + ('ir.filters', dict(name='a', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='b', is_default=True, user_id=False, model_id='ir.filters')), + ) + def test_update_filter_set_default(self): + """ + When updating an existing filter to @is_default, if an other filter + already has the flag an error should be generated + """ + Filters = self.registry('ir.filters') + + with self.assertRaises(exceptions.Warning): + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'a', + 'model_id': 'ir.filters', + 'user_id': False, + 'is_default': True, + }) From 80d962a4ccdf45448100a910b81f41f7201ebee5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 May 2012 14:56:30 +0200 Subject: [PATCH 5/8] [IMP] when moving is_default flag, only select private filters with is_default (0 or 1), instead of all filters for the user (potentially many) bzr revid: xmo@openerp.com-20120522125630-z7lfdutuabpx64u0 --- openerp/addons/base/ir/ir_filters.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openerp/addons/base/ir/ir_filters.py b/openerp/addons/base/ir/ir_filters.py index 40ef7d41a86..4f189d65002 100644 --- a/openerp/addons/base/ir/ir_filters.py +++ b/openerp/addons/base/ir/ir_filters.py @@ -92,9 +92,11 @@ class ir_filters(osv.osv): if vals.get('is_default'): if vals.get('user_id'): - act_ids = self.search(cr, uid, [('model_id', '=', vals['model_id']), - ('user_id', '=', vals['user_id'])], - context=context) + act_ids = self.search(cr, uid, [ + ('model_id', '=', vals['model_id']), + ('user_id', '=', vals['user_id']), + ('is_default', '=', True), + ], context=context) self.write(cr, uid, act_ids, {'is_default': False}, context=context) else: self._check_global_default( From 33de722e839aeab1cfb535f57c10b2e8ff6fcceb Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 May 2012 15:01:38 +0200 Subject: [PATCH 6/8] [FIX] documentation of get_filters: returns a new field bzr revid: xmo@openerp.com-20120522130138-tk4rdz2k97g9ohqb --- openerp/addons/base/ir/ir_filters.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/ir/ir_filters.py b/openerp/addons/base/ir/ir_filters.py index 4f189d65002..e867c535f8b 100644 --- a/openerp/addons/base/ir/ir_filters.py +++ b/openerp/addons/base/ir/ir_filters.py @@ -42,13 +42,16 @@ class ir_filters(osv.osv): def get_filters(self, cr, uid, model): """Obtain the list of filters available for the user on the given model. - :return: list of :meth:`~osv.read`-like dicts containing the ``name``, - ``domain``, ``user_id`` (m2o tuple) and ``context`` of the matching ``ir.filters``. + :return: list of :meth:`~osv.read`-like dicts containing the + ``name``, ``is_default``, ``domain``, ``user_id`` (m2o tuple) and + ``context`` of the matching ``ir.filters``. """ # available filters: private filters (user_id=uid) and public filters (uid=NULL) - act_ids = self.search(cr, uid, [('model_id','=',model),('user_id','in',[uid, False])]) - my_acts = self.read(cr, uid, act_ids, ['name', 'is_default', 'domain', 'context', 'user_id']) - return my_acts + filter_ids = self.search(cr, uid, + [('model_id','=',model),('user_id','in',[uid, False])]) + my_filters = self.read(cr, uid, filter_ids, + ['name', 'is_default', 'domain', 'context', 'user_id']) + return my_filters def _check_global_default(self, cr, uid, vals, matching_filters, context=None): """ _check_global_default(cursor, UID, dict, list(dict), dict) -> None @@ -102,7 +105,6 @@ class ir_filters(osv.osv): self._check_global_default( cr, uid, vals, matching_filters, context=None) - # When a filter exists for the same (name, model, user) triple, we simply # replace its definition. if matching_filters: From 384a95461a9b12d0420c7a2f3ba049c9b58d718e Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 8 Nov 2012 10:28:22 +0100 Subject: [PATCH 7/8] [IMP] ir_filters: use "shared filters" to designate global filters, to match the UI bzr revid: odo@openerp.com-20121108092822-l8bog0ow0m0ey0b8 --- openerp/addons/base/ir/ir_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_filters.py b/openerp/addons/base/ir/ir_filters.py index e867c535f8b..7c03341b55f 100644 --- a/openerp/addons/base/ir/ir_filters.py +++ b/openerp/addons/base/ir/ir_filters.py @@ -80,7 +80,7 @@ class ir_filters(osv.osv): return raise exceptions.Warning( - _("There is already a global filter set as default for %(model)s, delete or change it before setting a new default") % { + _("There is already a shared filter set as default for %(model)s, delete or change it before setting a new default") % { 'model': vals['model_id'] }) From 76b031cfd4ebbefe320938926f245badb5bcda76 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 8 Nov 2012 10:29:07 +0100 Subject: [PATCH 8/8] [IMP] ir_filters: add test for updating global default filter - to complete the over-coverage bzr revid: odo@openerp.com-20121108092907-e7cmjz4w4wn5u085 --- openerp/tests/test_ir_filters.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/openerp/tests/test_ir_filters.py b/openerp/tests/test_ir_filters.py index eaf5eb93d3c..c6582db1cb2 100644 --- a/openerp/tests/test_ir_filters.py +++ b/openerp/tests/test_ir_filters.py @@ -238,3 +238,27 @@ class TestGlobalDefaults(common.TransactionCase): 'user_id': False, 'is_default': True, }) + + @fixtures( + ('ir.filters', dict(name='a', user_id=False, model_id='ir.filters')), + ('ir.filters', dict(name='b', is_default=True, user_id=False, model_id='ir.filters')), + ) + def test_update_default_filter(self): + """ + Replacing the current default global filter should not generate any error + """ + Filters = self.registry('ir.filters') + context_value = "{'some_key': True}" + Filters.create_or_replace(self.cr, self.USER_ID, { + 'name': 'b', + 'model_id': 'ir.filters', + 'user_id': False, + 'context': context_value, + 'is_default': True, + }) + filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters') + + self.assertItemsEqual(map(noid, filters), [ + dict(name='a', user_id=False, is_default=False, domain='[]', context='{}'), + dict(name='b', user_id=False, is_default=True, domain='[]', context=context_value), + ]) \ No newline at end of file