You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
3.7 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2016 Daniel Reis
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. from openerp import models, fields, api
  5. from openerp import SUPERUSER_ID
  6. from openerp import tools
  7. # Extended name search is only used on some operators
  8. ALLOWED_OPS = set(['ilike', 'like'])
  9. @tools.ormcache(skiparg=0)
  10. def _get_rec_names(self):
  11. "List of fields to search into"
  12. model = self.env['ir.model'].search(
  13. [('model', '=', str(self._model))])
  14. rec_name = [self._rec_name] or []
  15. other_names = model.name_search_ids.mapped('name')
  16. return rec_name + other_names
  17. def _extend_name_results(self, domain, results, limit):
  18. result_count = len(results)
  19. if not limit or result_count < limit:
  20. domain += [('id', 'not in', [x[0] for x in results])]
  21. recs = self.search(
  22. domain, limit=limit - result_count if limit else limit
  23. )
  24. results.extend(recs.name_get())
  25. return results
  26. class ModelExtended(models.Model):
  27. _inherit = 'ir.model'
  28. name_search_ids = fields.Many2many(
  29. 'ir.model.fields',
  30. string='Name Search Fields')
  31. name_search_use_standard = fields.Boolean(
  32. 'Use standard search', default=True,
  33. help='First try to find matches with the standard search',
  34. )
  35. def _register_hook(self, cr, ids=None):
  36. def make_name_search():
  37. @api.model
  38. def name_search(self, name='', args=None,
  39. operator='ilike', limit=100):
  40. res = []
  41. model_record = self.env['ir.model'].search([
  42. ('model', '=', str(self._model)),
  43. ])
  44. # Perform standard name search
  45. if not name or model_record.name_search_use_standard:
  46. res = name_search.origin(
  47. self, name=name, args=args, operator=operator,
  48. limit=limit,
  49. )
  50. enabled = self.env.context.get('name_search_extended', True)
  51. # Perform extended name search
  52. # Note: Empty name causes error on
  53. # Customer->More->Portal Access Management
  54. if name and enabled and operator in ALLOWED_OPS:
  55. # Support a list of fields to search on
  56. all_names = _get_rec_names(self)
  57. base_domain = args or []
  58. # Try regular search on each additional search field
  59. for rec_name in all_names[1:]:
  60. domain = [(rec_name, operator, name)]
  61. res = _extend_name_results(
  62. self, base_domain + domain, res, limit)
  63. # Try ordered word search on each of the search fields
  64. for rec_name in all_names:
  65. domain = [(rec_name, operator, name.replace(' ', '%'))]
  66. res = _extend_name_results(
  67. self, base_domain + domain, res, limit)
  68. # Try unordered word search on each of the search fields
  69. for rec_name in all_names:
  70. domain = [(rec_name, operator, x)
  71. for x in name.split() if x]
  72. res = _extend_name_results(
  73. self, base_domain + domain, res, limit)
  74. return res
  75. return name_search
  76. if ids is None:
  77. ids = self.search(cr, SUPERUSER_ID, [])
  78. for model in self.browse(cr, SUPERUSER_ID, ids):
  79. Model = self.pool.get(model.model)
  80. if Model:
  81. Model._patch_method('name_search', make_name_search())
  82. return super(ModelExtended, self)._register_hook(cr)