diff --git a/tienda_ilusion/don_confiao/services/tryton/categories.py b/tienda_ilusion/don_confiao/services/tryton/categories.py index 89b1420..930dafe 100644 --- a/tienda_ilusion/don_confiao/services/tryton/categories.py +++ b/tienda_ilusion/don_confiao/services/tryton/categories.py @@ -53,15 +53,14 @@ class CategoryTrytonService: return self._empty_report() tryton_products = self._get_product_details(product_ids, context) - category_ids = set() - for tryton_product in tryton_products: - category_ids.update(self._extract_category_ids(tryton_product)) - if not category_ids: + category_names = self._extract_category_names(tryton_products) + if not category_names: return self._empty_report() - tryton_categories = self._get_category_details( - sorted(category_ids), context - ) + tryton_categories = [ + {"id": category_id, "name": category_names[category_id]} + for category_id in sorted(category_names) + ] checked = [ {"id": c.get("id"), "name": c.get("name")} @@ -121,21 +120,27 @@ class CategoryTrytonService: return self.client.call(method, params) or [] def _get_product_details(self, product_ids, context): - tryton_fields = ["id", "name", "template.categories"] + tryton_fields = [ + "id", + "name", + "template.categories", + "template.categories.name", + ] method = "model.product.product.read" params = (product_ids, tryton_fields, context) return self.client.call(method, params) @staticmethod - def _extract_category_ids(tryton_product): - """Extrae los IDs de categorías de la respuesta RPC de Tryton""" - template = tryton_product.get("template.") or {} - return template.get("categories") or [] - - def _get_category_details(self, category_ids, context): - method = "model.product.category.read" - params = (category_ids, ["id", "name"], context) - return self.client.call(method, params) + def _extract_category_names(tryton_products): + """Extrae el mapa {id_tryton: nombre} de las categorías anidadas en + la respuesta de product.read (clave 'template.categories.name', + agrupada bajo 'template.' como 'categories.')""" + names = {} + for tryton_product in tryton_products: + template = tryton_product.get("template.") or {} + for category in template.get("categories.") or []: + names[category.get("id")] = category.get("name") + return names def _empty_report(self): return { diff --git a/tienda_ilusion/don_confiao/services/tryton/products.py b/tienda_ilusion/don_confiao/services/tryton/products.py index d5a2f9d..344eddc 100644 --- a/tienda_ilusion/don_confiao/services/tryton/products.py +++ b/tienda_ilusion/don_confiao/services/tryton/products.py @@ -107,19 +107,16 @@ class ProductTrytonService: reporte {"created": [...], "updated": [...]} """ empty_report = {"created": [], "updated": []} - category_ids = { - category_id - for tryton_product in tryton_products - for category_id in self._extract_category_ids(tryton_product) - } - if not category_ids: + category_names = self._extract_category_names(tryton_products) + if not category_names: return {}, empty_report categories = {} report = {"created": [], "updated": []} - tryton_categories = self._get_category_details( - sorted(category_ids), context - ) + tryton_categories = [ + {"id": category_id, "name": category_names[category_id]} + for category_id in sorted(category_names) + ] for tryton_category in tryton_categories: try: category, status, changes = upsert_category(tryton_category) @@ -149,11 +146,17 @@ class ProductTrytonService: template = tryton_product.get("template.") or {} return template.get("categories") or [] - def _get_category_details(self, category_ids, context): - """Obtiene los nombres de categorías desde Tryton""" - method = "model.product.category.read" - params = (category_ids, ["id", "name"], context) - return self.client.call(method, params) + @staticmethod + def _extract_category_names(tryton_products): + """Extrae el mapa {id_tryton: nombre} de las categorías anidadas en + la respuesta de product.read (clave 'template.categories.name', + agrupada bajo 'template.' como 'categories.')""" + names = {} + for tryton_product in tryton_products: + template = tryton_product.get("template.") or {} + for category in template.get("categories.") or []: + names[category.get("id")] = category.get("name") + return names def _sync_product_categories(self, product, tryton_product, categories): """Vincula al producto las categorías importadas desde Tryton""" @@ -271,6 +274,7 @@ class ProductTrytonService: "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ] method = "model.product.product.read" params = (product_ids, tryton_fields, context) diff --git a/tienda_ilusion/don_confiao/tests/test_categories_from_tryton.py b/tienda_ilusion/don_confiao/tests/test_categories_from_tryton.py index ca57ed3..a03c5b1 100644 --- a/tienda_ilusion/don_confiao/tests/test_categories_from_tryton.py +++ b/tienda_ilusion/don_confiao/tests/test_categories_from_tryton.py @@ -30,19 +30,22 @@ class TestCategoryTrytonImport(TestCase): { "id": 1, "name": "Producto 1", - "template.": {"id": 999, "categories": [6]}, + "template.": { + "id": 999, + "categories": [6], + "categories.": [{"id": 6, "name": "Alimentos"}], + }, }, { "id": 2, "name": "Producto 2", - "template.": {"id": 999, "categories": [7]}, + "template.": { + "id": 999, + "categories": [7], + "categories.": [{"id": 7, "name": "Verduras"}], + }, }, ] - if args[0] == "model.product.category.read": - return [ - {"id": 6, "name": "Alimentos"}, - {"id": 7, "name": "Verduras"}, - ] raise Exception(f"args no esperados: {args}") mock_call.side_effect = fake_call @@ -93,11 +96,15 @@ class TestCategoryTrytonImport(TestCase): { "id": 1, "name": "Producto 1", - "template.": {"id": 999, "categories": [7]}, + "template.": { + "id": 999, + "categories": [7], + "categories.": [ + {"id": 7, "name": "Cereales y Granos"} + ], + }, }, ] - if args[0] == "model.product.category.read": - return [{"id": 7, "name": "Cereales y Granos"}] raise Exception(f"args no esperados: {args}") mock_call.side_effect = fake_call @@ -135,11 +142,13 @@ class TestCategoryTrytonImport(TestCase): { "id": 1, "name": "Producto 1", - "template.": {"id": 999, "categories": [6]}, + "template.": { + "id": 999, + "categories": [6], + "categories.": [{"id": 6, "name": "Alimentos"}], + }, }, ] - if args[0] == "model.product.category.read": - return [{"id": 6, "name": "Alimentos"}] raise Exception(f"args no esperados: {args}") mock_call.side_effect = fake_call @@ -182,11 +191,13 @@ class TestCategoryTrytonImport(TestCase): { "id": 1, "name": "Producto 1", - "template.": {"id": 999, "categories": [6]}, + "template.": { + "id": 999, + "categories": [6], + "categories.": [{"id": 6, "name": None}], + }, }, ] - if args[0] == "model.product.category.read": - return [{"id": 6, "name": None}] raise Exception(f"args no esperados: {args}") mock_call.side_effect = fake_call diff --git a/tienda_ilusion/don_confiao/tests/test_product_categories_api.py b/tienda_ilusion/don_confiao/tests/test_product_categories_api.py index 1e200e0..67db842 100644 --- a/tienda_ilusion/don_confiao/tests/test_product_categories_api.py +++ b/tienda_ilusion/don_confiao/tests/test_product_categories_api.py @@ -157,11 +157,13 @@ class ProductCategoryApiTest(TestCase): { "id": 1, "name": "Producto 1", - "template.": {"id": 999, "categories": [6]}, + "template.": { + "id": 999, + "categories": [6], + "categories.": [{"id": 6, "name": "Alimentos"}], + }, }, ] - if args[0] == "model.product.category.read": - return [{"id": 6, "name": "Alimentos"}] raise Exception(f"args no esperados: {args}") mock_call.side_effect = fake_call diff --git a/tienda_ilusion/don_confiao/tests/test_products_from_tryton.py b/tienda_ilusion/don_confiao/tests/test_products_from_tryton.py index 70db33a..c931ded 100644 --- a/tienda_ilusion/don_confiao/tests/test_products_from_tryton.py +++ b/tienda_ilusion/don_confiao/tests/test_products_from_tryton.py @@ -56,6 +56,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -157,6 +158,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -226,6 +228,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -288,6 +291,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -354,6 +358,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -364,22 +369,17 @@ class TestProductsFromTryton(TestCase, LoginMixin): "list_price": Decimal("25000"), "name": "Producto 1", "default_uom.": {"id": 1, "rec_name": "Unit"}, - "template.": {"id": 999, "categories": [5, 8]}, + "template.": { + "id": 999, + "categories": [5, 8], + "categories.": [ + {"id": 5, "name": "Abarrotes"}, + {"id": 8, "name": "Bebidas"}, + ], + }, }, ] - category_read = "model.product.category.read" - category_args = ( - [5, 8], - ["id", "name"], - {"company": 1}, - ) - if args == (category_read, category_args): - return [ - {"id": 5, "name": "Abarrotes"}, - {"id": 8, "name": "Bebidas"}, - ] - raise Exception( f"Sorry, args non expected on this test: {args}" ) @@ -445,6 +445,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -455,21 +456,14 @@ class TestProductsFromTryton(TestCase, LoginMixin): "list_price": Decimal("25000"), "name": "Producto 1", "default_uom.": {"id": 1, "rec_name": "Unit"}, - "template.": {"id": 999, "categories": [7]}, + "template.": { + "id": 999, + "categories": [7], + "categories.": [{"id": 7, "name": "Cereales"}], + }, }, ] - category_read = "model.product.category.read" - category_args = ( - [7], - ["id", "name"], - {"company": 1}, - ) - if args == (category_read, category_args): - return [ - {"id": 7, "name": "Cereales"}, - ] - raise Exception( f"Sorry, args non expected on this test: {args}" ) @@ -536,6 +530,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -546,21 +541,14 @@ class TestProductsFromTryton(TestCase, LoginMixin): "list_price": Decimal("25000"), "name": "Producto 1", "default_uom.": {"id": 1, "rec_name": "Unit"}, - "template.": {"id": 999, "categories": [5]}, + "template.": { + "id": 999, + "categories": [5], + "categories.": [{"id": 5, "name": "Abarrotes"}], + }, }, ] - category_read = "model.product.category.read" - category_args = ( - [5], - ["id", "name"], - {"company": 1}, - ) - if args == (category_read, category_args): - return [ - {"id": 5, "name": "Abarrotes"}, - ] - raise Exception( f"Sorry, args non expected on this test: {args}" ) @@ -627,6 +615,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -688,6 +677,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -698,21 +688,16 @@ class TestProductsFromTryton(TestCase, LoginMixin): "list_price": Decimal("4500"), "name": "Papa", "default_uom.": {"id": 2, "rec_name": "Kilogram"}, - "template.": {"id": 999, "categories": [9]}, + "template.": { + "id": 999, + "categories": [9], + "categories.": [ + {"id": 9, "name": "Tubérculos"} + ], + }, }, ] - category_read = "model.product.category.read" - category_args = ( - [9], - ["id", "name"], - {"company": 1}, - ) - if args == (category_read, category_args): - return [ - {"id": 9, "name": "Tubérculos"}, - ] - raise Exception( f"Sorry, args non expected on this test: {args}" ) @@ -786,6 +771,7 @@ class TestProductsFromTryton(TestCase, LoginMixin): "default_uom.rec_name", "list_price", "template.categories", + "template.categories.name", ], {"company": 1}, ) @@ -796,21 +782,14 @@ class TestProductsFromTryton(TestCase, LoginMixin): "list_price": Decimal("4500"), "name": "Papa", "default_uom.": {"id": 2, "rec_name": "Kilogram"}, - "template.": {"id": 999, "categories": [8]}, + "template.": { + "id": 999, + "categories": [8], + "categories.": [{"id": 8, "name": "Bebidas"}], + }, }, ] - category_read = "model.product.category.read" - category_args = ( - [8], - ["id", "name"], - {"company": 1}, - ) - if args == (category_read, category_args): - return [ - {"id": 8, "name": "Bebidas"}, - ] - raise Exception( f"Sorry, args non expected on this test: {args}" )