refactor: dunning
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 98462b8..5cee711 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -56,19 +56,6 @@
 			frm.page.set_inner_btn_group_as_primary(__("Create"));
 		}
 
-		if (frm.doc.docstatus > 0) {
-			frm.add_custom_button(__("Ledger"), function () {
-				frappe.route_options = {
-					"voucher_no": frm.doc.name,
-					"from_date": frm.doc.posting_date,
-					"to_date": frm.doc.posting_date,
-					"company": frm.doc.company,
-					"show_cancelled_entries": frm.doc.docstatus === 2
-				};
-				frappe.set_route("query-report", "General Ledger");
-			}, __("View"));
-		}
-
 		if (frm.doc.docstatus === 0) {
 			frm.add_custom_button(__("Fetch Overdue Payments"), function () {
 				erpnext.utils.map_current_doc({
@@ -248,22 +235,29 @@
 	calculate_interest: function (frm) {
 		frm.doc.overdue_payments.forEach((row) => {
 			const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
-			const interest = flt((interest_per_day * row.outstanding * cint(row.overdue_days)) / 365 || 0, precision("interest"));
+			const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest"));
 			frappe.model.set_value(row.doctype, row.name, "interest", interest);
 		});
 	},
 	calculate_totals: function (frm) {
+		debugger;
 		const total_interest = frm.doc.overdue_payments
 			.reduce((prev, cur) => prev + cur.interest, 0);
 		const total_outstanding = frm.doc.overdue_payments
 			.reduce((prev, cur) => prev + cur.outstanding, 0);
-		const dunning_amount = flt(total_interest + frm.doc.dunning_fee, precision("dunning_amount"));
-		const grand_total = flt(total_outstanding + dunning_amount, precision("grand_total"));
+		const dunning_amount = total_interest + frm.doc.dunning_fee;
+		const base_dunning_amount = dunning_amount * frm.doc.conversion_rate;
+		const grand_total = total_outstanding + dunning_amount;
 
-		frm.set_value("total_outstanding", total_outstanding);
-		frm.set_value("total_interest", total_interest);
-		frm.set_value("dunning_amount", dunning_amount);
-		frm.set_value("grand_total", grand_total);
+		function setWithPrecison(field, value) {
+			frm.set_value(field, flt(value, precision(field)));
+		}
+
+		setWithPrecison("total_outstanding", total_outstanding);
+		setWithPrecison("total_interest", total_interest);
+		setWithPrecison("dunning_amount", dunning_amount);
+		setWithPrecison("base_dunning_amount", base_dunning_amount);
+		setWithPrecison("grand_total", grand_total);
 	},
 	make_payment_entry: function (frm) {
 		return frappe.call({
@@ -283,6 +277,7 @@
 
 frappe.ui.form.on("Overdue Payment", {
 	interest: function (frm, cdt, cdn) {
+		debugger;
 		frm.trigger("calculate_totals");
 	}
 });
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 5194090..ec116f3 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -1,24 +1,44 @@
 # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
 # For license information, please see license.txt
+"""
+# Accounting
 
+1. Payment of outstanding invoices with dunning amount
+
+		- Debit full amount to bank
+		- Credit invoiced amount to receivables
+		- Credit dunning amount to interest and similar revenue
+
+		-> Resolves dunning automatically
+"""
+from __future__ import unicode_literals
 
 import json
 
 import frappe
+
+from frappe import _
 from frappe.utils import getdate
 
-from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
 from erpnext.controllers.accounts_controller import AccountsController
 
 
 class Dunning(AccountsController):
 
 	def validate(self):
+		self.validate_same_currency()
 		self.validate_overdue_payments()
 		self.validate_totals()
+		self.set_dunning_level()
 
-		if not self.income_account:
-			self.income_account = frappe.db.get_value("Company", self.company, "default_income_account")
+	def validate_same_currency(self):
+		"""
+		Throw an error if invoice currency differs from dunning currency.
+		"""
+		for row in self.overdue_payments:
+			invoice_currency = frappe.get_value("Sales Invoice", row.sales_invoice, "currency")
+			if invoice_currency != self.currency:
+				frappe.throw(_("The currency of invoice {} ({}) is different from the currency of this dunning ({}).").format(row.sales_invoice, invoice_currency, self.currency))
 
 	def validate_overdue_payments(self):
 		daily_interest = self.rate_of_interest / 100 / 365
@@ -31,51 +51,25 @@
 		self.total_outstanding = sum(row.outstanding for row in self.overdue_payments)
 		self.total_interest = sum(row.interest for row in self.overdue_payments)
 		self.dunning_amount = self.total_interest + self.dunning_fee
+		self.base_dunning_amount = self.dunning_amount * self.conversion_rate
 		self.grand_total = self.total_outstanding + self.dunning_amount
 
-	def on_submit(self):
-		self.make_gl_entries()
-
-	def on_cancel(self):
-		if self.dunning_amount:
-			self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
-			make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
-
-	def make_gl_entries(self):
-		if not self.dunning_amount:
-			return
-
-		cost_center = self.cost_center or frappe.get_cached_value("Company",  self.company,  "cost_center")
-
-		make_gl_entries(
-			[
-				self.get_gl_dict({
-					"account": self.debit_to,
-					"party_type": "Customer",
-					"party": self.customer,
-					"due_date": self.due_date,
-					"against": self.income_account,
-					"debit": self.dunning_amount,
-					"debit_in_account_currency": self.dunning_amount,
-					"against_voucher": self.name,
-					"against_voucher_type": "Dunning",
-					"cost_center": cost_center
-				}),
-				self.get_gl_dict({
-					"account": self.income_account,
-					"against": self.customer,
-					"credit": self.dunning_amount,
-					"cost_center": cost_center,
-					"credit_in_account_currency": self.dunning_amount
-				})
-			],
-			cancel=(self.docstatus == 2),
-			update_outstanding="No",
-			merge_entries=False
-		)
+	def set_dunning_level(self):
+		for row in self.overdue_payments:
+			past_dunnings = frappe.get_all("Overdue Payment",
+				filters={
+					"payment_schedule": row.payment_schedule,
+					"parent": ("!=", row.parent),
+					"docstatus": 1
+				}
+			)
+			row.dunning_level = len(past_dunnings) + 1
 
 
 def resolve_dunning(doc, state):
+	"""
+	Todo: refactor
+	"""
 	for reference in doc.references:
 		if reference.reference_doctype == "Sales Invoice" and reference.outstanding_amount <= 0:
 			dunnings = frappe.get_list(
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index b6d3e5a..397e998 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1849,30 +1849,20 @@
 				pe.append("references", reference)
 		else:
 			if dt == "Dunning":
-				pe.append(
-					"references",
-					{
+				for overdue_payment in doc.overdue_payments:
+					pe.append("references", {
 						"reference_doctype": "Sales Invoice",
-						"reference_name": doc.get("sales_invoice"),
-						"bill_no": doc.get("bill_no"),
-						"due_date": doc.get("due_date"),
-						"total_amount": doc.get("outstanding_amount"),
-						"outstanding_amount": doc.get("outstanding_amount"),
-						"allocated_amount": doc.get("outstanding_amount"),
-					},
-				)
-				pe.append(
-					"references",
-					{
-						"reference_doctype": dt,
-						"reference_name": dn,
-						"bill_no": doc.get("bill_no"),
-						"due_date": doc.get("due_date"),
-						"total_amount": doc.get("dunning_amount"),
-						"outstanding_amount": doc.get("dunning_amount"),
-						"allocated_amount": doc.get("dunning_amount"),
-					},
-				)
+						"reference_name": overdue_payment.sales_invoice,
+						"payment_term": overdue_payment.payment_term,
+						"due_date": overdue_payment.due_date,
+						"total_amount": overdue_payment.outstanding,
+						"outstanding_amount": overdue_payment.outstanding,
+						"allocated_amount": overdue_payment.outstanding
+					})
+
+				pe.append("deductions", {
+					"amount": doc.dunning_amount
+				})
 			else:
 				pe.append(
 					"references",