fix: incorrect stock value in return case (#23102)

diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 52a5be0..f6d76e5 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -1,5 +1,4 @@
 {
- "actions": [],
  "autoname": "hash",
  "creation": "2013-05-22 12:43:10",
  "doctype": "DocType",
@@ -82,6 +81,7 @@
   "item_tax_rate",
   "bom",
   "include_exploded_items",
+  "purchase_invoice_item",
   "col_break6",
   "purchase_order",
   "po_detail",
@@ -769,12 +769,21 @@
    "collapsible": 1,
    "fieldname": "col_break7",
    "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:parent.update_stock == 1",
+   "fieldname": "purchase_invoice_item",
+   "fieldtype": "Data",
+   "ignore_user_permissions": 1,
+   "label": "Purchase Invoice Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
- "links": [],
- "modified": "2020-04-22 10:37:35.103176",
+ "modified": "2020-08-20 11:48:01.398356",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 004d358..fb3dd6a 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -1,5 +1,4 @@
 {
- "actions": [],
  "autoname": "hash",
  "creation": "2013-06-04 11:02:19",
  "doctype": "DocType",
@@ -87,6 +86,7 @@
   "edit_references",
   "sales_order",
   "so_detail",
+  "sales_invoice_item",
   "column_break_74",
   "delivery_note",
   "dn_detail",
@@ -790,12 +790,22 @@
    "fieldtype": "Link",
    "label": "Project",
    "options": "Project"
-  }
+  },
+  {
+    "depends_on": "eval:parent.update_stock == 1",
+    "fieldname": "sales_invoice_item",
+    "fieldtype": "Data",
+    "ignore_user_permissions": 1,
+    "label": "Sales Invoice Item",
+    "no_copy": 1,
+    "print_hide": 1,
+    "read_only": 1
+   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-07-18 12:24:41.749986",
+ "modified": "2020-08-20 11:24:41.749986",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Item",
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 89b48f0..f982700 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -559,9 +559,19 @@
 						"serial_no": cstr(d.serial_no).strip()
 					})
 					if self.is_return:
-						original_incoming_rate = frappe.db.get_value("Stock Ledger Entry",
-							{"voucher_type": "Purchase Receipt", "voucher_no": self.return_against,
-							"item_code": d.item_code}, "incoming_rate")
+						filters = {
+							"voucher_type": self.doctype,
+							"voucher_no": self.return_against,
+							"item_code": d.item_code
+						}
+
+						if (self.doctype == "Purchase Invoice" and self.update_stock
+							and d.get("purchase_invoice_item")):
+							filters["voucher_detail_no"] = d.purchase_invoice_item
+						elif self.doctype == "Purchase Receipt" and d.get("purchase_receipt_item"):
+							filters["voucher_detail_no"] = d.purchase_receipt_item
+
+						original_incoming_rate = frappe.db.get_value("Stock Ledger Entry", filters, "incoming_rate")
 
 						sle.update({
 							"outgoing_rate": original_incoming_rate
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index 3f127a2..a03dee1 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -281,6 +281,8 @@
 			target_doc.rejected_warehouse = source_doc.rejected_warehouse
 			target_doc.po_detail = source_doc.po_detail
 			target_doc.pr_detail = source_doc.pr_detail
+			target_doc.purchase_invoice_item = source_doc.name
+
 		elif doctype == "Delivery Note":
 			target_doc.against_sales_order = source_doc.against_sales_order
 			target_doc.against_sales_invoice = source_doc.against_sales_invoice
@@ -296,6 +298,7 @@
 			target_doc.so_detail = source_doc.so_detail
 			target_doc.dn_detail = source_doc.dn_detail
 			target_doc.expense_account = source_doc.expense_account
+			target_doc.sales_invoice_item = source_doc.name
 			if default_warehouse_for_sales_return:
 				target_doc.warehouse = default_warehouse_for_sales_return
 
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index b696ac3..17f3ae5 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -217,7 +217,9 @@
 							'target_warehouse': p.target_warehouse,
 							'company': self.company,
 							'voucher_type': self.doctype,
-							'allow_zero_valuation': d.allow_zero_valuation_rate
+							'allow_zero_valuation': d.allow_zero_valuation_rate,
+							'sales_invoice_item': d.get("sales_invoice_item"),
+							'delivery_note_item': d.get("dn_detail")
 						}))
 			else:
 				il.append(frappe._dict({
@@ -233,7 +235,9 @@
 					'target_warehouse': d.target_warehouse,
 					'company': self.company,
 					'voucher_type': self.doctype,
-					'allow_zero_valuation': d.allow_zero_valuation_rate
+					'allow_zero_valuation': d.allow_zero_valuation_rate,
+					'sales_invoice_item': d.get("sales_invoice_item"),
+					'delivery_note_item': d.get("dn_detail")
 				}))
 		return il
 
@@ -302,7 +306,11 @@
 					d.conversion_factor = get_conversion_factor(d.item_code, d.uom).get("conversion_factor") or 1.0
 				return_rate = 0
 				if cint(self.is_return) and self.return_against and self.docstatus==1:
-					return_rate = self.get_incoming_rate_for_return(d.item_code, self.return_against)
+					against_document_no = (d.get("sales_invoice_item")
+						if self.doctype == "Sales Invoice" else d.get("delivery_note_item"))
+
+					return_rate = self.get_incoming_rate_for_return(d.item_code,
+						self.return_against, against_document_no)
 
 				# On cancellation or if return entry submission, make stock ledger entry for
 				# target warehouse first, to update serial no values properly
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index e8483da..394883d 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -301,14 +301,19 @@
 
 		return serialized_items
 
-	def get_incoming_rate_for_return(self, item_code, against_document):
+	def get_incoming_rate_for_return(self, item_code, against_document, against_document_no=None):
 		incoming_rate = 0.0
+		cond = ''
 		if against_document and item_code:
+			if against_document_no:
+				cond = " and voucher_detail_no = %s" %(frappe.db.escape(against_document_no))
+
 			incoming_rate = frappe.db.sql("""select abs(stock_value_difference / actual_qty)
 				from `tabStock Ledger Entry`
 				where voucher_type = %s and voucher_no = %s
-					and item_code = %s limit 1""",
+					and item_code = %s {0} limit 1""".format(cond),
 				(self.doctype, against_document, item_code))
+
 			incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
 
 		return incoming_rate