def name_search(self, name, args=None, operator='ilike', limit=100): res = super(ResPartner, self).name_search(name, args, operator=operator, limit=limit) if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql( ) where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company or search by phone also search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT id FROM res_partner {where} ({email} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format(where=where_str, operator=operator, email=unaccent('email'), display_name=unaccent('display_name'), reference=unaccent('ref'), percent=unaccent('%s')) where_clause_params += [search_name] * 4 if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = map(lambda x: x[0], self.env.cr.fetchall()) if partner_ids: return self.browse(partner_ids).name_get() if not partner_ids: partner_ids = self.search([ '|', ('phone', operator, name), '|', ('mobile', operator, name), '|', ('mobile1', operator, name), '|', ('mobile2', operator, name), ('whatsapp', operator, name) ]) return partner_ids.name_get() else: return [] return res
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): self = self.with_user(name_get_uid or self.env.uid) # as the implementation is in SQL, we force the recompute of fields if necessary self.recompute(['display_name']) self.flush() if args is None: args = [] order_by_rank = self.env.context.get('res_partner_search_mode') if (name or order_by_rank) and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql() from_str = from_clause if from_clause else 'res_partner' where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) fields = self._get_name_search_order_by_fields() query = """SELECT res_partner.id FROM {from_str} {where} ({email} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent} OR {vat} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {fields} {display_name} {operator} {percent} desc, {display_name} """.format(from_str=from_str, fields=fields, where=where_str, operator=operator, email=unaccent('res_partner.email'), display_name=unaccent('res_partner.display_name'), reference=unaccent('res_partner.ref'), percent=unaccent('%s'), vat=unaccent('res_partner.vat'),) where_clause_params += [search_name]*3 # for email / display_name, reference where_clause_params += [re.sub('[^a-zA-Z0-9]+', '', search_name) or None] # for vat where_clause_params += [search_name] # for order by if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: return models.lazy_name_get(self.browse(partner_ids)) else: return [] return super(Partner, self)._name_search(name, args, operator=operator, limit=limit, name_get_uid=name_get_uid)
def name_search(self, name, args=None, operator='ilike', limit=100): if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql( ) from_str = from_clause if from_clause else 'res_partner' where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT res_partner.id FROM {from_str} {where} ({email} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent} OR {vat} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format( from_str=from_str, where=where_str, operator=operator, email=unaccent('res_partner.email'), display_name=unaccent('res_partner.display_name'), reference=unaccent('res_partner.ref'), percent=unaccent('%s'), vat=unaccent('res_partner.vat'), ) where_clause_params += [search_name] * 5 if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: return self.browse(partner_ids).name_get() else: return [] return super(Partner, self).name_search(name, args, operator=operator, limit=limit)
def name_search(self, name, args=None, operator="ilike", limit=100): if args is None: args = [] if name and operator in ("=", "ilike", "=ilike", "like", "=like"): self.check_access_rights("read") where_query = self._where_calc(args) self._apply_ir_rules(where_query, "read") from_clause, where_clause, where_clause_params = where_query.get_sql( ) where_str = where_clause and (" WHERE %s AND " % where_clause) or " WHERE " # search on the name of the contacts and of its company search_name = name if operator in ("ilike", "like"): search_name = "%%%s%%" % name if operator in ("=ilike", "=like"): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT id FROM res_partner {where} ( {company_registry} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent} OR {company_registry} {operator} {percent} ) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format( where=where_str, operator=operator, email=unaccent("email"), display_name=unaccent("display_name"), reference=unaccent("ref"), company_registry=unaccent("company_registry"), percent=unaccent("%s"), ) where_clause_params += [search_name] * 5 if limit: query += " limit %s" where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = map(lambda x: x[0], self.env.cr.fetchall()) if partner_ids: return self.browse(partner_ids).name_get() else: return [] return super(ResPartner, self).name_search(name, args, operator=operator, limit=limit)
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): self = self.sudo(name_get_uid or self.env.uid) if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql() from_str = from_clause if from_clause else 'res_partner' where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT res_partner.id FROM {from_str} {where} ({email} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent} OR {vat} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format(from_str=from_str, where=where_str, operator=operator, email=unaccent('res_partner.email'), display_name=unaccent('res_partner.display_name'), reference=unaccent('res_partner.ref'), percent=unaccent('%s'), vat=unaccent('res_partner.vat'),) where_clause_params += [search_name]*3 # for email / display_name, reference where_clause_params += [re.sub('[^a-zA-Z0-9]+', '', search_name) or None] # for vat where_clause_params += [search_name] # for order by if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: return models.lazy_name_get(self.browse(partner_ids)) else: return [] return super(Partner, self)._name_search(name, args, operator=operator, limit=limit, name_get_uid=name_get_uid)
def name_search(self, name, args=None, operator='ilike', limit=100): result = super(ResPartner, self).name_search(name, args=None, operator='ilike', limit=100) if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql( ) where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT id FROM res_partner {where} ({phone} {operator} {percent} OR {mobile} {operator} {percent}) ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format( where=where_str, operator=operator, phone=unaccent('phone'), display_name=unaccent('display_name'), mobile=unaccent('mobile'), percent=unaccent('%s'), ) where_clause_params += [search_name] * 3 if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: result += self.browse(partner_ids).name_get() return result
def name_search(self, name, args=None, operator='ilike', limit=100): if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql() where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT id FROM res_partner {where} ({email} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent} OR {vat} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format(where=where_str, operator=operator, email=unaccent('email'), display_name=unaccent('display_name'), reference=unaccent('ref'), percent=unaccent('%s'), vat=unaccent('vat'),) where_clause_params += [search_name]*5 if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: return self.browse(partner_ids).name_get() else: return [] return super(Partner, self).name_search(name, args, operator=operator, limit=limit)
def name_search(self, name, args=None, operator='ilike', limit=100): res = super(ResPartner, self).name_search(name, args, operator, limit) if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): where_query = self._where_calc(args) from_clause, where_clause, where_clause_params = where_query.get_sql() where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT id FROM res_partner {where} ({fal_shortname} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format(where=where_str, operator=operator, fal_shortname=unaccent('fal_shortname'), display_name=unaccent('display_name'), percent=unaccent('%s'),) where_clause_params += [search_name]*2 if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] super_partner_ids = [] for partner_id in res: if partner_id[0] not in partner_ids: partner_ids.append(partner_id[0]) if partner_ids: return self.browse(partner_ids).name_get() else: return [] return super(ResPartner, self).name_search(name, args, operator=operator, limit=limit)
def _get_invoice_matching_query(self, st_lines_with_partner, excluded_ids): ''' Returns the query applying the current invoice_matching reconciliation model to the provided statement lines. :param st_lines_with_partner: A list of tuples (statement_line, partner), associating each statement line to treate with the corresponding partner, given by the partner map :param excluded_ids: Account.move.lines to exclude. :return: (query, params) ''' self.ensure_one() if self.rule_type != 'invoice_matching': raise UserError(_('Programmation Error: Can\'t call _get_invoice_matching_query() for different rules than \'invoice_matching\'')) unaccent = get_unaccent_wrapper(self._cr) # N.B: 'communication_flag' is there to distinguish invoice matching through the number/reference # (higher priority) from invoice matching using the partner (lower priority). query = r''' SELECT st_line.id AS id, aml.id AS aml_id, aml.currency_id AS aml_currency_id, aml.date_maturity AS aml_date_maturity, aml.amount_residual AS aml_amount_residual, aml.amount_residual_currency AS aml_amount_residual_currency, ''' + self._get_select_communication_flag() + r''' AS communication_flag, ''' + self._get_select_payment_reference_flag() + r''' AS payment_reference_flag FROM account_bank_statement_line st_line JOIN account_move st_line_move ON st_line_move.id = st_line.move_id JOIN res_company company ON company.id = st_line_move.company_id , account_move_line aml LEFT JOIN account_move move ON move.id = aml.move_id AND move.state = 'posted' LEFT JOIN account_account account ON account.id = aml.account_id LEFT JOIN res_partner aml_partner ON aml.partner_id = aml_partner.id LEFT JOIN account_payment payment ON payment.move_id = move.id WHERE aml.company_id = st_line_move.company_id AND move.state = 'posted' AND account.reconcile IS TRUE AND aml.reconciled IS FALSE ''' # Add conditions to handle each of the statement lines we want to match st_lines_queries = [] for st_line, partner in st_lines_with_partner: # In case we don't have any partner for this line, we try assigning one with the rule mapping if st_line.amount > 0: st_line_subquery = r"aml.balance > 0" else: st_line_subquery = r"aml.balance < 0" if self.match_same_currency: st_line_subquery += r" AND COALESCE(aml.currency_id, company.currency_id) = %s" % (st_line.foreign_currency_id.id or st_line.move_id.currency_id.id) if partner: st_line_subquery += r" AND aml.partner_id = %s" % partner.id else: st_line_subquery += r""" AND ( substring(REGEXP_REPLACE(st_line.payment_ref, '[^0-9\s]', '', 'g'), '\S(?:.*\S)*') != '' AND ( (""" + self._get_select_communication_flag() + """) OR (""" + self._get_select_payment_reference_flag() + """) ) ) OR ( /* We also match statement lines without partners with amls whose partner's name's parts (splitting on space) are all present within the payment_ref, in any order, with any characters between them. */ aml_partner.name IS NOT NULL AND """ + unaccent("st_line.payment_ref") + r""" ~* ('^' || ( SELECT string_agg(concat('(?=.*\m', chunk[1], '\M)'), '') FROM regexp_matches(""" + unaccent("aml_partner.name") + r""", '\w{3,}', 'g') AS chunk )) ) """ st_lines_queries.append(r"st_line.id = %s AND (%s)" % (st_line.id, st_line_subquery)) query += r" AND (%s) " % " OR ".join(st_lines_queries) params = {} # If this reconciliation model defines a past_months_limit, we add a condition # to the query to only search on move lines that are younger than this limit. if self.past_months_limit: date_limit = fields.Date.context_today(self) - relativedelta(months=self.past_months_limit) query += "AND aml.date >= %(aml_date_limit)s" params['aml_date_limit'] = date_limit # Filter out excluded account.move.line. if excluded_ids: query += 'AND aml.id NOT IN %(excluded_aml_ids)s' params['excluded_aml_ids'] = tuple(excluded_ids) if self.matching_order == 'new_first': query += ' ORDER BY aml_date_maturity DESC, aml_id DESC' else: query += ' ORDER BY aml_date_maturity ASC, aml_id ASC' return query, params
def name_search(self, name, args=None, operator="ilike", limit=100): if name and operator in ("=", "ilike", "=ilike", "like", "=like"): self.check_access_rights("read") # Cetmix force search by email email = False if args: for arg in args: if arg[0] == "email": email = arg args.remove(arg) break if email: email_args = self._tweak_args([("email", operator, email)]) else: email_args = self._tweak_args([("email", operator, name)]) where_query = self._where_calc(args) self._apply_ir_rules(where_query, "read") from_clause, where_clause, where_clause_params = where_query.get_sql( ) from_str = from_clause if from_clause else "res_partner" where_str = where_clause and (" WHERE %s AND " % where_clause) or " WHERE " # Compose email query args where_query_email = self.with_context( active_test=False)._where_calc(email_args) ( from_clause_email, where_clause_email, where_clause_params_email, ) = where_query_email.get_sql() # search on the name of the contacts and of its company search_name = name if operator in ("ilike", "like"): search_name = "%%%s%%" % name if operator in ("=ilike", "=like"): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT res_partner.id FROM {from_str} {where} ({display_name} {operator} {percent} OR {reference} {operator} {percent} OR {vat} {operator} {percent} OR {email_addresses}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format( from_str=from_str, where=where_str, operator=operator, email_addresses=where_clause_email, display_name=unaccent("res_partner.display_name"), reference=unaccent("res_partner.ref"), percent=unaccent("%s"), vat=unaccent("res_partner.vat"), ) where_clause_params += [search_name] * 3 where_clause_params += where_clause_params_email # partner ids where_clause_params.append(search_name) # The last one for sort if limit: query += " limit %s" where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: return self.browse(partner_ids).name_get() else: return [] return super(Partner, self).name_search(name=name, args=args, operator=operator, limit=limit)
def find_duplicates(self, batch_commits=False): """ Search for duplicate records and create the data_merge.group along with its data_merge.record :param bool batch_commits: If set, will automatically commit every X records """ # YTI CLEAN: Use add_join from the Query object maybe ? def field_join(field_id, table, res_model_name, env): join, join_data = '', () # Related non-stored field if rule.field_id.related and not rule.field_id.store: IrField = self.env['ir.model.fields']._get( res_model_name, field_id.related.split('.')[0]) rel_table = IrField.relation.replace('.', '_') join_data = (rel_table, IrField.relation_field, table, env[IrField.relation]._rec_name) # Many2one elif rule.field_id.relation: rel_table = field_id.relation.replace('.', '_') join_data = (table, field_id.name, rel_table, env[field_id.relation]._rec_name) if join_data: rel_where = '%s."%s" = %s.id' % (join_data[0], join_data[1], join_data[2]) join = """JOIN %s ON %s""" % (rel_table, rel_where) field_name = '%s."%s"' % (join_data[2], join_data[3]) else: field_name = '%s."%s"' % (table, field_id.name) return (field_name, join) unaccent = get_unaccent_wrapper(self.env.cr) self.flush() for dm_model in self: t1 = timeit.default_timer() ids = [] for rule in dm_model.rule_ids: table = self.env[dm_model.res_model_name]._table field_name, join = field_join(rule.field_id, table, dm_model.res_model_name, self.env) if rule.match_mode == 'accent': field_name = unaccent(field_name) domain = ast.literal_eval(dm_model.domain or '[]') tables, where_clause, where_clause_params = self.env[ dm_model.res_model_name]._where_calc(domain).get_sql() where_clause = where_clause and ('AND %s' % where_clause) or '' group_by = '' if 'company_id' in self.env[ dm_model. res_model_name]._fields and not dm_model.mix_by_company: group_by = ', %s.company_id' % table # Get all the rows matching the rule defined # (e.g. exact match of the name) having at least 2 records # Each row contains the matched value and an array of matching records: # | value matched | {array of record IDs matching the field} query = """ SELECT %(field)s as group_field_name, array_agg( %(model_table)s.id order by %(model_table)s.id asc ) FROM %(tables)s %(join)s WHERE length(%(field)s) > 0 %(where_clause)s GROUP BY group_field_name %(group_by)s HAVING COUNT(%(field)s) > 1""" % { 'field': field_name, 'model_table': table, 'tables': tables, 'join': join, 'where_clause': where_clause, 'group_by': group_by, } try: self._cr.execute(query, where_clause_params) except ProgrammingError: # YTI TODO: Explain why this is valid to suppose that the extentions # are missing raise UserError( 'Missing required PostgreSQL extension: unaccent') rows = self._cr.fetchall() ids = ids + [row[1] for row in rows] # Fetches the IDs of all the records who already matched (and are not merged), # as well as the discarded ones. # This prevents creating twice the same groups. self._cr.execute( """ SELECT ARRAY_AGG(res_id ORDER BY res_id ASC) FROM data_merge_record WHERE model_id = %s GROUP BY group_id""", [dm_model.id]) done_groups_res_ids = [set(x[0]) for x in self._cr.fetchall()] _logger.info('Query identification done after %s' % str(timeit.default_timer() - t1)) t1 = timeit.default_timer() if ast.literal_eval(self.env['ir.config_parameter'].get_param( 'data_merge.merge_lists', 'True')): merge_list = merge_common_lists else: merge_list = lambda x: x groups_to_create = [set(r) for r in merge_list(ids) if len(r) > 1] _logger.info('Merging lists done after %s' % str(timeit.default_timer() - t1)) t1 = timeit.default_timer() _logger.info('Record creation started at %s', str(t1)) groups_created = 0 groups_to_create_count = len(groups_to_create) for group_to_create in groups_to_create: groups_created += 1 if groups_created % 100 == 0: _logger.info('Created groups %s / %s' % (groups_created, groups_to_create_count)) # Check if the IDs of the group to create is already part of an existing group # e.g. # The group with records A B C already exists: # 1/ If group_to_create equals A B, do not create a new group # 2/ If group_to_create equals A D, create the new group (A D is not a subset of A B C) if any(group_to_create <= x for x in done_groups_res_ids): continue group = self.env['data_merge.group'].with_context( prefetch_fields=False).create({'model_id': dm_model.id}) d = [{ 'group_id': group.id, 'res_id': rec } for rec in group_to_create] self.env['data_merge.record'].with_context( prefetch_fields=False).create(d) if groups_created % 1000 == 0 and batch_commits: self.env.cr.commit() group._elect_master_record() if dm_model.create_threshold > 0 and group.similarity * 100 <= dm_model.create_threshold: group.unlink() continue if dm_model.merge_mode == 'automatic': if group.similarity * 100 >= dm_model.merge_threshold: group.merge_records() group.unlink() _logger.info('Record creation done after %s' % str(timeit.default_timer() - t1))
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): self = self.sudo(name_get_uid or self.env.uid) if args is None: args = [] if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): self.check_access_rights('read') where_query = self._where_calc(args) self._apply_ir_rules(where_query, 'read') from_clause, where_clause, where_clause_params = where_query.get_sql( ) where_str = where_clause and (" WHERE %s AND " % where_clause) or ' WHERE ' # search on the name of the contacts and of its company search_name = name if operator in ('ilike', 'like'): search_name = '%%%s%%' % name if operator in ('=ilike', '=like'): operator = operator[1:] unaccent = get_unaccent_wrapper(self.env.cr) query = """SELECT id FROM res_partner {where} ({email} {operator} {percent} OR {display_name} {operator} {percent} OR {reference} {operator} {percent} OR {vat} {operator} {percent} OR {phone} {operator} {percent} OR {mobile} {operator} {percent}) -- don't panic, trust postgres bitmap ORDER BY {display_name} {operator} {percent} desc, {display_name} """.format( where=where_str, operator=operator, email=unaccent('email'), display_name=unaccent('display_name'), reference=unaccent('ref'), percent=unaccent('%s'), vat=unaccent('vat'), phone=unaccent('phone'), mobile=unaccent('mobile'), ) where_clause_params += [ search_name ] * 3 # for email / display_name, reference where_clause_params += [re.sub('[^a-zA-Z0-9]+', '', search_name)] # for vat where_clause_params += [ re.sub("^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\'s\'./0-9]*$", '', search_name) ] * 2 # for phone / mobile where_clause_params += [search_name] # for order by if limit: query += ' limit %s' where_clause_params.append(limit) self.env.cr.execute(query, where_clause_params) partner_ids = [row[0] for row in self.env.cr.fetchall()] if partner_ids: return self.browse(partner_ids).name_get() else: return [] return super(Partner, self)._name_search(name, args, operator=operator, limit=limit, name_get_uid=name_get_uid)