Actualizando los inventarios con una planilla Excel

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

Muchas veces debemos actualizar los inventarios con un archivo de Excel. En este post explicamos como desarrollar un módulo que permite importar un archivo Excel utilizando la librería XLRD. Si bien uno puede hacerlo con las herramientas que brinda Odoo, hay veces que no queremos que el usuario tenga acceso al utilitario de importación de Odoo debido a que puede ser problemático para el usuario final.

El módulo lo pueden descargar de nuestro repositorio, no tiene muchas vueltas para instalar. No tiene practicamente requerimientos, simplemente que esté instalada la libreria xlrd (la cual se instala con Odoo, segun podemos ver en el archivo requirements.txt). 

El archivo que vamos a importar tiene tres columnas: sky, nro. de serie, cantidad


Y para importarlo tenemos un ítem de menú en la aplicación de Inventarios


Al clickear en dicho menú vamos a ver una lista de los archivos importados


Y podemos crear una nueva importación


Donde podemos agregar el archivo y seleccionar la ubicacion donde se va a actualizar el stock. Una vez agregado el archivo, podemos procesarlo y si el producto no se encuentra creado (lo hace chequeando el sku contra el campo default_code) procede a crearlo. Lo mismo con el número de serie


Es un módulo mejorable en lo que respecta al manejo de errores del procesamiento del archivo de Excel (por ejemplo si el archivo tiene columnas incorrectas) o agregar una columna con ubicaciones diferentes. Pero bueno, es una aproximación a como resolver el problema y seguro le va a servir a más de uno.

Notas técnicas

El archivo hace tres cosas que vale la pena comentar. La primera es el uso del campo state para habilitar la edición de campos o ejecución de métodos en un (o unos) estado determinado (en este caso, borrador).


<header>
<button name="btn_process_file"
string="Procesar"
states="draft" type="object" />
<field name="state" widget="statusbar" />
</header>
<sheet>
<group>
<field name="name" states="draft"/>
<field name="date" state="draft"/>
<field name="location_id" states="draft"
options="{'no_create': True, 'no_create_edit':True}" />
<field name="excel_file" states="draft"/>

El otro tema interesante de notar (y no me voy a cansar de repetirlo) es la actualización de stocks (lo que se hace con movimientos de stock). Eso lo hacemos creando un registro de stock.move y stock.move.line en cada línea del archivo que procesamos (con la lógica para descontar o aumentar stock según corresponda)

vals_move = {
'stock_file_id': self.id,
'product_uom': prod_id.uom_id.id,
'product_id': prod_id.id,
'name': 'Actualizacion inventario %s %s'%(self.name,prod_id.display_name),
'company_id': 1,
'state': 'draft',
'is_inventory': True,
'location_id': src_location,
'location_dest_id': dest_location,
'product_uom_qty': diff
}
move_id = self.env['stock.move'].create(vals_move)
vals_move_line = {
'stock_file_id': self.id,
'move_id': move_id.id,
'product_uom_id': prod_id.uom_id.id,
'product_id': prod_id.id,
'lot_id': lot_id.id,
'company_id': 1,
'state': 'draft',
'is_inventory': True,
'location_id': src_location,
'location_dest_id': dest_location,
'qty_done': diff
}
move_line_id = self.env['stock.move.line'].create(vals_move_line)
move_id._action_done()

El movimiento de stock una vez creado es confirmado. Por último, leemos el archivo Excel desde un campo binario:

wb = xlrd.open_workbook(file_contents = base64.decodebytes(self.excel_file))
sheet = wb.sheets()[0]
for row in range(sheet.nrows):
if row < 1:
continue
prod = None
serial = None
qty = 0
for col in range(sheet.ncols):
cell_value = sheet.cell(row,col).value
if col == 0:
prod = cell_value
elif col == 1:
serial = cell_value
else:
qty = cell_value
Gustavo Orrillo 19 de diciembre de 2023
Compartir
Archivar
Identificarse dejar un comentario