diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index 92dd5925205bffed4d2af337cbaf5e4abaec4a16..db1313fcd492ccab001d4c5b2bd79768a7a46c5b 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -249,6 +249,7 @@ class Product(models.Model): It will return all stock locations when no parameters are given Possible parameters are shop, warehouse, location, compute_child ''' + Location = self.env['stock.location'] Warehouse = self.env['stock.warehouse'] def _search_ids(model, values): @@ -277,7 +278,14 @@ class Product(models.Model): w_ids = set(Warehouse.browse(_search_ids('stock.warehouse', warehouse)).mapped('view_location_id').ids) if location: l_ids = _search_ids('stock.location', location) - location_ids = w_ids & l_ids + parents = Location.browse(w_ids).mapped("parent_path") + location_ids = { + loc.id + for loc in Location.browse(l_ids) + if any(loc.parent_path.startswith(parent) for parent in parents) + } + if not location_ids: + return [[expression.FALSE_LEAF]] * 3 else: location_ids = w_ids else: diff --git a/addons/stock/tests/test_product.py b/addons/stock/tests/test_product.py index 588e9b7ea4525a86bb18d756577cfb7435753e5a..0f2c4192f4366a2ce0990641185f051718ef8d6b 100644 --- a/addons/stock/tests/test_product.py +++ b/addons/stock/tests/test_product.py @@ -277,3 +277,47 @@ class TestVirtualAvailable(TestStockCommon): res = self.env['product.template'].name_search(name='123', operator='not ilike') res_ids = [r[0] for r in res] self.assertNotIn(template.id, res_ids) + + def test_product_qty_field_and_context(self): + main_warehouse = self.warehouse_1 + other_warehouse = self.env['stock.warehouse'].search([('id', '!=', main_warehouse.id)], limit=1) + warehouses = main_warehouse | other_warehouse + main_loc = main_warehouse.lot_stock_id + other_loc = other_warehouse.lot_stock_id + self.assertTrue(other_warehouse, 'The test needs another warehouse') + + (main_loc | other_loc).name = 'Stock' + sub_loc01, sub_loc02, sub_loc03 = self.env['stock.location'].create([{ + 'name': 'Sub0%s' % (i + 1), + 'location_id': main_loc.id, + } for i in range(3)]) + + self.env['stock.quant'].search([('product_id', '=', self.product_3.id)]).unlink() + self.env['stock.quant']._update_available_quantity(self.product_3, other_loc, 1000) + self.env['stock.quant']._update_available_quantity(self.product_3, main_loc, 100) + self.env['stock.quant']._update_available_quantity(self.product_3, sub_loc01, 10) + self.env['stock.quant']._update_available_quantity(self.product_3, sub_loc02, 1) + + for wh, loc, expected in [ + (False, False, 1111.0), + (False, other_loc.id, 1000.0), + (False, main_loc.id, 111.0), + (False, sub_loc01.id, 10.0), + (False, sub_loc01.name, 10.0), + (False, 'sub', 11.0), + (False, main_loc.name, 1111.0), + (False, (sub_loc01 | sub_loc02 | sub_loc03).ids, 11.0), + (main_warehouse.id, main_loc.name, 111.0), + (main_warehouse.id, main_loc.id, 111.0), + (main_warehouse.id, (main_loc | other_loc).ids, 111.0), + (main_warehouse.id, sub_loc01.id, 10.0), + (main_warehouse.id, (sub_loc01 | sub_loc02).ids, 11.0), + (other_warehouse.id, main_loc.name, 1000.0), + (other_warehouse.id, main_loc.id, 0.0), + (main_warehouse.name, False, 111.0), + (main_warehouse.id, False, 111.0), + (warehouses.ids, False, 1111.0), + (warehouses.ids, (other_loc | sub_loc02).ids, 1001), + ]: + product_qty = self.product_3.with_context(warehouse=wh, location=loc).qty_available + self.assertEqual(product_qty, expected)