Listas de materiales y recursividad en Odoo

21 de junio de 2023 por
Gustavo Orrillo
| Sin comentarios aún
 

La lista de materiales (modelo mrp.bom) es la piedra fundamental del módulo mrp en Odoo. Son "las recetas" en base a las cuales se fabrican los productos. Estas listas de materiales son estructuras jerárquicas, donde uno tiene componentes padres (productos finales o semi-elaborados o sub-assemblies) y componentes hijos (materias primas). Cuando trabajamos con el módulo mrp de Odoo; para cada producto final o semi-elaborado o sub-assembly tiene asociado una lista de materiales y este producto debe ser fabricado por medio de una orden de fabricación. Por otra parte cada componente que es materia prima debe ser comprado.

Si uno observa la estructura de una lista utilizando la base de demo de Odoo, podemos ver algo parecido a esto


Hay muchas veces que necesitamos realizar operaciones y cálculos con cada uno de los componentes de una lsita de materiales. Por ejemplo, por razones desconocidas en Argentina siempre piden calcular el costo en USD de la lista de materiales. O el lead-time total de la lista de materiales (teniendo en cuenta los componentes que ya se encuentran en stock). Esto requiere leer cada uno de los componentes de la lista de materiales, lo que no es leer los registros relacionados en un campo one2many.

Para eso tenemos que hablar de recursividad y vamos a dar un ejemplo de como se utiliza en Odoo. No quiero dar ejemplos de recursividad de factoriales ni nada por el estilo, ya que son inutiles en el contexto de Odoo (si el concepto, pero necesitamos mejores ejemplos). Vamos a brindar un ejemplo de como calcular un índice utilizando el ORM de Odoo y como se navega cada uno de los componentes de la lista de materiales. También vamos a hablar un poco del módulo mrp_utils.

Bueno, veamos el código de ejemplo de recursividad. Supongamos que tenemos que calcular el fingerprint de una lista de materiales (más de eso en el futuro) y para ello necesitamos sumar los IDs de las materias primas que componen la lista de materiales. Para ello podemos utilizar el siguiente código:

class MrpBom(models.Model):
_inherit = 'mrp.bom'

def _get_fingerprint(self, value=0):
for bom_line in self.bom_line_ids:
if not bom_line.product_id.bom_ids:
value = value + bom_line.product_id.id
else:
new_bom = bom_line.product_id.bom_ids[0]
value = new_bom._get_fingerprint(value)
return value

def get_fingerprint(self):
self.res_fingerprint = self._get_fingerprint()

​ fingerprint = fields.Integer('Fingerprint',compute=get_fingerprint)

Aca tenemos el campo fingerprint el cual es computado mediante el método get_fingerprint (podría ser llamado por un botón, o ser un campo stored... pero no es el propósito de este post hablar de eso). Y este método llama el método _get_fingerprint el cual calcula el fingerprint mismo. 

En esta función, se recorre cada uno de los componentes de la lista de materiales. Y si cada componente tiene asociada una lista de materiales (indicando que es un semi-elaborado o un sub-assembly) cambia la lista de materiales activda (ese es el truco) y vuelve a llamar al método _get_fingerprint. De lo contrario (o sea estamos trabajando con un componente final o materia prima), retorna el valor que se le pasa como parámetro (como indica la literatura sobre recursividad) más el ID de la materia prima.

Bueno, el ejemplo que acabo de brindar se puede extender a múltiples casos. Por ejemplo para calcular costos o el reemplazo de materiales como hace el módulo mrp_utils. Pero es algo que uno debe saber si trabaja con listas de materiales, como poder navegarlas ya que tarde o temprano vamos a tener que realizar operaciones con ellas.

Gustavo Orrillo 21 de junio de 2023
Compartir
Archivar
Identificarse dejar un comentario