Merge pull request #30509 from marination/buying-validate-items

fix: Add non-existent Item check and cleanup in `validate_for_items`
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 150f68b..c71ea36 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -204,7 +204,9 @@
 		if not self.account_currency:
 			self.account_currency = frappe.get_cached_value("Company", self.company, "default_currency")
 
-		elif self.account_currency != frappe.db.get_value("Account", self.name, "account_currency"):
+		gl_currency = frappe.db.get_value("GL Entry", {"account": self.name}, "account_currency")
+
+		if gl_currency and self.account_currency != gl_currency:
 			if frappe.db.get_value("GL Entry", {"account": self.name}):
 				frappe.throw(_("Currency can not be changed after making entries using some other currency"))
 
diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index efc063d..f9c9173 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -241,6 +241,28 @@
 		for doc in to_delete:
 			frappe.delete_doc("Account", doc)
 
+	def test_validate_account_currency(self):
+		from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
+
+		if not frappe.db.get_value("Account", "Test Currency Account - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Test Currency Account"
+			acc.parent_account = "Tax Assets - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+		else:
+			acc = frappe.get_doc("Account", "Test Currency Account - _TC")
+
+		self.assertEqual(acc.account_currency, "INR")
+
+		# Make a JV against this account
+		make_journal_entry(
+			"Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True
+		)
+
+		acc.account_currency = "USD"
+		self.assertRaises(frappe.ValidationError, acc.save)
+
 
 def _make_test_records(verbose=None):
 	from frappe.test_runner import make_test_objects
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 57bc0a7..e6a46d0 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -249,8 +249,9 @@
 
 	def validate_warehouse(self, for_validate=True):
 		if self.update_stock and for_validate:
+			stock_items = self.get_stock_items()
 			for d in self.get("items"):
-				if not d.warehouse:
+				if not d.warehouse and d.item_code in stock_items:
 					frappe.throw(
 						_(
 							"Row No {0}: Warehouse is required. Please set a Default Warehouse for Item {1} and Company {2}"
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 72ac1b3..3a20d3f 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1267,17 +1267,9 @@
 		stock_items = []
 		item_codes = list(set(item.item_code for item in self.get("items")))
 		if item_codes:
-			stock_items = [
-				r[0]
-				for r in frappe.db.sql(
-					"""
-				select name from `tabItem`
-				where name in (%s) and is_stock_item=1
-			"""
-					% (", ".join(["%s"] * len(item_codes)),),
-					item_codes,
-				)
-			]
+			stock_items = frappe.db.get_values(
+				"Item", {"name": ["in", item_codes], "is_stock_item": 1}, pluck="name", cache=True
+			)
 
 		return stock_items