Repository: OCA/server-tools

Issue:
base_name_search_improved  - Portal Access Managment
@dreispt 
This ocurrs in when click on customer --> More --> Portal Access Managment.

> Traceback (most recent call last):
>   File "/opt/odoov1/OCB/openerp/http.py", line 539, in _handle_exception
>     return super(JsonRequest, self)._handle_exception(exception)
>   File "/opt/odoov1/OCB/openerp/http.py", line 576, in dispatch
>     result = self._call_function(*_self.params)
>   File "/opt/odoov1/OCB/openerp/http.py", line 312, in _call_function
>     return checked_call(self.db, *args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/service/model.py", line 118, in wrapper
>     return f(dbname, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/http.py", line 309, in checked_call
>     return self.endpoint(_a, *_kw)
>   File "/opt/odoov1/OCB/openerp/http.py", line 805, in __call__
>     return self.method(_args, *_kw)
>   File "/opt/odoov1/OCB/openerp/http.py", line 405, in response_wrap
>     response = f(_args, *_kw)
>   File "/opt/odoov1/OCB/addons/web/controllers/main.py", line 944, in call_kw
>     return self._call_kw(model, method, args, kwargs)
>   File "/opt/odoov1/OCB/addons/web/controllers/main.py", line 936, in _call_kw
>     return getattr(request.registry.get(model), method)(request.cr, request.uid, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/api.py", line 268, in wrapper
>     return old_api(self, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/api.py", line 372, in old_api
>     result = method(recs, _args, *_kwargs)
>   File "/opt/odoov1/extra-addons/base_name_search_improved/models/ir_model.py", line 61, in name_search
>     res = _extend_name_results(self, domain, res, limit)
>   File "/opt/odoov1/extra-addons/base_name_search_improved/models/ir_model.py", line 27, in _extend_name_results
>     recs = self.search(domain, limit=limit - result_count)
>   File "/opt/odoov1/OCB/openerp/api.py", line 266, in wrapper
>     return new_api(self, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/api.py", line 508, in new_api
>     result = method(self._model, cr, uid, _args, *_old_kwargs)
>   File "/opt/odoov1/OCB/openerp/addons/base/res/res_users.py", line 121, in search
>     return super(res_groups, self).search(cr, uid, args, offset, limit, order, context, count)
>   File "/opt/odoov1/OCB/openerp/api.py", line 268, in wrapper
>     return old_api(self, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/models.py", line 1646, in search
>     return self._search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
>   File "/opt/odoov1/OCB/openerp/api.py", line 268, in wrapper
>     return old_api(self, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/models.py", line 4673, in _search
>     query = self._where_calc(cr, user, args, context=context)
>   File "/opt/odoov1/OCB/openerp/api.py", line 268, in wrapper
>     return old_api(self, _args, *_kwargs)
>   File "/opt/odoov1/OCB/openerp/models.py", line 4484, in _where_calc
>     e = expression.expression(cr, user, domain, self, context)
>   File "/opt/odoov1/OCB/openerp/osv/expression.py", line 662, in __init__
>     self.parse(cr, uid, context=context)
>   File "/opt/odoov1/OCB/openerp/osv/expression.py", line 921, in parse
>     fct_domain = column.search(cr, uid, model, left, [leaf.leaf], context=context)
>   File "/opt/odoov1/OCB/openerp/osv/fields.py", line 1423, in search
>     return self._fnct_search(obj, cr, uid, obj, name, args, context=context)
>   File "/opt/odoov1/OCB/openerp/addons/base/res/res_users.py", line 80, in _search_group
>     group_name = values.pop().strip()
> IndexError: pop from empty list



Discussion:

Resolving patch:
diff --git a/base_name_search_improved/models/ir_model.py b/base_name_search_improved/models/ir_model.py
--- a/base_name_search_improved/models/ir_model.py
+++ b/base_name_search_improved/models/ir_model.py
@@ -13,6 +13,7 @@
 
 @tools.ormcache(skiparg=0)
 def _get_rec_names(self):
+    "List of fields to search into"
     model = self.env['ir.model'].search(
         [('model', '=', str(self._model))])
     rec_name = [self._rec_name] or []
@@ -48,22 +49,28 @@ def name_search(self, name='', args=None,
                     self, name=name, args=args, operator=operator, limit=limit)
                 enabled = self.env.context.get('name_search_extended', True)
                 # Perform extended name search
-                if enabled and operator in ALLOWED_OPS:
+                # Note: Empty name causes error on
+                #       Customer->More->Portal Access Management
+                if name and enabled and operator in ALLOWED_OPS:
                     # Support a list of fields to search on
                     all_names = _get_rec_names(self)
+                    base_domain = args or []
                     # Try regular search on each additional search field
                     for rec_name in all_names[1:]:
                         domain = [(rec_name, operator, name)]
-                        res = _extend_name_results(self, domain, res, limit)
+                        res = _extend_name_results(
+                            self, base_domain + domain, res, limit)
                     # Try ordered word search on each of the search fields
                     for rec_name in all_names:
                         domain = [(rec_name, operator, name.replace(' ', '%'))]
-                        res = _extend_name_results(self, domain, res, limit)
+                        res = _extend_name_results(
+                            self, base_domain + domain, res, limit)
                     # Try unordered word search on each of the search fields
                     for rec_name in all_names:
                         domain = [(rec_name, operator, x)
                                   for x in name.split() if x]
-                        res = _extend_name_results(self, domain, res, limit)
+                        res = _extend_name_results(
+                            self, base_domain + domain, res, limit)
                 return res
             return name_search
 


Test patch:
diff --git a/base_name_search_improved/tests/test_name_search.py b/base_name_search_improved/tests/test_name_search.py
--- a/base_name_search_improved/tests/test_name_search.py
+++ b/base_name_search_improved/tests/test_name_search.py
@@ -17,12 +17,15 @@ def setUp(self):
         self.Partner = self.env['res.partner']
         self.partner1 = self.Partner.create(
             {'name': 'Luigi Verconti',
+             'customer': True,
              'phone': '+351 555 777 333'})
         self.partner2 = self.Partner.create(
             {'name': 'Ken Shabby',
+             'customer': True,
              'phone': '+351 555 333 777'})
         self.partner3 = self.Partner.create(
             {'name': 'Johann Gambolputty of Ulm',
+             'supplier': True,
              'phone': '+351 777 333 555'})
 
     def test_RelevanceOrderedResults(self):
@@ -42,3 +45,10 @@ def test_NameSearchMustMatchAllWords(self):
         """Must Match All Words"""
         res = self.Partner.name_search('ulm 555 777')
         self.assertFalse(res)
+
+    def test_MustHonorDomain(self):
+        """Must also honor a provided Domain"""
+        res = self.Partner.name_search('+351', args=[('supplier', '=', True)])
+        gambulputty = self.partner3.id
+        self.assertEqual(len(res), 1)
+        self.assertEqual(res[0][0], gambulputty)