fix: Payment against credit notes will be considered as payment against parent invoice in Accounts Receivable/Payable report (#35642)

* fix: payment against credit note should be linked to parent invoice

* test: AR/AP report for payment against cr note scenario

* fix: cr_note shows up as outstanding invoice

Payment made against cr_note causes it be reported as outstanding invoice
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index cc2b942..081fe70 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -6,7 +6,6 @@
 from frappe import _, msgprint, qb
 from frappe.model.document import Document
 from frappe.query_builder.custom import ConstantColumn
-from frappe.query_builder.functions import IfNull
 from frappe.utils import flt, get_link_to_form, getdate, nowdate, today
 
 import erpnext
@@ -127,12 +126,29 @@
 
 		return list(journal_entries)
 
+	def get_return_invoices(self):
+		voucher_type = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice"
+		doc = qb.DocType(voucher_type)
+		self.return_invoices = (
+			qb.from_(doc)
+			.select(
+				ConstantColumn(voucher_type).as_("voucher_type"),
+				doc.name.as_("voucher_no"),
+				doc.return_against,
+			)
+			.where(
+				(doc.docstatus == 1)
+				& (doc[frappe.scrub(self.party_type)] == self.party)
+				& (doc.is_return == 1)
+			)
+			.run(as_dict=True)
+		)
+
 	def get_dr_or_cr_notes(self):
 
 		self.build_qb_filter_conditions(get_return_invoices=True)
 
 		ple = qb.DocType("Payment Ledger Entry")
-		voucher_type = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice"
 
 		if erpnext.get_party_account_type(self.party_type) == "Receivable":
 			self.common_filter_conditions.append(ple.account_type == "Receivable")
@@ -140,19 +156,10 @@
 			self.common_filter_conditions.append(ple.account_type == "Payable")
 		self.common_filter_conditions.append(ple.account == self.receivable_payable_account)
 
-		# get return invoices
-		doc = qb.DocType(voucher_type)
-		return_invoices = (
-			qb.from_(doc)
-			.select(ConstantColumn(voucher_type).as_("voucher_type"), doc.name.as_("voucher_no"))
-			.where(
-				(doc.docstatus == 1)
-				& (doc[frappe.scrub(self.party_type)] == self.party)
-				& (doc.is_return == 1)
-				& (IfNull(doc.return_against, "") == "")
-			)
-			.run(as_dict=True)
-		)
+		self.get_return_invoices()
+		return_invoices = [
+			x for x in self.return_invoices if x.return_against == None or x.return_against == ""
+		]
 
 		outstanding_dr_or_cr = []
 		if return_invoices:
@@ -204,6 +211,9 @@
 			accounting_dimensions=self.accounting_dimension_filter_conditions,
 		)
 
+		cr_dr_notes = [x.voucher_no for x in self.return_invoices]
+		non_reconciled_invoices = [x for x in non_reconciled_invoices if x.voucher_no not in cr_dr_notes]
+
 		if self.invoice_limit:
 			non_reconciled_invoices = non_reconciled_invoices[: self.invoice_limit]
 
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 11de9a0..30f7fb3 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -181,6 +181,16 @@
 				return
 
 		key = (ple.against_voucher_type, ple.against_voucher_no, ple.party)
+
+		# If payment is made against credit note
+		# and credit note is made against a Sales Invoice
+		# then consider the payment against original sales invoice.
+		if ple.against_voucher_type in ("Sales Invoice", "Purchase Invoice"):
+			if ple.against_voucher_no in self.return_entries:
+				return_against = self.return_entries.get(ple.against_voucher_no)
+				if return_against:
+					key = (ple.against_voucher_type, return_against, ple.party)
+
 		row = self.voucher_balance.get(key)
 
 		if not row:
@@ -610,7 +620,7 @@
 
 	def get_return_entries(self):
 		doctype = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice"
-		filters = {"is_return": 1, "docstatus": 1}
+		filters = {"is_return": 1, "docstatus": 1, "company": self.filters.company}
 		party_field = scrub(self.filters.party_type)
 		if self.filters.get(party_field):
 			filters.update({party_field: self.filters.get(party_field)})
diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
index afd02a0..6f1889b 100644
--- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
@@ -210,6 +210,67 @@
 			],
 		)
 
+	def test_payment_against_credit_note(self):
+		"""
+		Payment against credit/debit note should be considered against the parent invoice
+		"""
+		company = "_Test Company 2"
+		customer = "_Test Customer 2"
+
+		si1 = make_sales_invoice()
+
+		pe = get_payment_entry("Sales Invoice", si1.name, bank_account="Cash - _TC2")
+		pe.paid_from = "Debtors - _TC2"
+		pe.insert()
+		pe.submit()
+
+		cr_note = make_credit_note(si1.name)
+
+		si2 = make_sales_invoice()
+
+		# manually link cr_note with si2 using journal entry
+		je = frappe.new_doc("Journal Entry")
+		je.company = company
+		je.voucher_type = "Credit Note"
+		je.posting_date = today()
+
+		debit_account = "Debtors - _TC2"
+		debit_entry = {
+			"account": debit_account,
+			"party_type": "Customer",
+			"party": customer,
+			"debit": 100,
+			"debit_in_account_currency": 100,
+			"reference_type": cr_note.doctype,
+			"reference_name": cr_note.name,
+			"cost_center": "Main - _TC2",
+		}
+		credit_entry = {
+			"account": debit_account,
+			"party_type": "Customer",
+			"party": customer,
+			"credit": 100,
+			"credit_in_account_currency": 100,
+			"reference_type": si2.doctype,
+			"reference_name": si2.name,
+			"cost_center": "Main - _TC2",
+		}
+
+		je.append("accounts", debit_entry)
+		je.append("accounts", credit_entry)
+		je = je.save().submit()
+
+		filters = {
+			"company": company,
+			"report_date": today(),
+			"range1": 30,
+			"range2": 60,
+			"range3": 90,
+			"range4": 120,
+		}
+		report = execute(filters)
+		self.assertEqual(report[1], [])
+
 
 def make_sales_invoice(no_payment_schedule=False, do_not_submit=False):
 	frappe.set_user("Administrator")
@@ -256,7 +317,7 @@
 
 
 def make_credit_note(docname):
-	create_sales_invoice(
+	credit_note = create_sales_invoice(
 		company="_Test Company 2",
 		customer="_Test Customer 2",
 		currency="EUR",
@@ -269,3 +330,5 @@
 		is_return=1,
 		return_against=docname,
 	)
+
+	return credit_note