test: multi currency invoice unreconciliation

exchange gain/loss associated with the unreconcile invoice should be
cancelled as well
diff --git a/erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py b/erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py
index 3d7c6cb..78e04bf 100644
--- a/erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py
+++ b/erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py
@@ -14,13 +14,14 @@
 	def setUp(self):
 		self.create_company()
 		self.create_customer()
+		self.create_usd_receivable_account()
 		self.create_item()
 		self.clear_old_entries()
 
 	def tearDown(self):
 		frappe.db.rollback()
 
-	def create_sales_invoice(self):
+	def create_sales_invoice(self, do_not_submit=False):
 		si = create_sales_invoice(
 			item=self.item,
 			company=self.company,
@@ -31,6 +32,7 @@
 			cost_center=self.cost_center,
 			rate=100,
 			price_list_rate=100,
+			do_not_submit=do_not_submit,
 		)
 		return si
 
@@ -160,3 +162,155 @@
 		self.assertEqual(len(pe2.references), 1)
 		self.assertEqual(pe1.unallocated_amount, 0)
 		self.assertEqual(pe2.unallocated_amount, 50)
+
+	def test_03_unreconciliation_on_multi_currency_invoice(self):
+		self.create_customer("_Test MC Customer USD", "USD")
+		si1 = self.create_sales_invoice(do_not_submit=True)
+		si1.currency = "USD"
+		si1.debit_to = self.debtors_usd
+		si1.conversion_rate = 80
+		si1.save().submit()
+
+		si2 = self.create_sales_invoice(do_not_submit=True)
+		si2.currency = "USD"
+		si2.debit_to = self.debtors_usd
+		si2.conversion_rate = 80
+		si2.save().submit()
+
+		pe = self.create_payment_entry()
+		pe.paid_from = self.debtors_usd
+		pe.paid_from_account_currency = "USD"
+		pe.source_exchange_rate = 75
+		pe.received_amount = 75 * 200
+		pe.save()
+		# Allocate payment against both invoices
+		pe.append(
+			"references",
+			{"reference_doctype": si1.doctype, "reference_name": si1.name, "allocated_amount": 100},
+		)
+		pe.append(
+			"references",
+			{"reference_doctype": si2.doctype, "reference_name": si2.name, "allocated_amount": 100},
+		)
+		pe.save().submit()
+
+		unreconcile = frappe.get_doc(
+			{
+				"doctype": "Unreconcile Payments",
+				"company": self.company,
+				"voucher_type": pe.doctype,
+				"voucher_no": pe.name,
+			}
+		)
+		unreconcile.add_references()
+		self.assertEqual(len(unreconcile.allocations), 2)
+		allocations = [x.reference_name for x in unreconcile.allocations]
+		self.assertEquals([si1.name, si2.name], allocations)
+		# unreconcile si1 from pe
+		for x in unreconcile.allocations:
+			if x.reference_name != si1.name:
+				unreconcile.remove(x)
+		unreconcile.save().submit()
+
+		# Assert outstanding and unallocated
+		[doc.reload() for doc in [si1, si2, pe]]
+		self.assertEqual(si1.outstanding_amount, 100)
+		self.assertEqual(si2.outstanding_amount, 0)
+		self.assertEqual(len(pe.references), 1)
+		self.assertEqual(pe.unallocated_amount, 100)
+
+		# Exc gain/loss JE should've been cancelled as well
+		self.assertEqual(
+			frappe.db.count(
+				"Journal Entry Account",
+				filters={"reference_type": si1.doctype, "reference_name": si1.name, "docstatus": 1},
+			),
+			0,
+		)
+
+	def test_04_unreconciliation_on_multi_currency_invoice(self):
+		"""
+		2 payments split against 2 foreign currency invoices
+		"""
+		self.create_customer("_Test MC Customer USD", "USD")
+		si1 = self.create_sales_invoice(do_not_submit=True)
+		si1.currency = "USD"
+		si1.debit_to = self.debtors_usd
+		si1.conversion_rate = 80
+		si1.save().submit()
+
+		si2 = self.create_sales_invoice(do_not_submit=True)
+		si2.currency = "USD"
+		si2.debit_to = self.debtors_usd
+		si2.conversion_rate = 80
+		si2.save().submit()
+
+		pe1 = self.create_payment_entry()
+		pe1.paid_from = self.debtors_usd
+		pe1.paid_from_account_currency = "USD"
+		pe1.source_exchange_rate = 75
+		pe1.received_amount = 75 * 100
+		pe1.save()
+		# Allocate payment against both invoices
+		pe1.append(
+			"references",
+			{"reference_doctype": si1.doctype, "reference_name": si1.name, "allocated_amount": 50},
+		)
+		pe1.append(
+			"references",
+			{"reference_doctype": si2.doctype, "reference_name": si2.name, "allocated_amount": 50},
+		)
+		pe1.save().submit()
+
+		pe2 = self.create_payment_entry()
+		pe2.paid_from = self.debtors_usd
+		pe2.paid_from_account_currency = "USD"
+		pe2.source_exchange_rate = 75
+		pe2.received_amount = 75 * 100
+		pe2.save()
+		# Allocate payment against both invoices
+		pe2.append(
+			"references",
+			{"reference_doctype": si1.doctype, "reference_name": si1.name, "allocated_amount": 50},
+		)
+		pe2.append(
+			"references",
+			{"reference_doctype": si2.doctype, "reference_name": si2.name, "allocated_amount": 50},
+		)
+		pe2.save().submit()
+
+		unreconcile = frappe.get_doc(
+			{
+				"doctype": "Unreconcile Payments",
+				"company": self.company,
+				"voucher_type": pe2.doctype,
+				"voucher_no": pe2.name,
+			}
+		)
+		unreconcile.add_references()
+		self.assertEqual(len(unreconcile.allocations), 2)
+		allocations = [x.reference_name for x in unreconcile.allocations]
+		self.assertEquals([si1.name, si2.name], allocations)
+		# unreconcile si1 from pe2
+		for x in unreconcile.allocations:
+			if x.reference_name != si1.name:
+				unreconcile.remove(x)
+		unreconcile.save().submit()
+
+		# Assert outstanding and unallocated
+		[doc.reload() for doc in [si1, si2, pe1, pe2]]
+		self.assertEqual(si1.outstanding_amount, 50)
+		self.assertEqual(si2.outstanding_amount, 0)
+		self.assertEqual(len(pe1.references), 2)
+		self.assertEqual(len(pe2.references), 1)
+		self.assertEqual(pe1.unallocated_amount, 0)
+		self.assertEqual(pe2.unallocated_amount, 50)
+
+		# Exc gain/loss JE from PE1 should be available
+		self.assertEqual(
+			frappe.db.count(
+				"Journal Entry Account",
+				filters={"reference_type": si1.doctype, "reference_name": si1.name, "docstatus": 1},
+			),
+			1,
+		)