fix: expense claim reimbursed amount update (#27204)

diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 937597b..7264875 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -643,7 +643,10 @@
 		for d in self.accounts:
 			if d.reference_type=="Expense Claim" and d.reference_name:
 				doc = frappe.get_doc("Expense Claim", d.reference_name)
-				update_reimbursed_amount(doc, jv=self.name)
+				if self.docstatus == 2:
+					update_reimbursed_amount(doc, -1 * d.debit)
+				else:
+					update_reimbursed_amount(doc, d.debit)
 
 
 	def validate_expense_claim(self):
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index b259b11..a5fcad4 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -75,9 +75,9 @@
 		if self.difference_amount:
 			frappe.throw(_("Difference Amount must be zero"))
 		self.make_gl_entries()
+		self.update_expense_claim()
 		self.update_outstanding_amounts()
 		self.update_advance_paid()
-		self.update_expense_claim()
 		self.update_donation()
 		self.update_payment_schedule()
 		self.set_status()
@@ -85,9 +85,9 @@
 	def on_cancel(self):
 		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 		self.make_gl_entries(cancel=1)
+		self.update_expense_claim()
 		self.update_outstanding_amounts()
 		self.update_advance_paid()
-		self.update_expense_claim()
 		self.update_donation(cancel=1)
 		self.delink_advance_entry_references()
 		self.update_payment_schedule(cancel=1)
@@ -831,7 +831,10 @@
 			for d in self.get("references"):
 				if d.reference_doctype=="Expense Claim" and d.reference_name:
 					doc = frappe.get_doc("Expense Claim", d.reference_name)
-					update_reimbursed_amount(doc, self.name)
+					if self.docstatus == 2:
+						update_reimbursed_amount(doc, -1 * d.allocated_amount)
+					else:
+						update_reimbursed_amount(doc, d.allocated_amount)
 
 	def update_donation(self, cancel=0):
 		if self.payment_type == "Receive" and self.party_type == "Donor" and self.party:
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index 95e2806..4dc089c 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -77,7 +77,7 @@
 		self.make_gl_entries()
 
 		if self.is_paid:
-			update_reimbursed_amount(self)
+			update_reimbursed_amount(self, self.grand_total)
 
 		self.set_status(update=True)
 		self.update_claimed_amount_in_employee_advance()
@@ -89,7 +89,7 @@
 			self.make_gl_entries(cancel=True)
 
 		if self.is_paid:
-			update_reimbursed_amount(self)
+			update_reimbursed_amount(self, -1 * self.grand_total)
 
 		self.update_claimed_amount_in_employee_advance()
 
@@ -270,20 +270,10 @@
 			if not expense.default_account or not validate:
 				expense.default_account = get_expense_claim_account(expense.expense_type, self.company)["account"]
 
-def update_reimbursed_amount(doc, jv=None):
+def update_reimbursed_amount(doc, amount):
 
-	condition = ""
-
-	if jv:
-		condition += "and voucher_no = '{0}'".format(jv)
-
-	amt = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) - ifnull(sum(credit_in_account_currency), 0)as amt
-		from `tabGL Entry` where against_voucher_type = 'Expense Claim' and against_voucher = %s
-		and party = %s {condition}""".format(condition=condition), #nosec
-		(doc.name, doc.employee) ,as_dict=1)[0].amt
-
-	doc.total_amount_reimbursed = amt
-	frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", amt)
+	doc.total_amount_reimbursed += amount
+	frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", doc.total_amount_reimbursed)
 
 	doc.set_status()
 	frappe.db.set_value("Expense Claim", doc.name , "status", doc.status)
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
index c2bd1e9..b5fc1fb 100644
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
@@ -4,7 +4,7 @@
 
 import frappe
 import unittest
-from frappe.utils import random_string, nowdate
+from frappe.utils import random_string, nowdate, flt
 from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry
 from erpnext.accounts.doctype.account.test_account import create_account
 from erpnext.hr.doctype.employee.test_employee import make_employee
@@ -138,6 +138,31 @@
 		expense_claim.submit()
 		frappe.set_user("Administrator")
 
+	def test_multiple_payment_entries_against_expense(self):
+		# Creating expense claim
+		payable_account = get_payable_account("_Test Company")
+		expense_claim = make_expense_claim(payable_account, 5500, 5500, "_Test Company", "Travel Expenses - _TC")
+		expense_claim.save()
+		expense_claim.submit()
+		
+		# Payment entry 1: paying 500
+		make_payment_entry(expense_claim, payable_account,500)
+		outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim)
+		self.assertEqual(outstanding_amount, 5000)
+		self.assertEqual(total_amount_reimbursed, 500)
+		
+		# Payment entry 1: paying 2000
+		make_payment_entry(expense_claim, payable_account,2000)
+		outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim)
+		self.assertEqual(outstanding_amount, 3000)
+		self.assertEqual(total_amount_reimbursed, 2500)
+		
+		# Payment entry 1: paying 3000		
+		make_payment_entry(expense_claim, payable_account,3000)
+		outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim)
+		self.assertEqual(outstanding_amount, 0)
+		self.assertEqual(total_amount_reimbursed, 5500)
+
 
 def get_payable_account(company):
 	return frappe.get_cached_value('Company', company, 'default_payable_account')
@@ -191,3 +216,23 @@
 		return expense_claim
 	expense_claim.submit()
 	return expense_claim
+
+def get_outstanding_and_total_reimbursed_amounts(expense_claim):
+	outstanding_amount = flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_sanctioned_amount")) - \
+			flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_amount_reimbursed"))
+	total_amount_reimbursed = flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_amount_reimbursed"))
+	
+	return outstanding_amount,total_amount_reimbursed
+
+def make_payment_entry(expense_claim, payable_account, amt):
+	from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+
+	pe = get_payment_entry("Expense Claim", expense_claim.name, bank_account="_Test Bank USD - _TC", bank_amount=amt)
+	pe.reference_no = "1"
+	pe.reference_date = nowdate()
+	pe.source_exchange_rate = 1
+	pe.paid_to = payable_account
+	pe.references[0].allocated_amount = amt
+	pe.insert()
+	pe.submit() 
+