Actualizando precios con archivos Excel

30 de abril de 2024 por
Gustavo Orrillo
| Sin comentarios aún
 

Muchas veces los usuarios necesitan de forma periódica (y este es un punto importante, la periodicidad es lo que te indica cuando tenés que desarrollar un módulo o un script de xmlrpc) actualizar precios con una planilla de Excel (por ejemplo, cuando los proveedores les envían listas de precios). 

Bien... continuamos el módulo massive_price_update. En ese módulo como decíamos anteriormente, no solo podemos modificar los precios como en una planilla de cálculo, sino también podemos seleccionar un archivo de Excel con dos columnas (código del producto, precio),


y actualiza los precios.

Tenemos un ítem de menú nuevo llamado "Archivos de Precios" en el cual llevamos un registro de los archivos procesados


Buscamos llevar un registro de los archivos procesados porque necesitamos tener un marco de auditoría para dichas actualizaciones.


En dicho marco podemos llevar un log de los archivos que procesamos, y que productos actualizamos. Lo que va a ser de utilidad para los usuarios y además vamos a poder volver atrás los cambios en precios en caso de errores.

Notas técnicas

Este funcionalidad tiene dos temas interesantes. La primera es genera un nuevo modelo para procesar los archivos Excel. Nada nuevo en eso, cualquier post de desarrollo de módulos cubre dicha funcionalidad. 

La segunda es la posibilidad de procesar los contenidos de un archivo Excel. Para ello almacenamos el archivo Excel en un campo binario.

file = fields.Binary('Archivo')

Y luego leemos los contenidos de dicho campo binario, y los procesamos utilizando la biblioteca openpyxl. Basicamente decodificamos el contenido del campo, y dicho contenido es leído como un archivo por la biblioteca openpyxl. Y luego lo procesamos como un archivo más:

        wb = openpyxl.load_workbook(filename=BytesIO(base64.b64decode(self.file)),read_only=True)
worksheet = wb.active
rows = worksheet.rows
for x,row in enumerate(rows):
# Saltea la primer fila porque tiene el nombre de las columnas
if x == 0:
continue
# Lee cada una de las celdas en la fila
vals = {}
default_code = None
new_price = 0
for i,cell in enumerate(row):
if i == 0 and cell.value:
default_code = cell.value

Y luego actualizamos el producto (primero lo buscamos por código y luego actualizamos el precio).

if default_code:
​product_tmpl_id = self.env['product.template'].search([('default_code','=',default_code)])
if not product_tmpl_id:
raise ValidationError('Producto %s inexistente'%(default_code))
vals = {
'file_id': self.id,
'product_tmpl_id': product_tmpl_id.id,
'old_price': product_tmpl_id.list_price,
'new_price': new_price,
}
line_id = self.env['product.prices.file.line'].create(vals)
product_tmpl_id.list_price = new_price

Como pueden ver, en el camino creamos un log con los productos actualizados. Dicho log nos permitirá controlar que productos actualizamos, juntos con los valores pre y post actualización.

Gustavo Orrillo 30 de abril de 2024
Compartir
Categorías
Archivar
Identificarse dejar un comentario