Como se administra el stock en Odoo? El modelo stock.quant

19 de julio de 2023 por
Gustavo Orrillo
| Sin comentarios aún
 

En un principio la gente de OpenERP tuvo la genial idea de no necesitarse una tabla (o modelo) para persistir el stock. Era una lógica propia de un sistema chica. Para que mantener un modelo con los stocks cuando los mismos podían ser computados en base a los movimientos de stock? Esto no tenía en cuenta no solo en la complejidad de las consultas que generaba sino también en los problemas de performance que eso podría llegar a ocasionar?


Por razones nunca aclarados (calculo que un partner europeo les dijo "queridos, esto no da para mas"); Odoo introdujo (por lo menos en la versión 9 creo) años atrás de forma silenciosa introdujo el modelo stock.quant el cual mantiene el stock. 

El modelo stock.quant se mantiene de forma automática cuando se confirman los movimientos de stock (modelo stock.move con sus correspondientes movimientos de producto, modelo stock.move.line). Siendo un desarrollador uno se despreocupa de los problemas relacionados con actualizar el stock manualmente debido a que Odoo lo hace en forma automática (y no es recomendable hacerlo). El modelo stock.quant mantiene tanto el stock físico (o las cantidades en mano), no mantiene el stock virtual.

Como es la estructura del modelo stock.quant? Estas son algunas columnas que nos resultan útiles:

  • location_id: es la ubicación donde se almacena el inventario. Puede ser una ubicación interna de stock (un bin o un depósito). O puede ser la ubicación de un partner, por ejemplo puede ser la ubicación de un proveedor que envió la materia prima (no se cuenta con el partner_id, el mismo podría obtenerse de los movimientos de producto que actualizaron el quant).
  • quantity: cantidad física en stock
  • product_id: producto de stock
  • lot_id: identificador de lote/número de serie de stock.

Los quantos son listados en varias partes (por ejemplo, cuando uno clickea "Actualizar cantidad" en el formulario de producto). Pero el lugar donde lo hace en forma más prominente es en la vista del módulo de Inventario "Informe de inventario" (la cual lista los quants agrupados por ubicación y producto). También se puede desde nuestro código. Supongamos que necesitamos conocer el stock de un producto y número de serie determinado, tenemos que hacer lo siguiente:

product_id = self.env['product.product'].search(\
​[('default_code','=','producto a consultar')])
lot_id = self.env['stock.production.lot'].search(\
​[('name','=','nro de serie a consultar'),('product_id','=',product_id.id)]
quants = self.env['stock.quant'].search(\
​[('location_id.usage','=','internal'),('lot_id','=',lot_id.id)])
for quant in quants:
print('Stock in location %s para producto %s nro de serie %s es %s'\
%(quant.location_id.name,quant.product_id.name,quant.lot_id.name,quant.quantity))

Otro ejemplo de como se puede consultar el stock se encuentra en el post Como hacer una planilla de Excel con los stocks de Odoo

Algo para tener en cuenta, recomendamos impedir los stocks negativos en el mismo (algún cráneo en Bélgica pensó que una empresa puede funcionar normalmente con stock negativos). Revisen el módulo stock_no_negative ya que brida ideas muy buenas sobre como 

Por último, no vamos a entrar en la valuación de stock debido a que nadie en su sano juicio utiliza dicha funcionalidad en Argentina. Igual vamos a hablar de eso en otro post.

Como agregar campos para consultar stocks

El modelo stock.quant como pudieron ver tiene muchas columnas por las cuales puede ser consultado. Pero esto no es suficiente. Por ejemplo, podemos necesitar columnas presentes en el modelo product.product o product.template (categoría o fabricante). En este ejemplo, vamos a agregar la categoría del producto (la idea es explicar como se hace).

Para ello, creamos un nuevo módulo llamado a2_stock_quant_category. En el mismo agregamos un campo computado (almacenado, así puede ser filtrado y sumarizado) al modelo stock.quant. Dicho campo es del tipo Many2one y apunta al modelo de categorías (product.category).

category_id = fields.Many2one(
​'product.category',
​'Category',
​store=True,
​compute=_compute_category_id)

Para computar el valor de este campo definimos el método _compute_category_id.

@api.depends('product_id')
def _compute_category_id(self):
for rec in self:
if rec.product_id and rec.product_id.categ_id:
rec.category_id = rec.product_id.categ_id.id
else:
rec.category_id = None


En este método vemos una técnica común en campos computados almacenados. Cada vez que el campo product_id en stock.quant cambia, actualiza el campo category_id con el valor de la categoría del producto.

Por último, vamos a agregar a la consulta de inventarios, el campo category_id. Dicho campo tendrá el atributo "optional" seteado a "hide" así es visible siempre y cuando lo desee el usuario.


<record id="a2_stock_quant_category" model="ir.ui.view">
<field name="name">a2.stock.quant.category</field>
<field name="model">stock.quant</field>
<field name="inherit_id" ref="stock.view_stock_quant_tree_inventory_editable"></field>
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="category_id" optional="hide" />
</field>
</field>
</record>

A continuación, vemos el resultado



Gustavo Orrillo 19 de julio de 2023
Compartir
Categorías
Archivar
Identificarse dejar un comentario