fix: performance issue of sales invoice while save/submit (#19598)

* fix: performace issue of sales invoice while save/submit

* Cached price list data, item group child data, added indexing for blanket order
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 7c2e09e..9f47edc 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -12,6 +12,7 @@
 from erpnext.stock.doctype.batch.batch import get_batch_no
 from erpnext import get_company_currency
 from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor
+from erpnext.stock.doctype.price_list.price_list import get_price_list_details
 from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
 from erpnext.setup.doctype.brand.brand import get_brand_defaults
 from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no
@@ -22,7 +23,7 @@
 purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
 
 @frappe.whitelist()
-def get_item_details(args, doc=None, overwrite_warehouse=True):
+def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=True):
 	"""
 		args = {
 			"item_code": "",
@@ -74,7 +75,9 @@
 		if args.get(key) is None:
 			args[key] = value
 
-	data = get_pricing_rule_for_item(args, out.price_list_rate, doc)
+	data = get_pricing_rule_for_item(args, out.price_list_rate,
+		doc, for_validate=for_validate)
+
 	out.update(data)
 
 	update_stock(args, out)
@@ -479,7 +482,6 @@
 	if meta.get_field("currency") or args.get('currency'):
 		pl_details = get_price_list_currency_and_exchange_rate(args)
 		args.update(pl_details)
-		validate_price_list(args)
 		if meta.get_field("currency"):
 			validate_conversion_rate(args, meta)
 
@@ -634,14 +636,6 @@
 
 	return flag
 
-def validate_price_list(args):
-	if args.get("price_list"):
-		if not frappe.db.get_value("Price List",
-			{"name": args.price_list, args.transaction_type: 1, "enabled": 1}):
-			throw(_("Price List {0} is disabled or does not exist").format(args.price_list))
-	elif args.get("customer"):
-		throw(_("Price List not selected"))
-
 def validate_conversion_rate(args, meta):
 	from erpnext.controllers.accounts_controller import validate_conversion_rate
 
@@ -905,27 +899,6 @@
 
 	return item_details
 
-def get_price_list_currency(price_list):
-	if price_list:
-		result = frappe.db.get_value("Price List", {"name": price_list,
-			"enabled": 1}, ["name", "currency"], as_dict=True)
-
-		if not result:
-			throw(_("Price List {0} is disabled or does not exist").format(price_list))
-
-		return result.currency
-
-def get_price_list_uom_dependant(price_list):
-	if price_list:
-		result = frappe.db.get_value("Price List", {"name": price_list,
-			"enabled": 1}, ["name", "price_not_uom_dependent"], as_dict=True)
-
-		if not result:
-			throw(_("Price List {0} is disabled or does not exist").format(price_list))
-
-		return not result.price_not_uom_dependent
-
-
 def get_price_list_currency_and_exchange_rate(args):
 	if not args.price_list:
 		return {}
@@ -935,8 +908,11 @@
 	elif args.doctype in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']:
 		args.update({"exchange_rate": "for_buying"})
 
-	price_list_currency = get_price_list_currency(args.price_list)
-	price_list_uom_dependant = get_price_list_uom_dependant(args.price_list)
+	price_list_details = get_price_list_details(args.price_list)
+
+	price_list_currency = price_list_details.get("currency")
+	price_list_uom_dependant = price_list_details.get("price_list_uom_dependant")
+
 	plc_conversion_rate = args.plc_conversion_rate
 	company_currency = get_company_currency(args.company)