Merge pull request #33335 from ruthra-kumar/cost_center_issue_on_reconciliation_tool

fix: paid invoices shows up as outstanding when 'cost_center' filter is applied
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 0a704ac..4be4764 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1187,6 +1187,7 @@
 
 	ple = qb.DocType("Payment Ledger Entry")
 	common_filter = []
+	accounting_dimensions_filter = []
 	posting_and_due_date = []
 
 	# confirm that Supplier is not blocked
@@ -1216,7 +1217,7 @@
 	# Add cost center condition
 	if args.get("cost_center"):
 		condition += " and cost_center='%s'" % args.get("cost_center")
-		common_filter.append(ple.cost_center == args.get("cost_center"))
+		accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center"))
 
 	date_fields_dict = {
 		"posting_date": ["from_posting_date", "to_posting_date"],
@@ -1242,6 +1243,7 @@
 		posting_date=posting_and_due_date,
 		min_outstanding=args.get("outstanding_amt_greater_than"),
 		max_outstanding=args.get("outstanding_amt_less_than"),
+		accounting_dimensions=accounting_dimensions_filter,
 	)
 
 	outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices)
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index 52efd33..ff212f2 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -23,6 +23,7 @@
 	def __init__(self, *args, **kwargs):
 		super(PaymentReconciliation, self).__init__(*args, **kwargs)
 		self.common_filter_conditions = []
+		self.accounting_dimension_filter_conditions = []
 		self.ple_posting_date_filter = []
 
 	@frappe.whitelist()
@@ -193,6 +194,7 @@
 			posting_date=self.ple_posting_date_filter,
 			min_outstanding=self.minimum_invoice_amount if self.minimum_invoice_amount else None,
 			max_outstanding=self.maximum_invoice_amount if self.maximum_invoice_amount else None,
+			accounting_dimensions=self.accounting_dimension_filter_conditions,
 		)
 
 		if self.invoice_limit:
@@ -381,7 +383,7 @@
 		self.common_filter_conditions.append(ple.company == self.company)
 
 		if self.get("cost_center") and (get_invoices or get_return_invoices):
-			self.common_filter_conditions.append(ple.cost_center == self.cost_center)
+			self.accounting_dimension_filter_conditions.append(ple.cost_center == self.cost_center)
 
 		if get_invoices:
 			if self.from_invoice_date:
diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
index dae029b..6030134 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
@@ -8,6 +8,8 @@
 from frappe.tests.utils import FrappeTestCase
 from frappe.utils import add_days, nowdate
 
+from erpnext import get_default_cost_center
+from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
 from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
 from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
 from erpnext.accounts.party import get_party_account
@@ -20,6 +22,7 @@
 		self.create_item()
 		self.create_customer()
 		self.create_account()
+		self.create_cost_center()
 		self.clear_old_entries()
 
 	def tearDown(self):
@@ -216,6 +219,22 @@
 		)
 		return je
 
+	def create_cost_center(self):
+		# Setup cost center
+		cc_name = "Sub"
+
+		self.main_cc = frappe.get_doc("Cost Center", get_default_cost_center(self.company))
+
+		cc_exists = frappe.db.get_list("Cost Center", filters={"cost_center_name": cc_name})
+		if cc_exists:
+			self.sub_cc = frappe.get_doc("Cost Center", cc_exists[0].name)
+		else:
+			sub_cc = frappe.new_doc("Cost Center")
+			sub_cc.cost_center_name = "Sub"
+			sub_cc.parent_cost_center = self.main_cc.parent_cost_center
+			sub_cc.company = self.main_cc.company
+			self.sub_cc = sub_cc.save()
+
 	def test_filter_min_max(self):
 		# check filter condition minimum and maximum amount
 		self.create_sales_invoice(qty=1, rate=300)
@@ -578,3 +597,24 @@
 		self.assertEqual(len(pr.payments), 1)
 		self.assertEqual(pr.payments[0].amount, amount)
 		self.assertEqual(pr.payments[0].currency, "EUR")
+
+	def test_differing_cost_center_on_invoice_and_payment(self):
+		"""
+		Cost Center filter should not affect outstanding amount calculation
+		"""
+
+		si = self.create_sales_invoice(qty=1, rate=100, do_not_submit=True)
+		si.cost_center = self.main_cc.name
+		si.submit()
+		pr = get_payment_entry(si.doctype, si.name)
+		pr.cost_center = self.sub_cc.name
+		pr = pr.save().submit()
+
+		pr = self.create_payment_reconciliation()
+		pr.cost_center = self.main_cc.name
+
+		pr.get_unreconciled_entries()
+
+		# check PR tool output
+		self.assertEqual(len(pr.get("invoices")), 0)
+		self.assertEqual(len(pr.get("payments")), 0)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 41702d6..1e573b0 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -836,6 +836,7 @@
 	posting_date=None,
 	min_outstanding=None,
 	max_outstanding=None,
+	accounting_dimensions=None,
 ):
 
 	ple = qb.DocType("Payment Ledger Entry")
@@ -866,6 +867,7 @@
 		min_outstanding=min_outstanding,
 		max_outstanding=max_outstanding,
 		get_invoices=True,
+		accounting_dimensions=accounting_dimensions or [],
 	)
 
 	for d in invoice_list:
@@ -1615,6 +1617,7 @@
 			.where(ple.delinked == 0)
 			.where(Criterion.all(filter_on_voucher_no))
 			.where(Criterion.all(self.common_filter))
+			.where(Criterion.all(self.dimensions_filter))
 			.where(Criterion.all(self.voucher_posting_date))
 			.groupby(ple.voucher_type, ple.voucher_no, ple.party_type, ple.party)
 		)
@@ -1702,6 +1705,7 @@
 		max_outstanding=None,
 		get_payments=False,
 		get_invoices=False,
+		accounting_dimensions=None,
 	):
 		"""
 		Fetch voucher amount and outstanding amount from Payment Ledger using Database CTE
@@ -1717,6 +1721,7 @@
 		self.reset()
 		self.vouchers = vouchers
 		self.common_filter = common_filter or []
+		self.dimensions_filter = accounting_dimensions or []
 		self.voucher_posting_date = posting_date or []
 		self.min_outstanding = min_outstanding
 		self.max_outstanding = max_outstanding