diff --git a/base_name_search_improved/__manifest__.py b/base_name_search_improved/__manifest__.py index cc1db964c..b618c6d25 100644 --- a/base_name_search_improved/__manifest__.py +++ b/base_name_search_improved/__manifest__.py @@ -1,18 +1,14 @@ # Copyright 2016 Daniel Reis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Improved Name Search', - 'summary': 'Friendlier search when typing in relation fields', - 'version': '11.0.1.0.0', - 'category': 'Uncategorized', - 'website': 'https://github.com/OCA/server-tools', - 'author': 'Daniel Reis, Odoo Community Association (OCA)', - 'license': 'AGPL-3', - 'data': [ - 'views/ir_model_views.xml', - ], - 'depends': [ - 'base', - ], - 'installable': True, + "name": "Improved Name Search", + "summary": "Friendlier search when typing in relation fields", + "version": "11.0.1.0.0", + "category": "Uncategorized", + "website": "https://github.com/OCA/server-tools", + "author": "Daniel Reis, Odoo Community Association (OCA)", + "license": "AGPL-3", + "data": ["views/ir_model_views.xml",], + "depends": ["base",], + "installable": True, } diff --git a/base_name_search_improved/models/ir_model.py b/base_name_search_improved/models/ir_model.py index 0b5baaac4..22cad23ee 100644 --- a/base_name_search_improved/models/ir_model.py +++ b/base_name_search_improved/models/ir_model.py @@ -1,51 +1,45 @@ # Copyright 2016 Daniel Reis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields, api, tools +from odoo import api, fields, models, tools # Extended name search is only used on some operators -ALLOWED_OPS = {'ilike', 'like'} +ALLOWED_OPS = {"ilike", "like"} @tools.ormcache(skiparg=0) def _get_rec_names(self): "List of fields to search into" - model = self.env['ir.model'].search( - [('model', '=', self._name)]) + model = self.env["ir.model"].search([("model", "=", self._name)]) rec_name = [self._rec_name] if bool(self._rec_name) else [] - other_names = model.name_search_ids.mapped('name') + other_names = model.name_search_ids.mapped("name") return rec_name + other_names def _extend_name_results(self, domain, results, limit): result_count = len(results) if result_count < limit: - domain += [('id', 'not in', [x[0] for x in results])] + domain += [("id", "not in", [x[0] for x in results])] recs = self.search(domain, limit=limit - result_count) results.extend(recs.name_get()) return results class IrModel(models.Model): - _inherit = 'ir.model' + _inherit = "ir.model" - name_search_ids = fields.Many2many( - 'ir.model.fields', - string='Name Search Fields') + name_search_ids = fields.Many2many("ir.model.fields", string="Name Search Fields") @api.model_cr def _register_hook(self): - def make_name_search(): - @api.model - def name_search(self, name='', args=None, - operator='ilike', limit=100): + def name_search(self, name="", args=None, operator="ilike", limit=100): # Perform standard name search res = name_search.origin( - self, name=name, args=args, operator=operator, - limit=limit) - enabled = self.env.context.get('name_search_extended', True) + self, name=name, args=args, operator=operator, limit=limit + ) + enabled = self.env.context.get("name_search_extended", True) # Perform extended name search # Note: Empty name causes error on # Customer->More->Portal Access Management @@ -57,24 +51,26 @@ class IrModel(models.Model): for rec_name in all_names[1:]: domain = [(rec_name, operator, name)] res = _extend_name_results( - self, base_domain + domain, res, limit) + 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(' ', '%'))] + domain = [(rec_name, operator, name.replace(" ", "%"))] res = _extend_name_results( - self, base_domain + domain, res, limit) + 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] + domain = [(rec_name, operator, x) for x in name.split() if x] res = _extend_name_results( - self, base_domain + domain, res, limit) + self, base_domain + domain, res, limit + ) return res + return name_search for model in self.sudo().search(self.ids or []): Model = self.env.get(model.model) if Model is not None: - Model._patch_method('name_search', make_name_search()) + Model._patch_method("name_search", make_name_search()) return super(IrModel, self)._register_hook() diff --git a/base_name_search_improved/tests/test_name_search.py b/base_name_search_improved/tests/test_name_search.py index 0ce407d8f..0be1ec610 100644 --- a/base_name_search_improved/tests/test_name_search.py +++ b/base_name_search_improved/tests/test_name_search.py @@ -7,47 +7,49 @@ from odoo.tests.common import TransactionCase, at_install, post_install @at_install(False) @post_install(True) class NameSearchCase(TransactionCase): - def setUp(self): super(NameSearchCase, self).setUp() - phone_field = self.env.ref('base.field_res_partner_phone') - model_partner = self.env.ref('base.model_res_partner') + phone_field = self.env.ref("base.field_res_partner_phone") + model_partner = self.env.ref("base.model_res_partner") model_partner.name_search_ids = phone_field - self.Partner = self.env['res.partner'] + self.Partner = self.env["res.partner"] self.partner1 = self.Partner.create( - {'name': 'Luigi Verconti', - 'customer': True, - 'phone': '+351 555 777 333'}) + {"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'}) + {"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'}) + { + "name": "Johann Gambolputty of Ulm", + "supplier": True, + "phone": "+351 777 333 555", + } + ) def test_RelevanceOrderedResults(self): """Return results ordered by relevance""" - res = self.Partner.name_search('555 777') + res = self.Partner.name_search("555 777") self.assertEqual( - res[0][0], self.partner1.id, - 'Match full string honoring spaces') + res[0][0], self.partner1.id, "Match full string honoring spaces" + ) self.assertEqual( - res[1][0], self.partner2.id, - 'Match words honoring order of appearance') + res[1][0], self.partner2.id, "Match words honoring order of appearance" + ) self.assertEqual( - res[2][0], self.partner3.id, - 'Match all words, regardless of order of appearance') + res[2][0], + self.partner3.id, + "Match all words, regardless of order of appearance", + ) def test_NameSearchMustMatchAllWords(self): """Must Match All Words""" - res = self.Partner.name_search('ulm 555 777') + 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)]) + res = self.Partner.name_search("+351", args=[("supplier", "=", True)]) gambulputty = self.partner3.id self.assertEqual(len(res), 1) self.assertEqual(res[0][0], gambulputty) diff --git a/base_name_search_improved/views/ir_model_views.xml b/base_name_search_improved/views/ir_model_views.xml index 7759f0bc3..25382516a 100644 --- a/base_name_search_improved/views/ir_model_views.xml +++ b/base_name_search_improved/views/ir_model_views.xml @@ -1,21 +1,19 @@ - + - - Add Name Searchable to Models ir.model - + - + -