diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index 871b590c0c1..38ab94ef644 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -30,14 +30,25 @@ def get_warehouse_account_map(company=None): filters["company"] = company frappe.flags.setdefault("warehouse_account_map", {}).setdefault(company, {}) - for d in frappe.get_all( + warehouses = frappe.get_all( "Warehouse", fields=["name", "account", "parent_warehouse", "company", "is_group"], filters=filters, order_by="lft, rgt", - ): + ) + stock_accounts = { + company_name: get_company_stock_accounts(company_name) + for company_name in {d.company for d in warehouses if d.company and not d.account} + } + + for d in warehouses: if not d.account: - d.account = get_warehouse_account(d, warehouse_account, raise_error=False) + d.account = get_warehouse_account( + d, + warehouse_account, + raise_error=False, + stock_accounts=stock_accounts.get(d.company, []), + ) if d.account: d.account_currency = frappe.db.get_value("Account", d.account, "account_currency", cache=True) @@ -53,7 +64,7 @@ def get_warehouse_account_map(company=None): return frappe.flags.warehouse_account_map -def get_warehouse_account(warehouse, warehouse_account=None, *, raise_error=True): +def get_warehouse_account(warehouse, warehouse_account=None, *, raise_error=True, stock_accounts=None): account = warehouse.account if not account and warehouse.parent_warehouse: if warehouse_account: @@ -79,12 +90,11 @@ def get_warehouse_account(warehouse, warehouse_account=None, *, raise_error=True account = get_company_default_inventory_account(warehouse.company) if not account and warehouse.company: - inventory_accounts = frappe.get_all( - "Account", {"account_type": "Stock", "is_group": 0, "company": warehouse.company}, pluck="name" - ) + if stock_accounts is None: + stock_accounts = get_company_stock_accounts(warehouse.company) - if len(inventory_accounts) == 1: - account = inventory_accounts[0] + if len(stock_accounts) == 1: + account = stock_accounts[0] if raise_error and not account and warehouse.company and not warehouse.is_group: frappe.throw( @@ -97,3 +107,9 @@ def get_warehouse_account(warehouse, warehouse_account=None, *, raise_error=True def get_company_default_inventory_account(company): return frappe.get_cached_value("Company", company, "default_inventory_account") + + +def get_company_stock_accounts(company): + return frappe.get_all( + "Account", {"account_type": "Stock", "is_group": 0, "company": company}, pluck="name" + ) diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index 6d17b21984d..bb0f2098de7 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -227,6 +227,27 @@ class TestWarehouse(ERPNextTestSuite): self.assertNotIn("account", warehouse.get_onload()) + def test_stock_accounts_are_fetched_once_per_company(self): + from unittest.mock import patch + + from erpnext.stock import get_company_stock_accounts, get_warehouse_account_map + + company, warehouse = create_ambiguous_inventory_account_warehouse() + other_warehouse = frappe.get_all( + "Warehouse", + filters={"company": company, "is_group": 0, "name": ["!=", warehouse.name]}, + pluck="name", + limit=1, + )[0] + frappe.db.set_value("Warehouse", other_warehouse, "account", None) + + with patch( + "erpnext.stock.get_company_stock_accounts", wraps=get_company_stock_accounts + ) as fetch_stock_accounts: + get_warehouse_account_map(company) + + fetch_stock_accounts.assert_called_once_with(company) + def create_inventory_fallback_company(): company = "_Test Company Inventory Fallback"