From 5ce9482ac42a337f195c9e5e0f87329d9223ca39 Mon Sep 17 00:00:00 2001 From: wdvargas Date: Mon, 10 Mar 2025 16:45:01 +0000 Subject: [PATCH 1/4] Se agrega script para crear atributos y valores desde drive --- create_AttributesValues_DriveToOdoo.py | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 create_AttributesValues_DriveToOdoo.py diff --git a/create_AttributesValues_DriveToOdoo.py b/create_AttributesValues_DriveToOdoo.py new file mode 100644 index 0000000..2d4526c --- /dev/null +++ b/create_AttributesValues_DriveToOdoo.py @@ -0,0 +1,65 @@ +import os +import odooly +import argparse +import pygsheets +import pandas as pd + +def create_values(attribute, df_attributes, odoo_value, values): + values_attribute = list(set(df_attributes.to_list())) + values_attribute.remove('') if '' in values_attribute else values_attribute + + for value in values_attribute: + value_exist = list(filter(lambda l: l.get('name') == str(value) and l.get('attribute_id')[1] == attribute.get('name'), values)) + + if value_exist: + continue + new_value = odoo_value.create({ + 'name': str(value), + 'attribute_id': attribute.get('id') + }) + print(f'El valor: {str(new_value.name)}, ha sido creado en el atributo: {new_value.attribute_id}') + +def main(odoo, filename, args): + + gc = pygsheets.authorize(service_file=os.path.expanduser('config/0a4abc985039aa.json')) # llave de credenciales para la api + ss = gc.open(filename) # Acceder al archivo + ws = ss.worksheet_by_title('Atributos') # Ingresa a la hoja especifica + df = ws.get_as_df(start=args.primer_atributo, end=args.ultimo_atributo) # Definir el rango de columnas que contienen los atributos !!!! Importante ¡¡¡¡¡¡¡ + attributes = list(df.columns) # Obtiene solo los atributos (Titulos) + + # Consulta los atributos y valores creados en Odoo + + Attribute = odoo.env['product.attribute'] + Value = odoo.env['product.attribute.value'] + odoo_attribute = Attribute.search_read([], ['id', 'name']) + odoo_value = Value.search_read([], ['id', 'name', 'attribute_id']) + + #Recorre cada atributo y a su vez los valores, en caso de que no existan los crea + + for attribute in attributes: + exist_attribute = list(filter(lambda l: l.get('name') == attribute, odoo_attribute)) + if not exist_attribute: + attribute_new = Attribute.create({'name': attribute}) + exist_attribute.append({'id': attribute_new.id, 'name': attribute_new.name}) + print(f'Nuevo atributo: {attribute}, creado en odoo') + if len(exist_attribute) > 1: + print(f'El atributo {exist_attribute} tiene mas de un registro duplicado') + continue + + values_odoo = list(filter(lambda l: l.get('attribute_id')[1] == attribute, odoo_value)) + create_values(exist_attribute[0], df[attribute], Value, values_odoo) + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='Crear Atributos y Valores de Drive a Odoo.') + parser.add_argument('--primer_atributo', required=True, help='Primera Celda donde se lee los atributos, Ejem: G1') + parser.add_argument('--ultimo_atributo', required=True, help='Ultima Celda donde se lee los atributos, Ejem: R') + args = parser.parse_args() + + filename = 'Maestro de Productos' + + # Valida las credenciales del usuario y determina el servicio a conectarse + + odooly.Client._config_file = os.path.expanduser('config/odooly.ini') + odoo = odooly.Client.from_config('odootest25') + main(odoo, filename, args) From dd72a5791790f62ac53435cb758caa45dadf426a Mon Sep 17 00:00:00 2001 From: wdvargas Date: Mon, 10 Mar 2025 17:27:47 +0000 Subject: [PATCH 2/4] Se documenta instrucciones del script para crear atributos y valores --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index abcbf03..779dc62 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,34 @@ Este script busca registros específicos en la base de datos de Odoo. * **Uso:** `python buscar_registros.py --modelo modelo_a_buscar --filtro filtro_de_busqueda` * **Ejemplo:** `python buscar_registros.py --modelo stock.picking --filtro "('requested_delivery', '=', True)"` +### create_AttributesValues_DriveToOdoo.py + +Este script crea los atributos y valores del Maestro de Productos en Odoo. + +* **Requisitos:** + * Configurar el archivo odooly.ini como en la instrucción de actualizar_precios.py + * Crear proyecto en Google Cloud + * Habilitar Servicio `Goole Sheets API` en `APIs Y servicios habilitados` + * Crear y configurar una `Cuenta de Servicio` en `Credenciales` + * Descargar la clave `0a4abc9.json` + ```text + { + "type": "service_account", + "project_id": "project_id", + "private_key_id": "private_key_id", + "private_key": "-----BEGIN PRIVATE KEY-----private_key", + "client_email": "client_email", + "client_id": "client_id", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "client_x509_cert_url", + "universe_domain": "googleapis.com" + } + ``` + +* **Ejemplo:** `python3 create_AttributesValues_DriveToOdoo.py --primer_atributo G1 --ultimo_atributo R` + ## Contribución Si quieres contribuir, sigue estos pasos: From 3c10cce0dabec00ba471c927e777c7f4b0b3577c Mon Sep 17 00:00:00 2001 From: wdvargas Date: Mon, 10 Mar 2025 20:18:51 +0000 Subject: [PATCH 3/4] Se agrega script para escribir los atributos en los productos desde drive --- write_AttributeProduct_DriveToOdoo.py | 82 +++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 write_AttributeProduct_DriveToOdoo.py diff --git a/write_AttributeProduct_DriveToOdoo.py b/write_AttributeProduct_DriveToOdoo.py new file mode 100644 index 0000000..2ecf384 --- /dev/null +++ b/write_AttributeProduct_DriveToOdoo.py @@ -0,0 +1,82 @@ +import os +import odooly +import argparse +import pygsheets +import pandas as pd + +def update_attributes_in_product(odoo_items, id, value_ids): + if not id: + return + + product_id = odoo_items.browse(int(id)) + + if not product_id.exists(): + print(f'el producto {product_id} no existe') + return + + product_tmp = product_id.product_tmpl_id + + if len(product_tmp.product_variant_ids) > 1: + print(f'Plantilla {product_tmp.name} #{product_tmp.id}: más de una variante.') + return + + attribute_lines = {line.attribute_id.id: line for line in product_tmp.attribute_line_ids} + + for product_attribute in value_ids: + if not product_attribute: + print(f'Revisar el producto {product_tmp.default_code}, No se encuentra el valor de algun atributo') + continue + + attribute_id = product_attribute[0]['attribute_id'][0] + attribute_value_id = product_attribute[0]['id'] + + if attribute_id in attribute_lines: + product_with_attribute = attribute_lines[attribute_id] + value_exist = attribute_value_id in product_with_attribute.value_ids[0].ids + + if value_exist: + continue + + product_with_attribute.value_ids = [(6, 0, [product_attribute[0]['id']])] + + else: + product_tmp.attribute_line_ids = [(0, 0, { + 'attribute_id': product_attribute[0]['attribute_id'][0], + 'value_ids': [(4, product_attribute[0]['id'], 0)] + })] + +def main(odoo, filename, args): + + gc = pygsheets.authorize(service_file=os.path.expanduser('config/0a4abc985039aa.json')) + ss = gc.open(filename) + ws = ss.worksheet_by_title('Atributos') + + Value = odoo.env['product.attribute.value'] + values = Value.search_read([], ['id', 'name', 'attribute_id']) # Obtiene todos los valores creados en Odoo + + df = ws.get_as_df() + attributes_df = df.iloc[:, int(args.num_atributo_primer):int(args.num_atributo_ultimo)] # df de atributos + product_attributes_df = df[(attributes_df != '').any(axis=1)] # df de los productos filtrados donde almenos tengan un atributo + + product_ids = product_attributes_df.iloc[:, int(args.num_product_ids)] # product_id de los productos con almenos un atributo + attributes_list = product_attributes_df.iloc[:, int(args.num_atributo_primer):int(args.num_atributo_ultimo)].values #valores del productos en tuplas + + # Recorre cada producto con su valores y actualiza el campo + + for product_id, product_attributes in zip(product_ids, attributes_list): + value_ids = [list(filter(lambda l: l['attribute_id'][1] == attribute and l['name'] == str(value), values)) + for attribute, value in zip(list(attributes_df.columns), product_attributes) if value] + update_attributes_in_product(odoo.env['product.product'], product_id, value_ids) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Escribir Atributos y valores a los productos') + parser.add_argument('--num_product_ids', required=True, help='Numero de la columna donde se encuentra el id de los productos, Ejem: 1') + parser.add_argument('--num_atributo_primer', required=True, help='Numero de la primera columna de los atributos, Ejem: 6') + parser.add_argument('--num_atributo_ultimo', required=True, help='Numero de la primera columna de los atributos, Ejem: 18') + args = parser.parse_args() + + filename = 'Maestro de Productos' + + odooly.Client._config_file = os.path.expanduser('config/odooly.ini') + odoo = odooly.Client.from_config('odootest25') + main(odoo, filename, args) From 6479025d05762e6d796c589ec491e5e3b6a3cd92 Mon Sep 17 00:00:00 2001 From: wdvargas Date: Mon, 10 Mar 2025 20:34:17 +0000 Subject: [PATCH 4/4] Se documenta instrucciones del script para escribir los atributos en los productos --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 779dc62..6027e89 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,16 @@ Este script crea los atributos y valores del Maestro de Productos en Odoo. * **Ejemplo:** `python3 create_AttributesValues_DriveToOdoo.py --primer_atributo G1 --ultimo_atributo R` +### write_AttributeProduct_DriveToOdoo.py + +Este script escribe atributos y valores del Maestro de Productos en los productos de Odoo. + +* **Requisitos:** + * Configurar archivo odooly.ini + * Crear proyecto en Google Cloud y seguir los pasos anteriores para descargar la llave + +* **Ejemplo:** `python3 write_AttributeProduct_DriveToOdoo.py --num_product_ids 1 --num_atributo_primer 6 --num_atributo_ultimo 18` + ## Contribución Si quieres contribuir, sigue estos pasos: