Creación de un dominio dinámico para Odoo
Una pregunta y necesidad que tuve hace poco tiempo fue agregar un dominio en una vista de árbol generada por un campo One2many, buscando información y ejemplos finalmente no encontré y lo trate de realizar por medio de JS, un total fracaso, el tiempo que tenia no ayudaba mucho y fue entonces que intente realizarlo por medio de un dominio dinámico y una emulación de botón que retornara mi objeto con el filtro dinámico.
Primero voy a ejemplificar mis 2 clases, realmente no eran como el siguiente ejemplo pero trato de que sea mas digerible para todos nosotros.
Mi Clase Linea:
class DescargaAlmacenProducto(models.Model): _name = 'descarga.almacen.producto' _description = 'Linea Descarga de Productos' _rec_name = 'product_id' _order = 'id desc' download_id = fields.Many2one('descarga.almacen', 'ID Ref') product_id = fields.Many2one('product.product', 'Nombre', required=True) familia_producto = fields.Char('Familia', size=128, related="product_id.familia_producto") product_qty = fields.Float('Cantidad', digits=(14,4)) uom_id = fields.Many2one('product.uom', 'UdM')
Mi Clase Principal:
class DescargaAlmacen(models.Model): _name = 'descarga.almacen' _description = 'Asistente Descarga de Productos' _rec_name = 'sequence_name' _order = 'id desc' def _compute_selection_family(self): selection_options = [('no_one','Sin Filtro')] cr = self.env.cr context = self._context if 'family_complete_list_ctx' in context and context['family_complete_list_ctx']: family_complete_list_ctx = context['family_complete_list_ctx'] if family_complete_list_ctx: for f2 in family_complete_list_ctx: selection_options.append((f2,f2)) return selection_options def _get_domain_func(self, ): context = self._context if 'dynamic_domain' in context and context['dynamic_domain']: if 'record_ids' in context and context['record_ids']: self_br = self.browse(context['record_ids'])[0] filter_familia_producto = self_br.filter_familia_producto if not filter_familia_producto or filter_familia_producto == 'no_one': return [] domain = [('familia_producto', '=', filter_familia_producto)] return domain return [] filter_familia_producto = fields.Selection(selection=lambda self: self._compute_selection_family(), string="Familia", default="no_one") space_download_line_ids = fields.One2many('descarga.almacen.producto', 'download_id', 'Lineas de Descarga', ondelete="cascade", domain=_get_domain_func) sequence_name = fields.Char('Secuencia', size=128) #### Filtro Dinamico ###### def refresh_filter(self): family_complete_list_ctx = [] for rec in self: print ("## rec.space_download_line_id >>>>> ",rec.space_download_line_ids) for line in rec.space_download_line_ids: line_familia = line.familia_producto if line_familia and line_familia not in family_complete_list_ctx: family_complete_list_ctx.append(line_familia) return { 'name': _('Descarga - Familia' % self.filter_familia_producto), 'view_mode': 'form', 'view_id': self.env.ref('mi_modulo.mi_vista').id, 'res_model': 'descarga.almacen', 'context': "{'readonly_by_pass': True, 'record_ids': %s, 'dynamic_domain': True, 'family_complete_list_ctx': %s}" % (self.ids, family_complete_list_ctx), # self.env.context 'type': 'ir.actions.act_window', 'res_id': self.id, 'flags': {'initial_mode': 'edit'} }
El campo que utilizare para filtrar los datos es un tipo Selection:
- filter_familia_producto
Un dato importante es que este campo de tipo "seleccion" es calculado para solo tener los filtros de mis registros, no quisiera mostrar todos por que no traeria información.
Mi campo One2many que contiene las lineas principales de mi registro tiene por nombre:
- space_download-line_ids
Podemos observar que dentro de estas lineas se encuentra mi dominio dinámico:
domain=_get_domain_func
Estos datos los estoy retornando por medio del contexto en mi función refresh_filter
'context': "{'readonly_by_pass': True, 'record_ids': %s, 'dynamic_domain': True, 'family_complete_list_ctx': %s}" % (self.ids, family_complete_list_ctx), # self.env.context
Para no tener errores con mi funcion domain, dentro del contexto vuelvo a retornar las opciones calculadas en todos mis registros y los ids de estos.
Para finalizar, agregue en mi vista el campo y el boton que retornara mi objeto con los nuevos filtros:
<group > <group> <field name="filter_familia_producto" string="Filtro Familia" /> </group> <group class="oe_subtotal_footer oe_right" > <button string="Filtrar" icon="fa-search" name="refresh_filter" style="display: inline-block; padding: 5px 15px; font-size: 12px; cursor: pointer; text-align: center; text-decoration: none; outline: none; color: #fff; background-color: #b787aa; border: none; border-radius: 5px; box-shadow: 0 5px #999;"/> </group> </group>
Agregue unos estilos para dar mejor presentación y el resultado se muestra asi:
Espero sea de su ayuda.