Merge pull request #33577 from rohitwaghchaure/timeout-error-in-purchase-invoice

fix: Timeout error while saving the purchase invoice
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index 28158a3..34417f7 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -9,8 +9,8 @@
   "supplier_and_price_defaults_section",
   "supp_master_name",
   "supplier_group",
-  "column_break_4",
   "buying_price_list",
+  "column_break_4",
   "maintain_same_rate_action",
   "role_to_override_stop_action",
   "transaction_settings_section",
@@ -20,6 +20,7 @@
   "maintain_same_rate",
   "allow_multiple_items",
   "bill_for_rejected_quantity_in_purchase_invoice",
+  "disable_last_purchase_rate",
   "subcontract",
   "backflush_raw_materials_of_subcontract_based_on",
   "column_break_11",
@@ -71,7 +72,7 @@
   },
   {
    "fieldname": "subcontract",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Subcontracting Settings"
   },
   {
@@ -118,8 +119,8 @@
   },
   {
    "fieldname": "supplier_and_price_defaults_section",
-   "fieldtype": "Section Break",
-   "label": "Supplier and Price Defaults"
+   "fieldtype": "Tab Break",
+   "label": "Naming Series and Price Defaults"
   },
   {
    "fieldname": "column_break_4",
@@ -127,12 +128,18 @@
   },
   {
    "fieldname": "transaction_settings_section",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Transaction Settings"
   },
   {
    "fieldname": "column_break_12",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "disable_last_purchase_rate",
+   "fieldtype": "Check",
+   "label": "Disable Last Purchase Rate"
   }
  ],
  "icon": "fa fa-cog",
@@ -140,7 +147,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2022-09-27 10:50:27.050252",
+ "modified": "2023-01-09 17:08:28.828173",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 7989a40..54f0d94 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -274,6 +274,9 @@
 		if self.doctype not in ("Purchase Receipt", "Purchase Invoice", "Purchase Order"):
 			return
 
+		if not self.is_internal_transfer():
+			return
+
 		ref_doctype_map = {
 			"Purchase Order": "Sales Order Item",
 			"Purchase Receipt": "Delivery Note Item",
@@ -544,7 +547,9 @@
 			self.process_fixed_asset()
 			self.update_fixed_asset(field)
 
-		if self.doctype in ["Purchase Order", "Purchase Receipt"]:
+		if self.doctype in ["Purchase Order", "Purchase Receipt"] and not frappe.db.get_single_value(
+			"Buying Settings", "disable_last_purchase_rate"
+		):
 			update_last_purchase_rate(self, is_submit=1)
 
 	def on_cancel(self):
@@ -553,7 +558,9 @@
 		if self.get("is_return"):
 			return
 
-		if self.doctype in ["Purchase Order", "Purchase Receipt"]:
+		if self.doctype in ["Purchase Order", "Purchase Receipt"] and not frappe.db.get_single_value(
+			"Buying Settings", "disable_last_purchase_rate"
+		):
 			update_last_purchase_rate(self, is_submit=0)
 
 		if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index cf12380..686e6cb 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -166,10 +166,7 @@
 		if not self.is_stock_item or self.has_serial_no or self.has_batch_no:
 			return
 
-		if not self.valuation_rate and self.standard_rate:
-			self.valuation_rate = self.standard_rate
-
-		if not self.valuation_rate and not self.is_customer_provided_item:
+		if not self.valuation_rate and not self.standard_rate and not self.is_customer_provided_item:
 			frappe.throw(_("Valuation Rate is mandatory if Opening Stock entered"))
 
 		from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
@@ -194,7 +191,7 @@
 					item_code=self.name,
 					target=default_warehouse,
 					qty=self.opening_stock,
-					rate=self.valuation_rate,
+					rate=self.valuation_rate or self.standard_rate,
 					company=default.company,
 					posting_date=getdate(),
 					posting_time=nowtime(),
@@ -281,7 +278,7 @@
 				frappe.throw(_("Row #{0}: Maximum Net Rate cannot be greater than Minimum Net Rate"))
 
 	def update_template_tables(self):
-		template = frappe.get_doc("Item", self.variant_of)
+		template = frappe.get_cached_doc("Item", self.variant_of)
 
 		# add item taxes from template
 		for d in template.get("taxes"):
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index dc9f2b2..b634146 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -1501,6 +1501,49 @@
 
 		self.assertTrue(return_pi.docstatus == 1)
 
+	def test_disable_last_purchase_rate(self):
+		from erpnext.stock.get_item_details import get_item_details
+
+		item = make_item(
+			"_Test Disable Last Purchase Rate",
+			{"is_purchase_item": 1, "is_stock_item": 1},
+		)
+
+		frappe.db.set_single_value("Buying Settings", "disable_last_purchase_rate", 1)
+
+		pr = make_purchase_receipt(
+			qty=1,
+			rate=100,
+			item_code=item.name,
+		)
+
+		args = pr.items[0].as_dict()
+		args.update(
+			{
+				"supplier": pr.supplier,
+				"doctype": pr.doctype,
+				"conversion_rate": pr.conversion_rate,
+				"currency": pr.currency,
+				"company": pr.company,
+				"posting_date": pr.posting_date,
+				"posting_time": pr.posting_time,
+			}
+		)
+
+		res = get_item_details(args)
+		self.assertEqual(res.get("last_purchase_rate"), 0)
+
+		frappe.db.set_single_value("Buying Settings", "disable_last_purchase_rate", 0)
+
+		pr = make_purchase_receipt(
+			qty=1,
+			rate=100,
+			item_code=item.name,
+		)
+
+		res = get_item_details(args)
+		self.assertEqual(res.get("last_purchase_rate"), 100)
+
 
 def prepare_data_for_internal_transfer():
 	from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 8561dc2..f7fcb30 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -411,7 +411,9 @@
 	args.stock_qty = out.stock_qty
 
 	# calculate last purchase rate
-	if args.get("doctype") in purchase_doctypes:
+	if args.get("doctype") in purchase_doctypes and not frappe.db.get_single_value(
+		"Buying Settings", "disable_last_purchase_rate"
+	):
 		from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
 
 		out.last_purchase_rate = item_last_purchase_rate(
@@ -813,6 +815,9 @@
 			flt(price_list_rate) * flt(args.plc_conversion_rate) / flt(args.conversion_rate)
 		)
 
+		if frappe.db.get_single_value("Buying Settings", "disable_last_purchase_rate"):
+			return out
+
 		if not out.price_list_rate and args.transaction_type == "buying":
 			from erpnext.stock.doctype.item.item import get_last_purchase_details