# Copyright 2025 Criptomart # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) from datetime import datetime from datetime import timedelta from odoo.tests.common import TransactionCase class TestEskaerShop(TransactionCase): """Test suite para la lógica de eskaera_shop (descubrimiento de productos).""" def setUp(self): super().setUp() # Crear un grupo (res.partner) self.group = self.env["res.partner"].create( { "name": "Grupo Test Eskaera", "is_company": True, "email": "grupo@test.com", } ) # Crear usuario miembro del grupo user_partner = self.env["res.partner"].create( { "name": "Usuario Test Partner", "email": "usuario_test@test.com", } ) self.user = self.env["res.users"].create( { "name": "Usuario Test", "login": "usuario_test@test.com", "email": "usuario_test@test.com", "partner_id": user_partner.id, } ) # Añadir el partner del usuario como miembro del grupo self.group.member_ids = [(4, user_partner.id)] # Crear categorías de producto self.category1 = self.env["product.category"].create( { "name": "Categoría Test 1", } ) self.category2 = self.env["product.category"].create( { "name": "Categoría Test 2", } ) # Crear proveedor self.supplier = self.env["res.partner"].create( { "name": "Proveedor Test", "is_company": True, "supplier_rank": 1, "email": "proveedor@test.com", } ) # Crear productos self.product_cat1 = self.env["product.product"].create( { "name": "Producto Categoría 1", "type": "consu", "list_price": 10.0, "categ_id": self.category1.id, "active": True, } ) self.product_cat1.product_tmpl_id.write( { "is_published": True, "sale_ok": True, } ) self.product_cat2 = self.env["product.product"].create( { "name": "Producto Categoría 2", "type": "consu", "list_price": 20.0, "categ_id": self.category2.id, "active": True, } ) self.product_cat2.product_tmpl_id.write( { "is_published": True, "sale_ok": True, } ) # Crear producto con relación a proveedor self.product_supplier_template = self.env["product.template"].create( { "name": "Producto Proveedor", "type": "consu", "list_price": 30.0, "categ_id": self.category1.id, "is_published": True, "sale_ok": True, } ) self.product_supplier = self.product_supplier_template.product_variant_ids[0] self.product_supplier.active = True # Crear relación con proveedor self.env["product.supplierinfo"].create( { "product_tmpl_id": self.product_supplier_template.id, "partner_id": self.supplier.id, "min_qty": 1.0, } ) self.product_direct = self.env["product.product"].create( { "name": "Producto Directo", "type": "consu", "list_price": 40.0, "categ_id": self.category1.id, "active": True, } ) self.product_direct.product_tmpl_id.write( { "is_published": True, "sale_ok": True, } ) def test_product_discovery_direct(self): """Test que los productos directos se descubren correctamente.""" order = self.env["group.order"].create( { "name": "Pedido Directo", "group_ids": [(6, 0, [self.group.id])], "type": "regular", "start_date": datetime.now().date(), "end_date": (datetime.now() + timedelta(days=7)).date(), "period": "weekly", "pickup_day": "5", "cutoff_day": "0", "product_ids": [(6, 0, [self.product_direct.id])], } ) order.action_open() # Simular lo que hace eskaera_shop products = order.product_ids self.assertEqual(len(products), 1) self.assertIn(self.product_direct, products) products = self.env["product.product"]._get_products_for_group_order(order.id) self.assertIn( self.product_direct.product_tmpl_id, products.mapped("product_tmpl_id") ) def test_product_discovery_by_category(self): """Test que los productos se descubren por categoría cuando no hay directos.""" order = self.env["group.order"].create( { "name": "Pedido por Categoría", "group_ids": [(6, 0, [self.group.id])], "type": "regular", "start_date": datetime.now().date(), "end_date": (datetime.now() + timedelta(days=7)).date(), "period": "weekly", "pickup_day": "5", "cutoff_day": "0", "category_ids": [(6, 0, [self.category1.id])], } ) order.action_open() # Simular lo que hace eskaera_shop (fallback a categorías) products = order.product_ids if not products: products = self.env["product.product"].search( [ ("categ_id", "in", order.category_ids.ids), ] ) # Debe incluir todos los productos de la categoría 1 self.assertGreaterEqual(len(products), 2) self.assertIn( self.product_cat1.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertIn( self.product_supplier.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertIn( self.product_direct.product_tmpl_id, products.mapped("product_tmpl_id") ) order.write({"category_ids": [(4, self.category1.id)]}) products = self.env["product.product"]._get_products_for_group_order(order.id) self.assertIn( self.product_cat1.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertNotIn( self.product_cat2.product_tmpl_id, products.mapped("product_tmpl_id") ) def test_product_discovery_by_supplier(self): """Test que los productos se descubren por proveedor cuando no hay directos ni categorías.""" order = self.env["group.order"].create( { "name": "Pedido por Proveedor", "group_ids": [(6, 0, [self.group.id])], "type": "regular", "start_date": datetime.now().date(), "end_date": (datetime.now() + timedelta(days=7)).date(), "period": "weekly", "pickup_day": "5", "cutoff_day": "0", "supplier_ids": [(6, 0, [self.supplier.id])], } ) order.action_open() # Simular lo que hace eskaera_shop (fallback a proveedores) products = order.product_ids if not products and order.category_ids: products = self.env["product.product"].search( [ ("categ_id", "in", order.category_ids.ids), ] ) if not products and order.supplier_ids: # Buscar productos que tienen estos proveedores en seller_ids product_templates = self.env["product.template"].search( [ ("seller_ids.partner_id", "in", order.supplier_ids.ids), ] ) products = product_templates.mapped("product_variant_ids") # Debe incluir el producto del proveedor self.assertEqual(len(products), 1) self.assertIn( self.product_supplier.product_tmpl_id, products.mapped("product_tmpl_id") ) order.write({"supplier_ids": [(4, self.supplier.id)]}) products = self.env["product.product"]._get_products_for_group_order(order.id) self.assertIn( self.product_supplier.product_tmpl_id, products.mapped("product_tmpl_id") ) def test_product_discovery_priority(self): """Test que la prioridad de descubrimiento es: directos > categorías > proveedores.""" order = self.env["group.order"].create( { "name": "Pedido con Todos", "group_ids": [(6, 0, [self.group.id])], "type": "regular", "start_date": datetime.now().date(), "end_date": (datetime.now() + timedelta(days=7)).date(), "period": "weekly", "pickup_day": "5", "cutoff_day": "0", "product_ids": [(6, 0, [self.product_direct.id])], "category_ids": [(6, 0, [self.category1.id, self.category2.id])], "supplier_ids": [(6, 0, [self.supplier.id])], } ) order.action_open() # Simular lo que hace eskaera_shop con prioridad products = order.product_ids # Debe retornar los productos directos, no los de categoría/proveedor self.assertEqual(len(products), 1) self.assertIn( self.product_direct.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertNotIn( self.product_cat1.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertNotIn( self.product_cat2.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertNotIn( self.product_supplier.product_tmpl_id, products.mapped("product_tmpl_id") ) # 2. The canonical helper now returns the UNION of all association # sources (direct products, categories, suppliers). Assert all are # present to reflect the new behaviour. products = self.env["product.product"]._get_products_for_group_order(order.id) tmpl_ids = products.mapped("product_tmpl_id") self.assertIn(self.product_direct.product_tmpl_id, tmpl_ids) self.assertIn(self.product_cat1.product_tmpl_id, tmpl_ids) self.assertIn(self.product_supplier.product_tmpl_id, tmpl_ids) def test_product_discovery_fallback_from_category_to_supplier(self): """Test que si no hay directos ni categorías, usa proveedores.""" order = self.env["group.order"].create( { "name": "Pedido Fallback", "group_ids": [(6, 0, [self.group.id])], "type": "regular", "start_date": datetime.now().date(), "end_date": (datetime.now() + timedelta(days=7)).date(), "period": "weekly", "pickup_day": "5", "cutoff_day": "0", # Sin product_ids # Sin category_ids "supplier_ids": [(6, 0, [self.supplier.id])], } ) order.action_open() # Simular lo que hace eskaera_shop products = order.product_ids if not products and order.category_ids: products = self.env["product.product"].search( [ ("categ_id", "in", order.category_ids.ids), ] ) if not products and order.supplier_ids: # Buscar productos que tienen estos proveedores en seller_ids product_templates = self.env["product.template"].search( [ ("seller_ids.partner_id", "in", order.supplier_ids.ids), ] ) products = product_templates.mapped("product_variant_ids") # Debe retornar productos del proveedor self.assertEqual(len(products), 1) self.assertIn( self.product_supplier.product_tmpl_id, products.mapped("product_tmpl_id") ) # Clear categories so supplier-only fallback remains active order.write( { "category_ids": [(5, 0, 0)], "supplier_ids": [(4, self.supplier.id)], } ) products = self.env["product.product"]._get_products_for_group_order(order.id) self.assertIn( self.product_supplier.product_tmpl_id, products.mapped("product_tmpl_id") ) self.assertNotIn( self.product_direct.product_tmpl_id, products.mapped("product_tmpl_id") ) def test_no_products_available(self): """Test que retorna vacío si no hay productos definidos de ninguna forma.""" order = self.env["group.order"].create( { "name": "Pedido Sin Productos", "group_ids": [(6, 0, [self.group.id])], "type": "regular", "start_date": datetime.now().date(), "end_date": (datetime.now() + timedelta(days=7)).date(), "period": "weekly", "pickup_day": "5", "cutoff_day": "0", # Sin product_ids, category_ids, supplier_ids } ) order.action_open() # Simular lo que hace eskaera_shop products = order.product_ids if not products and order.category_ids: products = self.env["product.product"].search( [ ("categ_id", "in", order.category_ids.ids), ] ) if not products and order.supplier_ids: # Buscar productos que tienen estos proveedores en seller_ids product_templates = self.env["product.template"].search( [ ("seller_ids.partner_id", "in", order.supplier_ids.ids), ] ) products = product_templates.mapped("product_variant_ids") # Debe estar vacío self.assertEqual(len(products), 0)