Merge pull request #40812 from deepeshgarg007/multi_pr_pi

fix: Multiple partial payment requests against Purchase Invoice
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index c4a99c0..41ed66c 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -92,7 +92,7 @@
 			self.status = "Draft"
 		self.validate_reference_document()
 		self.validate_payment_request_amount()
-		self.validate_currency()
+		# self.validate_currency()
 		self.validate_subscription_details()
 
 	def validate_reference_document(self):
@@ -335,21 +335,17 @@
 			}
 		)
 
+		if party_account_currency == ref_doc.company_currency and party_account_currency != self.currency:
+			amount = payment_entry.base_paid_amount
+		else:
+			amount = self.grand_total
+
+		payment_entry.received_amount = amount
+		payment_entry.get("references")[0].allocated_amount = amount
+
 		for dimension in get_accounting_dimensions():
 			payment_entry.update({dimension: self.get(dimension)})
 
-		if payment_entry.difference_amount:
-			company_details = get_company_defaults(ref_doc.company)
-
-			payment_entry.append(
-				"deductions",
-				{
-					"account": company_details.exchange_gain_loss_account,
-					"cost_center": company_details.cost_center,
-					"amount": payment_entry.difference_amount,
-				},
-			)
-
 		if submit:
 			payment_entry.insert(ignore_permissions=True)
 			payment_entry.submit()
@@ -479,6 +475,12 @@
 		pr = frappe.get_doc("Payment Request", draft_payment_request)
 	else:
 		pr = frappe.new_doc("Payment Request")
+
+		if not args.get("payment_request_type"):
+			args["payment_request_type"] = (
+				"Outward" if args.get("dt") in ["Purchase Order", "Purchase Invoice"] else "Inward"
+			)
+
 		pr.update(
 			{
 				"payment_gateway_account": gateway_account.get("name"),
@@ -538,9 +540,9 @@
 	elif dt in ["Sales Invoice", "Purchase Invoice"]:
 		if not ref_doc.get("is_pos"):
 			if ref_doc.party_account_currency == ref_doc.currency:
-				grand_total = flt(ref_doc.outstanding_amount)
+				grand_total = flt(ref_doc.grand_total)
 			else:
-				grand_total = flt(ref_doc.outstanding_amount) / ref_doc.conversion_rate
+				grand_total = flt(ref_doc.base_grand_total) / ref_doc.conversion_rate
 		elif dt == "Sales Invoice":
 			for pay in ref_doc.payments:
 				if pay.type == "Phone" and pay.account == payment_account:
diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py
index 70de886..9320608 100644
--- a/erpnext/accounts/doctype/payment_request/test_payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py
@@ -86,6 +86,8 @@
 		pr = make_payment_request(
 			dt="Purchase Invoice",
 			dn=si_usd.name,
+			party_type="Supplier",
+			party="_Test Supplier USD",
 			recipient_id="user@example.com",
 			mute_email=1,
 			payment_gateway_account="_Test Gateway - USD",
@@ -98,6 +100,51 @@
 
 		self.assertEqual(pr.status, "Paid")
 
+	def test_multiple_payment_entry_against_purchase_invoice(self):
+		purchase_invoice = make_purchase_invoice(
+			customer="_Test Supplier USD",
+			debit_to="_Test Payable USD - _TC",
+			currency="USD",
+			conversion_rate=50,
+		)
+
+		pr = make_payment_request(
+			dt="Purchase Invoice",
+			party_type="Supplier",
+			party="_Test Supplier USD",
+			dn=purchase_invoice.name,
+			recipient_id="user@example.com",
+			mute_email=1,
+			payment_gateway_account="_Test Gateway - USD",
+			return_doc=1,
+		)
+
+		pr.grand_total = pr.grand_total / 2
+
+		pr.submit()
+		pr.create_payment_entry()
+
+		purchase_invoice.load_from_db()
+		self.assertEqual(purchase_invoice.status, "Partly Paid")
+
+		pr = make_payment_request(
+			dt="Purchase Invoice",
+			party_type="Supplier",
+			party="_Test Supplier USD",
+			dn=purchase_invoice.name,
+			recipient_id="user@example.com",
+			mute_email=1,
+			payment_gateway_account="_Test Gateway - USD",
+			return_doc=1,
+		)
+
+		pr.save()
+		pr.submit()
+		pr.create_payment_entry()
+
+		purchase_invoice.load_from_db()
+		self.assertEqual(purchase_invoice.status, "Paid")
+
 	def test_payment_entry(self):
 		frappe.db.set_value(
 			"Company", "_Test Company", "exchange_gain_loss_account", "_Test Exchange Gain/Loss - _TC"