Odoo ricerca su campi calcolati o relazionati

ORM e API nelle varie versioni

Nelle varie versioni di Odoo sono state effettuate diverse modifiche al modello di oggetti ORM (object relational mapping)e alle relative API di accesso.

A causa del sistema di accessi ai dati, alcune operazioni sono agevolate ma altre risultano di difficile accesso nelle viste.

E’ il caso della ricerca sui campi calcolati o sui campi di relazione.Nello specifico il codice di seguito è applicato a Odoo 12.

Prendiamo ad esempio il caso in cui è necessario avere una particolare logica su un campo.

LA FUNZIONE PER IL CAMPO CALCOLATO

Nel mio caso devo riportare un fornitore in base a un elenco ordinato per sequenza, quindi definisco un campo calcolato supplier (nel caso specifico dipendente dal campo supplier_category):

supplier = fields.Char(string='FORNITORE', compute='_compute_supplier')

@api.depends('supplier_category')
def _compute_supplier(self):
    for record in self:
        supplier = None
        category = record.product_id.supplier_category
        if category:
            supplier_ids = self.env['category.supplier'].search([('supplier_category',  '=',  category)],order='sequence')
            if supplier_ids:
                supplier = supplier_ids[0].partner_id
                record.supplier = supplier.name

Avremo quindi il campo popolato correttamente ma di fatto non ricercabile in un’eventuale vista.

LA FUNZIONE DI RICERCA

Affinchè sia ricercabile possiamo utilizzare l’attributo search del campo e creare una funzione personalizzata per la ricerca:

supplier = fields.Char(string='FORNITORE', compute='_compute_supplier', search='_search_supplier')

@api.depends('supplier_category')
def _compute_supplier(self):
    for record in self:
        supplier = None
        category = record.product_id.supplier_category
        if category:
            supplier_ids = self.env['category.supplier'].search([('supplier_category',  '=',  category)],order='sequence')
            if supplier_ids:
                supplier = supplier_ids[0].partner_id
                record.supplier = supplier.name

def _search_supplier(self, operator, value):
    recs = self.search([])
    res = []
    for i in recs:
        if i.supplier:
            if value in i.supplier or value.upper() in i.supplier:
                res.append(i)
    if res:
        return [('id', 'in', [x.id for x in res])]

LA SEARCH VIEW

A questo punto ci si potra riferire al campo, semplicemente tramite il nome, nella vista di ricerca dell’XML:

<record id="stock_move_bom_lines_search" model="ir.ui.view">
    <field name="name">stock.move.line.mod.search</field>
    <field name="model">stock.move</field>
    <field name="arch" type="xml">
        <search string="Ricerca categoria fornitora">
            <field name="product_id" string="Prodotto" filter_domain="['|',('product_id','ilike',self),('name','ilike',self)]"/>
            <field name="supplier" string="Fornitore"/>
            <field name="supplier_category" string="Categoria fornitura"/>
        </search>
    </field>
</record>

Altre soluzioni (in lingua inglese):

https://stackoverflow.com/questions/40819280/how-can-i-search-by-a-computed-field-in-odoo

https://www.odoo.com/it_IT/forum/help-1/question/calculated-fields-in-search-filter-possible-118501