fix: GP incorrect buying amount if no upd on SI and Delivery Note
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index f0106be..dacc809 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -3,7 +3,8 @@
 
 
 import frappe
-from frappe import _, scrub
+from frappe import _, qb, scrub
+from frappe.query_builder import Order
 from frappe.utils import cint, flt, formatdate
 
 from erpnext.controllers.queries import get_match_cond
@@ -398,6 +399,7 @@
 		self.average_buying_rate = {}
 		self.filters = frappe._dict(filters)
 		self.load_invoice_items()
+		self.get_delivery_notes()
 
 		if filters.group_by == "Invoice":
 			self.group_items_by_invoice()
@@ -591,6 +593,21 @@
 
 		return flt(buying_amount, self.currency_precision)
 
+	def calculate_buying_amount_from_sle(self, row, my_sle, parenttype, parent, item_row, item_code):
+		for i, sle in enumerate(my_sle):
+			# find the stock valution rate from stock ledger entry
+			if (
+				sle.voucher_type == parenttype
+				and parent == sle.voucher_no
+				and sle.voucher_detail_no == item_row
+			):
+				previous_stock_value = len(my_sle) > i + 1 and flt(my_sle[i + 1].stock_value) or 0.0
+
+				if previous_stock_value:
+					return abs(previous_stock_value - flt(sle.stock_value)) * flt(row.qty) / abs(flt(sle.qty))
+				else:
+					return flt(row.qty) * self.get_average_buying_rate(row, item_code)
+
 	def get_buying_amount(self, row, item_code):
 		# IMP NOTE
 		# stock_ledger_entries should already be filtered by item_code and warehouse and
@@ -607,19 +624,22 @@
 				if row.dn_detail:
 					parenttype, parent = "Delivery Note", row.delivery_note
 
-				for i, sle in enumerate(my_sle):
-					# find the stock valution rate from stock ledger entry
-					if (
-						sle.voucher_type == parenttype
-						and parent == sle.voucher_no
-						and sle.voucher_detail_no == row.item_row
-					):
-						previous_stock_value = len(my_sle) > i + 1 and flt(my_sle[i + 1].stock_value) or 0.0
-
-						if previous_stock_value:
-							return abs(previous_stock_value - flt(sle.stock_value)) * flt(row.qty) / abs(flt(sle.qty))
-						else:
-							return flt(row.qty) * self.get_average_buying_rate(row, item_code)
+				return self.calculate_buying_amount_from_sle(
+					row, my_sle, parenttype, parent, row.item_row, item_code
+				)
+			elif self.delivery_notes.get((row.parent, row.item_code), None):
+				#  check if Invoice has delivery notes
+				dn = self.delivery_notes.get((row.parent, row.item_code))
+				parenttype, parent, item_row, warehouse = (
+					"Delivery Note",
+					dn["delivery_note"],
+					dn["item_row"],
+					dn["warehouse"],
+				)
+				my_sle = self.sle.get((item_code, warehouse))
+				return self.calculate_buying_amount_from_sle(
+					row, my_sle, parenttype, parent, item_row, item_code
+				)
 			else:
 				return flt(row.qty) * self.get_average_buying_rate(row, item_code)
 
@@ -753,6 +773,29 @@
 			as_dict=1,
 		)
 
+	def get_delivery_notes(self):
+		self.delivery_notes = frappe._dict({})
+		if self.si_list:
+			invoices = [x.parent for x in self.si_list]
+			dni = qb.DocType("Delivery Note Item")
+			delivery_notes = (
+				qb.from_(dni)
+				.select(
+					dni.against_sales_invoice.as_("sales_invoice"),
+					dni.item_code,
+					dni.warehouse,
+					dni.parent.as_("delivery_note"),
+					dni.name.as_("item_row"),
+				)
+				.where((dni.docstatus == 1) & (dni.against_sales_invoice.isin(invoices)))
+				.groupby(dni.against_sales_invoice, dni.item_code)
+				.orderby(dni.creation, order=Order.desc)
+				.run(as_dict=True)
+			)
+
+			for entry in delivery_notes:
+				self.delivery_notes[(entry.sales_invoice, entry.item_code)] = entry
+
 	def group_items_by_invoice(self):
 		"""
 		Turns list of Sales Invoice Items to a tree of Sales Invoices with their Items as children.