1# -*- coding: utf-8 -*- 2# Part of Odoo. See LICENSE file for full copyright and licensing details. 3 4from odoo.tests.common import TransactionCase 5 6 7class test_search(TransactionCase): 8 9 def test_00_search_order(self): 10 # Create 6 partners with a given name, and a given creation order to 11 # ensure the order of their ID. Some are set as inactive to verify they 12 # are by default excluded from the searches and to provide a second 13 # `order` argument. 14 15 Partner = self.env['res.partner'] 16 c = Partner.create({'name': 'test_search_order_C'}) 17 d = Partner.create({'name': 'test_search_order_D', 'active': False}) 18 a = Partner.create({'name': 'test_search_order_A'}) 19 b = Partner.create({'name': 'test_search_order_B'}) 20 ab = Partner.create({'name': 'test_search_order_AB'}) 21 e = Partner.create({'name': 'test_search_order_E', 'active': False}) 22 23 # The tests. 24 25 # The basic searches should exclude records that have active = False. 26 # The order of the returned ids should be given by the `order` 27 # parameter of search(). 28 29 name_asc = Partner.search([('name', 'like', 'test_search_order%')], order="name asc") 30 self.assertEqual([a, ab, b, c], list(name_asc), "Search with 'NAME ASC' order failed.") 31 name_desc = Partner.search([('name', 'like', 'test_search_order%')], order="name desc") 32 self.assertEqual([c, b, ab, a], list(name_desc), "Search with 'NAME DESC' order failed.") 33 id_asc = Partner.search([('name', 'like', 'test_search_order%')], order="id asc") 34 self.assertEqual([c, a, b, ab], list(id_asc), "Search with 'ID ASC' order failed.") 35 id_desc = Partner.search([('name', 'like', 'test_search_order%')], order="id desc") 36 self.assertEqual([ab, b, a, c], list(id_desc), "Search with 'ID DESC' order failed.") 37 38 # The inactive records shouldn't be excluded as soon as a condition on 39 # that field is present in the domain. The `order` parameter of 40 # search() should support any legal coma-separated values. 41 42 active_asc_id_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active asc, id asc") 43 self.assertEqual([d, e, c, a, b, ab], list(active_asc_id_asc), "Search with 'ACTIVE ASC, ID ASC' order failed.") 44 active_desc_id_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active desc, id asc") 45 self.assertEqual([c, a, b, ab, d, e], list(active_desc_id_asc), "Search with 'ACTIVE DESC, ID ASC' order failed.") 46 active_asc_id_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active asc, id desc") 47 self.assertEqual([e, d, ab, b, a, c], list(active_asc_id_desc), "Search with 'ACTIVE ASC, ID DESC' order failed.") 48 active_desc_id_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active desc, id desc") 49 self.assertEqual([ab, b, a, c, e, d], list(active_desc_id_desc), "Search with 'ACTIVE DESC, ID DESC' order failed.") 50 id_asc_active_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id asc, active asc") 51 self.assertEqual([c, d, a, b, ab, e], list(id_asc_active_asc), "Search with 'ID ASC, ACTIVE ASC' order failed.") 52 id_asc_active_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id asc, active desc") 53 self.assertEqual([c, d, a, b, ab, e], list(id_asc_active_desc), "Search with 'ID ASC, ACTIVE DESC' order failed.") 54 id_desc_active_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id desc, active asc") 55 self.assertEqual([e, ab, b, a, d, c], list(id_desc_active_asc), "Search with 'ID DESC, ACTIVE ASC' order failed.") 56 id_desc_active_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id desc, active desc") 57 self.assertEqual([e, ab, b, a, d, c], list(id_desc_active_desc), "Search with 'ID DESC, ACTIVE DESC' order failed.") 58 59 def test_10_inherits_m2order(self): 60 Users = self.env['res.users'] 61 62 # Find Employee group 63 group_employee = self.env.ref('base.group_user') 64 65 # Get country/state data 66 country_be = self.env.ref('base.be') 67 country_us = self.env.ref('base.us') 68 states_us = country_us.state_ids[:2] 69 70 # Create test users 71 u = Users.create({'name': '__search', 'login': '__search', 'groups_id': [(6, 0, [group_employee.id])]}) 72 a = Users.create({'name': '__test_A', 'login': '__test_A', 'country_id': country_be.id, 'state_id': country_be.id}) 73 b = Users.create({'name': '__test_B', 'login': '__a_test_B', 'country_id': country_us.id, 'state_id': states_us[1].id}) 74 c = Users.create({'name': '__test_B', 'login': '__z_test_B', 'country_id': country_us.id, 'state_id': states_us[0].id}) 75 76 # Search as search user 77 Users = Users.with_user(u) 78 79 # Do: search on res.users, order on a field on res.partner to try inherits'd fields, then res.users 80 expected_ids = [u.id, a.id, c.id, b.id] 81 user_ids = Users.search([('id', 'in', expected_ids)], order='name asc, login desc').ids 82 self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order') 83 84 # Do: order on many2one and inherits'd fields 85 expected_ids = [c.id, b.id, a.id, u.id] 86 user_ids = Users.search([('id', 'in', expected_ids)], order='state_id asc, country_id desc, name asc, login desc').ids 87 self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order') 88 89 # Do: order on many2one and inherits'd fields 90 expected_ids = [u.id, b.id, c.id, a.id] 91 user_ids = Users.search([('id', 'in', expected_ids)], order='country_id desc, state_id desc, name asc, login desc').ids 92 self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order') 93 94 # Do: order on many2one, but not by specifying in order parameter of search, but by overriding _order of res_users 95 self.patch_order('res.users', 'country_id desc, name asc, login desc') 96 expected_ids = [u.id, c.id, b.id, a.id] 97 user_ids = Users.search([('id', 'in', expected_ids)]).ids 98 self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order') 99 100 def test_11_indirect_inherits_m2o_order(self): 101 Cron = self.env['ir.cron'] 102 Users = self.env['res.users'] 103 104 user_ids = {} 105 cron_ids = {} 106 for u in 'BAC': 107 user_ids[u] = Users.create({'name': u, 'login': u}).id 108 cron_ids[u] = Cron.create({'name': u, 'model_id': self.env.ref('base.model_res_partner').id, 'user_id': user_ids[u]}).id 109 110 ids = Cron.search([('id', 'in', list(cron_ids.values()))], order='user_id').ids 111 expected_ids = [cron_ids[l] for l in 'ABC'] 112 self.assertEqual(ids, expected_ids) 113 114 def test_12_m2o_order_loop_self(self): 115 Cats = self.env['ir.module.category'] 116 cat_ids = {} 117 def create(name, **kw): 118 cat_ids[name] = Cats.create(dict(kw, name=name)).id 119 120 self.patch_order('ir.module.category', 'parent_id desc, name') 121 122 create('A') 123 create('B', parent_id=cat_ids['A']) 124 create('C', parent_id=cat_ids['A']) 125 create('D') 126 create('E', parent_id=cat_ids['D']) 127 create('F', parent_id=cat_ids['D']) 128 129 expected_ids = [cat_ids[x] for x in 'ADEFBC'] 130 found_ids = Cats.search([('id', 'in', list(cat_ids.values()))]).ids 131 self.assertEqual(found_ids, expected_ids) 132 133 def test_13_m2o_order_loop_multi(self): 134 Users = self.env['res.users'] 135 136 # will sort by login desc of the creator, then by name 137 self.patch_order('res.partner', 'create_uid, name') 138 self.patch_order('res.users', 'partner_id, login desc') 139 140 kw = dict(groups_id=[(6, 0, [self.ref('base.group_system'), 141 self.ref('base.group_partner_manager')])]) 142 143 u1 = Users.create(dict(name='Q', login='m', **kw)).id 144 u2 = Users.with_user(u1).create(dict(name='B', login='f', **kw)).id 145 u3 = Users.create(dict(name='C', login='c', **kw)).id 146 u4 = Users.with_user(u2).create(dict(name='D', login='z', **kw)).id 147 148 expected_ids = [u2, u4, u3, u1] 149 found_ids = Users.search([('id', 'in', expected_ids)]).ids 150 self.assertEqual(found_ids, expected_ids) 151 152 def test_20_x_active(self): 153 """Check the behaviour of the x_active field.""" 154 # test that a custom field x_active filters like active 155 # we take the model res.country as a test model as it is included in base and does 156 # not have an active field 157 model_country = self.env['res.country'] 158 self.assertNotIn('active', model_country._fields) # just in case someone adds the active field in the model 159 self.env['ir.model.fields'].create({ 160 'name': 'x_active', 161 'model_id': self.env.ref('base.model_res_country').id, 162 'ttype': 'boolean', 163 }) 164 self.assertEqual('x_active', model_country._active_name) 165 country_ussr = model_country.create({'name': 'USSR', 'x_active': False}) 166 ussr_search = model_country.search([('name', '=', 'USSR')]) 167 self.assertFalse(ussr_search) 168 ussr_search = model_country.with_context(active_test=False).search([('name', '=', 'USSR')]) 169 self.assertIn(country_ussr, ussr_search, "Search with active_test on a custom x_active field failed") 170 ussr_search = model_country.search([('name', '=', 'USSR'), ('x_active', '=', False)]) 171 self.assertIn(country_ussr, ussr_search, "Search with active_test on a custom x_active field failed") 172 # test that a custom field x_active on a model with the standard active 173 # field does not interfere with the standard behaviour 174 # use res.bank since it has an active field and is simple to use 175 model_bank = self.env['res.bank'] 176 self.env['ir.model.fields'].create({ 177 'name': 'x_active', 178 'model_id': self.env.ref('base.model_res_bank').id, 179 'ttype': 'boolean', 180 }) 181 self.assertEqual('active', model_bank._active_name) 182 bank_credit_communal = model_bank.create({'name': 'Crédit Communal', 'x_active': False, 'active': True}) 183 cc_search = model_bank.search([('name', '=', 'Crédit Communal')]) 184 self.assertIn(bank_credit_communal, cc_search, "Search for active record with x_active set to False has failed") 185 bank_credit_communal.write({ 186 'active': False, 187 'x_active': True, 188 }) 189 cc_search = model_bank.search([('name', '=', 'Crédit Communal')]) 190 self.assertNotIn(bank_credit_communal, cc_search, "Search for inactive record with x_active set to True has failed") 191