pythonodooerpodoo-14

How to add search other field in many2one?


HI I have a customer field and the default search is by name, and I want to add a search by barcode as well to the customer field

I have tried adding a barcode(partner_id.barcode) on the domain as below, but it still doesn't work (model = sale.order)

 @api.model
    def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
        if self._context.get('sale_show_partner_name'):
            if operator == 'ilike' and not (name or '').strip():
                domain = []
            elif operator in ('ilike', 'like', '=', '=like', '=ilike'):
                domain = expression.AND([
                    args or [],
                    ['|', '|', ('name', operator, name), ('partner_id.name', operator, name), ('partner_id.barcode', operator, name)]
                ])
                return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
        return super(SaleOrder, self)._name_search(name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid)

I have also tried in the (res.partner) model as below. it can search customer by barcode, but cannot search customer by name :

 @api.model
    def name_search(self, name, args=None, operator='ilike', limit=100):
        if not self.env.context.get('display_barcode', True):
            return super(ResPartnerInherit, self).name_search(name, args, operator, limit)
        else:
            args = args or []
            recs = self.browse()
            if not recs:
                recs = self.search([('barcode', operator, name)] + args, limit=limit)
            return recs.name_get()

What should I do if I want to find a customer by name and barcode?

If anyone knows, please let me know

Best Regards


Solution

  • The barcode field in res.partner is a property field and stored in ir.property model which name is Company Propeties in Odoo and you can access it with developer mode from Settings -> Technical -> Company Propeties.

    The _name_search method for res.partner enable you to search in any Many2one partner relation field in any model by one of these fields display_name, email, reference and vat and you can override it to add barcode as below:

    from odoo import api, models
    from odoo.osv.expression import get_unaccent_wrapper
    import re
    
    
    class ResPartner(models.Model):
        _inherit = 'res.partner'
    
        @api.model
        def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
            self = self.with_user(name_get_uid) if name_get_uid else self
            # as the implementation is in SQL, we force the recompute of fields if necessary
            self.recompute(['display_name'])
            self.flush()
            print(args)
            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 '
                print(where_clause_params)
                # 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}
                             LEFT JOIN ir_property trust_property ON (
                                trust_property.res_id = 'res.partner,'|| {from_str}."id"
                                AND trust_property.name = 'barcode')
                          {where} ({email} {operator} {percent}
                               OR {display_name} {operator} {percent}
                               OR {reference} {operator} {percent}
                               OR {barcode} {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'),
                                   barcode=unaccent('trust_property.value_text'),
                                   percent=unaccent('%s'),
                                   vat=unaccent('res_partner.vat'), )
    
                where_clause_params += [search_name] * 4  # 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)
                print(query)
                print(where_clause_params)
                self.env.cr.execute(query, where_clause_params)
                return [row[0] for row in self.env.cr.fetchall()]
    
            return super(ResPartner, self)._name_search(name, args, operator=operator, limit=limit, name_get_uid=name_get_uid)