Merge pull request #24035 from nextchamp-saqib/abs-value-in-pf

fix: get formatted value in 'taxes' print template
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..24f122a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# Root editor config file
+root = true
+
+# Common settings
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+
+# python, js indentation settings
+[{*.py,*.js}]
+indent_style = tab
+indent_size = 4
diff --git a/.travis/site_config.json b/.travis/site_config.json
index dae8009..572bbd0 100644
--- a/.travis/site_config.json
+++ b/.travis/site_config.json
@@ -9,5 +9,6 @@
  "root_login": "root",
  "root_password": "travis",
  "host_name": "http://test_site:8000",
- "install_apps": ["erpnext"]
+ "install_apps": ["erpnext"],
+ "throttle_user_limit": 100
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
index 6c83e3b..acb11e5 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
@@ -245,6 +245,9 @@
                     "account_number": "2200"
                 },
                 _("Duties and Taxes"): {
+                    _("TDS Payable"): {
+                        "account_number": "2310"
+                    },
                     "account_type": "Tax",
                     "is_group": 1,
                     "account_number": "2300"
diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
index 2754633..e9fc5f0 100644
--- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
@@ -9,11 +9,13 @@
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
 from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
 from erpnext.accounts.page.bank_reconciliation.bank_reconciliation import reconcile, get_linked_payments
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
 
 test_dependencies = ["Item", "Cost Center"]
 
 class TestBankTransaction(unittest.TestCase):
 	def setUp(self):
+		make_pos_profile()
 		add_transactions()
 		add_payments()
 
@@ -27,6 +29,9 @@
 		frappe.db.sql("""delete from `tabPayment Entry Reference`""")
 		frappe.db.sql("""delete from `tabPayment Entry`""")
 
+		# Delete POS Profile
+		frappe.db.sql("delete from `tabPOS Profile`")
+
 		frappe.flags.test_bank_transactions_created = False
 		frappe.flags.test_payments_created = False
 
diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.js b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.js
index d3040c8..7a06d35 100644
--- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.js
+++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.js
@@ -1,13 +1,17 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-cur_frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
-	var d = locals[cdt][cdn];
-	return{
-		filters: [
-			['Account', 'account_type', 'in', 'Bank, Cash, Receivable'],
-			['Account', 'is_group', '=', 0],
-			['Account', 'company', '=', d.company]
-		]
-	}
-});
+frappe.ui.form.on('Mode of Payment', {
+	setup: function(frm) {
+		frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
+			let d = locals[cdt][cdn];
+			return {
+				filters: [
+					['Account', 'account_type', 'in', 'Bank, Cash, Receivable'],
+					['Account', 'is_group', '=', 0],
+					['Account', 'company', '=', d.company]
+				]
+			};
+		});
+	},
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index d51856a..ee2092a 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -155,7 +155,8 @@
 			"posting_date": row.posting_date,
 			frappe.scrub(row.party_type): row.party,
 			"is_pos": 0,
-			"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice"
+			"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
+			"update_stock": 0
 		})
 
 		accounting_dimension = get_accounting_dimensions()
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
index 54229f5..bdfe532 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
@@ -7,17 +7,24 @@
 import unittest
 
 test_dependencies = ["Customer", "Supplier"]
+from frappe.custom.doctype.property_setter.property_setter import make_property_setter
 from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import get_temporary_opening_account
 
 class TestOpeningInvoiceCreationTool(unittest.TestCase):
-	def make_invoices(self, invoice_type="Sales"):
+	def setUp(self):
+		if not frappe.db.exists("Company", "_Test Opening Invoice Company"):
+			make_company()
+
+	def make_invoices(self, invoice_type="Sales", company=None, party_1=None, party_2=None):
 		doc = frappe.get_single("Opening Invoice Creation Tool")
-		args = get_opening_invoice_creation_dict(invoice_type=invoice_type)
+		args = get_opening_invoice_creation_dict(invoice_type=invoice_type, company=company,
+			party_1=party_1, party_2=party_2)
 		doc.update(args)
 		return doc.make_invoices()
 
 	def test_opening_sales_invoice_creation(self):
-		invoices = self.make_invoices()
+		property_setter = make_property_setter("Sales Invoice", "update_stock", "default", 1, "Check")
+		invoices = self.make_invoices(company="_Test Opening Invoice Company")
 
 		self.assertEqual(len(invoices), 2)
 		expected_value = {
@@ -27,6 +34,13 @@
 		}
 		self.check_expected_values(invoices, expected_value)
 
+		si = frappe.get_doc("Sales Invoice", invoices[0])
+
+		# Check if update stock is not enabled
+		self.assertEqual(si.update_stock, 0)
+
+		property_setter.delete()
+
 	def check_expected_values(self, invoices, expected_value, invoice_type="Sales"):
 		doctype = "Sales Invoice" if invoice_type == "Sales" else "Purchase Invoice"
 
@@ -36,7 +50,7 @@
 				self.assertEqual(si.get(field, ""), expected_value[invoice_idx][field_idx])
 
 	def test_opening_purchase_invoice_creation(self):
-		invoices = self.make_invoices(invoice_type="Purchase")
+		invoices = self.make_invoices(invoice_type="Purchase", company="_Test Opening Invoice Company")
 
 		self.assertEqual(len(invoices), 2)
 		expected_value = {
@@ -46,6 +60,32 @@
 		}
 		self.check_expected_values(invoices, expected_value, "Purchase")
 
+	def test_opening_sales_invoice_creation_with_missing_debit_account(self):
+		company = "_Test Opening Invoice Company"
+		party_1, party_2 = make_customer("Customer A"), make_customer("Customer B")
+
+		old_default_receivable_account = frappe.db.get_value("Company", company, "default_receivable_account")
+		frappe.db.set_value("Company", company, "default_receivable_account", "")
+
+		if not frappe.db.exists("Cost Center", "_Test Opening Invoice Company - _TOIC"):
+			cc = frappe.get_doc({"doctype": "Cost Center", "cost_center_name": "_Test Opening Invoice Company",
+				"is_group": 1, "company": "_Test Opening Invoice Company"})
+			cc.insert(ignore_mandatory=True)
+			cc2 = frappe.get_doc({"doctype": "Cost Center", "cost_center_name": "Main", "is_group": 0,
+				"company": "_Test Opening Invoice Company", "parent_cost_center": cc.name})
+			cc2.insert()
+
+		frappe.db.set_value("Company", company, "cost_center", "Main - _TOIC")
+
+		self.make_invoices(company="_Test Opening Invoice Company", party_1=party_1, party_2=party_2)
+
+		# Check if missing debit account error raised
+		error_log = frappe.db.exists("Error Log", {"error": ["like", "%erpnext.controllers.accounts_controller.AccountMissingError%"]})
+		self.assertTrue(error_log)
+
+		# teardown
+		frappe.db.set_value("Company", company, "default_receivable_account", old_default_receivable_account)
+
 def get_opening_invoice_creation_dict(**args):
 	party = "Customer" if args.get("invoice_type", "Sales") == "Sales" else "Supplier"
 	company = args.get("company", "_Test Company")
@@ -57,7 +97,7 @@
 			{
 				"qty": 1.0,
 				"outstanding_amount": 300,
-				"party": "_Test {0}".format(party),
+				"party": args.get("party_1") or "_Test {0}".format(party),
 				"item_name": "Opening Item",
 				"due_date": "2016-09-10",
 				"posting_date": "2016-09-05",
@@ -66,7 +106,7 @@
 			{
 				"qty": 2.0,
 				"outstanding_amount": 250,
-				"party": "_Test {0} 1".format(party),
+				"party": args.get("party_2") or "_Test {0} 1".format(party),
 				"item_name": "Opening Item",
 				"due_date": "2016-09-10",
 				"posting_date": "2016-09-05",
@@ -76,4 +116,31 @@
 	})
 
 	invoice_dict.update(args)
-	return invoice_dict
\ No newline at end of file
+	return invoice_dict
+
+def make_company():
+	if frappe.db.exists("Company", "_Test Opening Invoice Company"):
+		return frappe.get_doc("Company", "_Test Opening Invoice Company")
+
+	company = frappe.new_doc("Company")
+	company.company_name = "_Test Opening Invoice Company"
+	company.abbr = "_TOIC"
+	company.default_currency = "INR"
+	company.country = "India"
+	company.insert()
+	return company
+
+def make_customer(customer=None):
+	customer_name = customer or "Opening Customer"
+	customer = frappe.get_doc({
+		"doctype": "Customer",
+		"customer_name": customer_name,
+		"customer_group": "All Customer Groups",
+		"customer_type": "Company",
+		"territory": "All Territories"
+	})
+	if not frappe.db.exists("Customer", customer_name):
+		customer.insert(ignore_permissions=True)
+		return customer.name
+	else:
+		return frappe.db.exists("Customer", customer_name)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 11ab020..31a4c8a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -202,17 +202,32 @@
 		# if account_type not in account_types:
 		# 	frappe.throw(_("Account Type for {0} must be {1}").format(account, comma_or(account_types)))
 
-	def set_exchange_rate(self):
+	def set_exchange_rate(self, ref_doc=None):
+		self.set_source_exchange_rate(ref_doc)
+		self.set_target_exchange_rate(ref_doc)
+
+	def set_source_exchange_rate(self, ref_doc=None):
 		if self.paid_from and not self.source_exchange_rate:
 			if self.paid_from_account_currency == self.company_currency:
 				self.source_exchange_rate = 1
 			else:
-				self.source_exchange_rate = get_exchange_rate(self.paid_from_account_currency,
-					self.company_currency, self.posting_date)
+				if ref_doc:
+					if self.paid_from_account_currency == ref_doc.currency:
+						self.source_exchange_rate = ref_doc.get("exchange_rate")
 
+			if not self.source_exchange_rate:
+					self.source_exchange_rate = get_exchange_rate(self.paid_from_account_currency,
+						self.company_currency, self.posting_date)
+
+	def set_target_exchange_rate(self, ref_doc=None):
 		if self.paid_to and not self.target_exchange_rate:
-			self.target_exchange_rate = get_exchange_rate(self.paid_to_account_currency,
-				self.company_currency, self.posting_date)
+			if ref_doc:
+				if self.paid_to_account_currency == ref_doc.currency:
+					self.target_exchange_rate = ref_doc.get("exchange_rate")
+
+			if not self.target_exchange_rate:
+				self.target_exchange_rate = get_exchange_rate(self.paid_to_account_currency,
+					self.company_currency, self.posting_date)
 
 	def validate_mandatory(self):
 		for field in ("paid_amount", "received_amount", "source_exchange_rate", "target_exchange_rate"):
@@ -282,9 +297,10 @@
 					no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)
 
 		for k, v in no_oustanding_refs.items():
-			frappe.msgprint(_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.<br><br>\
-					If this is undesirable please cancel the corresponding Payment Entry.")
-				.format(k, frappe.bold(", ".join([d.reference_name for d in v])), frappe.bold("negative outstanding amount")),
+			frappe.msgprint(
+				_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.")
+					.format(k, frappe.bold(", ".join([d.reference_name for d in v])), frappe.bold("negative outstanding amount"))
+				+ "<br><br>" + _("If this is undesirable please cancel the corresponding Payment Entry."),
 				title=_("Warning"), indicator="orange")
 
 
@@ -909,22 +925,24 @@
 			exchange_rate = 1
 			outstanding_amount = get_outstanding_on_journal_entry(reference_name)
 	elif reference_doctype != "Journal Entry":
-		if party_account_currency == company_currency:
-			if ref_doc.doctype == "Expense Claim":
+		if ref_doc.doctype == "Expense Claim":
 				total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges)
-			elif ref_doc.doctype == "Employee Advance":
-				total_amount = ref_doc.advance_amount
-			else:
+		elif ref_doc.doctype == "Employee Advance":
+			total_amount = ref_doc.advance_amount
+			exchange_rate = ref_doc.get("exchange_rate")
+			if party_account_currency != ref_doc.currency:
+				total_amount = flt(total_amount) * flt(exchange_rate)
+		if not total_amount:
+			if party_account_currency == company_currency:
 				total_amount = ref_doc.base_grand_total
-			exchange_rate = 1
-		else:
-			total_amount = ref_doc.grand_total
-
+				exchange_rate = 1
+			else:
+				total_amount = ref_doc.grand_total
+		if not exchange_rate:
 			# Get the exchange rate from the original ref doc
-			# or get it based on the posting date of the ref doc
+			# or get it based on the posting date of the ref doc.
 			exchange_rate = ref_doc.get("conversion_rate") or \
 				get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)
-
 		if reference_doctype in ("Sales Invoice", "Purchase Invoice"):
 			outstanding_amount = ref_doc.get("outstanding_amount")
 			bill_no = ref_doc.get("bill_no")
@@ -932,11 +950,15 @@
 			outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) + flt(ref_doc.get("total_taxes_and_charges"))\
 				- flt(ref_doc.get("total_amount_reimbursed")) - flt(ref_doc.get("total_advance_amount"))
 		elif reference_doctype == "Employee Advance":
-			outstanding_amount = ref_doc.advance_amount - flt(ref_doc.paid_amount)
+			outstanding_amount = (flt(ref_doc.advance_amount) - flt(ref_doc.paid_amount))
+			if party_account_currency != ref_doc.currency:
+				outstanding_amount = flt(outstanding_amount) * flt(exchange_rate)
+				if party_account_currency == company_currency:
+					exchange_rate = 1
 		else:
 			outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid)
 	else:
-		# Get the exchange rate based on the posting date of the ref doc
+		# Get the exchange rate based on the posting date of the ref doc.
 		exchange_rate = get_exchange_rate(party_account_currency,
 			company_currency, ref_doc.posting_date)
 
@@ -948,102 +970,104 @@
 		"bill_no": bill_no
 	})
 
+def get_amounts_based_on_reference_doctype(reference_doctype, ref_doc, party_account_currency, company_currency, reference_name):
+	total_amount, outstanding_amount, exchange_rate = None
+	if reference_doctype == "Fees":
+		total_amount = ref_doc.get("grand_total")
+		exchange_rate = 1
+		outstanding_amount = ref_doc.get("outstanding_amount")
+	elif reference_doctype == "Dunning":
+		total_amount = ref_doc.get("dunning_amount")
+		exchange_rate = 1
+		outstanding_amount = ref_doc.get("dunning_amount")
+	elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1:
+		total_amount = ref_doc.get("total_amount")
+		if ref_doc.multi_currency:
+			exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)
+		else:
+			exchange_rate = 1
+			outstanding_amount = get_outstanding_on_journal_entry(reference_name)
+
+	return total_amount, outstanding_amount, exchange_rate
+
+def get_amounts_based_on_ref_doc(reference_doctype, ref_doc, party_account_currency, company_currency):
+	total_amount, outstanding_amount, exchange_rate = None
+	if ref_doc.doctype == "Expense Claim":
+			total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges)
+	elif ref_doc.doctype == "Employee Advance":
+		total_amount, exchange_rate = get_total_amount_exchange_rate_for_employee_advance(party_account_currency, ref_doc)
+		
+	if not total_amount:
+		total_amount, exchange_rate = get_total_amount_exchange_rate_base_on_currency(
+			party_account_currency, company_currency, ref_doc)
+
+	if not exchange_rate:
+		# Get the exchange rate from the original ref doc
+		# or get it based on the posting date of the ref doc
+		exchange_rate = ref_doc.get("conversion_rate") or \
+			get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)
+
+	outstanding_amount, exchange_rate, bill_no = get_bill_no_and_update_amounts(
+		reference_doctype, ref_doc, total_amount, exchange_rate, party_account_currency, company_currency)
+
+	return total_amount, outstanding_amount, exchange_rate, bill_no
+
+def get_total_amount_exchange_rate_for_employee_advance(party_account_currency, ref_doc):
+	total_amount = ref_doc.advance_amount
+	exchange_rate = ref_doc.get("exchange_rate")
+	if party_account_currency != ref_doc.currency:
+		total_amount = flt(total_amount) * flt(exchange_rate)
+
+	return total_amount, exchange_rate
+
+def get_total_amount_exchange_rate_base_on_currency(party_account_currency, company_currency, ref_doc):
+	exchange_rate = None
+	if party_account_currency == company_currency:
+		total_amount = ref_doc.base_grand_total
+		exchange_rate = 1
+	else:
+		total_amount = ref_doc.grand_total
+
+	return total_amount, exchange_rate
+
+def get_bill_no_and_update_amounts(reference_doctype, ref_doc, total_amount, exchange_rate, party_account_currency, company_currency):
+	outstanding_amount, bill_no = None
+	if reference_doctype in ("Sales Invoice", "Purchase Invoice"):
+		outstanding_amount = ref_doc.get("outstanding_amount")
+		bill_no = ref_doc.get("bill_no")
+	elif reference_doctype == "Expense Claim":
+		outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) + flt(ref_doc.get("total_taxes_and_charges"))\
+			- flt(ref_doc.get("total_amount_reimbursed")) - flt(ref_doc.get("total_advance_amount"))
+	elif reference_doctype == "Employee Advance":
+		outstanding_amount = (flt(ref_doc.advance_amount) - flt(ref_doc.paid_amount))
+		if party_account_currency != ref_doc.currency:
+			outstanding_amount = flt(outstanding_amount) * flt(exchange_rate)
+			if party_account_currency == company_currency:
+				exchange_rate = 1
+	else:
+		outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid)
+
+	return outstanding_amount, exchange_rate, bill_no
+
 
 @frappe.whitelist()
 def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None):
+	reference_doc = None
 	doc = frappe.get_doc(dt, dn)
 	if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0:
 		frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
 
-	if dt in ("Sales Invoice", "Sales Order", "Dunning"):
-		party_type = "Customer"
-	elif dt in ("Purchase Invoice", "Purchase Order"):
-		party_type = "Supplier"
-	elif dt in ("Expense Claim", "Employee Advance"):
-		party_type = "Employee"
-	elif dt in ("Fees"):
-		party_type = "Student"
-
-	# party account
-	if dt == "Sales Invoice":
-		party_account = get_party_account_based_on_invoice_discounting(dn) or doc.debit_to
-	elif dt == "Purchase Invoice":
-		party_account = doc.credit_to
-	elif dt == "Fees":
-		party_account = doc.receivable_account
-	elif dt == "Employee Advance":
-		party_account = doc.advance_account
-	elif dt == "Expense Claim":
-		party_account = doc.payable_account
-	else:
-		party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
-
-	if dt not in ("Sales Invoice", "Purchase Invoice"):
-		party_account_currency = get_account_currency(party_account)
-	else:
-		party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
-
-	# payment type
-	if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
-		or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
-			payment_type = "Receive"
-	else:
-		payment_type = "Pay"
-
-	# amounts
-	grand_total = outstanding_amount = 0
-	if party_amount:
-		grand_total = outstanding_amount = party_amount
-	elif dt in ("Sales Invoice", "Purchase Invoice"):
-		if party_account_currency == doc.company_currency:
-			grand_total = doc.base_rounded_total or doc.base_grand_total
-		else:
-			grand_total = doc.rounded_total or doc.grand_total
-		outstanding_amount = doc.outstanding_amount
-	elif dt in ("Expense Claim"):
-		grand_total = doc.total_sanctioned_amount + doc.total_taxes_and_charges
-		outstanding_amount = doc.grand_total \
-			- doc.total_amount_reimbursed
-	elif dt == "Employee Advance":
-		grand_total = doc.advance_amount
-		outstanding_amount = flt(doc.advance_amount) - flt(doc.paid_amount)
-	elif dt == "Fees":
-		grand_total = doc.grand_total
-		outstanding_amount = doc.outstanding_amount
-	elif dt == "Dunning":
-		grand_total = doc.grand_total
-		outstanding_amount = doc.grand_total
-	else:
-		if party_account_currency == doc.company_currency:
-			grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total)
-		else:
-			grand_total = flt(doc.get("rounded_total") or doc.grand_total)
-		outstanding_amount = grand_total - flt(doc.advance_paid)
+	party_type = set_party_type(dt)
+	party_account = set_party_account(dt, dn, doc, party_type)
+	party_account_currency = set_party_account_currency(dt, party_account, doc)
+	payment_type = set_payment_type(dt, doc)
+	grand_total, outstanding_amount = set_grand_total_and_outstanding_amount(party_amount, dt, party_account_currency, doc)
 
 	# bank or cash
-	bank = get_default_bank_cash_account(doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"),
-		account=bank_account)
+	bank = get_bank_cash_account(doc, bank_account)
 
-	if not bank:
-		bank = get_default_bank_cash_account(doc.company, "Cash", mode_of_payment=doc.get("mode_of_payment"),
-			account=bank_account)
-
-	paid_amount = received_amount = 0
-	if party_account_currency == bank.account_currency:
-		paid_amount = received_amount = abs(outstanding_amount)
-	elif payment_type == "Receive":
-		paid_amount = abs(outstanding_amount)
-		if bank_amount:
-			received_amount = bank_amount
-		else:
-			received_amount = paid_amount * doc.get('conversion_rate', 1)
-	else:
-		received_amount = abs(outstanding_amount)
-		if bank_amount:
-			paid_amount = bank_amount
-		else:
-			# if party account currency and bank currency is different then populate paid amount as well
-			paid_amount = received_amount * doc.get('conversion_rate', 1)
+	paid_amount, received_amount = set_paid_amount_and_received_amount(
+		dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc)
 
 	pe = frappe.new_doc("Payment Entry")
 	pe.payment_type = payment_type
@@ -1115,10 +1139,120 @@
 	pe.setup_party_account_field()
 	pe.set_missing_values()
 	if party_account and bank:
-		pe.set_exchange_rate()
+		if dt == "Employee Advance":
+			reference_doc = doc
+		pe.set_exchange_rate(ref_doc=reference_doc)
 		pe.set_amounts()
 	return pe
 
+def get_bank_cash_account(doc, bank_account):
+	bank = get_default_bank_cash_account(doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"),
+		account=bank_account)
+
+	if not bank:
+		bank = get_default_bank_cash_account(doc.company, "Cash", mode_of_payment=doc.get("mode_of_payment"),
+			account=bank_account)
+
+	return bank
+
+def set_party_type(dt):
+	if dt in ("Sales Invoice", "Sales Order", "Dunning"):
+		party_type = "Customer"
+	elif dt in ("Purchase Invoice", "Purchase Order"):
+		party_type = "Supplier"
+	elif dt in ("Expense Claim", "Employee Advance"):
+		party_type = "Employee"
+	elif dt in ("Fees"):
+		party_type = "Student"
+	return party_type
+
+def set_party_account(dt, dn, doc, party_type):
+	if dt == "Sales Invoice":
+		party_account = get_party_account_based_on_invoice_discounting(dn) or doc.debit_to
+	elif dt == "Purchase Invoice":
+		party_account = doc.credit_to
+	elif dt == "Fees":
+		party_account = doc.receivable_account
+	elif dt == "Employee Advance":
+		party_account = doc.advance_account
+	elif dt == "Expense Claim":
+		party_account = doc.payable_account
+	else:
+		party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
+	return party_account
+
+def set_party_account_currency(dt, party_account, doc):
+	if dt not in ("Sales Invoice", "Purchase Invoice"):
+		party_account_currency = get_account_currency(party_account)
+	else:
+		party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
+	return party_account_currency
+
+def set_payment_type(dt, doc):
+	if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
+		or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
+			payment_type = "Receive"
+	else:
+		payment_type = "Pay"
+	return payment_type
+
+def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_currency, doc):
+	grand_total = outstanding_amount = 0
+	if party_amount:
+		grand_total = outstanding_amount = party_amount
+	elif dt in ("Sales Invoice", "Purchase Invoice"):
+		if party_account_currency == doc.company_currency:
+			grand_total = doc.base_rounded_total or doc.base_grand_total
+		else:
+			grand_total = doc.rounded_total or doc.grand_total
+		outstanding_amount = doc.outstanding_amount
+	elif dt in ("Expense Claim"):
+		grand_total = doc.total_sanctioned_amount + doc.total_taxes_and_charges
+		outstanding_amount = doc.grand_total \
+			- doc.total_amount_reimbursed
+	elif dt == "Employee Advance":
+		grand_total = flt(doc.advance_amount)
+		outstanding_amount = flt(doc.advance_amount) - flt(doc.paid_amount)
+		if party_account_currency != doc.currency:
+			grand_total = flt(doc.advance_amount) * flt(doc.exchange_rate)
+			outstanding_amount = (flt(doc.advance_amount) - flt(doc.paid_amount)) * flt(doc.exchange_rate)
+	elif dt == "Fees":
+		grand_total = doc.grand_total
+		outstanding_amount = doc.outstanding_amount
+	elif dt == "Dunning":
+		grand_total = doc.grand_total
+		outstanding_amount = doc.grand_total
+	else:
+		if party_account_currency == doc.company_currency:
+			grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total)
+		else:
+			grand_total = flt(doc.get("rounded_total") or doc.grand_total)
+		outstanding_amount = grand_total - flt(doc.advance_paid)
+	return grand_total, outstanding_amount
+
+def set_paid_amount_and_received_amount(dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc):
+	paid_amount = received_amount = 0
+	if party_account_currency == bank.account_currency:
+		paid_amount = received_amount = abs(outstanding_amount)
+	elif payment_type == "Receive":
+		paid_amount = abs(outstanding_amount)
+		if bank_amount:
+			received_amount = bank_amount
+		else:
+			received_amount = paid_amount * doc.get('conversion_rate', 1)
+			if dt == "Employee Advance":
+				received_amount = paid_amount * doc.get('exchange_rate', 1)
+	else:
+		received_amount = abs(outstanding_amount)
+		if bank_amount:
+			paid_amount = bank_amount
+		else:
+			# if party account currency and bank currency is different then populate paid amount as well
+			paid_amount = received_amount * doc.get('conversion_rate', 1)
+			if dt == "Employee Advance":
+				paid_amount = received_amount * doc.get('exchange_rate', 1)
+	return paid_amount, received_amount
+
 def get_reference_as_per_payment_terms(payment_schedule, dt, dn, doc, grand_total, outstanding_amount):
 	references = []
 	for payment_term in payment_schedule:
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index edf8659..62dc1fc 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -70,6 +70,7 @@
 		""".format(cond=cond), tuple([company] + args_list), as_dict=1)
 
 def make_pos_profile(**args):
+	frappe.db.sql("delete from `tabPOS Payment Method`")
 	frappe.db.sql("delete from `tabPOS Profile`")
 
 	args = frappe._dict(args)
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
index cc8ed4b..d08a854 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
@@ -406,6 +406,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "default": "0",
    "depends_on": "eval:doc.rate_or_discount==\"Rate\"",
    "fieldname": "rate",
    "fieldtype": "Currency",
@@ -469,6 +470,7 @@
    "options": "UOM"
   },
   {
+   "description": "If rate is zero them item will be treated as \"Free Item\"",
    "fieldname": "free_item_rate",
    "fieldtype": "Currency",
    "label": "Rate"
@@ -563,7 +565,7 @@
  "icon": "fa fa-gift",
  "idx": 1,
  "links": [],
- "modified": "2020-10-28 16:53:14.416172",
+ "modified": "2020-12-04 00:36:24.698219",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Pricing Rule",
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index ec0a485..af8d21d 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -521,6 +521,22 @@
 		frappe.get_doc("Item Price", {"item_code": "Water Flask"}).delete()
 		item.delete()
 
+	def test_pricing_rule_for_transaction(self):
+		make_item("Water Flask 1")
+		frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
+		make_pricing_rule(selling=1, min_qty=5, price_or_product_discount="Product",
+			apply_on="Transaction", free_item="Water Flask 1", free_qty=1, free_item_rate=10)
+
+		si = create_sales_invoice(qty=5, do_not_submit=True)
+		self.assertEquals(len(si.items), 2)
+		self.assertEquals(si.items[1].rate, 10)
+
+		si1 = create_sales_invoice(qty=2, do_not_submit=True)
+		self.assertEquals(len(si1.items), 1)
+
+		for doc in [si, si1]:
+			doc.delete()
+
 def make_pricing_rule(**args):
 	args = frappe._dict(args)
 
@@ -539,20 +555,23 @@
 		"rate_or_discount": args.rate_or_discount or "Discount Percentage",
 		"discount_percentage": args.discount_percentage or 0.0,
 		"rate": args.rate or 0.0,
-		"margin_type": args.margin_type,
 		"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
 		"condition": args.condition or '',
 		"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0
 	})
 
-	if args.get("priority"):
-		doc.priority = args.get("priority")
+	for field in ["free_item", "free_qty", "free_item_rate", "priority",
+		"margin_type", "price_or_product_discount"]:
+		if args.get(field):
+			doc.set(field, args.get(field))
 
 	apply_on = doc.apply_on.replace(' ', '_').lower()
 	child_table = {'Item Code': 'items', 'Item Group': 'item_groups', 'Brand': 'brands'}
-	doc.append(child_table.get(doc.apply_on), {
-		apply_on: args.get(apply_on) or "_Test Item"
-	})
+
+	if doc.apply_on != "Transaction":
+		doc.append(child_table.get(doc.apply_on), {
+			apply_on: args.get(apply_on) or "_Test Item"
+		})
 
 	doc.insert(ignore_permissions=True)
 	if args.get(apply_on) and apply_on != "item_code":
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index b003328..2c7cd14 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -457,6 +457,9 @@
 		pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
 			doc.total, pricing_rules)
 
+		if not pricing_rules:
+			remove_free_item(doc)
+
 		for d in pricing_rules:
 			if d.price_or_product_discount == 'Price':
 				if d.apply_discount_on:
@@ -480,6 +483,12 @@
 				get_product_discount_rule(d, item_details, doc=doc)
 				apply_pricing_rule_for_free_items(doc, item_details.free_item_data)
 				doc.set_missing_values()
+				doc.calculate_taxes_and_totals()
+
+def remove_free_item(doc):
+	for d in doc.items:
+		if d.is_free_item:
+			doc.remove(d)
 
 def get_applied_pricing_rules(pricing_rules):
 	if pricing_rules:
@@ -492,7 +501,7 @@
 
 def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
 	free_item = pricing_rule.free_item
-	if pricing_rule.same_item:
+	if pricing_rule.same_item and pricing_rule.get("apply_on") != 'Transaction':
 		free_item = item_details.item_code or args.item_code
 
 	if not free_item:
diff --git a/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py
index 31356c6..e08a0e5 100644
--- a/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py
+++ b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py
@@ -21,7 +21,7 @@
 		item.no_of_months = 12
 		item.save()
 
-		si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True)
+		si = create_sales_invoice(item=item.name, update_stock=0, posting_date="2019-01-10", do_not_submit=True)
 		si.items[0].enable_deferred_revenue = 1
 		si.items[0].service_start_date = "2019-01-10"
 		si.items[0].service_end_date = "2019-03-15"
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 91c4dfb..8bd7888 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -147,6 +147,11 @@
 			throw(_("Conversion rate cannot be 0 or 1"))
 
 	def validate_credit_to_acc(self):
+		if not self.credit_to:
+			self.credit_to = get_party_account("Supplier", self.supplier, self.company)
+			if not self.credit_to:
+				self.raise_missing_debit_credit_account_error("Supplier", self.supplier)
+
 		account = frappe.db.get_value("Account", self.credit_to,
 			["account_type", "report_type", "account_currency"], as_dict=True)
 
@@ -1032,7 +1037,9 @@
 				updated_pr += update_billed_amount_based_on_po(d.po_detail, update_modified)
 
 		for pr in set(updated_pr):
-			frappe.get_doc("Purchase Receipt", pr).update_billing_percentage(update_modified=update_modified)
+			from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billing_percentage
+			pr_doc = frappe.get_doc("Purchase Receipt", pr)
+			update_billing_percentage(pr_doc, update_modified=update_modified)
 
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		self.due_date = None
diff --git a/erpnext/accounts/doctype/salary_component_account/salary_component_account.json b/erpnext/accounts/doctype/salary_component_account/salary_component_account.json
index 23dc6c4..f1ed8ef 100644
--- a/erpnext/accounts/doctype/salary_component_account/salary_component_account.json
+++ b/erpnext/accounts/doctype/salary_component_account/salary_component_account.json
@@ -1,92 +1,38 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2016-07-27 17:24:24.956896", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
+ "actions": [],
+ "creation": "2016-07-27 17:24:24.956896",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "company",
+  "account"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "Default Bank / Cash account will be automatically updated in Salary Journal Entry when this mode is selected.", 
-   "fieldname": "default_account", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Default Account", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Account", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "description": "Default Bank / Cash account will be automatically updated in Salary Journal Entry when this mode is selected.",
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account",
+   "options": "Account"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-09-02 07:49:06.567389", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Salary Component Account", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-10-18 17:57:57.110257",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Salary Component Account",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index af6c696..81f425f 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -405,6 +405,8 @@
 		from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
 		if not self.pos_profile:
 			pos_profile = get_pos_profile(self.company) or {}
+			if not pos_profile:
+				frappe.throw(_("No POS Profile found. Please create a New POS Profile first"))
 			self.pos_profile = pos_profile.get('name')
 
 		pos = {}
@@ -472,6 +474,11 @@
 		return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
 
 	def validate_debit_to_acc(self):
+		if not self.debit_to:
+			self.debit_to = get_party_account("Customer", self.customer, self.company)
+			if not self.debit_to:
+				self.raise_missing_debit_credit_account_error("Customer", self.customer)
+
 		account = frappe.get_cached_value("Account", self.debit_to,
 			["account_type", "report_type", "account_currency"], as_dict=True)
 
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 9660c95..46e954d 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -690,7 +690,8 @@
 		self.assertTrue(gle)
 
 	def test_pos_gl_entry_with_perpetual_inventory(self):
-		make_pos_profile()
+		make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1", 
+			expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
 
 		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
 
@@ -746,7 +747,8 @@
 		self.assertEqual(pos_return.get('payments')[0].amount, -1000)
 
 	def test_pos_change_amount(self):
-		make_pos_profile()
+		make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1", 
+			expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
 
 		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
 			item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
diff --git a/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py b/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py
index 3ffb3ac..515fd99 100644
--- a/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py
+++ b/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py
@@ -14,11 +14,93 @@
 
 def get_column():
 	return [
-		_("Delivery Note") + ":Link/Delivery Note:120", _("Status") + "::120", _("Date") + ":Date:100",
-		_("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120",
-		_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
-		_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100",
-		_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
+		{
+			"label": _("Delivery Note"),
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"options": "Delivery Note",
+			"width": 160
+		},
+		{
+			"label": _("Date"),
+			"fieldname": "date",
+			"fieldtype": "Date",
+			"width": 100
+		},
+		{
+			"label": _("Customer"),
+			"fieldname": "customer",
+			"fieldtype": "Link",
+			"options": "Customer",
+			"width": 120
+		},
+		{
+			"label": _("Customer Name"),
+			"fieldname": "customer_name",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Item Code"),
+			"fieldname": "item_code",
+			"fieldtype": "Link",
+			"options": "Item",
+			"width": 120
+		},
+		{
+			"label": _("Amount"),
+			"fieldname": "amount",
+			"fieldtype": "Currency",
+			"width": 100,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Billed Amount"),
+			"fieldname": "billed_amount",
+			"fieldtype": "Currency",
+			"width": 100,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Returned Amount"),
+			"fieldname": "returned_amount",
+			"fieldtype": "Currency",
+			"width": 120,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Pending Amount"),
+			"fieldname": "pending_amount",
+			"fieldtype": "Currency",
+			"width": 120,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Item Name"),
+			"fieldname": "item_name",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Description"),
+			"fieldname": "description",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Project"),
+			"fieldname": "project",
+			"fieldtype": "Link",
+			"options": "Project",
+			"width": 120
+		},
+		{
+			"label": _("Company"),
+			"fieldname": "company",
+			"fieldtype": "Link",
+			"options": "Company",
+			"width": 120
+		}
 	]
 
 def get_args():
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index 3445df7..a36e7f8 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -8,6 +8,7 @@
 from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts,
 	get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row,
 	get_group_by_conditions)
+from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import get_item_details
 
 def execute(filters=None):
 	return _execute(filters)
@@ -22,7 +23,7 @@
 	aii_account_map = get_aii_accounts()
 	if item_list:
 		itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
-			doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
+			doctype='Purchase Invoice', tax_doctype='Purchase Taxes and Charges')
 
 	po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
 
@@ -34,10 +35,14 @@
 	if filters.get('group_by'):
 		grand_total = get_grand_total(filters, 'Purchase Invoice')
 
+	item_details = get_item_details()
+
 	for d in item_list:
 		if not d.stock_qty:
 			continue
 
+		item_record = item_details.get(d.item_code)
+
 		purchase_receipt = None
 		if d.purchase_receipt:
 			purchase_receipt = d.purchase_receipt
@@ -48,8 +53,8 @@
 
 		row = {
 			'item_code': d.item_code,
-			'item_name': d.item_name,
-			'item_group': d.item_group,
+			'item_name': item_record.item_name,
+			'item_group': item_record.item_group,
 			'description': d.description,
 			'invoice': d.parent,
 			'posting_date': d.posting_date,
@@ -81,10 +86,10 @@
 		for tax in tax_columns:
 			item_tax = itemised_tax.get(d.name, {}).get(tax, {})
 			row.update({
-				frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
-				frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
+				frappe.scrub(tax + ' Rate'): item_tax.get('tax_rate', 0),
+				frappe.scrub(tax + ' Amount'): item_tax.get('tax_amount', 0),
 			})
-			total_tax += flt(item_tax.get("tax_amount"))
+			total_tax += flt(item_tax.get('tax_amount'))
 
 		row.update({
 			'total_tax': total_tax,
@@ -309,8 +314,8 @@
 		select
 			`tabPurchase Invoice Item`.`name`, `tabPurchase Invoice Item`.`parent`,
 			`tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company,
-			`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total, `tabPurchase Invoice Item`.`item_code`,
-			`tabPurchase Invoice Item`.`item_name`, `tabPurchase Invoice Item`.`item_group`, `tabPurchase Invoice Item`.description,
+			`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total,
+			`tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description,
 			`tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`,
 			`tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`,
 			`tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`,
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index a05dcd7..f54ceb0 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -8,6 +8,7 @@
 from frappe.model.meta import get_field_precision
 from frappe.utils.xlsxutils import handle_html
 from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
+from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import get_item_details, get_customer_details
 
 def execute(filters=None):
 	return _execute(filters)
@@ -16,7 +17,7 @@
 	if not filters: filters = {}
 	columns = get_columns(additional_table_columns, filters)
 
-	company_currency = frappe.get_cached_value('Company',  filters.get("company"),  "default_currency")
+	company_currency = frappe.get_cached_value('Company',  filters.get('company'),  'default_currency')
 
 	item_list = get_items(filters, additional_query_columns)
 	if item_list:
@@ -33,7 +34,13 @@
 	if filters.get('group_by'):
 		grand_total = get_grand_total(filters, 'Sales Invoice')
 
+	customer_details = get_customer_details()
+	item_details = get_item_details()
+
 	for d in item_list:
+		customer_record = customer_details.get(d.customer)
+		item_record = item_details.get(d.item_code)
+
 		delivery_note = None
 		if d.delivery_note:
 			delivery_note = d.delivery_note
@@ -45,14 +52,14 @@
 
 		row = {
 			'item_code': d.item_code,
-			'item_name': d.item_name,
-			'item_group': d.item_group,
+			'item_name': item_record.item_name,
+			'item_group': item_record.item_group,
 			'description': d.description,
 			'invoice': d.parent,
 			'posting_date': d.posting_date,
 			'customer': d.customer,
-			'customer_name': d.customer_name,
-			'customer_group': d.customer_group,
+			'customer_name': customer_record.customer_name,
+			'customer_group': customer_record.customer_group,
 		}
 
 		if additional_query_columns:
@@ -90,10 +97,10 @@
 		for tax in tax_columns:
 			item_tax = itemised_tax.get(d.name, {}).get(tax, {})
 			row.update({
-				frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
-				frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
+				frappe.scrub(tax + ' Rate'): item_tax.get('tax_rate', 0),
+				frappe.scrub(tax + ' Amount'): item_tax.get('tax_amount', 0),
 			})
-			total_tax += flt(item_tax.get("tax_amount"))
+			total_tax += flt(item_tax.get('tax_amount'))
 
 		row.update({
 			'total_tax': total_tax,
@@ -226,7 +233,7 @@
 	if filters.get('group_by') != 'Territory':
 		columns.extend([
 			{
-				'label': _("Territory"),
+				'label': _('Territory'),
 				'fieldname': 'territory',
 				'fieldtype': 'Link',
 				'options': 'Territory',
@@ -374,13 +381,12 @@
 			`tabSales Invoice`.posting_date, `tabSales Invoice`.debit_to,
 			`tabSales Invoice`.project, `tabSales Invoice`.customer, `tabSales Invoice`.remarks,
 			`tabSales Invoice`.territory, `tabSales Invoice`.company, `tabSales Invoice`.base_net_total,
-			`tabSales Invoice Item`.item_code, `tabSales Invoice Item`.item_name,
-			`tabSales Invoice Item`.item_group, `tabSales Invoice Item`.description, `tabSales Invoice Item`.sales_order,
-			`tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.income_account,
-			`tabSales Invoice Item`.cost_center, `tabSales Invoice Item`.stock_qty,
-			`tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.base_net_rate,
-			`tabSales Invoice Item`.base_net_amount, `tabSales Invoice`.customer_name,
-			`tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
+			`tabSales Invoice Item`.item_code, `tabSales Invoice Item`.description,
+			`tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.delivery_note,
+			`tabSales Invoice Item`.income_account, `tabSales Invoice Item`.cost_center,
+			`tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom,
+			`tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount,
+			`tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
 			`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
 		from `tabSales Invoice`, `tabSales Invoice Item`
 		where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
@@ -417,14 +423,14 @@
 	return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
 
 def get_tax_accounts(item_list, columns, company_currency,
-		doctype="Sales Invoice", tax_doctype="Sales Taxes and Charges"):
+		doctype='Sales Invoice', tax_doctype='Sales Taxes and Charges'):
 	import json
 	item_row_map = {}
 	tax_columns = []
 	invoice_item_row = {}
 	itemised_tax = {}
 
-	tax_amount_precision = get_field_precision(frappe.get_meta(tax_doctype).get_field("tax_amount"),
+	tax_amount_precision = get_field_precision(frappe.get_meta(tax_doctype).get_field('tax_amount'),
 		currency=company_currency) or 2
 
 	for d in item_list:
@@ -469,8 +475,8 @@
 						tax_rate = tax_data
 						tax_amount = 0
 
-					if charge_type == "Actual" and not tax_rate:
-						tax_rate = "NA"
+					if charge_type == 'Actual' and not tax_rate:
+						tax_rate = 'NA'
 
 					item_net_amount = sum([flt(d.base_net_amount)
 						for d in item_row_map.get(parent, {}).get(item_code, [])])
@@ -484,17 +490,17 @@
 								if (doctype == 'Purchase Invoice' and name in deducted_tax) else tax_value)
 
 							itemised_tax.setdefault(d.name, {})[description] = frappe._dict({
-								"tax_rate": tax_rate,
-								"tax_amount": tax_value
+								'tax_rate': tax_rate,
+								'tax_amount': tax_value
 							})
 
 			except ValueError:
 				continue
-		elif charge_type == "Actual" and tax_amount:
+		elif charge_type == 'Actual' and tax_amount:
 			for d in invoice_item_row.get(parent, []):
 				itemised_tax.setdefault(d.name, {})[description] = frappe._dict({
-					"tax_rate": "NA",
-					"tax_amount": flt((tax_amount * d.base_net_amount) / d.base_net_total,
+					'tax_rate': 'NA',
+					'tax_amount': flt((tax_amount * d.base_net_amount) / d.base_net_total,
 						tax_amount_precision)
 				})
 
@@ -563,7 +569,7 @@
 		})
 
 		total_row_map.setdefault('total_row', {
-			subtotal_display_field: "Total",
+			subtotal_display_field: 'Total',
 			'stock_qty': 0.0,
 			'amount': 0.0,
 			'bold': 1,
diff --git a/erpnext/accounts/report/non_billed_report.py b/erpnext/accounts/report/non_billed_report.py
index a9e25bc..2e18ce1 100644
--- a/erpnext/accounts/report/non_billed_report.py
+++ b/erpnext/accounts/report/non_billed_report.py
@@ -17,18 +17,26 @@
 
 	return frappe.db.sql("""
 		Select
-			`{parent_tab}`.name, `{parent_tab}`.status, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
-			{project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount,
+			`{parent_tab}`.name, `{parent_tab}`.{date_field},
+			`{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
+			`{child_tab}`.item_code,
+			`{child_tab}`.base_amount,
 			(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
-			(`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))),
-			`{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company
+			(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0)),
+			(`{child_tab}`.base_amount -
+			(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)) -
+			(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0))),
+			`{child_tab}`.item_name, `{child_tab}`.description,
+			{project_field}, `{parent_tab}`.company
 		from
 			`{parent_tab}`, `{child_tab}`
 		where
 			`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1
 			and `{parent_tab}`.status not in ('Closed', 'Completed')
-			and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt *
-			ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount
+			and `{child_tab}`.amount > 0
+			and (`{child_tab}`.base_amount -
+			round(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) -
+			(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0))) > 0
 		order by
 			`{parent_tab}`.{order} {order_by}
 		""".format(parent_tab = 'tab' + doctype, child_tab = 'tab' + child_tab, precision= precision, party = party,
diff --git a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py
index 5e8d773..e9e9c9c 100644
--- a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py
+++ b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py
@@ -14,11 +14,93 @@
 
 def get_column():
 	return [
-		_("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Status") + "::120", _("Date") + ":Date:100",
-		_("Supplier") + ":Link/Supplier:120", _("Supplier Name") + "::120",
-		_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
-		_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100",
-		_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
+		{
+			"label": _("Purchase Receipt"),
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"options": "Purchase Receipt",
+			"width": 160
+		},
+		{
+			"label": _("Date"),
+			"fieldname": "date",
+			"fieldtype": "Date",
+			"width": 100
+		},
+		{
+			"label": _("Supplier"),
+			"fieldname": "supplier",
+			"fieldtype": "Link",
+			"options": "Supplier",
+			"width": 120
+		},
+		{
+			"label": _("Supplier Name"),
+			"fieldname": "supplier_name",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Item Code"),
+			"fieldname": "item_code",
+			"fieldtype": "Link",
+			"options": "Item",
+			"width": 120
+		},
+		{
+			"label": _("Amount"),
+			"fieldname": "amount",
+			"fieldtype": "Currency",
+			"width": 100,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Billed Amount"),
+			"fieldname": "billed_amount",
+			"fieldtype": "Currency",
+			"width": 100,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Returned Amount"),
+			"fieldname": "returned_amount",
+			"fieldtype": "Currency",
+			"width": 120,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Pending Amount"),
+			"fieldname": "pending_amount",
+			"fieldtype": "Currency",
+			"width": 120,
+			"options": "Company:company:default_currency"
+		},
+		{
+			"label": _("Item Name"),
+			"fieldname": "item_name",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Description"),
+			"fieldname": "description",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Project"),
+			"fieldname": "project",
+			"fieldtype": "Link",
+			"options": "Project",
+			"width": 120
+		},
+		{
+			"label": _("Company"),
+			"fieldname": "company",
+			"fieldtype": "Link",
+			"options": "Company",
+			"width": 120
+		}
 	]
 
 def get_args():
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 53677cd..550aaef 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -78,7 +78,10 @@
 			else:
 				return ((fy.name, fy.year_start_date, fy.year_end_date),)
 
-	error_msg = _("""{0} {1} not in any active Fiscal Year.""").format(label, formatdate(transaction_date))
+	error_msg = _("""{0} {1} is not in any active Fiscal Year""").format(label, formatdate(transaction_date))
+	if company:
+		error_msg = _("""{0} for {1}""").format(error_msg, frappe.bold(company))
+	
 	if verbose==1: frappe.msgprint(error_msg)
 	raise FiscalYearError(error_msg)
 
diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
index af08a2a..d1457b9 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
@@ -75,24 +75,23 @@
 	for asset in assets_record:
 		asset_value = asset.gross_purchase_amount - flt(asset.opening_accumulated_depreciation) \
 			- flt(depreciation_amount_map.get(asset.name))
-		if asset_value:
-			row = {
-				"asset_id": asset.asset_id,
-				"asset_name": asset.asset_name,
-				"status": asset.status,
-				"department": asset.department,
-				"cost_center": asset.cost_center,
-				"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
-				"gross_purchase_amount": asset.gross_purchase_amount,
-				"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
-				"depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0,
-				"available_for_use_date": asset.available_for_use_date,
-				"location": asset.location,
-				"asset_category": asset.asset_category,
-				"purchase_date": asset.purchase_date,
-				"asset_value": asset_value
-			}
-			data.append(row)
+		row = {
+			"asset_id": asset.asset_id,
+			"asset_name": asset.asset_name,
+			"status": asset.status,
+			"department": asset.department,
+			"cost_center": asset.cost_center,
+			"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
+			"gross_purchase_amount": asset.gross_purchase_amount,
+			"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
+			"depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0,
+			"available_for_use_date": asset.available_for_use_date,
+			"location": asset.location,
+			"asset_category": asset.asset_category,
+			"purchase_date": asset.purchase_date,
+			"asset_value": asset_value
+		}
+		data.append(row)
 
 	return data
 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 71231f6..75da71c 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -168,6 +168,7 @@
    "bold": 1,
    "fieldname": "supplier",
    "fieldtype": "Link",
+   "in_global_search": 1,
    "in_standard_filter": 1,
    "label": "Supplier",
    "oldfieldname": "supplier",
@@ -1106,7 +1107,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-30 13:58:14.697921",
+ "modified": "2020-12-03 16:46:44.229351",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index c427242..e537771 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -290,11 +290,17 @@
 				dialog.show();
 			}, __("Get Items From"));
 
+			// Link Material Requests
+			this.frm.add_custom_button(__('Link to Material Requests'),
+				function() {
+					erpnext.buying.link_to_mrs(me.frm);
+				}, __("Tools"));
+
 			// Get Suppliers
 			this.frm.add_custom_button(__('Get Suppliers'),
 				function() {
 					me.get_suppliers_button(me.frm);
-				});
+				}, __("Tools"));
 		}
 	},
 
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
index 3af6cf8..4ce4100 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
@@ -18,7 +18,6 @@
   "suppliers",
   "items_section",
   "items",
-  "link_to_mrs",
   "supplier_response_section",
   "salutation",
   "subject",
@@ -118,13 +117,6 @@
    "reqd": 1
   },
   {
-   "depends_on": "eval:doc.docstatus===0 && (doc.items && doc.items.length)",
-   "fieldname": "link_to_mrs",
-   "fieldtype": "Button",
-   "label": "Link to Material Requests"
-  },
-  {
-   "depends_on": "eval:!doc.__islocal",
    "fieldname": "supplier_response_section",
    "fieldtype": "Section Break",
    "label": "Email Details"
@@ -260,7 +252,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-11-04 22:04:29.017134",
+ "modified": "2020-11-05 22:04:29.017134",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Request for Quotation",
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index a7cab50..a3b2085 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -50,6 +50,12 @@
 					})
 				}, __("Get Items From"));
 
+			// Link Material Requests
+			this.frm.add_custom_button(__('Link to Material Requests'),
+				function() {
+					erpnext.buying.link_to_mrs(me.frm);
+				}, __("Tools"));
+
 			this.frm.add_custom_button(__("Request for Quotation"),
 			function() {
 				if (!me.frm.doc.supplier) {
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index b39c989..40fbe2c 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -35,7 +35,6 @@
   "ignore_pricing_rule",
   "items_section",
   "items",
-  "link_to_mrs",
   "pricing_rule_details",
   "pricing_rules",
   "section_break_22",
@@ -323,12 +322,6 @@
    "reqd": 1
   },
   {
-   "depends_on": "eval:doc.docstatus===0 && (doc.items && doc.items.length)",
-   "fieldname": "link_to_mrs",
-   "fieldtype": "Button",
-   "label": "Link to material requests"
-  },
-  {
    "fieldname": "pricing_rule_details",
    "fieldtype": "Section Break",
    "label": "Pricing Rules"
@@ -806,9 +799,10 @@
  ],
  "icon": "fa fa-shopping-cart",
  "idx": 29,
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-30 13:58:33.043971",
+ "modified": "2020-12-03 15:18:29.073368",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier Quotation",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 6108a61..93a79ec 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -23,6 +23,8 @@
 from erpnext.stock.get_item_details import get_item_warehouse, _get_item_tax_template, get_item_tax_map
 from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
 
+class AccountMissingError(frappe.ValidationError): pass
+
 force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
 
 class AccountsController(TransactionBase):
@@ -735,6 +737,21 @@
 
 		return self._abbr
 
+	def raise_missing_debit_credit_account_error(self, party_type, party):
+		"""Raise an error if debit to/credit to account does not exist."""
+		db_or_cr = frappe.bold("Debit To") if self.doctype == "Sales Invoice" else frappe.bold("Credit To")
+		rec_or_pay = "Receivable" if self.doctype == "Sales Invoice" else "Payable"
+
+		link_to_party = frappe.utils.get_link_to_form(party_type, party)
+		link_to_company = frappe.utils.get_link_to_form("Company", self.company)
+
+		message = _("{0} Account not found against Customer {1}.").format(db_or_cr, frappe.bold(party) or '')
+		message += "<br>" + _("Please set one of the following:") + "<br>"
+		message += "<br><ul><li>" + _("'Account' in the Accounting section of Customer {0}").format(link_to_party) + "</li>"
+		message += "<li>" + _("'Default {0} Account' in Company {1}").format(rec_or_pay, link_to_company) + "</li></ul>"
+
+		frappe.throw(message, title=_("Account Missing"), exc=AccountMissingError)
+
 	def validate_party(self):
 		party_type, party = self.get_party()
 		validate_party_frozen_disabled(party_type, party)
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 9ee83e3..5fabf70 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -497,6 +497,10 @@
 					frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
 				d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
 
+				if self.doctype=="Purchase Receipt" and d.meta.get_field("received_stock_qty"):
+					# Set Received Qty in Stock UOM
+					d.received_stock_qty = flt(d.received_qty) * flt(d.conversion_factor, d.precision("conversion_factor"))
+
 	def validate_purchase_return(self):
 		for d in self.get("items"):
 			if self.is_return and flt(d.rejected_qty) != 0:
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index afc5f81..5299b25 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -203,10 +203,37 @@
 
 	return items
 
+def get_returned_qty_map_for_row(row_name, doctype):
+	child_doctype = doctype + " Item"
+	reference_field = frappe.scrub(child_doctype) if doctype == "Purchase Receipt" else "dn_detail"
+
+	fields = [
+		"sum(abs(`tab{0}`.qty)) as qty".format(child_doctype),
+		"sum(abs(`tab{0}`.stock_qty)) as stock_qty".format(child_doctype)
+	]
+
+	if doctype == "Purchase Receipt":
+		fields += [
+			"sum(abs(`tab{0}`.rejected_qty)) as rejected_qty".format(child_doctype),
+			"sum(abs(`tab{0}`.received_qty)) as received_qty".format(child_doctype),
+			"sum(abs(`tab{0}`.received_stock_qty)) as received_stock_qty".format(child_doctype)
+		]
+
+	data = frappe.db.get_list(doctype,
+		fields = fields,
+		filters = [
+			[doctype, "docstatus", "=", 1],
+			[doctype, "is_return", "=", 1],
+			[child_doctype, reference_field, "=", row_name]
+	])
+
+	return data[0]
+
 def make_return_doc(doctype, source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
 	company = frappe.db.get_value("Delivery Note", source_name, "company")
 	default_warehouse_for_sales_return = frappe.db.get_value("Company", company, "default_warehouse_for_sales_return")
+
 	def set_missing_values(source, target):
 		doc = frappe.get_doc(target)
 		doc.is_return = 1
@@ -261,20 +288,25 @@
 		doc.run_method("calculate_taxes_and_totals")
 
 	def update_item(source_doc, target_doc, source_parent):
-		target_doc.qty = -1* source_doc.qty
+		target_doc.qty = -1 * source_doc.qty
+
 		if doctype == "Purchase Receipt":
-			target_doc.received_qty = -1* source_doc.received_qty
-			target_doc.rejected_qty = -1* source_doc.rejected_qty
-			target_doc.qty = -1* source_doc.qty
-			target_doc.stock_qty = -1 * source_doc.stock_qty
+			returned_qty_map = get_returned_qty_map_for_row(source_doc.name, doctype)
+			target_doc.received_qty = -1 * flt(source_doc.received_qty - (returned_qty_map.get('received_qty') or 0))
+			target_doc.rejected_qty = -1 * flt(source_doc.rejected_qty - (returned_qty_map.get('rejected_qty') or 0))
+			target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get('qty') or 0))
+
+			target_doc.stock_qty = -1 * flt(source_doc.stock_qty - (returned_qty_map.get('stock_qty') or 0))
+			target_doc.received_stock_qty = -1 * flt(source_doc.received_stock_qty - (returned_qty_map.get('received_stock_qty') or 0))
+
 			target_doc.purchase_order = source_doc.purchase_order
 			target_doc.purchase_order_item = source_doc.purchase_order_item
 			target_doc.rejected_warehouse = source_doc.rejected_warehouse
 			target_doc.purchase_receipt_item = source_doc.name
 
 		elif doctype == "Purchase Invoice":
-			target_doc.received_qty = -1* source_doc.received_qty
-			target_doc.rejected_qty = -1* source_doc.rejected_qty
+			target_doc.received_qty = -1 * source_doc.received_qty
+			target_doc.rejected_qty = -1 * source_doc.rejected_qty
 			target_doc.qty = -1* source_doc.qty
 			target_doc.stock_qty = -1 * source_doc.stock_qty
 			target_doc.purchase_order = source_doc.purchase_order
@@ -285,6 +317,10 @@
 			target_doc.purchase_invoice_item = source_doc.name
 
 		elif doctype == "Delivery Note":
+			returned_qty_map = get_returned_qty_map_for_row(source_doc.name, doctype)
+			target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get('qty') or 0))
+			target_doc.stock_qty = -1 * flt(source_doc.stock_qty - (returned_qty_map.get('stock_qty') or 0))
+
 			target_doc.against_sales_order = source_doc.against_sales_order
 			target_doc.against_sales_invoice = source_doc.against_sales_invoice
 			target_doc.so_detail = source_doc.so_detail
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 515239a..4dbd7bf 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -42,7 +42,7 @@
 		self.validate_max_discount()
 		self.validate_selling_price()
 		self.set_qty_as_per_stock_uom()
-		self.set_po_nos()
+		self.set_po_nos(for_validate=True)
 		self.set_gross_profit()
 		set_default_income_account_for_item(self)
 		self.set_customer_address()
@@ -370,20 +370,28 @@
 						}))
 		self.make_sl_entries(sl_entries)
 
-	def set_po_nos(self):
+	def set_po_nos(self, for_validate=False):
 		if self.doctype == 'Sales Invoice' and hasattr(self, "items"):
+			if for_validate and self.po_no:
+				return
 			self.set_pos_for_sales_invoice()
 		if self.doctype == 'Delivery Note' and hasattr(self, "items"):
+			if for_validate and self.po_no:
+				return
 			self.set_pos_for_delivery_note()
 
 	def set_pos_for_sales_invoice(self):
 		po_nos = []
+		if self.po_no:
+			po_nos.append(self.po_no)
 		self.get_po_nos('Sales Order', 'sales_order', po_nos)
 		self.get_po_nos('Delivery Note', 'delivery_note', po_nos)
 		self.po_no = ', '.join(list(set(x.strip() for x in ','.join(po_nos).split(','))))
 
 	def set_pos_for_delivery_note(self):
 		po_nos = []
+		if self.po_no:
+			po_nos.append(self.po_no)
 		self.get_po_nos('Sales Order', 'against_sales_order', po_nos)
 		self.get_po_nos('Sales Invoice', 'against_sales_invoice', po_nos)
 		self.po_no = ', '.join(list(set(x.strip() for x in ','.join(po_nos).split(','))))
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 9feac78..2555edf 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -58,6 +58,7 @@
 	"Delivery Note": [
 		["Draft", None],
 		["To Bill", "eval:self.per_billed < 100 and self.docstatus == 1"],
+		["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
 		["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
 		["Cancelled", "eval:self.docstatus==2"],
 		["Closed", "eval:self.status=='Closed'"],
@@ -65,6 +66,7 @@
 	"Purchase Receipt": [
 		["Draft", None],
 		["To Bill", "eval:self.per_billed < 100 and self.docstatus == 1"],
+		["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
 		["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
 		["Cancelled", "eval:self.docstatus==2"],
 		["Closed", "eval:self.status=='Closed'"],
@@ -232,7 +234,7 @@
 
 			self._update_children(args, update_modified)
 
-			if "percent_join_field" in args:
+			if "percent_join_field" in args or "percent_join_field_parent" in args:
 				self._update_percent_field_in_targets(args, update_modified)
 
 	def _update_children(self, args, update_modified):
@@ -272,13 +274,19 @@
 
 	def _update_percent_field_in_targets(self, args, update_modified=True):
 		"""Update percent field in parent transaction"""
-		distinct_transactions = set([d.get(args['percent_join_field'])
-			for d in self.get_all_children(args['source_dt'])])
+		if args.get('percent_join_field_parent'):
+			# if reference to target doc where % is to be updated, is
+			# in source doc's parent form, consider percent_join_field_parent
+			args['name'] = self.get(args['percent_join_field_parent'])
+			self._update_percent_field(args, update_modified)
+		else:
+			distinct_transactions = set([d.get(args['percent_join_field'])
+				for d in self.get_all_children(args['source_dt'])])
 
-		for name in distinct_transactions:
-			if name:
-				args['name'] = name
-				self._update_percent_field(args, update_modified)
+			for name in distinct_transactions:
+				if name:
+					args['name'] = name
+					self._update_percent_field(args, update_modified)
 
 	def _update_percent_field(self, args, update_modified=True):
 		"""Update percent field in parent transaction"""
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 2d2fff8..2f7b361 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -340,11 +340,15 @@
 			validate_warehouse_company(w, self.company)
 
 	def update_billing_percentage(self, update_modified=True):
+		target_ref_field = "amount"
+		if self.doctype == "Delivery Note":
+			target_ref_field = "amount - (returned_qty * rate)"
+
 		self._update_percent_field({
 			"target_dt": self.doctype + " Item",
 			"target_parent_dt": self.doctype,
 			"target_parent_field": "per_billed",
-			"target_ref_field": "amount",
+			"target_ref_field": target_ref_field,
 			"target_field": "billed_amt",
 			"name": self.name,
 		}, update_modified)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 81d07c1..ad58f13 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -641,7 +641,8 @@
 		if default_mode_of_payment:
 			self.doc.append('payments', {
 				'mode_of_payment': default_mode_of_payment.mode_of_payment,
-				'amount': total_amount_to_pay
+				'amount': total_amount_to_pay,
+				'default': 1
 			})
 		else:
 			self.doc.is_pos = 0
diff --git a/erpnext/crm/doctype/contract/contract.js b/erpnext/crm/doctype/contract/contract.js
index ee9e895..9968855 100644
--- a/erpnext/crm/doctype/contract/contract.js
+++ b/erpnext/crm/doctype/contract/contract.js
@@ -1,23 +1,31 @@
 // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
 // For license information, please see license.txt
 
-cur_frm.add_fetch("contract_template", "contract_terms", "contract_terms");
-cur_frm.add_fetch("contract_template", "requires_fulfilment", "requires_fulfilment");
-
-// Add fulfilment terms from contract template into contract
 frappe.ui.form.on("Contract", {
 	contract_template: function (frm) {
-		// Populate the fulfilment terms table from a contract template, if any
 		if (frm.doc.contract_template) {
-			frappe.model.with_doc("Contract Template", frm.doc.contract_template, function () {
-				var tabletransfer = frappe.model.get_doc("Contract Template", frm.doc.contract_template);
-
-				frm.doc.fulfilment_terms = [];
-				$.each(tabletransfer.fulfilment_terms, function (index, row) {
-					var d = frm.add_child("fulfilment_terms");
-					d.requirement = row.requirement;
-					frm.refresh_field("fulfilment_terms");
-				});
+			frappe.call({
+				method: 'erpnext.crm.doctype.contract_template.contract_template.get_contract_template',
+				args: {
+					template_name: frm.doc.contract_template,
+					doc: frm.doc
+				},
+				callback: function(r) {
+					if (r && r.message) {
+						let contract_template = r.message.contract_template;
+						frm.set_value("contract_terms", r.message.contract_terms);
+						frm.set_value("requires_fulfilment", contract_template.requires_fulfilment);
+						
+						if (frm.doc.requires_fulfilment) {
+							// Populate the fulfilment terms table from a contract template, if any
+							r.message.contract_template.fulfilment_terms.forEach(element => {
+								let d = frm.add_child("fulfilment_terms");
+								d.requirement = element.requirement;
+							});
+							frm.refresh_field("fulfilment_terms");
+						}		
+					}
+				}
 			});
 		}
 	}
diff --git a/erpnext/crm/doctype/contract/contract.json b/erpnext/crm/doctype/contract/contract.json
index 0026e4a..de3230f 100755
--- a/erpnext/crm/doctype/contract/contract.json
+++ b/erpnext/crm/doctype/contract/contract.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "allow_rename": 1,
  "creation": "2018-04-12 06:32:04.582486",
@@ -247,7 +248,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-03-30 06:56:07.257932",
+ "modified": "2020-12-07 11:15:58.385521",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Contract",
diff --git a/erpnext/crm/doctype/contract_template/contract_template.json b/erpnext/crm/doctype/contract_template/contract_template.json
index 5e4582f..7cc5ec1 100644
--- a/erpnext/crm/doctype/contract_template/contract_template.json
+++ b/erpnext/crm/doctype/contract_template/contract_template.json
@@ -11,7 +11,9 @@
   "contract_terms",
   "sb_fulfilment",
   "requires_fulfilment",
-  "fulfilment_terms"
+  "fulfilment_terms",
+  "section_break_6",
+  "contract_template_help"
  ],
  "fields": [
   {
@@ -41,10 +43,20 @@
    "fieldtype": "Table",
    "label": "Fulfilment Terms and Conditions",
    "options": "Contract Template Fulfilment Terms"
+  },
+  {
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "contract_template_help",
+   "fieldtype": "HTML",
+   "label": "Contract Template Help",
+   "options": "<h4>Contract Template Example</h4>\n\n<pre>Contract for Customer {{ party_name }}\n\n-Valid From : {{ start_date }} \n-Valid To : {{ end_date }}\n</pre>\n\n<h4>How to get fieldnames</h4>\n\n<p>The field names you can use in your Contract Template are the fields in the Contract for which you are creating the template. You can find out the fields of any documents via Setup &gt; Customize Form View and selecting the document type (e.g. Contract)</p>\n\n<h4>Templating</h4>\n\n<p>Templates are compiled using the Jinja Templating Language. To learn more about Jinja, <a class=\"strong\" href=\"http://jinja.pocoo.org/docs/dev/templates/\">read this documentation.</a></p>"
   }
  ],
  "links": [],
- "modified": "2020-11-11 17:49:44.879363",
+ "modified": "2020-12-07 10:44:22.587047",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Contract Template",
diff --git a/erpnext/crm/doctype/contract_template/contract_template.py b/erpnext/crm/doctype/contract_template/contract_template.py
index 601ee9a..69fd86f 100644
--- a/erpnext/crm/doctype/contract_template/contract_template.py
+++ b/erpnext/crm/doctype/contract_template/contract_template.py
@@ -5,6 +5,27 @@
 from __future__ import unicode_literals
 import frappe
 from frappe.model.document import Document
+from frappe.utils.jinja import validate_template
+from six import string_types
+import json
 
 class ContractTemplate(Document):
-	pass
+	def validate(self):
+		if self.contract_terms:
+			validate_template(self.contract_terms)
+
+@frappe.whitelist()
+def get_contract_template(template_name, doc):
+	if isinstance(doc, string_types):
+		doc = json.loads(doc)
+
+	contract_template = frappe.get_doc("Contract Template", template_name)
+	contract_terms = None
+
+	if contract_template.contract_terms:
+		contract_terms = frappe.render_template(contract_template.contract_terms, doc)
+	
+	return {
+		'contract_template': contract_template, 
+		'contract_terms': contract_terms
+	}
\ No newline at end of file
diff --git a/erpnext/demo/setup/setup_data.py b/erpnext/demo/setup/setup_data.py
index a395c7c..05ee28a 100644
--- a/erpnext/demo/setup/setup_data.py
+++ b/erpnext/demo/setup/setup_data.py
@@ -134,7 +134,7 @@
 		salary_component = frappe.get_doc('Salary Component', d.name)
 		salary_component.append('accounts', dict(
 			company=erpnext.get_default_company(),
-			default_account=frappe.get_value('Account', dict(account_name=('like', 'Salary%')))
+			account=frappe.get_value('Account', dict(account_name=('like', 'Salary%')))
 		))
 		salary_component.save()
 
diff --git a/erpnext/erpnext_integrations/utils.py b/erpnext/erpnext_integrations/utils.py
index e278fd7..362f6cf 100644
--- a/erpnext/erpnext_integrations/utils.py
+++ b/erpnext/erpnext_integrations/utils.py
@@ -60,4 +60,12 @@
 				"default_account": payment_gateway_account
 			}]
 		})
-		mode_of_payment.insert(ignore_permissions=True)
\ No newline at end of file
+		mode_of_payment.insert(ignore_permissions=True)
+
+def get_tracking_url(carrier, tracking_number):
+	# Return the formatted Tracking URL.
+	tracking_url = ''
+	url_reference = frappe.get_value('Parcel Service', carrier, 'url_reference')
+	if url_reference:
+		tracking_url = frappe.render_template(url_reference, {'tracking_number': tracking_number})
+	return tracking_url
diff --git a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
index cdf692e..7e7fd82 100644
--- a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
+++ b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
@@ -7,6 +7,7 @@
 import unittest
 from frappe.utils import nowdate, add_days
 from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_appointment, create_healthcare_service_items
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
 
 test_dependencies = ["Company"]
 
@@ -15,6 +16,7 @@
 		frappe.db.sql("""delete from `tabPatient Appointment`""")
 		frappe.db.sql("""delete from `tabFee Validity`""")
 		frappe.db.sql("""delete from `tabPatient`""")
+		make_pos_profile()
 
 	def test_fee_validity(self):
 		item = create_healthcare_service_items()
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index eeed157..3df7ba1 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -7,12 +7,14 @@
 from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter
 from frappe.utils import nowdate, add_days
 from frappe.utils.make_random import get_random
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
 
 class TestPatientAppointment(unittest.TestCase):
 	def setUp(self):
 		frappe.db.sql("""delete from `tabPatient Appointment`""")
 		frappe.db.sql("""delete from `tabFee Validity`""")
 		frappe.db.sql("""delete from `tabPatient Encounter`""")
+		make_pos_profile()
 
 	def test_status(self):
 		patient, medical_department, practitioner = create_healthcare_docs()
diff --git a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
index aa85a23..419d956 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
+++ b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
@@ -6,11 +6,13 @@
 import frappe
 from frappe.utils import nowdate
 from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_encounter, create_healthcare_docs, create_appointment
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
 
 class TestPatientMedicalRecord(unittest.TestCase):
 	def setUp(self):
 		frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
 		frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+		make_pos_profile()
 
 	def test_medical_record(self):
 		patient, medical_department, practitioner = create_healthcare_docs()
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 726ab6e..1e3bb6a 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -271,11 +271,11 @@
 	},
 	"Contact": {
 		"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
-		"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information",
+		"after_insert": "erpnext.telephony.doctype.call_log.call_log.set_caller_information",
 		"validate": "erpnext.crm.utils.update_lead_phone_numbers"
 	},
 	"Lead": {
-		"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information"
+		"after_insert": "erpnext.telephony.doctype.call_log.call_log.set_caller_information"
 	},
 	"Email Unsubscribe": {
 		"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
@@ -441,42 +441,43 @@
 		{"doctype": "Sales Order", "index": 8},
 		{"doctype": "Quotation", "index": 9},
 		{"doctype": "Work Order", "index": 10},
-		{"doctype": "Purchase Receipt", "index": 11},
-		{"doctype": "Purchase Invoice", "index": 12},
-		{"doctype": "Delivery Note", "index": 13},
-		{"doctype": "Stock Entry", "index": 14},
-		{"doctype": "Material Request", "index": 15},
-		{"doctype": "Delivery Trip", "index": 16},
-		{"doctype": "Pick List", "index": 17},
-		{"doctype": "Salary Slip", "index": 18},
-		{"doctype": "Leave Application", "index": 19},
-		{"doctype": "Expense Claim", "index": 20},
-		{"doctype": "Payment Entry", "index": 21},
-		{"doctype": "Lead", "index": 22},
-		{"doctype": "Opportunity", "index": 23},
-		{"doctype": "Item Price", "index": 24},
-		{"doctype": "Purchase Taxes and Charges Template", "index": 25},
-		{"doctype": "Sales Taxes and Charges", "index": 26},
-		{"doctype": "Asset", "index": 27},
-		{"doctype": "Project", "index": 28},
-		{"doctype": "Task", "index": 29},
-		{"doctype": "Timesheet", "index": 30},
-		{"doctype": "Issue", "index": 31},
-		{"doctype": "Serial No", "index": 32},
-		{"doctype": "Batch", "index": 33},
-		{"doctype": "Branch", "index": 34},
-		{"doctype": "Department", "index": 35},
-		{"doctype": "Employee Grade", "index": 36},
-		{"doctype": "Designation", "index": 37},
-		{"doctype": "Job Opening", "index": 38},
-		{"doctype": "Job Applicant", "index": 39},
-		{"doctype": "Job Offer", "index": 40},
-		{"doctype": "Salary Structure Assignment", "index": 41},
-		{"doctype": "Appraisal", "index": 42},
-		{"doctype": "Loan", "index": 43},
-		{"doctype": "Maintenance Schedule", "index": 44},
-		{"doctype": "Maintenance Visit", "index": 45},
-		{"doctype": "Warranty Claim", "index": 46},
+		{"doctype": "Purchase Order", "index": 11},
+		{"doctype": "Purchase Receipt", "index": 12},
+		{"doctype": "Purchase Invoice", "index": 13},
+		{"doctype": "Delivery Note", "index": 14},
+		{"doctype": "Stock Entry", "index": 15},
+		{"doctype": "Material Request", "index": 16},
+		{"doctype": "Delivery Trip", "index": 17},
+		{"doctype": "Pick List", "index": 18},
+		{"doctype": "Salary Slip", "index": 19},
+		{"doctype": "Leave Application", "index": 20},
+		{"doctype": "Expense Claim", "index": 21},
+		{"doctype": "Payment Entry", "index": 22},
+		{"doctype": "Lead", "index": 23},
+		{"doctype": "Opportunity", "index": 24},
+		{"doctype": "Item Price", "index": 25},
+		{"doctype": "Purchase Taxes and Charges Template", "index": 26},
+		{"doctype": "Sales Taxes and Charges", "index": 27},
+		{"doctype": "Asset", "index": 28},
+		{"doctype": "Project", "index": 29},
+		{"doctype": "Task", "index": 30},
+		{"doctype": "Timesheet", "index": 31},
+		{"doctype": "Issue", "index": 32},
+		{"doctype": "Serial No", "index": 33},
+		{"doctype": "Batch", "index": 34},
+		{"doctype": "Branch", "index": 35},
+		{"doctype": "Department", "index": 36},
+		{"doctype": "Employee Grade", "index": 37},
+		{"doctype": "Designation", "index": 38},
+		{"doctype": "Job Opening", "index": 39},
+		{"doctype": "Job Applicant", "index": 40},
+		{"doctype": "Job Offer", "index": 41},
+		{"doctype": "Salary Structure Assignment", "index": 42},
+		{"doctype": "Appraisal", "index": 43},
+		{"doctype": "Loan", "index": 44},
+		{"doctype": "Maintenance Schedule", "index": 45},
+		{"doctype": "Maintenance Visit", "index": 46},
+		{"doctype": "Warranty Claim", "index": 47},
 	],
 	"Healthcare": [
 		{'doctype': 'Patient', 'index': 1},
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js
index cba8ee9..7056adf 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.js
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.js
@@ -15,11 +15,16 @@
 		});
 
 		frm.set_query("advance_account", function() {
+			if (!frm.doc.employee) {
+				frappe.msgprint(__("Please select employee first"));
+			}
+			var company_currency = erpnext.get_currency(frm.doc.company);
 			return {
 				filters: {
 					"root_type": "Asset",
 					"is_group": 0,
-					"company": frm.doc.company
+					"company": frm.doc.company,
+					"account_currency": ["in", [frm.doc.currency, company_currency]],
 				}
 			};
 		});
@@ -63,7 +68,7 @@
 				}, __('Create'));
 			}else if (frm.doc.repay_unclaimed_amount_from_salary == 1 && frappe.model.can_create("Additional Salary")){
 				frm.add_custom_button(__("Deduction from salary"),  function() {
-					frm.events.make_deduction_via_additional_salary(frm)
+					frm.events.make_deduction_via_additional_salary(frm);
 				}, __('Create'));
 			}
 		}
@@ -127,7 +132,9 @@
 				'employee_advance_name': frm.doc.name,
 				'return_amount': flt(frm.doc.paid_amount - frm.doc.claimed_amount),
 				'advance_account': frm.doc.advance_account,
-				'mode_of_payment': frm.doc.mode_of_payment
+				'mode_of_payment': frm.doc.mode_of_payment,
+				'currency': frm.doc.currency,
+				'exchange_rate': frm.doc.exchange_rate
 			},
 			callback: function(r) {
 				const doclist = frappe.model.sync(r.message);
@@ -138,16 +145,72 @@
 
 	employee: function (frm) {
 		if (frm.doc.employee) {
-			return frappe.call({
-				method: "erpnext.hr.doctype.employee_advance.employee_advance.get_pending_amount",
-				args: {
-					"employee": frm.doc.employee,
-					"posting_date": frm.doc.posting_date
-				},
-				callback: function(r) {
-					frm.set_value("pending_amount",r.message);
-				}
-			});
+			frappe.run_serially([
+				() => 	frm.trigger('get_employee_currency'),
+				() => 	frm.trigger('get_pending_amount')
+			]);
 		}
+	},
+
+	get_pending_amount: function(frm) {
+		frappe.call({
+			method: "erpnext.hr.doctype.employee_advance.employee_advance.get_pending_amount",
+			args: {
+				"employee": frm.doc.employee,
+				"posting_date": frm.doc.posting_date
+			},
+			callback: function(r) {
+				frm.set_value("pending_amount", r.message);
+			}
+		});
+	},
+
+	get_employee_currency: function(frm) {
+		frappe.call({
+			method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+			args: {
+				employee: frm.doc.employee,
+			},
+			callback: function(r) {
+				if (r.message) {
+					frm.set_value('currency', r.message);
+					frm.refresh_fields();
+				}
+			}
+		});
+	},
+
+	currency: function(frm) {
+		var from_currency = frm.doc.currency;
+		var company_currency;
+		if (!frm.doc.company) {
+			company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
+		} else {
+			company_currency = erpnext.get_currency(frm.doc.company);
+		}
+		if (from_currency != company_currency) {
+			frm.events.set_exchange_rate(frm, from_currency, company_currency);
+		} else {
+			frm.set_value("exchange_rate", 1.0);
+			frm.set_df_property('exchange_rate', 'hidden', 1);
+			frm.set_df_property("exchange_rate", "description", "" );
+		}
+		frm.refresh_fields();
+	},
+
+	set_exchange_rate: function(frm, from_currency, company_currency) {
+		frappe.call({
+			method: "erpnext.setup.utils.get_exchange_rate",
+			args: {
+				from_currency: from_currency,
+				to_currency: company_currency,
+			},
+			callback: function(r) {
+				frm.set_value("exchange_rate", flt(r.message));
+				frm.set_df_property('exchange_rate', 'hidden', 0);
+				frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
+					+ " = [?] " + company_currency);
+			}
+		});
 	}
 });
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json
index 0d90913..cf6b540 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.json
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.json
@@ -13,6 +13,8 @@
   "department",
   "column_break_4",
   "posting_date",
+  "currency",
+  "exchange_rate",
   "repay_unclaimed_amount_from_salary",
   "section_break_8",
   "purpose",
@@ -91,7 +93,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Advance Amount",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "reqd": 1
   },
   {
@@ -99,7 +101,7 @@
    "fieldtype": "Currency",
    "label": "Paid Amount",
    "no_copy": 1,
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -107,7 +109,7 @@
    "fieldtype": "Currency",
    "label": "Claimed Amount",
    "no_copy": 1,
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -161,7 +163,7 @@
    "fieldname": "return_amount",
    "fieldtype": "Currency",
    "label": "Returned Amount",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -175,13 +177,31 @@
    "fieldname": "pending_amount",
    "fieldtype": "Currency",
    "label": "Pending Amount",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.employee)",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "reqd": 1
+  },
+  {
+   "depends_on": "currency",
+   "fieldname": "exchange_rate",
+   "fieldtype": "Float",
+   "label": "Exchange Rate",
+   "precision": "9",
+   "print_hide": 1,
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-12 12:42:39.833818",
+ "modified": "2020-11-25 12:01:55.980721",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Advance",
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 3c435b8..cb72f6b 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -19,7 +19,6 @@
 
 	def validate(self):
 		self.set_status()
-		self.validate_employee_advance_account()
 
 	def on_cancel(self):
 		self.ignore_linked_doctypes = ('GL Entry')
@@ -38,16 +37,9 @@
 		elif self.docstatus == 2:
 			self.status = "Cancelled"
 
-	def validate_employee_advance_account(self):
-		company_currency = erpnext.get_company_currency(self.company)
-		if (self.advance_account and
-			company_currency != frappe.db.get_value('Account', self.advance_account, 'account_currency')):
-			frappe.throw(_("Advance account currency should be same as company currency {0}")
-				.format(company_currency))
-
 	def set_total_advance_paid(self):
 		paid_amount = frappe.db.sql("""
-			select ifnull(sum(debit_in_account_currency), 0) as paid_amount
+			select ifnull(sum(debit), 0) as paid_amount
 			from `tabGL Entry`
 			where against_voucher_type = 'Employee Advance'
 				and against_voucher = %s
@@ -56,7 +48,7 @@
 		""", (self.name, self.employee), as_dict=1)[0].paid_amount
 
 		return_amount = frappe.db.sql("""
-			select name, ifnull(sum(credit_in_account_currency), 0) as return_amount
+			select ifnull(sum(credit), 0) as return_amount
 			from `tabGL Entry`
 			where against_voucher_type = 'Employee Advance'
 				and voucher_type != 'Expense Claim'
@@ -65,6 +57,11 @@
 				and party = %s
 		""", (self.name, self.employee), as_dict=1)[0].return_amount
 
+		if paid_amount != 0:
+			paid_amount = flt(paid_amount) / flt(self.exchange_rate)
+		if return_amount != 0:
+			return_amount = flt(return_amount) / flt(self.exchange_rate)
+
 		if flt(paid_amount) > self.advance_amount:
 			frappe.throw(_("Row {0}# Paid Amount cannot be greater than requested advance amount"),
 				EmployeeAdvanceOverPayment)
@@ -107,16 +104,27 @@
 	doc = frappe.get_doc(dt, dn)
 	payment_account = get_default_bank_cash_account(doc.company, account_type="Cash",
 		mode_of_payment=doc.mode_of_payment)
+	if not payment_account:
+		frappe.throw(_("Please set a Default Cash Account in Company defaults"))
+
+	advance_account_currency = frappe.db.get_value('Account', doc.advance_account, 'account_currency')
+
+	advance_amount, advance_exchange_rate = get_advance_amount_advance_exchange_rate(advance_account_currency,doc )
+
+	paying_amount, paying_exchange_rate = get_paying_amount_paying_exchange_rate(payment_account, doc)
 
 	je = frappe.new_doc("Journal Entry")
 	je.posting_date = nowdate()
 	je.voucher_type = 'Bank Entry'
 	je.company = doc.company
 	je.remark = 'Payment against Employee Advance: ' + dn + '\n' + doc.purpose
+	je.multi_currency = 1 if advance_account_currency != payment_account.account_currency else 0
 
 	je.append("accounts", {
 		"account": doc.advance_account,
-		"debit_in_account_currency": flt(doc.advance_amount),
+		"account_currency": advance_account_currency,
+		"exchange_rate": flt(advance_exchange_rate),
+		"debit_in_account_currency": flt(advance_amount),
 		"reference_type": "Employee Advance",
 		"reference_name": doc.name,
 		"party_type": "Employee",
@@ -128,19 +136,41 @@
 	je.append("accounts", {
 		"account": payment_account.account,
 		"cost_center": erpnext.get_default_cost_center(doc.company),
-		"credit_in_account_currency": flt(doc.advance_amount),
+		"credit_in_account_currency": flt(paying_amount),
 		"account_currency": payment_account.account_currency,
-		"account_type": payment_account.account_type
+		"account_type": payment_account.account_type,
+		"exchange_rate": flt(paying_exchange_rate)
 	})
 
 	return je.as_dict()
 
+def get_advance_amount_advance_exchange_rate(advance_account_currency, doc):
+	if advance_account_currency != doc.currency:
+		advance_amount = flt(doc.advance_amount) * flt(doc.exchange_rate)
+		advance_exchange_rate = 1
+	else:
+		advance_amount = doc.advance_amount
+		advance_exchange_rate = doc.exchange_rate
+
+	return advance_amount, advance_exchange_rate
+
+def get_paying_amount_paying_exchange_rate(payment_account, doc):
+	if payment_account.account_currency != doc.currency:
+		paying_amount = flt(doc.advance_amount) * flt(doc.exchange_rate)
+		paying_exchange_rate = 1
+	else:
+		paying_amount = doc.advance_amount
+		paying_exchange_rate = doc.exchange_rate
+
+	return paying_amount, paying_exchange_rate
+
 @frappe.whitelist()
 def create_return_through_additional_salary(doc):
 	import json
 	doc = frappe._dict(json.loads(doc))
 	additional_salary = frappe.new_doc('Additional Salary')
 	additional_salary.employee = doc.employee
+	additional_salary.currency = doc.currency
 	additional_salary.amount = doc.paid_amount - doc.claimed_amount
 	additional_salary.company = doc.company
 	additional_salary.ref_doctype = doc.doctype
@@ -149,26 +179,28 @@
 	return additional_salary
 
 @frappe.whitelist()
-def make_return_entry(employee, company, employee_advance_name, return_amount,  advance_account, mode_of_payment=None):
-	return_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment)
-
-	mode_of_payment_type = ''
-	if mode_of_payment:
-		mode_of_payment_type = frappe.get_cached_value('Mode of Payment', mode_of_payment, 'type')
-		if mode_of_payment_type not in ["Cash", "Bank"]:
-			# if mode of payment is General then it unset the type
-			mode_of_payment_type = None
-
+def make_return_entry(employee, company, employee_advance_name, return_amount,  advance_account, currency, exchange_rate, mode_of_payment=None):
+	bank_cash_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment)
+	if not bank_cash_account:
+		frappe.throw(_("Please set a Default Cash Account in Company defaults"))
+	
+	advance_account_currency = frappe.db.get_value('Account', advance_account, 'account_currency')
+	
 	je = frappe.new_doc('Journal Entry')
 	je.posting_date = nowdate()
-	# if mode of payment is Bank then voucher type is Bank Entry
-	je.voucher_type = '{} Entry'.format(mode_of_payment_type) if mode_of_payment_type else 'Cash Entry'
+	je.voucher_type = get_voucher_type(mode_of_payment)
 	je.company = company
 	je.remark = 'Return against Employee Advance: ' + employee_advance_name
+	je.multi_currency = 1 if advance_account_currency != bank_cash_account.account_currency else 0
+
+	advance_account_amount = flt(return_amount) if advance_account_currency==currency \
+		else flt(return_amount) * flt(exchange_rate)
 
 	je.append('accounts', {
 		'account': advance_account,
-		'credit_in_account_currency': return_amount,
+		'credit_in_account_currency': advance_account_amount,
+		'account_currency': advance_account_currency,
+		'exchange_rate': flt(exchange_rate) if advance_account_currency == currency else 1,
 		'reference_type': 'Employee Advance',
 		'reference_name': employee_advance_name,
 		'party_type': 'Employee',
@@ -176,13 +208,25 @@
 		'is_advance': 'Yes'
 	})
 
+	bank_amount = flt(return_amount) if bank_cash_account.account_currency==currency \
+		else flt(return_amount) * flt(exchange_rate)
+
 	je.append("accounts", {
-		"account": return_account.account,
-		"debit_in_account_currency": return_amount,
-		"account_currency": return_account.account_currency,
-		"account_type": return_account.account_type
+		"account": bank_cash_account.account,
+		"debit_in_account_currency": bank_amount,
+		"account_currency": bank_cash_account.account_currency,
+		"account_type": bank_cash_account.account_type,
+		"exchange_rate": flt(exchange_rate) if bank_cash_account.account_currency == currency else 1
 	})
 
 	return je.as_dict()
 
+def get_voucher_type(mode_of_payment=None):
+	voucher_type = "Cash Entry"
 
+	if mode_of_payment:
+		mode_of_payment_type = frappe.get_cached_value('Mode of Payment', mode_of_payment, 'type')
+		if mode_of_payment_type == "Bank":
+			voucher_type = "Bank Entry"
+
+	return voucher_type
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_advance/test_employee_advance.py b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
index 2097e71..c88b2b8 100644
--- a/erpnext/hr/doctype/employee_advance/test_employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
@@ -3,15 +3,17 @@
 # See license.txt
 from __future__ import unicode_literals
 
-import frappe
+import frappe, erpnext
 import unittest
 from frappe.utils import nowdate
 from erpnext.hr.doctype.employee_advance.employee_advance import make_bank_entry
 from erpnext.hr.doctype.employee_advance.employee_advance import EmployeeAdvanceOverPayment
+from erpnext.hr.doctype.employee.test_employee import make_employee
 
 class TestEmployeeAdvance(unittest.TestCase):
 	def test_paid_amount_and_status(self):
-		advance = make_employee_advance()
+		employee_name = make_employee("_T@employe.advance")
+		advance = make_employee_advance(employee_name)
 
 		journal_entry = make_payment_entry(advance)
 		journal_entry.submit()
@@ -33,11 +35,13 @@
 
 	return journal_entry
 
-def make_employee_advance():
+def make_employee_advance(employee_name):
 	doc = frappe.new_doc("Employee Advance")
-	doc.employee = "_T-Employee-00001"
+	doc.employee = employee_name
 	doc.company  = "_Test company"
 	doc.purpose = "For site visit"
+	doc.currency = erpnext.get_company_currency("_Test company")
+	doc.exchange_rate = 1
 	doc.advance_amount = 1000
 	doc.posting_date = nowdate()
 	doc.advance_account = "_Test Employee Advance - _TC"
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
index 6e97f05..4a0908d 100644
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
@@ -7,6 +7,7 @@
 from frappe.utils import random_string, nowdate
 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
 
 test_records = frappe.get_test_records('Expense Claim')
 test_dependencies = ['Employee']
@@ -126,6 +127,9 @@
 
 def make_expense_claim(payable_account, amount, sanctioned_amount, company, account, project=None, task_name=None, do_not_submit=False, taxes=None):
 	employee = frappe.db.get_value("Employee", {"status": "Active"})
+	if not employee:
+		employee = make_employee("test_employee@expense_claim.com", company=company)
+
 	currency, cost_center = frappe.db.get_value('Company', company, ['default_currency', 'cost_center'])
 	expense_claim = {
 		 "doctype": "Expense Claim",
diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json
index 885e3ee..020457d 100644
--- a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json
+++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json
@@ -71,9 +71,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Amount",
-   "oldfieldname": "tax_amount",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   },
   {
    "columns": 2,
@@ -81,9 +79,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Total",
-   "oldfieldname": "total",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -106,7 +102,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-05-11 19:01:26.611758",
+ "modified": "2020-09-23 20:27:36.027728",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Expense Taxes and Charges",
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.js b/erpnext/hr/doctype/leave_encashment/leave_encashment.js
index 71a3422..81936a4 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.js
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.js
@@ -22,7 +22,12 @@
 		}
 	},
 	employee: function(frm) {
-		frm.trigger("get_leave_details_for_encashment");
+		if (frm.doc.employee) {
+			frappe.run_serially([
+				() => 	frm.trigger('get_employee_currency'),
+				() => 	frm.trigger('get_leave_details_for_encashment')
+			]);
+		}
 	},
 	leave_type: function(frm) {
 		frm.trigger("get_leave_details_for_encashment");
@@ -40,5 +45,20 @@
 				}
 			});
 		}
-	}
+	},
+
+	get_employee_currency: function(frm) {
+		frappe.call({
+			method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+			args: {
+				employee: frm.doc.employee,
+			},
+			callback: function(r) {
+				if (r.message) {
+					frm.set_value('currency', r.message);
+					frm.refresh_fields();
+				}
+			}
+		});
+	},
 });
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.json b/erpnext/hr/doctype/leave_encashment/leave_encashment.json
index 2cf6ccf..83eeae3 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.json
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.json
@@ -12,6 +12,7 @@
   "employee",
   "employee_name",
   "department",
+  "company",
   "column_break_4",
   "leave_type",
   "leave_allocation",
@@ -19,9 +20,11 @@
   "encashable_days",
   "amended_from",
   "payroll",
-  "encashment_amount",
   "encashment_date",
-  "additional_salary"
+  "additional_salary",
+  "column_break_14",
+  "currency",
+  "encashment_amount"
  ],
  "fields": [
   {
@@ -109,6 +112,7 @@
    "in_list_view": 1,
    "label": "Encashment Amount",
    "no_copy": 1,
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -124,11 +128,34 @@
    "no_copy": 1,
    "options": "Additional Salary",
    "read_only": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.employee)",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "employee.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-16 11:51:57.732223",
+ "modified": "2020-11-25 11:56:06.777241",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Leave Encashment",
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
index c1dcc97..4c1a465 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
@@ -16,10 +16,16 @@
 	def validate(self):
 		set_employee_name(self)
 		self.get_leave_details_for_encashment()
+		self.validate_salary_structure()
 
 		if not self.encashment_date:
 			self.encashment_date = getdate(nowdate())
 
+	def validate_salary_structure(self):
+		if not frappe.db.exists('Salary Structure Assignment', {'employee': self.employee}):
+			frappe.throw(_("There is no Salary Structure assigned to {0}. First assign a Salary Stucture.").format(self.employee))
+
+
 	def before_submit(self):
 		if self.encashment_amount <= 0:
 			frappe.throw(_("You can only submit Leave Encashment for a valid encashment amount"))
@@ -30,6 +36,7 @@
 		additional_salary = frappe.new_doc("Additional Salary")
 		additional_salary.company = frappe.get_value("Employee", self.employee, "company")
 		additional_salary.employee = self.employee
+		additional_salary.currency = self.currency
 		earning_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
 		if not earning_component:
 			frappe.throw(_("Please set Earning Component for Leave type: {0}.").format(self.leave_type))
diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
index bbee18b..aafc964 100644
--- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
@@ -48,6 +48,10 @@
 		frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]).grant_leave_alloc_for_employee()
 
 
+	def tearDown(self):
+		for dt in ["Leave Period", "Leave Allocation", "Leave Ledger Entry", "Additional Salary", "Leave Encashment", "Salary Structure", "Leave Policy"]:
+			frappe.db.sql("delete from `tab%s`" % dt)
+
 	def test_leave_balance_value_and_amount(self):
 		frappe.db.sql('''delete from `tabLeave Encashment`''')
 		leave_encashment = frappe.get_doc(dict(
@@ -55,7 +59,8 @@
 			employee=self.employee,
 			leave_type="_Test Leave Type Encashment",
 			leave_period=self.leave_period.name,
-			payroll_date=today()
+			payroll_date=today(),
+			currency="INR"
 		)).insert()
 
 		self.assertEqual(leave_encashment.leave_balance, 10)
@@ -75,7 +80,8 @@
 			employee=self.employee,
 			leave_type="_Test Leave Type Encashment",
 			leave_period=self.leave_period.name,
-			payroll_date=today()
+			payroll_date=today(),
+			currency="INR"
 		)).insert()
 
 		leave_encashment.submit()
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index d468f52..acf09f5 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -26,11 +26,11 @@
   "disbursed_amount",
   "column_break_11",
   "maximum_loan_amount",
-  "is_term_loan",
   "repayment_method",
   "repayment_periods",
   "monthly_repayment_amount",
   "repayment_start_date",
+  "is_term_loan",
   "account_info",
   "mode_of_payment",
   "payment_account",
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 8405d6e..cd40a66 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -13,6 +13,8 @@
 
 class Loan(AccountsController):
 	def validate(self):
+		if self.applicant_type == 'Employee' and self.repay_from_salary:
+			validate_employee_currency_with_company_currency(self.applicant, self.company)
 		self.set_loan_amount()
 		self.validate_loan_amount()
 		self.set_missing_fields()
@@ -329,5 +331,14 @@
 
 	return unpledge_request
 
-
-
+def validate_employee_currency_with_company_currency(applicant, company):
+		from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_employee_currency
+		if not applicant:
+			frappe.throw(_("Please select Applicant"))
+		if not company:
+			frappe.throw(_("Please select Company"))
+		employee_currency = get_employee_currency(applicant)
+		company_currency = erpnext.get_company_currency(company)
+		if employee_currency != company_currency:
+			frappe.throw(_("Loan cannot be repayed from salary for Employee {0} because salary is processed in currency {1}")
+				.format(applicant, employee_currency))
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 10a7b11..a63d065 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -19,6 +19,7 @@
 from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
 from erpnext.loan_management.doctype.loan_disbursement.loan_disbursement import get_disbursal_amount
 from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
+from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
 
 class TestLoan(unittest.TestCase):
 	def setUp(self):
@@ -44,6 +45,7 @@
 		create_loan_security_price("Test Security 2", 250, "Nos", get_datetime() , get_datetime(add_to_date(nowdate(), hours=24)))
 
 		self.applicant1 = make_employee("robert_loan@loan.com")
+		make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant1, currency='INR')
 		if not frappe.db.exists("Customer", "_Test Loan Customer"):
 			frappe.get_doc(get_customer_dict('_Test Loan Customer')).insert(ignore_permissions=True)
 
diff --git a/erpnext/loan_management/doctype/loan_application/test_loan_application.py b/erpnext/loan_management/doctype/loan_application/test_loan_application.py
index 687c580..2a659e9 100644
--- a/erpnext/loan_management/doctype/loan_application/test_loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/test_loan_application.py
@@ -5,7 +5,7 @@
 
 import frappe
 import unittest
-from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee
+from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee, make_salary_structure
 from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan_accounts
 
 class TestLoanApplication(unittest.TestCase):
@@ -14,6 +14,7 @@
 		create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
 			'Interest Income Account - _TC', 'Penalty Income Account - _TC', 'Repay Over Number of Periods', 18)
 		self.applicant = make_employee("kate_loan@loan.com", "_Test Company")
+		make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency='INR')
 		self.create_loan_application()
 
 	def create_loan_application(self):
@@ -29,7 +30,6 @@
 		})
 		loan_application.insert()
 
-
 	def test_loan_totals(self):
 		loan_application = frappe.get_doc("Loan Application", {"applicant":self.applicant})
 
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 8888a96..6363242 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -169,8 +169,8 @@
 			 'qty'			: args.get("qty") or args.get("stock_qty") or 1,
 			 'stock_qty'	: args.get("qty") or args.get("stock_qty") or 1,
 			 'base_rate'	: flt(rate) * (flt(self.conversion_rate) or 1),
-			 'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0,
-			 'sourced_by_supplier'		: args['sourced_by_supplier'] or 0
+			 'include_item_in_manufacturing': cint(args.get('transfer_for_manufacture')),
+			 'sourced_by_supplier'		: args.get('sourced_by_supplier', 0)
 		}
 
 		return ret_item
diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
index ebc01c6..806d268 100644
--- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
+++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
@@ -124,7 +124,7 @@
 				if self.filters.include_subassembly_raw_materials else "(bom_item.qty / bom.quantity)")
 
 			raw_materials = frappe.db.sql(""" SELECT bom_item.parent, bom_item.item_code,
-					bom_item.item_name as raw_material_name, {0} as required_qty
+					bom_item.item_name as raw_material_name, {0} as required_qty_per_unit
 				FROM
 					`tabBOM` as bom, `tab{1}` as bom_item
 				WHERE
@@ -208,7 +208,7 @@
 		warehouses = self.mrp_warehouses or []
 		for d in self.raw_materials_dict.get(key):
 			if self.filters.based_on != "Work Order":
-				d.required_qty = d.required_qty * data.qty_to_manufacture
+				d.required_qty = d.required_qty_per_unit * data.qty_to_manufacture
 
 			if not warehouses:
 				warehouses = [data.warehouse]
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index 1e2aeea..62f5dce 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -25,4 +25,5 @@
 Quality Management
 Communication
 Loan Management
-Payroll
\ No newline at end of file
+Payroll
+Telephony
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 98b2fcd..86ac613 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -691,6 +691,7 @@
 erpnext.patches.v12_0.set_serial_no_status #2020-05-21
 erpnext.patches.v12_0.update_price_list_currency_in_bom
 execute:frappe.reload_doctype('Dashboard')
+execute:frappe.reload_doc('desk', 'doctype', 'number_card_link')
 execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts')
 erpnext.patches.v13_0.update_actual_start_and_end_date_in_wo
 erpnext.patches.v13_0.set_company_field_in_healthcare_doctypes #2020-05-25
@@ -732,7 +733,11 @@
 erpnext.patches.v13_0.print_uom_after_quantity_patch
 erpnext.patches.v13_0.set_payment_channel_in_payment_gateway_account
 erpnext.patches.v13_0.create_healthcare_custom_fields_in_stock_entry_detail
+erpnext.patches.v13_0.updates_for_multi_currency_payroll
 erpnext.patches.v13_0.update_reason_for_resignation_in_employee
 erpnext.patches.v13_0.update_custom_fields_for_shopify
 execute:frappe.delete_doc("Report", "Quoted Item Comparison")
+erpnext.patches.v13_0.updates_for_multi_currency_payroll
 erpnext.patches.v13_0.create_leave_policy_assignment_based_on_employee_current_leave_policy
+erpnext.patches.v13_0.add_po_to_global_search
+erpnext.patches.v13_0.update_returned_qty_in_pr_dn
diff --git a/erpnext/patches/v11_0/create_salary_structure_assignments.py b/erpnext/patches/v11_0/create_salary_structure_assignments.py
index c51c381..a908c16 100644
--- a/erpnext/patches/v11_0/create_salary_structure_assignments.py
+++ b/erpnext/patches/v11_0/create_salary_structure_assignments.py
@@ -8,8 +8,8 @@
 from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import DuplicateAssignment
 
 def execute():
-	frappe.reload_doc('Payroll', 'doctype', 'salary_structure')
-	frappe.reload_doc("Payroll", "doctype", "salary_structure_assignment")
+	frappe.reload_doc('Payroll', 'doctype', 'Salary Structure')
+	frappe.reload_doc("Payroll", "doctype", "Salary Structure Assignment")
 	frappe.db.sql("""
 		delete from `tabSalary Structure Assignment`
 		where salary_structure in (select name from `tabSalary Structure` where is_active='No' or docstatus!=1)
@@ -33,6 +33,13 @@
 			AND employee in (select name from `tabEmployee` where ifNull(status, '') != 'Left')
 		""".format(cols), as_dict=1)
 
+	all_companies = frappe.db.get_all("Company", fields=["name", "default_currency"])
+	for d in all_companies:
+		company = d.name
+		company_currency = d.default_currency
+
+		frappe.db.sql("""update `tabSalary Structure` set currency = %s where company=%s""", (company_currency, company))
+
 	for d in ss_details:
 		try:
 			joining_date, relieving_date = frappe.db.get_value("Employee", d.employee,
@@ -42,6 +49,7 @@
 				from_date = joining_date
 			elif relieving_date and getdate(from_date) > relieving_date:
 				continue
+			company_currency = frappe.db.get_value('Company', d.company, 'default_currency')
 
 			s = frappe.new_doc("Salary Structure Assignment")
 			s.employee = d.employee
@@ -52,6 +60,7 @@
 			s.base = d.get("base")
 			s.variable = d.get("variable")
 			s.company = d.company
+			s.currency = company_currency
 
 			# to migrate the data of the old employees
 			s.flags.old_employee = True
diff --git a/erpnext/patches/v13_0/add_po_to_global_search.py b/erpnext/patches/v13_0/add_po_to_global_search.py
new file mode 100644
index 0000000..1c60b18
--- /dev/null
+++ b/erpnext/patches/v13_0/add_po_to_global_search.py
@@ -0,0 +1,17 @@
+from __future__ import unicode_literals
+import frappe
+
+
+def execute():
+    global_search_settings = frappe.get_single("Global Search Settings")
+
+    if "Purchase Order" in (
+        dt.document_type for dt in global_search_settings.allowed_in_global_search
+    ):
+        return
+
+    global_search_settings.append(
+        "allowed_in_global_search", {"document_type": "Purchase Order"}
+    )
+
+    global_search_settings.save(ignore_permissions=True)
diff --git a/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py b/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py
index 80c9137..90dc0e2 100644
--- a/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py
+++ b/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py
@@ -52,6 +52,8 @@
     if leave_period:
         filters["leave_period"] = leave_period
 
+    frappe.reload_doc('hr', 'doctype', 'leave_policy_assignment')
+
     if not frappe.db.exists("Leave Policy Assignment" , filters):
         lpa = frappe.new_doc("Leave Policy Assignment")
         lpa.employee = employee
diff --git a/erpnext/patches/v13_0/rename_issue_doctype_fields.py b/erpnext/patches/v13_0/rename_issue_doctype_fields.py
index 96a6362..fa1dfed 100644
--- a/erpnext/patches/v13_0/rename_issue_doctype_fields.py
+++ b/erpnext/patches/v13_0/rename_issue_doctype_fields.py
@@ -29,7 +29,7 @@
 				'response_by_variance': response_by_variance,
 				'resolution_by_variance': resolution_by_variance,
 				'first_response_time': mins_to_first_response
-			})
+			}, update_modified=False)
 			# commit after every 100 updates
 			count += 1
 			if count%100 == 0:
@@ -44,7 +44,7 @@
 		count = 0
 		for entry in opportunities:
 			mins_to_first_response = convert_to_seconds(entry.mins_to_first_response, 'Minutes')
-			frappe.db.set_value('Opportunity', entry.name, 'first_response_time', mins_to_first_response)
+			frappe.db.set_value('Opportunity', entry.name, 'first_response_time', mins_to_first_response, update_modified=False)
 			# commit after every 100 updates
 			count += 1
 			if count%100 == 0:
diff --git a/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py b/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py
new file mode 100644
index 0000000..7f42cd9
--- /dev/null
+++ b/erpnext/patches/v13_0/update_returned_qty_in_pr_dn.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
+	frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
+	frappe.reload_doc('stock', 'doctype', 'delivery_note')
+	frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
+
+	def update_from_return_docs(doctype):
+		for return_doc in frappe.get_all(doctype, filters={'is_return' : 1, 'docstatus' : 1}):
+			# Update original receipt/delivery document from return
+			return_doc = frappe.get_cached_doc(doctype, return_doc.name)
+			return_doc.update_prevdoc_status()
+			return_against = frappe.get_doc(doctype, return_doc.return_against)
+			return_against.update_billing_status()
+
+	# Set received qty in stock uom in PR, as returned qty is checked against it
+	frappe.db.sql(""" update `tabPurchase Receipt Item`
+		set received_stock_qty = received_qty * conversion_factor
+		where docstatus = 1 """)
+
+	for doctype in ('Purchase Receipt', 'Delivery Note'):
+		update_from_return_docs(doctype)
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py b/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py
new file mode 100644
index 0000000..340bf49
--- /dev/null
+++ b/erpnext/patches/v13_0/updates_for_multi_currency_payroll.py
@@ -0,0 +1,136 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+from frappe import _
+from frappe.model.utils.rename_field import rename_field
+
+def execute():
+
+	frappe.reload_doc('Accounts', 'doctype', 'Salary Component Account')
+	if frappe.db.has_column('Salary Component Account', 'default_account'):
+		rename_field("Salary Component Account", "default_account", "account")
+
+	doctype_list = [
+		{
+		'module':'HR',
+		'doctype':'Employee Advance'
+		},
+		{
+		'module':'HR',
+		'doctype':'Leave Encashment'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Additional Salary'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Employee Benefit Application'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Employee Benefit Claim'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Employee Incentive'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Employee Tax Exemption Declaration'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Employee Tax Exemption Proof Submission'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Income Tax Slab'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Payroll Entry'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Retention Bonus'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Salary Structure'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Salary Structure Assignment'
+		},
+		{
+		'module':'Payroll',
+		'doctype':'Salary Slip'
+		},
+	]
+
+	for item in doctype_list:
+		frappe.reload_doc(item['module'], 'doctype', item['doctype'])
+
+	# update company in employee advance based on employee company
+	for dt in ['Employee Incentive', 'Leave Encashment', 'Employee Benefit Application', 'Employee Benefit Claim']:
+		frappe.db.sql("""
+			update `tab{doctype}`
+			set company = (select company from tabEmployee where name=`tab{doctype}`.employee)
+		""".format(doctype=dt))
+
+	# update exchange rate for employee advance
+	frappe.db.sql("update `tabEmployee Advance` set exchange_rate=1")
+
+	# get all companies and it's currency
+	all_companies = frappe.db.get_all("Company", fields=["name", "default_currency", "default_payroll_payable_account"])
+	for d in all_companies:
+		company = d.name
+		company_currency = d.default_currency
+		default_payroll_payable_account = d.default_payroll_payable_account
+
+		if not default_payroll_payable_account:
+			default_payroll_payable_account = frappe.db.get_value("Account",
+				{"account_name": _("Payroll Payable"), "company": company, "account_currency": company_currency, "is_group": 0})
+
+		# update currency in following doctypes based on company currency
+		doctypes_for_currency = ['Employee Advance', 'Leave Encashment', 'Employee Benefit Application',
+			'Employee Benefit Claim', 'Employee Incentive', 'Additional Salary', 
+			'Employee Tax Exemption Declaration', 'Employee Tax Exemption Proof Submission', 
+			'Income Tax Slab', 'Retention Bonus', 'Salary Structure']
+
+		for dt in doctypes_for_currency:
+			frappe.db.sql("""update `tab{doctype}` set currency = %s where company=%s"""
+				.format(doctype=dt), (company_currency, company))
+
+		# update fields in payroll entry
+		frappe.db.sql("""
+			update `tabPayroll Entry`
+			set currency = %s,
+				exchange_rate = 1,
+				payroll_payable_account=%s
+			where company=%s
+		""", (company_currency, default_payroll_payable_account, company))
+
+		# update fields in Salary Structure Assignment
+		frappe.db.sql("""
+			update `tabSalary Structure Assignment`
+			set currency = %s,
+				payroll_payable_account=%s
+			where company=%s
+		""", (company_currency, default_payroll_payable_account, company))
+
+		# update fields in Salary Slip
+		frappe.db.sql("""
+			update `tabSalary Slip`
+			set currency = %s,
+				exchange_rate = 1,
+				base_hour_rate = hour_rate,
+				base_gross_pay = gross_pay,
+				base_total_deduction = total_deduction,
+				base_net_pay = net_pay,
+				base_rounded_total = rounded_total,
+				base_total_in_words = total_in_words
+			where company=%s
+		""", (company_currency, company))
diff --git a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py b/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
index 6e92ffb..910814f 100644
--- a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
+++ b/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
@@ -7,19 +7,23 @@
 def execute():
 	parent_list = []
 	count = 0
-	for data in frappe.db.sql(""" 
-		select 
+
+	frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
+	frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
+
+	for data in frappe.db.sql("""
+		select
 			`tabPurchase Receipt Item`.purchase_order, `tabPurchase Receipt Item`.name,
 			`tabPurchase Receipt Item`.item_code, `tabPurchase Receipt Item`.idx,
 			`tabPurchase Receipt Item`.parent
-		from 
+		from
 			`tabPurchase Receipt Item`, `tabPurchase Receipt`
 		where
 			`tabPurchase Receipt Item`.parent = `tabPurchase Receipt`.name and
 			`tabPurchase Receipt Item`.purchase_order_item is null and
 			`tabPurchase Receipt Item`.purchase_order is not null and
 			`tabPurchase Receipt`.is_return = 1""", as_dict=1):
-			name = frappe.db.get_value('Purchase Order Item', 
+			name = frappe.db.get_value('Purchase Order Item',
 				{'item_code': data.item_code, 'parent': data.purchase_order, 'idx': data.idx}, 'name')
 
 			if name:
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.js b/erpnext/payroll/doctype/additional_salary/additional_salary.js
index d56cd4e..0784de9 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.js
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.js
@@ -12,5 +12,57 @@
 				}
 			};
 		});
+
+		if (!frm.doc.currency) return;
+		frm.set_query("salary_component", function() {
+			return {
+				query: "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
+				filters: {currency: frm.doc.currency, company: frm.doc.company}
+			};
+		});
+	},
+
+	employee: function(frm) {
+		if (frm.doc.employee) {
+			frappe.run_serially([
+				() => 	frm.trigger('get_employee_currency'),
+				() => 	frm.trigger('set_company')
+			]);
+		} else {
+			frm.set_value("company", null);
+		}
+	},
+
+	set_company: function(frm) {
+		frappe.call({
+			method: "frappe.client.get_value",
+			args: {
+				doctype: "Employee",
+				fieldname: "company",
+				filters: {
+					name: frm.doc.employee
+				}
+			},
+			callback: function(data) {
+				if (data.message) {
+					frm.set_value("company", data.message.company);
+				}
+			}
+		});
+	},
+
+	get_employee_currency: function(frm) {
+		frappe.call({
+			method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+			args: {
+				employee: frm.doc.employee,
+			},
+			callback: function(r) {
+				if (r.message) {
+					frm.set_value('currency', r.message);
+					frm.refresh_fields();
+				}
+			}
+		});
 	},
 });
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.json b/erpnext/payroll/doctype/additional_salary/additional_salary.json
index 69cb5da..2b29f66 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.json
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.json
@@ -11,20 +11,21 @@
   "employee",
   "employee_name",
   "salary_component",
-  "overwrite_salary_structure_amount",
-  "deduct_full_tax_on_selected_payroll_date",
+  "type",
+  "amount",
   "ref_doctype",
   "ref_docname",
+  "amended_from",
   "column_break_5",
   "company",
-  "is_recurring",
+  "department",
+  "currency",
   "from_date",
   "to_date",
   "payroll_date",
-  "type",
-  "department",
-  "amount",
-  "amended_from"
+  "is_recurring",
+  "overwrite_salary_structure_amount",
+  "deduct_full_tax_on_selected_payroll_date"
  ],
  "fields": [
   {
@@ -59,6 +60,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Amount",
+   "options": "currency",
    "reqd": 1
   },
   {
@@ -159,11 +161,22 @@
    "label": "Reference Document",
    "options": "ref_doctype",
    "read_only": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.employee)",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 21:10:50.374063",
+ "modified": "2020-10-20 17:51:13.419716",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Additional Salary",
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.py b/erpnext/payroll/doctype/additional_salary/additional_salary.py
index e3dc907..f5af677 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.py
@@ -22,10 +22,15 @@
 
 	def validate(self):
 		self.validate_dates()
+		self.validate_salary_structure()
 		self.validate_recurring_additional_salary_overlap()
 		if self.amount < 0:
 			frappe.throw(_("Amount should not be less than zero."))
 
+	def validate_salary_structure(self):
+		if not frappe.db.exists('Salary Structure Assignment', {'employee': self.employee}):
+			frappe.throw(_("There is no Salary Structure assigned to {0}. First assign a Salary Stucture.").format(self.employee))
+
 	def validate_recurring_additional_salary_overlap(self):
 		if self.is_recurring:
 			additional_salaries = frappe.db.sql("""
diff --git a/erpnext/payroll/doctype/additional_salary/test_additional_salary.py b/erpnext/payroll/doctype/additional_salary/test_additional_salary.py
index de26543..4d47f25 100644
--- a/erpnext/payroll/doctype/additional_salary/test_additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/test_additional_salary.py
@@ -8,6 +8,7 @@
 from erpnext.hr.doctype.employee.test_employee import make_employee
 from erpnext.payroll.doctype.salary_component.test_salary_component import create_salary_component
 from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_employee_salary_slip, setup_test
+from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
 
 
 class TestAdditionalSalary(unittest.TestCase):
@@ -15,12 +16,19 @@
 	def setUp(self):
 		setup_test()
 
+	def tearDown(self):
+		for dt in ["Salary Slip", "Additional Salary", "Salary Structure Assignment", "Salary Structure"]:
+			frappe.db.sql("delete from `tab%s`" % dt)
+
 	def test_recurring_additional_salary(self):
+		amount = 0
+		salary_component = None
 		emp_id = make_employee("test_additional@salary.com")
 		frappe.db.set_value("Employee", emp_id, "relieving_date", add_days(nowdate(), 1800))
+		salary_structure = make_salary_structure("Test Salary Structure Additional Salary", "Monthly", employee=emp_id)
 		add_sal = get_additional_salary(emp_id)
-
-		ss = make_employee_salary_slip("test_additional@salary.com", "Monthly")
+		
+		ss = make_employee_salary_slip("test_additional@salary.com", "Monthly", salary_structure=salary_structure.name)
 		for earning in ss.earnings:
 			if earning.salary_component == "Recurring Salary Component":
 				amount = earning.amount
@@ -29,8 +37,6 @@
 		self.assertEqual(amount, add_sal.amount)
 		self.assertEqual(salary_component, add_sal.salary_component)
 
-
-
 def get_additional_salary(emp_id):
 	create_salary_component("Recurring Salary Component")
 	add_sal = frappe.new_doc("Additional Salary")
@@ -40,6 +46,7 @@
 	add_sal.from_date = add_days(nowdate(), -50)
 	add_sal.to_date = add_days(nowdate(), 180)
 	add_sal.amount = 5000
+	add_sal.currency = erpnext.get_default_currency()
 	add_sal.save()
 	add_sal.submit()
 
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js
index f509df3..6756cd9 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js
@@ -3,7 +3,12 @@
 
 frappe.ui.form.on('Employee Benefit Application', {
 	employee: function(frm) {
-		frm.trigger('set_earning_component');
+		if (frm.doc.employee) {
+			frappe.run_serially([
+				() => 	frm.trigger('get_employee_currency'),
+				() => 	frm.trigger('set_earning_component')
+			]);
+		}
 		var method, args;
 		if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
 			method = "erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
@@ -38,9 +43,26 @@
 		});
 	},
 
+	get_employee_currency: function(frm) {
+		if (frm.doc.employee) {
+			frappe.call({
+				method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+				args: {
+					employee: frm.doc.employee,
+				},
+				callback: function(r) {
+					if (r.message) {
+						frm.set_value('currency', r.message);
+						frm.refresh_fields();
+					}
+				}
+			});
+		}
+	},
+
 	payroll_period: function(frm) {
 		var method, args;
-		if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
+		if (frm.doc.employee && frm.doc.date && frm.doc.payroll_period) {
 			method = "erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
 			args = {
 				employee: frm.doc.employee,
@@ -60,11 +82,14 @@
 		method: method,
 		args: args,
 		callback: function (data) {
-			if(!data.exc){
-				if(data.message){
+			if (!data.exc) {
+				if (data.message) {
 					frm.set_value("max_benefits", data.message);
+				} else {
+					frm.set_value("max_benefits", 0);
 				}
 			}
+			frm.refresh_fields();
 		}
 	});
 };
@@ -82,14 +107,19 @@
 	var tbl = doc.employee_benefits || [];
 	var pro_rata_dispensed_amount = 0;
 	var total_amount = 0;
-	for(var i = 0; i < tbl.length; i++){
-		if(cint(tbl[i].amount) > 0) {
-			total_amount += flt(tbl[i].amount);
-		}
-		if(tbl[i].pay_against_benefit_claim != 1){
-			pro_rata_dispensed_amount += flt(tbl[i].amount);
+	if (doc.max_benefits === 0) {
+		doc.employee_benefits = [];
+	} else {
+		for (var i = 0; i < tbl.length; i++) {
+			if (cint(tbl[i].amount) > 0) {
+				total_amount += flt(tbl[i].amount);
+			}
+			if (tbl[i].pay_against_benefit_claim != 1) {
+				pro_rata_dispensed_amount += flt(tbl[i].amount);
+			}
 		}
 	}
+
 	doc.total_amount = total_amount;
 	doc.remaining_benefit = doc.max_benefits - total_amount;
 	doc.pro_rata_dispensed_amount = pro_rata_dispensed_amount;
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
index b0c1bd6..9a5a463 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
@@ -10,12 +10,14 @@
  "field_order": [
   "employee",
   "employee_name",
+  "currency",
   "max_benefits",
   "remaining_benefit",
   "column_break_2",
   "date",
   "payroll_period",
   "department",
+  "company",
   "amended_from",
   "section_break_4",
   "employee_benefits",
@@ -43,12 +45,14 @@
    "fieldname": "max_benefits",
    "fieldtype": "Currency",
    "label": "Max Benefits (Yearly)",
+   "options": "currency",
    "read_only": 1
   },
   {
    "fieldname": "remaining_benefit",
    "fieldtype": "Currency",
    "label": "Remaining Benefits (Yearly)",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -108,18 +112,38 @@
    "fieldname": "total_amount",
    "fieldtype": "Currency",
    "label": "Total Amount",
+   "options": "currency",
    "read_only": 1
   },
   {
    "fieldname": "pro_rata_dispensed_amount",
    "fieldtype": "Currency",
    "label": "Dispensed Amount (Pro-rated)",
+   "options": "currency",
    "read_only": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.employee)",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fetch_from": "employee.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 22:58:31.271922",
+ "modified": "2020-11-25 11:49:05.095101",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Benefit Application",
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
index ef844fb..27df30a 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
@@ -33,8 +33,8 @@
 					benefit_given = get_sal_slip_total_benefit_given(self.employee, payroll_period, component = benefit.earning_component)
 					benefit_claim_remining = benefit_claimed - benefit_given
 					if benefit_claimed > 0 and benefit_claim_remining > benefit.amount:
-						frappe.throw(_("An amount of {0} already claimed for the component {1},\
-						 set the amount equal or greater than {2}").format(benefit_claimed, benefit.earning_component, benefit_claim_remining))
+						frappe.throw(_("An amount of {0} already claimed for the component {1}, set the amount equal or greater than {2}").format(
+							benefit_claimed, benefit.earning_component, benefit_claim_remining))
 
 	def validate_remaining_benefit_amount(self):
 		# check salary structure earnings have flexi component (sum of max_benefit_amount)
@@ -62,11 +62,11 @@
 			if pro_rata_amount == 0  and non_pro_rata_amount == 0:
 				frappe.throw(_("Please add the remaining benefits {0} to any of the existing component").format(self.remaining_benefit))
 			elif non_pro_rata_amount > 0 and non_pro_rata_amount < rounded(self.remaining_benefit):
-				frappe.throw(_("You can claim only an amount of {0}, the rest amount {1} should be in the application \
-				as pro-rata component").format(non_pro_rata_amount, self.remaining_benefit - non_pro_rata_amount))
+				frappe.throw(_("You can claim only an amount of {0}, the rest amount {1} should be in the application as pro-rata component").format(
+					non_pro_rata_amount, self.remaining_benefit - non_pro_rata_amount))
 			elif non_pro_rata_amount == 0:
-				frappe.throw(_("Please add the remaining benefits {0} to the application as \
-				pro-rata component").format(self.remaining_benefit))
+				frappe.throw(_("Please add the remaining benefits {0} to the application as pro-rata component").format(
+					self.remaining_benefit))
 
 	def validate_max_benefit_for_component(self):
 		if self.employee_benefits:
@@ -115,7 +115,7 @@
 	if max_benefits and max_benefits > 0:
 		have_depends_on_payment_days = False
 		per_day_amount_total = 0
-		payroll_period_days = get_payroll_period_days(on_date, on_date, employee)[0]
+		payroll_period_days = get_payroll_period_days(on_date, on_date, employee)[1]
 		payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
 
 		# Get all salary slip flexi amount in the payroll period
@@ -239,4 +239,17 @@
 		""", salary_structure)
 	else:
 		frappe.throw(_("Salary Structure not found for employee {0} and date {1}")
-			.format(filters['employee'], filters['date']))
\ No newline at end of file
+			.format(filters['employee'], filters['date']))
+
+@frappe.whitelist()
+def get_earning_components_max_benefits(employee, date, earning_component):
+	salary_structure = get_assigned_salary_structure(employee, date)
+	amount = frappe.db.sql("""
+			select amount
+			from `tabSalary Detail`
+			where parent = %s and is_flexible_benefit = 1
+			and salary_component = %s
+			order by name
+		""", salary_structure, earning_component)
+
+	return amount if amount else 0
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json b/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json
index fa6b4da..c93d356 100644
--- a/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json
+++ b/erpnext/payroll/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json
@@ -33,6 +33,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Max Benefit Amount",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -40,12 +41,13 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Amount",
+   "options": "currency",
    "reqd": 1
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:45:00.519134",
+ "modified": "2020-09-29 16:22:15.783854",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Benefit Application Detail",
diff --git a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js
index 6db6cb8..ea9ccd5 100644
--- a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js
+++ b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js
@@ -12,5 +12,24 @@
 	},
 	employee: function(frm) {
 		frm.set_value("earning_component", null);
+		if (frm.doc.employee) {
+			frappe.call({
+				method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+				args: {
+					employee: frm.doc.employee,
+				},
+				callback: function(r) {
+					if (r.message) {
+						frm.set_value('currency', r.message);
+						frm.set_df_property('currency', 'hidden', 0);
+					}
+				}
+			});
+		}
+		if (!frm.doc.earning_component) {
+			frm.doc.max_amount_eligible = null;
+			frm.doc.claimed_amount = null;
+		}
+		frm.refresh_fields();
 	}
 });
diff --git a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json
index ae4c218..da24aac 100644
--- a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json
+++ b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json
@@ -12,6 +12,8 @@
   "department",
   "column_break_3",
   "claim_date",
+  "currency",
+  "company",
   "benefit_type_and_amount",
   "earning_component",
   "max_amount_eligible",
@@ -76,6 +78,7 @@
    "fieldname": "max_amount_eligible",
    "fieldtype": "Currency",
    "label": "Max Amount Eligible",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -92,6 +95,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Claimed Amount",
+   "options": "currency",
    "reqd": 1
   },
   {
@@ -119,11 +123,29 @@
    "fieldname": "attachments",
    "fieldtype": "Attach",
    "label": "Attachments"
+  },
+  {
+   "default": "Company:company:default_currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Currency",
+   "options": "Currency",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fetch_from": "employee.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 23:01:50.791676",
+ "modified": "2020-11-25 11:49:56.097352",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Benefit Claim",
diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.js b/erpnext/payroll/doctype/employee_incentive/employee_incentive.js
index db0f83a..85d1c54 100644
--- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.js
+++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.js
@@ -11,12 +11,57 @@
 			};
 		});
 
+		if (!frm.doc.currency) return;
 		frm.set_query("salary_component", function() {
 			return {
-				filters: {
-					"type": "Earning"
-				}
+				query: "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
+				filters: {type: "earning", currency: frm.doc.currency, company: frm.doc.company}
 			};
 		});
-	}
+
+	},
+
+	employee: function(frm) {
+		if (frm.doc.employee) {
+			frappe.run_serially([
+				() => 	frm.trigger('get_employee_currency'),
+				() => 	frm.trigger('set_company')
+			]);
+		} else {
+			frm.set_value("company", null);
+		}
+	},
+
+	set_company: function(frm) {
+		frappe.call({
+			method: "frappe.client.get_value",
+			args: {
+				doctype: "Employee",
+				fieldname: "company",
+				filters: {
+					name: frm.doc.employee
+				}
+			},
+			callback: function(data) {
+				if (data.message) {
+					frm.set_value("company", data.message.company);
+				}
+			}
+		});
+	},
+
+	get_employee_currency: function(frm) {
+		frappe.call({
+			method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+			args: {
+				employee: frm.doc.employee,
+			},
+			callback: function(r) {
+				if (r.message) {
+					frm.set_value('currency', r.message);
+					frm.refresh_fields();
+				}
+			}
+		});
+	},
 });
diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.json b/erpnext/payroll/doctype/employee_incentive/employee_incentive.json
index 204c9a4..e5b1052 100644
--- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.json
+++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.json
@@ -7,10 +7,12 @@
  "engine": "InnoDB",
  "field_order": [
   "employee",
-  "incentive_amount",
   "employee_name",
-  "salary_component",
+  "company",
+  "currency",
+  "incentive_amount",
   "column_break_5",
+  "salary_component",
   "payroll_date",
   "department",
   "amended_from"
@@ -28,6 +30,7 @@
    "fieldname": "incentive_amount",
    "fieldtype": "Currency",
    "label": "Incentive Amount",
+   "options": "currency",
    "reqd": 1
   },
   {
@@ -70,11 +73,29 @@
    "label": "Salary Component",
    "options": "Salary Component",
    "reqd": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.employee)",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 22:42:51.209630",
+ "modified": "2020-10-20 17:22:16.468042",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Incentive",
diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.py b/erpnext/payroll/doctype/employee_incentive/employee_incentive.py
index 84a97f6..ead3db1 100644
--- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.py
+++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.py
@@ -4,14 +4,23 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe import _
 from frappe.model.document import Document
 
 class EmployeeIncentive(Document):
+	def validate(self):
+		self.validate_salary_structure()
+
+	def validate_salary_structure(self):
+		if not frappe.db.exists('Salary Structure Assignment', {'employee': self.employee}):
+			frappe.throw(_("There is no Salary Structure assigned to {0}. First assign a Salary Stucture.").format(self.employee))
+
 	def on_submit(self):
 		company = frappe.db.get_value('Employee', self.employee, 'company')
 
 		additional_salary = frappe.new_doc('Additional Salary')
 		additional_salary.employee = self.employee
+		additional_salary.currency = self.currency
 		additional_salary.salary_component = self.salary_component
 		additional_salary.overwrite_salary_structure_amount = 0
 		additional_salary.amount = self.incentive_amount
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
index de7c348..83d4ae5 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
+++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
@@ -14,6 +14,7 @@
   "column_break_2",
   "payroll_period",
   "company",
+  "currency",
   "amended_from",
   "section_break_8",
   "declarations",
@@ -92,6 +93,7 @@
    "fieldname": "total_declared_amount",
    "fieldtype": "Currency",
    "label": "Total Declared Amount",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -102,12 +104,22 @@
    "fieldname": "total_exemption_amount",
    "fieldtype": "Currency",
    "label": "Total Exemption Amount",
+   "options": "currency",
    "read_only": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 22:49:43.829892",
+ "modified": "2020-10-20 16:42:24.493761",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Tax Exemption Declaration",
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py b/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
index 9549fd1..0609d19 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
+++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
@@ -22,6 +22,7 @@
 			"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
 			"company": erpnext.get_default_company(),
 			"payroll_period": "_Test Payroll Period",
+			"currency": erpnext.get_default_currency(),
 			"declarations": [
 				dict(exemption_sub_category = "_Test Sub Category",
 					exemption_category = "_Test Category",
@@ -39,6 +40,7 @@
 			"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
 			"company":  erpnext.get_default_company(),
 			"payroll_period": "_Test Payroll Period",
+			"currency": erpnext.get_default_currency(),
 			"declarations": [
 				dict(exemption_sub_category = "_Test Sub Category",
 					exemption_category = "_Test Category",
@@ -54,6 +56,7 @@
 			"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
 			"company":  erpnext.get_default_company(),
 			"payroll_period": "_Test Payroll Period",
+			"currency": erpnext.get_default_currency(),
 			"declarations": [
 				dict(exemption_sub_category = "_Test Sub Category",
 					exemption_category = "_Test Category",
@@ -70,6 +73,7 @@
 			"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
 			"company":  erpnext.get_default_company(),
 			"payroll_period": "_Test Payroll Period",
+			"currency": erpnext.get_default_currency(),
 			"declarations": [
 				dict(exemption_sub_category = "_Test Sub Category",
 					exemption_category = "_Test Category",
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json b/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json
index 8c2f9aa..723a3df 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json
+++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json
@@ -35,6 +35,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Maximum Exempted Amount",
+   "options": "currency",
    "read_only": 1,
    "reqd": 1
   },
@@ -43,12 +44,13 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Declared Amount",
+   "options": "currency",
    "reqd": 1
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:41:03.638739",
+ "modified": "2020-10-20 16:43:09.606265",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Tax Exemption Declaration Category",
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js
index 715d755..497f35c 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js
+++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js
@@ -54,5 +54,9 @@
 				});
 			});
 		}
+	},
+
+	currency: function(frm) {
+		frm.refresh_fields();
 	}
 });
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
index b62b5aa..53f18cb 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
+++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
@@ -11,6 +11,7 @@
   "employee",
   "employee_name",
   "department",
+  "currency",
   "column_break_2",
   "submission_date",
   "payroll_period",
@@ -97,6 +98,7 @@
    "fieldname": "total_actual_amount",
    "fieldtype": "Currency",
    "label": "Total Actual Amount",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -107,6 +109,7 @@
    "fieldname": "exemption_amount",
    "fieldtype": "Currency",
    "label": "Total Exemption Amount",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -126,11 +129,20 @@
    "options": "Employee Tax Exemption Proof Submission",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 22:53:10.412321",
+ "modified": "2020-10-20 16:47:03.410020",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Tax Exemption Proof Submission",
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json
index c1f5320..2fd8b94 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json
+++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json
@@ -34,6 +34,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Maximum Exemption Amount",
+   "options": "currency",
    "read_only": 1,
    "reqd": 1
   },
@@ -48,12 +49,13 @@
    "fieldname": "amount",
    "fieldtype": "Currency",
    "in_list_view": 1,
-   "label": "Actual Amount"
+   "label": "Actual Amount",
+   "options": "currency"
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:37:08.265600",
+ "modified": "2020-10-20 16:47:31.480870",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Tax Exemption Proof Submission Detail",
diff --git a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js
index 73a54eb..7d780d3 100644
--- a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js
+++ b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js
@@ -2,5 +2,7 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Income Tax Slab', {
-
+	currency: function(frm) {
+		frm.refresh_fields();
+	}
 });
diff --git a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json
index 6337d5a..9fa261d 100644
--- a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json
+++ b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json
@@ -9,8 +9,9 @@
   "effective_from",
   "company",
   "column_break_3",
-  "allow_tax_exemption",
+  "currency",
   "standard_tax_exemption_amount",
+  "allow_tax_exemption",
   "disabled",
   "amended_from",
   "taxable_salary_slabs_section",
@@ -70,7 +71,7 @@
    "fieldname": "standard_tax_exemption_amount",
    "fieldtype": "Currency",
    "label": "Standard Tax Exemption Amount",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   },
   {
    "fieldname": "company",
@@ -90,11 +91,20 @@
    "fieldtype": "Table",
    "label": "Other Taxes and Charges",
    "options": "Income Tax Slab Other Charges"
+  },
+  {
+   "default": "Company:company:default_currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 20:27:13.425084",
+ "modified": "2020-10-19 13:54:24.728075",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Income Tax Slab",
diff --git a/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json b/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json
index 7f21204..0dba338 100644
--- a/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json
+++ b/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json
@@ -45,7 +45,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Min Taxable Income",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   },
   {
    "fieldname": "column_break_7",
@@ -57,12 +57,12 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Max Taxable Income",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:33:17.931912",
+ "modified": "2020-10-19 13:45:12.850090",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Income Tax Slab Other Charges",
diff --git a/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.json b/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.json
index bb68e18..8a55224 100644
--- a/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.json
+++ b/erpnext/payroll/doctype/payroll_employee_detail/payroll_employee_detail.json
@@ -52,7 +52,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:25:13.779032",
+ "modified": "2020-09-30 12:40:07.999878",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll Employee Detail",
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
index 1abc869..cb48abb 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
@@ -17,6 +17,16 @@
 				}
 			};
 		});
+
+		frm.set_query("payroll_payable_account", function() {
+			return {
+				filters: {
+					"company": frm.doc.company,
+					"root_type": "Liability",
+					"is_group": 0,
+				}
+			};
+		});
 	},
 
 	refresh: function(frm) {
@@ -139,6 +149,36 @@
 		frm.events.clear_employee_table(frm);
 	},
 
+	currency: function (frm) {
+		var company_currency;
+		if (!frm.doc.company) {
+			company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
+		} else {
+			company_currency = erpnext.get_currency(frm.doc.company);
+		}
+		if (frm.doc.currency) {
+			if (company_currency != frm.doc.currency) {
+				frappe.call({
+					method: "erpnext.setup.utils.get_exchange_rate",
+					args: {
+						from_currency: frm.doc.currency,
+						to_currency: company_currency,
+					},
+					callback: function(r) {
+						frm.set_value("exchange_rate", flt(r.message));
+						frm.set_df_property('exchange_rate', 'hidden', 0);
+						frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
+							+ " = [?] " + company_currency);
+					}
+				});
+			} else {
+				frm.set_value("exchange_rate", 1.0);
+				frm.set_df_property('exchange_rate', 'hidden', 1);
+				frm.set_df_property("exchange_rate", "description", "" );
+			}
+		}
+	},
+
 	department: function (frm) {
 		frm.events.clear_employee_table(frm);
 	},
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.json b/erpnext/payroll/doctype/payroll_entry/payroll_entry.json
index 31a8996..7a48dd1 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.json
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.json
@@ -11,8 +11,11 @@
   "column_break0",
   "posting_date",
   "payroll_frequency",
-  "column_break1",
   "company",
+  "column_break1",
+  "currency",
+  "exchange_rate",
+  "payroll_payable_account",
   "section_break_8",
   "branch",
   "department",
@@ -257,12 +260,37 @@
   {
    "fieldname": "column_break_33",
    "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "company",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Currency",
+   "options": "Currency",
+   "reqd": 1
+  },
+  {
+   "depends_on": "company",
+   "fieldname": "exchange_rate",
+   "fieldtype": "Float",
+   "label": "Exchange Rate",
+   "precision": "9",
+   "reqd": 1
+  },
+  {
+   "depends_on": "company",
+   "fieldname": "payroll_payable_account",
+   "fieldtype": "Link",
+   "label": "Payroll Payable Account",
+   "options": "Account",
+   "reqd": 1
   }
  ],
  "icon": "fa fa-cog",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 20:06:06.953904",
+ "modified": "2020-10-23 13:00:33.753228",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll Entry",
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index a3d12c3..8c2d974 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -3,7 +3,7 @@
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 from frappe.model.document import Document
 from dateutil.relativedelta import relativedelta
 from frappe.utils import cint, flt, nowdate, add_days, getdate, fmt_money, add_to_date, DATE_FORMAT, date_diff
@@ -51,13 +51,15 @@
 				where
 					docstatus = 1 and
 					is_active = 'Yes'
-					and company = %(company)s and
+					and company = %(company)s
+					and currency = %(currency)s and
 					ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s
 					{condition}""".format(condition=condition),
-				{"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
+				{"company": self.company, "currency": self.currency, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
 
 		if sal_struct:
 			cond += "and t2.salary_structure IN %(sal_struct)s "
+			cond += "and t2.payroll_payable_account = %(payroll_payable_account)s "
 			cond += "and %(from_date)s >= t2.from_date"
 			emp_list = frappe.db.sql("""
 				select
@@ -68,14 +70,26 @@
 					t1.name = t2.employee
 					and t2.docstatus = 1
 			%s order by t2.from_date desc
-			""" % cond, {"sal_struct": tuple(sal_struct), "from_date": self.end_date}, as_dict=True)
+			""" % cond, {"sal_struct": tuple(sal_struct), "from_date": self.end_date, "payroll_payable_account": self.payroll_payable_account}, as_dict=True)
 			return emp_list
 
 	def fill_employee_details(self):
 		self.set('employees', [])
 		employees = self.get_emp_list()
 		if not employees:
-			frappe.throw(_("No employees for the mentioned criteria"))
+			error_msg = _("No employees found for the mentioned criteria:<br>Company: {0}<br> Currency: {1}<br>Payroll Payable Account: {2}").format(
+				frappe.bold(self.company), frappe.bold(self.currency), frappe.bold(self.payroll_payable_account))
+			if self.branch:
+				error_msg += "<br>" + _("Branch: {0}").format(frappe.bold(self.branch))
+			if self.department:
+				error_msg += "<br>" + _("Department: {0}").format(frappe.bold(self.department))
+			if self.designation:
+				error_msg += "<br>" + _("Designation: {0}").format(frappe.bold(self.designation))
+			if self.start_date:
+				error_msg += "<br>" + _("Start date: {0}").format(frappe.bold(self.start_date))
+			if self.end_date:
+				error_msg += "<br>" + _("End date: {0}").format(frappe.bold(self.end_date))
+			frappe.throw(error_msg, title=_("No employees found"))
 
 		for d in employees:
 			self.append('employees', d)
@@ -123,7 +137,9 @@
 				"posting_date": self.posting_date,
 				"deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits,
 				"deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof,
-				"payroll_entry": self.name
+				"payroll_entry": self.name,
+				"exchange_rate": self.exchange_rate,
+				"currency": self.currency
 			})
 			if len(emp_list) > 30:
 				frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args)
@@ -160,10 +176,10 @@
 
 	def get_salary_component_account(self, salary_component):
 		account = frappe.db.get_value("Salary Component Account",
-			{"parent": salary_component, "company": self.company}, "default_account")
+			{"parent": salary_component, "company": self.company}, "account")
 
 		if not account:
-			frappe.throw(_("Please set default account in Salary Component {0}")
+			frappe.throw(_("Please set account in Salary Component {0}")
 				.format(salary_component))
 
 		return account
@@ -203,21 +219,11 @@
 			account_dict[(account, key[1])] = account_dict.get((account, key[1]), 0) + amount
 		return account_dict
 
-	def get_default_payroll_payable_account(self):
-		payroll_payable_account = frappe.get_cached_value('Company',
-			{"company_name": self.company},  "default_payroll_payable_account")
-
-		if not payroll_payable_account:
-			frappe.throw(_("Please set Default Payroll Payable Account in Company {0}")
-				.format(self.company))
-
-		return payroll_payable_account
-
 	def make_accrual_jv_entry(self):
 		self.check_permission('write')
 		earnings = self.get_salary_component_total(component_type = "earnings") or {}
 		deductions = self.get_salary_component_total(component_type = "deductions") or {}
-		default_payroll_payable_account = self.get_default_payroll_payable_account()
+		payroll_payable_account = self.payroll_payable_account
 		jv_name = ""
 		precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
 
@@ -230,14 +236,19 @@
 			journal_entry.posting_date = self.posting_date
 
 			accounts = []
+			currencies = []
 			payable_amount = 0
+			multi_currency = 0
+			company_currency = erpnext.get_company_currency(self.company)
 
 			# Earnings
 			for acc_cc, amount in earnings.items():
+				exchange_rate, amt = self.get_amount_and_exchange_rate_for_journal_entry(acc_cc[0], amount, company_currency, currencies)
 				payable_amount += flt(amount, precision)
 				accounts.append({
 						"account": acc_cc[0],
-						"debit_in_account_currency": flt(amount, precision),
+						"debit_in_account_currency": flt(amt, precision),
+						"exchange_rate": flt(exchange_rate),
 						"party_type": '',
 						"cost_center": acc_cc[1] or self.cost_center,
 						"project": self.project
@@ -245,25 +256,32 @@
 
 			# Deductions
 			for acc_cc, amount in deductions.items():
+				exchange_rate, amt = self.get_amount_and_exchange_rate_for_journal_entry(acc_cc[0], amount, company_currency, currencies)
 				payable_amount -= flt(amount, precision)
 				accounts.append({
 						"account": acc_cc[0],
-						"credit_in_account_currency": flt(amount, precision),
+						"credit_in_account_currency": flt(amt, precision),
+						"exchange_rate": flt(exchange_rate),
 						"cost_center": acc_cc[1] or self.cost_center,
 						"party_type": '',
 						"project": self.project
 					})
 
 			# Payable amount
+			exchange_rate, payable_amt = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, payable_amount, company_currency, currencies)
 			accounts.append({
-				"account": default_payroll_payable_account,
-				"credit_in_account_currency": flt(payable_amount, precision),
+				"account": payroll_payable_account,
+				"credit_in_account_currency": flt(payable_amt, precision),
+				"exchange_rate": flt(exchange_rate),
 				"party_type": '',
 				"cost_center": self.cost_center
 			})
 
 			journal_entry.set("accounts", accounts)
-			journal_entry.title = default_payroll_payable_account
+			if len(currencies) > 1:
+				multi_currency = 1
+			journal_entry.multi_currency = multi_currency
+			journal_entry.title = payroll_payable_account
 			journal_entry.save()
 
 			try:
@@ -271,10 +289,24 @@
 				jv_name = journal_entry.name
 				self.update_salary_slip_status(jv_name = jv_name)
 			except Exception as e:
-				frappe.msgprint(e)
+				if type(e) in (str, list, tuple):
+					frappe.msgprint(e)
+				raise
 
 		return jv_name
 
+	def get_amount_and_exchange_rate_for_journal_entry(self, account, amount, company_currency, currencies):
+		conversion_rate = 1
+		exchange_rate = self.exchange_rate
+		account_currency = frappe.db.get_value('Account', account, 'account_currency')
+		if account_currency not in currencies:
+			currencies.append(account_currency)
+		if account_currency == company_currency:
+			conversion_rate = self.exchange_rate
+			exchange_rate = 1
+		amount = flt(amount) * flt(conversion_rate)
+		return exchange_rate, amount
+
 	def make_payment_entry(self):
 		self.check_permission('write')
 
@@ -303,31 +335,43 @@
 				self.create_journal_entry(salary_slip_total, "salary")
 
 	def create_journal_entry(self, je_payment_amount, user_remark):
-		default_payroll_payable_account = self.get_default_payroll_payable_account()
+		payroll_payable_account = self.payroll_payable_account
 		precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
 
+		accounts = []
+		currencies = []
+		multi_currency = 0
+		company_currency = erpnext.get_company_currency(self.company)
+
+		exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(self.payment_account, je_payment_amount, company_currency, currencies)
+		accounts.append({
+				"account": self.payment_account,
+				"bank_account": self.bank_account,
+				"credit_in_account_currency": flt(amount, precision),
+				"exchange_rate": flt(exchange_rate),
+			})
+
+		exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, je_payment_amount, company_currency, currencies)
+		accounts.append({
+				"account": payroll_payable_account,
+				"debit_in_account_currency": flt(amount, precision),
+				"exchange_rate": flt(exchange_rate),
+				"reference_type": self.doctype,
+				"reference_name": self.name
+			})
+
+		if len(currencies) > 1:
+				multi_currency = 1
+
 		journal_entry = frappe.new_doc('Journal Entry')
 		journal_entry.voucher_type = 'Bank Entry'
 		journal_entry.user_remark = _('Payment of {0} from {1} to {2}')\
 			.format(user_remark, self.start_date, self.end_date)
 		journal_entry.company = self.company
 		journal_entry.posting_date = self.posting_date
+		journal_entry.multi_currency = multi_currency
 
-		payment_amount = flt(je_payment_amount, precision)
-
-		journal_entry.set("accounts", [
-			{
-				"account": self.payment_account,
-				"bank_account": self.bank_account,
-				"credit_in_account_currency": payment_amount
-			},
-			{
-				"account": default_payroll_payable_account,
-				"debit_in_account_currency": payment_amount,
-				"reference_type": self.doctype,
-				"reference_name": self.name
-			}
-		])
+		journal_entry.set("accounts", accounts)
 		journal_entry.save(ignore_permissions = True)
 
 	def update_salary_slip_status(self, jv_name = None):
@@ -496,6 +540,21 @@
 			if publish_progress:
 				frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)),
 					title = _("Creating Salary Slips..."))
+		else:
+			salary_slip_name = frappe.db.sql(
+				'''SELECT 
+						name
+					FROM `tabSalary Slip`
+					WHERE company=%s
+					AND start_date >= %s
+					AND end_date <= %s
+					AND employee = %s
+				''', (args.company, args.start_date, args.end_date, emp), as_dict=True)
+
+			salary_slip_doc = frappe.get_doc('Salary Slip', salary_slip_name[0].name)
+			salary_slip_doc.exchange_rate = args.exchange_rate
+			salary_slip_doc.set_totals()
+			salary_slip_doc.db_update()
 
 	payroll_entry = frappe.get_doc("Payroll Entry", args.payroll_entry)
 	payroll_entry.db_set("salary_slips_created", 1)
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
index b0f225d..54106c8 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
@@ -10,8 +10,8 @@
 from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_start_end_dates, get_end_date
 from erpnext.hr.doctype.employee.test_employee import make_employee
 from erpnext.payroll.doctype.salary_slip.test_salary_slip import get_salary_component_account, \
-		make_earning_salary_component, make_deduction_salary_component, create_account
-from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
+		make_earning_salary_component, make_deduction_salary_component, create_account, make_employee_salary_slip
+from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure, create_salary_structure_assignment
 from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
 
@@ -34,10 +34,47 @@
 				get_salary_component_account(data.name)
 
 		employee = frappe.db.get_value("Employee", {'company': company})
-		make_salary_structure("_Test Salary Structure", "Monthly", employee, company=company)
+		company_doc = frappe.get_doc('Company', company)
+		make_salary_structure("_Test Salary Structure", "Monthly", employee, company=company, currency=company_doc.default_currency)
 		dates = get_start_end_dates('Monthly', nowdate())
 		if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}):
-			make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date)
+			make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date, payable_account=company_doc.default_payroll_payable_account,
+				currency=company_doc.default_currency)
+
+	def test_multi_currency_payroll_entry(self): # pylint: disable=no-self-use
+		company = erpnext.get_default_company()
+		employee = make_employee("test_muti_currency_employee@payroll.com", company=company)
+		for data in frappe.get_all('Salary Component', fields = ["name"]):
+			if not frappe.db.get_value('Salary Component Account',
+				{'parent': data.name, 'company': company}, 'name'):
+				get_salary_component_account(data.name)
+
+		company_doc = frappe.get_doc('Company', company)
+		salary_structure = make_salary_structure("_Test Multi Currency Salary Structure", "Monthly", company=company, currency='USD')
+		create_salary_structure_assignment(employee, salary_structure.name, company=company)
+		frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""",(frappe.db.get_value("Employee", {"user_id": "test_muti_currency_employee@payroll.com"})))
+		salary_slip = get_salary_slip("test_muti_currency_employee@payroll.com", "Monthly", "_Test Multi Currency Salary Structure")
+		dates = get_start_end_dates('Monthly', nowdate())
+		payroll_entry = make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date, 
+			payable_account=company_doc.default_payroll_payable_account, currency='USD', exchange_rate=70)
+		payroll_entry.make_payment_entry()
+
+		salary_slip.load_from_db()
+
+		payroll_je = salary_slip.journal_entry
+		payroll_je_doc = frappe.get_doc('Journal Entry', payroll_je)
+
+		self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_debit)
+		self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_credit)
+
+		payment_entry = frappe.db.sql('''
+			Select ifnull(sum(je.total_debit),0) as total_debit, ifnull(sum(je.total_credit),0) as total_credit from `tabJournal Entry` je, `tabJournal Entry Account` jea
+			Where je.name = jea.parent
+			And jea.reference_name = %s
+			''', (payroll_entry.name), as_dict=1)
+
+		self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_debit)
+		self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_credit)
 
 	def test_payroll_entry_with_employee_cost_center(self): # pylint: disable=no-self-use
 		for data in frappe.get_all('Salary Component', fields = ["name"]):
@@ -52,24 +89,32 @@
 				"company": "_Test Company"
 			}).insert()
 
+		frappe.db.sql("""delete from `tabEmployee` where employee_name='test_employee1@example.com' """)
+		frappe.db.sql("""delete from `tabEmployee` where employee_name='test_employee2@example.com' """)
+		frappe.db.sql("""delete from `tabSalary Structure` where name='_Test Salary Structure 1' """)
+		frappe.db.sql("""delete from `tabSalary Structure` where name='_Test Salary Structure 2' """)
+
 		employee1 = make_employee("test_employee1@example.com", payroll_cost_center="_Test Cost Center - _TC",
 			department="cc - _TC", company="_Test Company")
 		employee2 = make_employee("test_employee2@example.com", payroll_cost_center="_Test Cost Center 2 - _TC",
 			department="cc - _TC", company="_Test Company")
 
-		make_salary_structure("_Test Salary Structure 1", "Monthly", employee1, company="_Test Company")
-		make_salary_structure("_Test Salary Structure 2", "Monthly", employee2, company="_Test Company")
-
 		if not frappe.db.exists("Account", "_Test Payroll Payable - _TC"):
-			create_account(account_name="_Test Payroll Payable",
-				company="_Test Company", parent_account="Current Liabilities - _TC")
-			frappe.db.set_value("Company", "_Test Company", "default_payroll_payable_account",
-				"_Test Payroll Payable - _TC")
+				create_account(account_name="_Test Payroll Payable",
+					company="_Test Company", parent_account="Current Liabilities - _TC")
+
+		if not frappe.db.get_value("Company", "_Test Company", "default_payroll_payable_account") or \
+			frappe.db.get_value("Company", "_Test Company", "default_payroll_payable_account") != "_Test Payroll Payable - _TC":
+				frappe.db.set_value("Company", "_Test Company", "default_payroll_payable_account",
+					"_Test Payroll Payable - _TC")
+
+		make_salary_structure("_Test Salary Structure 1", "Monthly", employee1, company="_Test Company", currency=frappe.db.get_value("Company", "_Test Company", "default_currency"))
+		make_salary_structure("_Test Salary Structure 2", "Monthly", employee2, company="_Test Company", currency=frappe.db.get_value("Company", "_Test Company", "default_currency"))
 
 		dates = get_start_end_dates('Monthly', nowdate())
 		if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}):
-			pe = make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date,
-				department="cc - _TC", company="_Test Company", payment_account="Cash - _TC", cost_center="Main - _TC")
+			pe = make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date, payable_account="_Test Payroll Payable - _TC",
+				currency=frappe.db.get_value("Company", "_Test Company", "default_currency"), department="cc - _TC", company="_Test Company", payment_account="Cash - _TC", cost_center="Main - _TC")
 			je = frappe.db.get_value("Salary Slip", {"payroll_entry": pe.name}, "journal_entry")
 			je_entries = frappe.db.sql("""
 				select account, cost_center, debit, credit
@@ -121,7 +166,7 @@
 		employee_doc.save()
 
 		salary_structure = "Test Salary Structure for Loan"
-		make_salary_structure(salary_structure, "Monthly", employee=employee_doc.name, company="_Test Company")
+		make_salary_structure(salary_structure, "Monthly", employee=employee_doc.name, company="_Test Company", currency=company_doc.default_currency)
 
 		loan = create_loan(applicant, "Car Loan", 280000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1))
 		loan.repay_from_salary = 1
@@ -133,8 +178,8 @@
 
 
 		dates = get_start_end_dates('Monthly', nowdate())
-		make_payroll_entry(company="_Test Company", start_date=dates.start_date,
-			end_date=dates.end_date, branch=branch, cost_center="Main - _TC", payment_account="Cash - _TC")
+		make_payroll_entry(company="_Test Company", start_date=dates.start_date, payable_account=company_doc.default_payroll_payable_account,
+			currency=company_doc.default_currency, end_date=dates.end_date, branch=branch, cost_center="Main - _TC", payment_account="Cash - _TC")
 
 		name = frappe.db.get_value('Salary Slip',
 			{'posting_date': nowdate(), 'employee': applicant}, 'name')
@@ -165,6 +210,9 @@
 	payroll_entry.payroll_frequency = "Monthly"
 	payroll_entry.branch = args.branch or None
 	payroll_entry.department = args.department or None
+	payroll_entry.payroll_payable_account = args.payable_account
+	payroll_entry.currency = args.currency
+	payroll_entry.exchange_rate = args.exchange_rate or 1
 
 	if args.cost_center:
 		payroll_entry.cost_center = args.cost_center
@@ -212,3 +260,11 @@
 		}).insert()
 
 	return holiday_list_name
+
+def get_salary_slip(user, period, salary_structure):
+	salary_slip = make_employee_salary_slip(user, period, salary_structure)
+	salary_slip.exchange_rate = 70
+	salary_slip.calculate_net_pay()
+	salary_slip.db_update()
+
+	return salary_slip
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js b/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js
index 8ff5515..092cbd8 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js
+++ b/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js
@@ -9,45 +9,45 @@
 		() => {
 			var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
 			row.company = 'For Testing';
-			row.default_account = 'Salary - FT';
+			row.account = 'Salary - FT';
 		},
 
 		() => cur_frm.save(),
 		() => frappe.timeout(2),
-		() => assert.equal(cur_frm.doc.accounts[0].default_account, 'Salary - FT'),
+		() => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
 
 		() => frappe.set_route('Form', 'Salary Component', 'Basic'),
 		() => {
 			var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
 			row.company = 'For Testing';
-			row.default_account = 'Salary - FT';
+			row.account = 'Salary - FT';
 		},
 
 		() => cur_frm.save(),
 		() => frappe.timeout(2),
-		() => assert.equal(cur_frm.doc.accounts[0].default_account, 'Salary - FT'),
+		() => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
 
 		() => frappe.set_route('Form', 'Salary Component', 'Income Tax'),
 		() => {
 			var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
 			row.company = 'For Testing';
-			row.default_account = 'Salary - FT';
+			row.account = 'Salary - FT';
 		},
 
 		() => cur_frm.save(),
 		() => frappe.timeout(2),
-		() => assert.equal(cur_frm.doc.accounts[0].default_account, 'Salary - FT'),
+		() => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
 
 		() => frappe.set_route('Form', 'Salary Component', 'Arrear'),
 		() => {
 			var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
 			row.company = 'For Testing';
-			row.default_account = 'Salary - FT';
+			row.account = 'Salary - FT';
 		},
 
 		() => cur_frm.save(),
 		() => frappe.timeout(2),
-		() => assert.equal(cur_frm.doc.accounts[0].default_account, 'Salary - FT'),
+		() => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
 
 		() => frappe.set_route('Form', 'Company', 'For Testing'),
 		() => cur_frm.set_value('default_payroll_payable_account', 'Payroll Payable - FT'),
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.js b/erpnext/payroll/doctype/retention_bonus/retention_bonus.js
index 64e726d..6fe8cca 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.js
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.js
@@ -18,5 +18,22 @@
 				}
 			};
 		});
+	},
+
+	employee: function(frm) {
+		if (frm.doc.employee) {
+			frappe.call({
+				method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
+				args: {
+					employee: frm.doc.employee,
+				},
+				callback: function(r) {
+					if (r.message) {
+						frm.set_value('currency', r.message);
+						frm.refresh_fields();
+					}
+				}
+			});
+		}
 	}
 });
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.json b/erpnext/payroll/doctype/retention_bonus/retention_bonus.json
index da884c2..6647230 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.json
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.json
@@ -17,7 +17,8 @@
   "column_break_6",
   "employee_name",
   "department",
-  "date_of_joining"
+  "date_of_joining",
+  "currency"
  ],
  "fields": [
   {
@@ -46,6 +47,7 @@
    "fieldname": "bonus_amount",
    "fieldtype": "Currency",
    "label": "Bonus Amount",
+   "options": "currency",
    "reqd": 1
   },
   {
@@ -89,11 +91,22 @@
    "label": "Salary Component",
    "options": "Salary Component",
    "reqd": 1
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.employee)",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 22:42:05.251951",
+ "modified": "2020-10-20 17:27:47.003134",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Retention Bonus",
@@ -151,7 +164,6 @@
    "share": 1
   }
  ],
- "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
diff --git a/erpnext/payroll/doctype/salary_component/salary_component.js b/erpnext/payroll/doctype/salary_component/salary_component.js
index c455eb3..dbf7514 100644
--- a/erpnext/payroll/doctype/salary_component/salary_component.js
+++ b/erpnext/payroll/doctype/salary_component/salary_component.js
@@ -3,7 +3,7 @@
 
 frappe.ui.form.on('Salary Component', {
 	setup: function(frm) {
-		frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
+		frm.set_query("account", "accounts", function(doc, cdt, cdn) {
 			var d = locals[cdt][cdn];
 			return {
 				filters: {
diff --git a/erpnext/payroll/doctype/salary_detail/salary_detail.json b/erpnext/payroll/doctype/salary_detail/salary_detail.json
index eedb56e..5c1eb61 100644
--- a/erpnext/payroll/doctype/salary_detail/salary_detail.json
+++ b/erpnext/payroll/doctype/salary_detail/salary_detail.json
@@ -147,7 +147,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Amount",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   },
   {
    "default": "0",
@@ -160,7 +160,7 @@
    "fieldname": "default_amount",
    "fieldtype": "Currency",
    "label": "Default Amount",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "print_hide": 1
   },
   {
@@ -169,6 +169,7 @@
    "hidden": 1,
    "label": "Additional Amount",
    "no_copy": 1,
+   "options": "currency",
    "print_hide": 1,
    "read_only": 1
   },
@@ -177,6 +178,7 @@
    "fieldname": "tax_on_flexible_benefit",
    "fieldtype": "Currency",
    "label": "Tax on flexible benefit",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -184,6 +186,7 @@
    "fieldname": "tax_on_additional_salary",
    "fieldtype": "Currency",
    "label": "Tax on additional salary",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -227,7 +230,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-10-07 20:39:41.619283",
+ "modified": "2020-11-25 13:12:41.081106",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Detail",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.js b/erpnext/payroll/doctype/salary_slip/salary_slip.js
index 0671b57..f7e22c6 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.js
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.js
@@ -74,14 +74,85 @@
 		if (!frm.doc.letter_head && company.default_letter_head) {
 			frm.set_value('letter_head', company.default_letter_head);
 		}
+		frm.trigger("set_dynamic_labels");
+	},
+
+	set_dynamic_labels: function(frm) {
+		var company_currency = frm.doc.company? erpnext.get_currency(frm.doc.company): frappe.defaults.get_default("currency");
+		frappe.run_serially([
+			() => 	frm.events.set_exchange_rate(frm, company_currency),
+			() => 	frm.events.change_form_labels(frm, company_currency),
+			() => 	frm.events.change_grid_labels(frm),
+			() => 	frm.refresh_fields()
+		]);
+	},
+
+	set_exchange_rate: function(frm, company_currency) {
+		if (frm.doc.docstatus === 0) {
+			if (frm.doc.currency) {
+				var from_currency = frm.doc.currency;
+				if (from_currency != company_currency) {
+					frm.events.hide_loan_section(frm);
+					frappe.call({
+						method: "erpnext.setup.utils.get_exchange_rate",
+						args: {
+							from_currency: from_currency,
+							to_currency: company_currency,
+						},
+						callback: function(r) {
+							frm.set_value("exchange_rate", flt(r.message));
+							frm.set_df_property('exchange_rate', 'hidden', 0);
+							frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
+								+ " = [?] " + company_currency);
+						}
+					});
+				} else {
+					frm.set_value("exchange_rate", 1.0);
+					frm.set_df_property('exchange_rate', 'hidden', 1);
+					frm.set_df_property("exchange_rate", "description", "" );
+				}
+			}
+		}
+	},
+
+	exchange_rate: function(frm) {
+		calculate_totals(frm);
+	},
+
+	hide_loan_section: function(frm) {
+		frm.set_df_property('section_break_43', 'hidden', 1);
+	},
+
+	change_form_labels: function(frm, company_currency) {
+		frm.set_currency_labels(["base_hour_rate", "base_gross_pay", "base_total_deduction",
+			"base_net_pay", "base_rounded_total", "base_total_in_words"],
+		company_currency);
+
+		frm.set_currency_labels(["hour_rate", "gross_pay", "total_deduction", "net_pay", "rounded_total", "total_in_words"],
+			frm.doc.currency);
+
+		// toggle fields
+		frm.toggle_display(["exchange_rate", "base_hour_rate", "base_gross_pay", "base_total_deduction",
+			"base_net_pay", "base_rounded_total", "base_total_in_words"],
+		frm.doc.currency != company_currency);
+	},
+
+	change_grid_labels: function(frm) {
+		frm.set_currency_labels(["amount", "default_amount", "additional_amount", "tax_on_flexible_benefit",
+			"tax_on_additional_salary"], frm.doc.currency, "earnings");
+
+		frm.set_currency_labels(["amount", "default_amount", "additional_amount", "tax_on_flexible_benefit",
+			"tax_on_additional_salary"], frm.doc.currency, "deductions");
 	},
 
 	refresh: function(frm) {
 		frm.trigger("toggle_fields");
 
 		var salary_detail_fields = ["formula", "abbr", "statistical_component", "variable_based_on_taxable_salary"];
-		cur_frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields, false);
-		cur_frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields, false);
+		frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields, false);
+		frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields, false);
+		calculate_totals(frm);
+		frm.trigger("set_dynamic_labels");
 	},
 
 	salary_slip_based_on_timesheet: function(frm) {
@@ -118,51 +189,94 @@
 	},
 
 	get_emp_and_working_day_details: function(frm) {
-		return frappe.call({
-			method: 'get_emp_and_working_day_details',
-			doc: frm.doc,
-			callback: function(r) {
-				frm.refresh();
-				if (r.message[1] !== "Leave" && r.message[0]) {
-					frm.fields_dict.absent_days.set_description(__("Unmarked Days is treated as ")+ r.message[0] +__(". You can can change this in ") + frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true));
+		if (frm.doc.employee) {
+			return frappe.call({
+				method: 'get_emp_and_working_day_details',
+				doc: frm.doc,
+				callback: function(r) {
+					if (r.message[1] !== "Leave" && r.message[0]) {
+						frm.fields_dict.absent_days.set_description(__("Unmarked Days is treated as {0}. You can can change this in {1}", [r.message, frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true)]));
+					}
+					frm.refresh();
 				}
-			}
-		});
+			});
+		}
 	}
 });
 
 frappe.ui.form.on('Salary Slip Timesheet', {
-	time_sheet: function(frm, dt, dn) {
-		total_work_hours(frm, dt, dn);
+	time_sheet: function(frm) {
+		calculate_totals(frm);
 	},
-	timesheets_remove: function(frm, dt, dn) {
-		total_work_hours(frm, dt, dn);
+	timesheets_remove: function(frm) {
+		calculate_totals(frm);
 	}
 });
 
-// calculate total working hours, earnings based on hourly wages and totals
-var total_work_hours = function(frm) {
-	var total_working_hours = 0.0;
-	$.each(frm.doc["timesheets"] || [], function(i, timesheet) {
-		total_working_hours += timesheet.working_hours;
-	});
-	frm.set_value('total_working_hours', total_working_hours);
-
-	var wages_amount = frm.doc.total_working_hours * frm.doc.hour_rate;
-
-	frappe.db.get_value('Salary Structure', {'name': frm.doc.salary_structure}, 'salary_component', (r) => {
-		var gross_pay = 0.0;
-		$.each(frm.doc["earnings"], function(i, earning) {
-			if (earning.salary_component == r.salary_component) {
-				earning.amount = wages_amount;
-				frm.refresh_fields('earnings');
+var calculate_totals = function(frm) {
+	if (frm.doc.earnings || frm.doc.deductions) {
+		frappe.call({
+			method: "set_totals",
+			doc: frm.doc,
+			callback: function() {
+				frm.refresh_fields();
 			}
-			gross_pay += earning.amount;
 		});
-		frm.set_value('gross_pay', gross_pay);
-
-		frm.doc.net_pay = flt(frm.doc.gross_pay) - flt(frm.doc.total_deduction);
-		frm.doc.rounded_total = Math.round(frm.doc.net_pay);
-		refresh_many(['net_pay', 'rounded_total']);
-	});
+	}
 };
+
+frappe.ui.form.on('Salary Detail', {
+	amount: function(frm) {
+		calculate_totals(frm);
+	},
+
+	earnings_remove: function(frm) {
+		calculate_totals(frm);
+	},
+
+	deductions_remove: function(frm) {
+		calculate_totals(frm);
+	},
+
+	salary_component: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+		if (child.salary_component) {
+			frappe.call({
+				method: "frappe.client.get",
+				args: {
+					doctype: "Salary Component",
+					name: child.salary_component
+				},
+				callback: function(data) {
+					if (data.message) {
+						var result = data.message;
+						frappe.model.set_value(cdt, cdn, 'condition', result.condition);
+						frappe.model.set_value(cdt, cdn, 'amount_based_on_formula', result.amount_based_on_formula);
+						if (result.amount_based_on_formula === 1) {
+							frappe.model.set_value(cdt, cdn, 'formula', result.formula);
+						} else {
+							frappe.model.set_value(cdt, cdn, 'amount', result.amount);
+						}
+						frappe.model.set_value(cdt, cdn, 'statistical_component', result.statistical_component);
+						frappe.model.set_value(cdt, cdn, 'depends_on_payment_days', result.depends_on_payment_days);
+						frappe.model.set_value(cdt, cdn, 'do_not_include_in_total', result.do_not_include_in_total);
+						frappe.model.set_value(cdt, cdn, 'variable_based_on_taxable_salary', result.variable_based_on_taxable_salary);
+						frappe.model.set_value(cdt, cdn, 'is_tax_applicable', result.is_tax_applicable);
+						frappe.model.set_value(cdt, cdn, 'is_flexible_benefit', result.is_flexible_benefit);
+						refresh_field("earnings");
+						refresh_field("deductions");
+					}
+				}
+			});
+		}
+	},
+
+	amount_based_on_formula: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+		if (child.amount_based_on_formula === 1) {
+			frappe.model.set_value(cdt, cdn, 'amount', null);
+		} else {
+			frappe.model.set_value(cdt, cdn, 'formula', null);
+		}
+	}
+});
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 619c45f..386618c 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -18,6 +18,8 @@
   "journal_entry",
   "payroll_entry",
   "company",
+  "currency",
+  "exchange_rate",
   "letter_head",
   "section_break_10",
   "start_date",
@@ -38,6 +40,7 @@
   "column_break_20",
   "total_working_hours",
   "hour_rate",
+  "base_hour_rate",
   "section_break_26",
   "bank_name",
   "bank_account_no",
@@ -52,8 +55,10 @@
   "deductions",
   "totals",
   "gross_pay",
+  "base_gross_pay",
   "column_break_25",
   "total_deduction",
+  "base_total_deduction",
   "loan_repayment",
   "loans",
   "section_break_43",
@@ -63,10 +68,15 @@
   "total_loan_repayment",
   "net_pay_info",
   "net_pay",
+  "base_net_pay",
   "column_break_53",
   "rounded_total",
+  "base_rounded_total",
   "section_break_55",
   "total_in_words",
+  "column_break_69",
+  "base_total_in_words",
+  "section_break_75",
   "amended_from"
  ],
  "fields": [
@@ -205,9 +215,13 @@
   {
    "fieldname": "salary_structure",
    "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
    "label": "Salary Structure",
    "options": "Salary Structure",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1,
+   "search_index": 1
   },
   {
    "depends_on": "eval:(!doc.salary_slip_based_on_timesheet)",
@@ -265,7 +279,7 @@
    "fieldname": "hour_rate",
    "fieldtype": "Currency",
    "label": "Hour Rate",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "print_hide_if_no_value": 1
   },
   {
@@ -347,9 +361,7 @@
    "fieldname": "gross_pay",
    "fieldtype": "Currency",
    "label": "Gross Pay",
-   "oldfieldname": "gross_pay",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -357,15 +369,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "fieldname": "total_deduction",
-   "fieldtype": "Currency",
-   "label": "Total Deduction",
-   "oldfieldname": "total_deduction",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency",
-   "read_only": 1
-  },
-  {
    "depends_on": "total_loan_repayment",
    "fieldname": "loan_repayment",
    "fieldtype": "Section Break",
@@ -379,6 +382,7 @@
    "print_hide": 1
   },
   {
+   "depends_on": "eval:doc.docstatus != 0",
    "fieldname": "section_break_43",
    "fieldtype": "Section Break"
   },
@@ -416,13 +420,10 @@
    "label": "net pay info"
   },
   {
-   "description": "Gross Pay - Total Deduction - Loan Repayment",
    "fieldname": "net_pay",
    "fieldtype": "Currency",
    "label": "Net Pay",
-   "oldfieldname": "net_pay",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -434,7 +435,7 @@
    "fieldname": "rounded_total",
    "fieldtype": "Currency",
    "label": "Rounded Total",
-   "options": "Company:company:default_currency",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -442,15 +443,6 @@
    "fieldtype": "Section Break"
   },
   {
-   "description": "Net Pay (in words) will be visible once you save the Salary Slip.",
-   "fieldname": "total_in_words",
-   "fieldtype": "Data",
-   "label": "Total in words",
-   "oldfieldname": "net_pay_in_words",
-   "oldfieldtype": "Data",
-   "read_only": 1
-  },
-  {
    "fieldname": "amended_from",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
@@ -500,13 +492,99 @@
   {
    "fieldname": "column_break_18",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.salary_structure)",
+   "fetch_from": "salary_structure.currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "total_deduction",
+   "fieldtype": "Currency",
+   "label": "Total Deduction",
+   "options": "currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_in_words",
+   "fieldtype": "Data",
+   "label": "Total in words",
+   "length": 240,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_75",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "base_hour_rate",
+   "fieldtype": "Currency",
+   "label": "Hour Rate (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide_if_no_value": 1
+  },
+  {
+   "fieldname": "base_gross_pay",
+   "fieldtype": "Currency",
+   "label": "Gross Pay (Company Currency)",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "default": "1.0",
+   "fieldname": "exchange_rate",
+   "fieldtype": "Float",
+   "hidden": 1,
+   "label": "Exchange Rate",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "base_total_deduction",
+   "fieldtype": "Currency",
+   "label": "Total Deduction (Company Currency)",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_net_pay",
+   "fieldtype": "Currency",
+   "label": "Net Pay (Company Currency)",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "bold": 1,
+   "fieldname": "base_rounded_total",
+   "fieldtype": "Currency",
+   "label": "Rounded Total (Company Currency)",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_total_in_words",
+   "fieldtype": "Data",
+   "label": "Total in words (Company Currency)",
+   "length": 240,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_69",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 9,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-11 17:37:54.274384",
+ "modified": "2020-10-21 23:02:59.400249",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Slip",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 7b87ae5..20365b1 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -50,16 +50,20 @@
 
 		self.calculate_net_pay()
 
-		company_currency = erpnext.get_company_currency(self.company)
-		total = self.net_pay if self.is_rounding_total_disabled() else self.rounded_total
-		self.total_in_words = money_in_words(total, company_currency)
-
 		if frappe.db.get_single_value("Payroll Settings", "max_working_hours_against_timesheet"):
 			max_working_hours = frappe.db.get_single_value("Payroll Settings", "max_working_hours_against_timesheet")
 			if self.salary_slip_based_on_timesheet and (self.total_working_hours > int(max_working_hours)):
 				frappe.msgprint(_("Total working hours should not be greater than max working hours {0}").
 								format(max_working_hours), alert=True)
 
+	def set_net_total_in_words(self):
+		doc_currency = self.currency
+		company_currency = erpnext.get_company_currency(self.company)
+		total = self.net_pay if self.is_rounding_total_disabled() else self.rounded_total
+		base_total = self.base_net_pay if self.is_rounding_total_disabled() else self.base_rounded_total
+		self.total_in_words = money_in_words(total, doc_currency)
+		self.base_total_in_words = money_in_words(base_total, company_currency)
+
 	def on_submit(self):
 		if self.net_pay < 0:
 			frappe.throw(_("Net Pay cannot be less than 0"))
@@ -182,6 +186,7 @@
 		if self.salary_slip_based_on_timesheet:
 			self.salary_structure = self._salary_structure_doc.name
 			self.hour_rate = self._salary_structure_doc.hour_rate
+			self.base_hour_rate = flt(self.hour_rate) * flt(self.exchange_rate)
 			self.total_working_hours = sum([d.working_hours or 0.0 for d in self.timesheets]) or 0.0
 			wages_amount = self.hour_rate * self.total_working_hours
 
@@ -417,15 +422,22 @@
 		if self.salary_structure:
 			self.calculate_component_amounts("earnings")
 		self.gross_pay = self.get_component_totals("earnings")
+		self.base_gross_pay = flt(flt(self.gross_pay) * flt(self.exchange_rate), self.precision('base_gross_pay'))
 
 		if self.salary_structure:
 			self.calculate_component_amounts("deductions")
 		self.total_deduction = self.get_component_totals("deductions")
+		self.base_total_deduction = flt(flt(self.total_deduction) * flt(self.exchange_rate), self.precision('base_total_deduction'))
 
 		self.set_loan_repayment()
 
 		self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
 		self.rounded_total = rounded(self.net_pay)
+		self.base_net_pay = flt(flt(self.net_pay) * flt(self.exchange_rate), self.precision('base_net_pay'))
+		self.base_rounded_total = flt(rounded(self.base_net_pay), self.precision('base_net_pay'))
+		if self.hour_rate:
+			self.base_hour_rate = flt(flt(self.hour_rate) * flt(self.exchange_rate), self.precision('base_hour_rate'))
+		self.set_net_total_in_words()
 
 	def calculate_component_amounts(self, component_type):
 		if not getattr(self, '_salary_structure_doc', None):
@@ -976,8 +988,9 @@
 			amounts = calculate_amounts(payment.loan, self.posting_date, "Regular Payment")
 			total_amount = amounts['interest_amount'] + amounts['payable_principal_amount']
 			if payment.total_payment > total_amount:
-				frappe.throw(_("Row {0}: Paid amount {1} is greater than pending accrued amount {2}against loan {3}").format(
-					payment.idx, frappe.bold(payment.total_payment),frappe.bold(total_amount), frappe.bold(payment.loan)))
+				frappe.throw(_("""Row {0}: Paid amount {1} is greater than pending accrued amount {2} against loan {3}""")
+					.format(payment.idx, frappe.bold(payment.total_payment),
+						frappe.bold(total_amount), frappe.bold(payment.loan)))
 
 			self.total_interest_amount += payment.interest_amount
 			self.total_principal_amount += payment.principal_amount
@@ -1072,6 +1085,46 @@
 		self.get_working_days_details(lwp=self.leave_without_pay)
 		self.calculate_net_pay()
 
+	def set_totals(self):
+		self.gross_pay = 0
+		if self.salary_slip_based_on_timesheet == 1:
+			self.calculate_total_for_salary_slip_based_on_timesheet()
+		else:
+			self.total_deduction = 0
+			if self.earnings:
+				for earning in self.earnings:
+					self.gross_pay += flt(earning.amount)
+			if self.deductions:
+				for deduction in self.deductions:
+					self.total_deduction += flt(deduction.amount)
+			self.net_pay = flt(self.gross_pay) - flt(self.total_deduction) - flt(self.total_loan_repayment)
+		self.set_base_totals()
+
+	def set_base_totals(self):
+		self.base_gross_pay = flt(self.gross_pay) * flt(self.exchange_rate)
+		self.base_total_deduction = flt(self.total_deduction) * flt(self.exchange_rate)
+		self.rounded_total = rounded(self.net_pay)
+		self.base_net_pay = flt(self.net_pay) * flt(self.exchange_rate)
+		self.base_rounded_total = rounded(self.base_net_pay)
+		self.set_net_total_in_words()
+
+	#calculate total working hours, earnings based on hourly wages and totals
+	def calculate_total_for_salary_slip_based_on_timesheet(self):
+		if self.timesheets:
+			for timesheet in self.timesheets:
+				if timesheet.working_hours:
+					self.total_working_hours += timesheet.working_hours
+
+		wages_amount = self.total_working_hours * self.hour_rate
+		self.base_hour_rate = flt(self.hour_rate) * flt(self.exchange_rate)
+		salary_component = frappe.db.get_value('Salary Structure', {'name': self.salary_structure}, 'salary_component')
+		if self.earnings:
+			for i, earning in enumerate(self.earnings):
+				if earning.salary_component == salary_component:
+					self.earnings[i].amount = wages_amount
+				self.gross_pay += self.earnings[i].amount
+		self.net_pay = flt(self.gross_pay) - flt(self.total_deduction)
+
 def unlink_ref_doc_from_salary_slip(ref_no):
 	linked_ss = frappe.db.sql_list("""select name from `tabSalary Slip`
 	where journal_entry=%s and docstatus < 2""", (ref_no))
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index e08dc7c..5daf1d4 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -33,7 +33,7 @@
 		frappe.db.set_value("Payroll Settings", None, "payroll_based_on", "Attendance")
 		frappe.db.set_value("Payroll Settings", None, "daily_wages_fraction_for_half_day", 0.75)
 
-		emp_id = make_employee("test_for_attendance@salary.com")
+		emp_id = make_employee("test_payment_days_based_on_attendance@salary.com")
 		frappe.db.set_value("Employee", emp_id, {"relieving_date": None, "status": "Active"})
 
 		frappe.db.set_value("Leave Type", "Leave Without Pay", "include_holiday", 0)
@@ -55,7 +55,7 @@
 		mark_attendance(emp_id, add_days(first_sunday, 4), 'On Leave', leave_type='Casual Leave', ignore_validate=True) # invalid lwp
 		mark_attendance(emp_id, add_days(first_sunday, 7), 'On Leave', leave_type='Leave Without Pay', ignore_validate=True) # invalid lwp
 
-		ss = make_employee_salary_slip("test_for_attendance@salary.com", "Monthly")
+		ss = make_employee_salary_slip("test_payment_days_based_on_attendance@salary.com", "Monthly", "Test Payment Based On Attendence")
 
 		self.assertEqual(ss.leave_without_pay, 1.25)
 		self.assertEqual(ss.absent_days, 1)
@@ -78,7 +78,7 @@
 		# Payroll based on attendance
 		frappe.db.set_value("Payroll Settings", None, "payroll_based_on", "Leave")
 
-		emp_id = make_employee("test_for_attendance@salary.com")
+		emp_id = make_employee("test_payment_days_based_on_leave_application@salary.com")
 		frappe.db.set_value("Employee", emp_id, {"relieving_date": None, "status": "Active"})
 
 		frappe.db.set_value("Leave Type", "Leave Without Pay", "include_holiday", 0)
@@ -108,7 +108,8 @@
 		#two day leave ppl with fraction_of_daily_salary_per_leave = 0.5 equivalent to single day lwp
 		make_leave_application(emp_id, add_days(first_sunday, 4), add_days(first_sunday, 5), "Test Partially Paid Leave")
 
-		ss = make_employee_salary_slip("test_for_attendance@salary.com", "Monthly")
+		ss = make_employee_salary_slip("test_payment_days_based_on_leave_application@salary.com", "Monthly", "Test Payment Based On Leave Application")
+
 
 		self.assertEqual(ss.leave_without_pay, 4)
 
@@ -117,22 +118,17 @@
 
 		self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 4)
 
-		#Gross pay calculation based on attendances
-		gross_pay = 78000 - ((78000 / (days_in_month - no_of_holidays)) * flt(ss.leave_without_pay))
-
-		self.assertEqual(flt(ss.gross_pay, 2), flt(gross_pay, 2))
-
 		frappe.db.set_value("Payroll Settings", None, "payroll_based_on", "Leave")
 
 	def test_salary_slip_with_holidays_included(self):
 		no_of_days = self.get_no_of_days()
 		frappe.db.set_value("Payroll Settings", None, "include_holidays_in_total_working_days", 1)
-		make_employee("test_employee@salary.com")
+		make_employee("test_salary_slip_with_holidays_included@salary.com")
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+			{"employee_name":"test_salary_slip_with_holidays_included@salary.com"}, "name"), "relieving_date", None)
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
-		ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
+			{"employee_name":"test_salary_slip_with_holidays_included@salary.com"}, "name"), "status", "Active")
+		ss = make_employee_salary_slip("test_salary_slip_with_holidays_included@salary.com", "Monthly", "Test Salary Slip With Holidays Included")
 
 		self.assertEqual(ss.total_working_days, no_of_days[0])
 		self.assertEqual(ss.payment_days, no_of_days[0])
@@ -143,12 +139,12 @@
 	def test_salary_slip_with_holidays_excluded(self):
 		no_of_days = self.get_no_of_days()
 		frappe.db.set_value("Payroll Settings", None, "include_holidays_in_total_working_days", 0)
-		make_employee("test_employee@salary.com")
+		make_employee("test_salary_slip_with_holidays_excluded@salary.com")
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+			{"employee_name":"test_salary_slip_with_holidays_excluded@salary.com"}, "name"), "relieving_date", None)
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
-		ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
+			{"employee_name":"test_salary_slip_with_holidays_excluded@salary.com"}, "name"), "status", "Active")
+		ss = make_employee_salary_slip("test_salary_slip_with_holidays_excluded@salary.com", "Monthly",  "Test Salary Slip With Holidays Excluded")
 
 		self.assertEqual(ss.total_working_days, no_of_days[0] - no_of_days[1])
 		self.assertEqual(ss.payment_days, no_of_days[0] - no_of_days[1])
@@ -163,7 +159,7 @@
 		frappe.db.set_value("Payroll Settings", None, "include_holidays_in_total_working_days", 1)
 
 		# set joinng date in the same month
-		make_employee("test_employee@salary.com")
+		make_employee("test_payment_days@salary.com")
 		if getdate(nowdate()).day >= 15:
 			relieving_date = getdate(add_days(nowdate(),-10))
 			date_of_joining = getdate(add_days(nowdate(),-10))
@@ -178,39 +174,39 @@
 			relieving_date = getdate(nowdate())
 
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", date_of_joining)
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "date_of_joining", date_of_joining)
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", None)
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Active")
 
-		ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
+		ss = make_employee_salary_slip("test_payment_days@salary.com", "Monthly", "Test Payment Days")
 
 		self.assertEqual(ss.total_working_days, no_of_days[0])
 		self.assertEqual(ss.payment_days, (no_of_days[0] - getdate(date_of_joining).day + 1))
 
 		# set relieving date in the same month
 		frappe.db.set_value("Employee",frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60)))
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60)))
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", relieving_date)
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", relieving_date)
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Left")
 		ss.save()
 
 		self.assertEqual(ss.total_working_days, no_of_days[0])
 		self.assertEqual(ss.payment_days, getdate(relieving_date).day)
 
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", None)
 		frappe.db.set_value("Employee", frappe.get_value("Employee",
-			{"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
+			{"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Active")
 
 	def test_employee_salary_slip_read_permission(self):
-		make_employee("test_employee@salary.com")
+		make_employee("test_employee_salary_slip_read_permission@salary.com")
 
-		salary_slip_test_employee = make_employee_salary_slip("test_employee@salary.com", "Monthly")
-		frappe.set_user("test_employee@salary.com")
+		salary_slip_test_employee = make_employee_salary_slip("test_employee_salary_slip_read_permission@salary.com", "Monthly", "Test Employee Salary Slip Read Permission")
+		frappe.set_user("test_employee_salary_slip_read_permission@salary.com")
 		self.assertTrue(salary_slip_test_employee.has_permission("read"))
 
 	def test_email_salary_slip(self):
@@ -218,8 +214,8 @@
 
 		frappe.db.set_value("Payroll Settings", None, "email_salary_slip_to_employee", 1)
 
-		make_employee("test_employee@salary.com")
-		ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
+		make_employee("test_email_salary_slip@salary.com")
+		ss = make_employee_salary_slip("test_email_salary_slip@salary.com", "Monthly", "Test Salary Slip Email")
 		ss.company = "_Test Company"
 		ss.save()
 		ss.submit()
@@ -230,8 +226,9 @@
 	def test_loan_repayment_salary_slip(self):
 		from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan, make_loan_disbursement_entry, create_loan_accounts
 		from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
+		from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
 
-		applicant = make_employee("test_loanemployee@salary.com", company="_Test Company")
+		applicant = make_employee("test_loan_repayment_salary_slip@salary.com", company="_Test Company")
 
 		create_loan_accounts()
 
@@ -243,6 +240,8 @@
 			interest_income_account='Interest Income Account - _TC',
 			penalty_income_account='Penalty Income Account - _TC')
 
+		make_salary_structure("Test Loan Repayment Salary Structure", "Monthly", employee=applicant, currency='INR')
+		frappe.db.sql("""delete from `tabLoan""")
 		loan = create_loan(applicant, "Car Loan", 11000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1))
 		loan.repay_from_salary = 1
 		loan.submit()
@@ -251,7 +250,7 @@
 
 		process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
 
-		ss = make_employee_salary_slip("test_loanemployee@salary.com", "Monthly")
+		ss = make_employee_salary_slip("test_loan_repayment_salary_slip@salary.com", "Monthly", "Test Loan Repayment Salary Structure")
 		ss.submit()
 
 		self.assertEqual(ss.total_loan_repayment, 592)
@@ -264,7 +263,7 @@
 
 		for payroll_frequency in ["Monthly", "Bimonthly", "Fortnightly", "Weekly", "Daily"]:
 			make_employee(payroll_frequency + "_test_employee@salary.com")
-			ss = make_employee_salary_slip(payroll_frequency + "_test_employee@salary.com", payroll_frequency)
+			ss = make_employee_salary_slip(payroll_frequency + "_test_employee@salary.com", payroll_frequency, payroll_frequency + "_Test Payroll Frequency")
 			if payroll_frequency == "Monthly":
 				self.assertEqual(ss.end_date, m['month_end_date'])
 			elif payroll_frequency == "Bimonthly":
@@ -279,6 +278,18 @@
 			elif payroll_frequency == "Daily":
 				self.assertEqual(ss.end_date, nowdate())
 
+	def test_multi_currency_salary_slip(self):
+		from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
+		applicant = make_employee("test_multi_currency_salary_slip@salary.com", company="_Test Company")
+		frappe.db.sql("""delete from `tabSalary Structure` where name='Test Multi Currency Salary Slip'""")
+		salary_structure = make_salary_structure("Test Multi Currency Salary Slip", "Monthly", employee=applicant, company="_Test Company", currency='USD')
+		salary_slip = make_salary_slip(salary_structure.name, employee = applicant)
+		salary_slip.exchange_rate = 70
+		salary_slip.calculate_net_pay()
+
+		self.assertEqual(salary_slip.gross_pay, 78000)
+		self.assertEqual(salary_slip.base_gross_pay, 78000*70)
+
 	def test_tax_for_payroll_period(self):
 		data = {}
 		# test the impact of tax exemption declaration, tax exemption proof submission
@@ -399,16 +410,21 @@
 		salary_structure = payroll_frequency + " Salary Structure Test for Salary Slip"
 
 	employee = frappe.db.get_value("Employee", {"user_id": user})
-	salary_structure_doc = make_salary_structure(salary_structure, payroll_frequency, employee)
-	salary_slip = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
+	if not frappe.db.exists('Salary Structure', salary_structure):
+		salary_structure_doc = make_salary_structure(salary_structure, payroll_frequency, employee)
+	else:
+		salary_structure_doc = frappe.get_doc('Salary Structure', salary_structure)
+	salary_slip_name = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
 
-	if not salary_slip:
+	if not salary_slip_name:
 		salary_slip = make_salary_slip(salary_structure_doc.name, employee = employee)
 		salary_slip.employee_name = frappe.get_value("Employee",
 			{"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
 		salary_slip.payroll_frequency = payroll_frequency
 		salary_slip.posting_date = nowdate()
 		salary_slip.insert()
+	else:
+		salary_slip = frappe.get_doc('Salary Slip', salary_slip_name)
 
 	return salary_slip
 
@@ -449,7 +465,7 @@
 
 			sal_comp.append("accounts", {
 				"company": d,
-				"default_account": create_account(account_name, d, parent_account)
+				"account": create_account(account_name, d, parent_account)
 			})
 			sal_comp.save()
 
@@ -576,7 +592,8 @@
 		"doctype": "Employee Tax Exemption Declaration",
 		"employee": employee,
 		"payroll_period": payroll_period,
-		"company": erpnext.get_default_company()
+		"company": erpnext.get_default_company(),
+		"currency": erpnext.get_default_currency()
 	})
 	declaration.append("declarations", {
 		"exemption_sub_category": "_Test Sub Category",
@@ -591,7 +608,8 @@
 		"doctype": "Employee Tax Exemption Proof Submission",
 		"employee": employee,
 		"payroll_period": payroll_period.name,
-		"submission_date": submission_date
+		"submission_date": submission_date,
+		"currency": erpnext.get_default_currency()
 	})
 	proof_submission.append("tax_exemption_proofs", {
 		"exemption_sub_category": "_Test Sub Category",
@@ -608,13 +626,13 @@
 		"employee": employee,
 		"claimed_amount": amount,
 		"claim_date": claim_date,
-		"earning_component": component
+		"earning_component": component,
+		"currency": erpnext.get_default_currency()
 	}).submit()
 	return claim_date
 
-def create_tax_slab(payroll_period, effective_date = None, allow_tax_exemption = False, dont_submit = False):
-	if frappe.db.exists("Income Tax Slab", "Tax Slab: " + payroll_period.name):
-		return
+def create_tax_slab(payroll_period, effective_date = None, allow_tax_exemption = False, dont_submit = False, currency=erpnext.get_default_currency()):
+	frappe.db.sql("""delete from `tabIncome Tax Slab`""")
 
 	slabs = [
 		{
@@ -637,6 +655,7 @@
 	income_tax_slab = frappe.new_doc("Income Tax Slab")
 	income_tax_slab.name = "Tax Slab: " + payroll_period.name
 	income_tax_slab.effective_from = effective_date or add_days(payroll_period.start_date, -2)
+	income_tax_slab.currency = currency
 
 	if allow_tax_exemption:
 		income_tax_slab.allow_tax_exemption = 1
@@ -687,7 +706,8 @@
 		"salary_component": "Performance Bonus",
 		"payroll_date": salary_date,
 		"amount": amount,
-		"type": "Earning"
+		"type": "Earning",
+		"currency": erpnext.get_default_currency()
 	}).submit()
 	return salary_date
 
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js
index ad93a2f..7daae49 100755
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.js
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js
@@ -41,20 +41,6 @@
 
 		frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet)
 
-		frm.set_query("salary_component", "earnings", function() {
-			return {
-				filters: {
-					type: "earning"
-				}
-			}
-		});
-		frm.set_query("salary_component", "deductions", function() {
-			return {
-				filters: {
-					type: "deduction"
-				}
-			}
-		});
 		frm.set_query("payment_account", function () {
 			var account_types = ["Bank", "Cash"];
 			return {
@@ -65,9 +51,48 @@
 				}
 			};
 		});
+		frm.trigger('set_earning_deduction_component');
+	},
+
+	set_earning_deduction_component: function(frm) {
+		if(!frm.doc.currency && !frm.doc.company) return;
+		frm.set_query("salary_component", "earnings", function() {
+			return {
+				query : "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
+				filters: {type: "earning", currency: frm.doc.currency, company: frm.doc.company}
+			};
+		});
+		frm.set_query("salary_component", "deductions", function() {
+			return {
+				query : "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
+				filters: {type: "deduction", currency: frm.doc.currency, company: frm.doc.company}
+			};
+		});
+	},
+
+
+	currency: function(frm) {
+		calculate_totals(frm.doc);
+		frm.trigger("set_dynamic_labels")
+		frm.trigger('set_earning_deduction_component');
+		frm.refresh()
+	},
+
+	set_dynamic_labels: function(frm) {
+		frm.set_currency_labels(["net_pay","hour_rate", "leave_encashment_amount_per_day", "max_benefits", "total_earning",
+			"total_deduction"], frm.doc.currency);
+
+		frm.set_currency_labels(["amount", "additional_amount", "tax_on_flexible_benefit", "tax_on_additional_salary"],
+			frm.doc.currency, "earnings");
+
+		frm.set_currency_labels(["amount", "additional_amount", "tax_on_flexible_benefit", "tax_on_additional_salary"],
+			frm.doc.currency, "deductions");
+
+		frm.refresh_fields();
 	},
 
 	refresh: function(frm) {
+		frm.trigger("set_dynamic_labels")
 		frm.trigger("toggle_fields");
 		frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false);
 		frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false);
@@ -101,10 +126,12 @@
 			fields: [
 				{fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
 				{fieldname: "company", fieldtype: "Link", options: "Company", label: __("Company"), default: frm.doc.company, read_only:1},
+				{fieldname: "currency", fieldtype: "Link", options: "Currency", label: __("Currency"), default: frm.doc.currency, read_only:1},
 				{fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
 				{fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
 				{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
-                {fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
+				{fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
+				{fieldname:"payroll_payable_account", fieldtype: "Link", options: "Account", filters: {"company": frm.doc.company, "root_type": "Liability", "is_group": 0, "account_currency": frm.doc.currency}, label: __("Payroll Payable Account")},
 				{fieldname:'base_variable', fieldtype:'Section Break'},
 				{fieldname:'from_date', fieldtype:'Date', label: __('From Date'), "reqd": 1},
 				{fieldname:'income_tax_slab', fieldtype:'Link', label: __('Income Tax Slab'), options: 'Income Tax Slab'},
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.json b/erpnext/payroll/doctype/salary_structure/salary_structure.json
index 5f94929..de56fc8 100644
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.json
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.json
@@ -13,6 +13,7 @@
   "column_break1",
   "is_active",
   "payroll_frequency",
+  "currency",
   "is_default",
   "time_sheet_earning_detail",
   "salary_slip_based_on_timesheet",
@@ -26,9 +27,9 @@
   "deductions",
   "conditions_and_formula_variable_and_example",
   "net_pay_detail",
-  "column_break2",
   "total_earning",
   "total_deduction",
+  "column_break2",
   "net_pay",
   "account",
   "mode_of_payment",
@@ -43,23 +44,17 @@
    "label": "Company",
    "options": "Company",
    "remember_last_selected_value": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "letter_head",
    "fieldtype": "Link",
    "label": "Letter Head",
-   "options": "Letter Head",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Letter Head"
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -72,9 +67,7 @@
    "oldfieldname": "is_active",
    "oldfieldtype": "Select",
    "options": "\nYes\nNo",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "default": "Monthly",
@@ -82,9 +75,7 @@
    "fieldname": "payroll_frequency",
    "fieldtype": "Select",
    "label": "Payroll Frequency",
-   "options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily"
   },
   {
    "default": "No",
@@ -95,62 +86,46 @@
    "no_copy": 1,
    "options": "Yes\nNo",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "time_sheet_earning_detail",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "default": "0",
    "fieldname": "salary_slip_based_on_timesheet",
    "fieldtype": "Check",
-   "label": "Salary Slip Based on Timesheet",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Salary Slip Based on Timesheet"
   },
   {
    "fieldname": "column_break_17",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "description": "Salary Component for timesheet based payroll.",
    "fieldname": "salary_component",
    "fieldtype": "Link",
    "label": "Salary Component",
-   "options": "Salary Component",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Salary Component"
   },
   {
    "fieldname": "hour_rate",
    "fieldtype": "Currency",
    "label": "Hour Rate",
-   "options": "Company:company:default_currency",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "currency"
   },
   {
    "fieldname": "leave_encashment_amount_per_day",
    "fieldtype": "Currency",
    "label": "Leave Encashment Amount Per Day",
-   "options": "Company:company:default_currency",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "currency"
   },
   {
    "fieldname": "max_benefits",
    "fieldtype": "Currency",
    "label": "Max Benefits (Amount)",
-   "options": "Company:company:default_currency",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "currency"
   },
   {
    "description": "Salary breakup based on Earning and Deduction.",
@@ -158,9 +133,7 @@
    "fieldtype": "Section Break",
    "oldfieldname": "earning_deduction",
    "oldfieldtype": "Section Break",
-   "precision": "2",
-   "show_days": 1,
-   "show_seconds": 1
+   "precision": "2"
   },
   {
    "fieldname": "earnings",
@@ -168,9 +141,7 @@
    "label": "Earnings",
    "oldfieldname": "earning_details",
    "oldfieldtype": "Table",
-   "options": "Salary Detail",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Salary Detail"
   },
   {
    "fieldname": "deductions",
@@ -178,22 +149,16 @@
    "label": "Deductions",
    "oldfieldname": "deduction_details",
    "oldfieldtype": "Table",
-   "options": "Salary Detail",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Salary Detail"
   },
   {
    "fieldname": "net_pay_detail",
    "fieldtype": "Section Break",
-   "options": "Simple",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Simple"
   },
   {
    "fieldname": "column_break2",
    "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -201,63 +166,45 @@
    "fieldtype": "Currency",
    "hidden": 1,
    "label": "Total Earning",
-   "oldfieldname": "total_earning",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "currency",
+   "read_only": 1
   },
   {
    "fieldname": "total_deduction",
    "fieldtype": "Currency",
    "hidden": 1,
    "label": "Total Deduction",
-   "oldfieldname": "total_deduction",
-   "oldfieldtype": "Currency",
-   "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "currency",
+   "read_only": 1
   },
   {
    "fieldname": "net_pay",
    "fieldtype": "Currency",
    "hidden": 1,
    "label": "Net Pay",
-   "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "currency",
+   "read_only": 1
   },
   {
    "fieldname": "account",
    "fieldtype": "Section Break",
-   "label": "Account",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Account"
   },
   {
    "fieldname": "mode_of_payment",
    "fieldtype": "Link",
    "label": "Mode of Payment",
-   "options": "Mode of Payment",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Mode of Payment"
   },
   {
    "fieldname": "column_break_28",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "payment_account",
    "fieldtype": "Link",
    "label": "Payment Account",
-   "options": "Account",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Account"
   },
   {
    "fieldname": "amended_from",
@@ -266,23 +213,26 @@
    "no_copy": 1,
    "options": "Salary Structure",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "conditions_and_formula_variable_and_example",
    "fieldtype": "HTML",
-   "label": "Conditions and Formula variable and example",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Conditions and Formula variable and example"
+  },
+  {
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "reqd": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 17:07:26.129355",
+ "modified": "2020-09-30 11:30:32.190798",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Structure",
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.py b/erpnext/payroll/doctype/salary_structure/salary_structure.py
index ffc16d7..877e41d 100644
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.py
@@ -2,7 +2,7 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 
 from frappe.utils import flt, cint, cstr
 from frappe import _
@@ -88,24 +88,26 @@
 		return employees
 
 	@frappe.whitelist()
-	def assign_salary_structure(self, company=None, grade=None, department=None, designation=None,employee=None,
-			from_date=None, base=None, variable=None, income_tax_slab=None):
-		employees = self.get_employees(company= company, grade= grade,department= department,designation= designation,name=employee)
+	def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None,
+			payroll_payable_account=None, from_date=None, base=None, variable=None, income_tax_slab=None):
+		employees = self.get_employees(company= self.company, grade= grade,department= department,designation= designation,name=employee)
 
 		if employees:
 			if len(employees) > 20:
 				frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
-					employees=employees, salary_structure=self,from_date=from_date,
-					base=base, variable=variable, income_tax_slab=income_tax_slab)
+					employees=employees, salary_structure=self,
+					payroll_payable_account=payroll_payable_account,
+					from_date=from_date, base=base, variable=variable, income_tax_slab=income_tax_slab)
 			else:
-				assign_salary_structure_for_employees(employees, self, from_date=from_date,
-					base=base, variable=variable, income_tax_slab=income_tax_slab)
+				assign_salary_structure_for_employees(employees, self,
+					payroll_payable_account=payroll_payable_account, 
+					from_date=from_date, base=base, variable=variable, income_tax_slab=income_tax_slab)
 		else:
 			frappe.msgprint(_("No Employee Found"))
 
 
 
-def assign_salary_structure_for_employees(employees, salary_structure, from_date=None, base=None, variable=None, income_tax_slab=None):
+def assign_salary_structure_for_employees(employees, salary_structure, payroll_payable_account=None, from_date=None, base=None, variable=None, income_tax_slab=None):
 	salary_structures_assignments = []
 	existing_assignments_for = get_existing_assignments(employees, salary_structure, from_date)
 	count=0
@@ -115,7 +117,7 @@
 		count +=1
 
 		salary_structures_assignment = create_salary_structures_assignment(employee,
-			salary_structure, from_date, base, variable, income_tax_slab)
+			salary_structure, payroll_payable_account, from_date, base, variable, income_tax_slab)
 		salary_structures_assignments.append(salary_structures_assignment)
 		frappe.publish_progress(count*100/len(set(employees) - set(existing_assignments_for)), title = _("Assigning Structures..."))
 
@@ -123,11 +125,22 @@
 		frappe.msgprint(_("Structures have been assigned successfully"))
 
 
-def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable, income_tax_slab=None):
+def create_salary_structures_assignment(employee, salary_structure, payroll_payable_account, from_date, base, variable, income_tax_slab=None):
+	if not payroll_payable_account:
+		payroll_payable_account = frappe.db.get_value('Company', salary_structure.company, 'default_payroll_payable_account')
+		if not payroll_payable_account:
+			frappe.throw(_('Please set "Default Payroll Payable Account" in Company Defaults'))
+	payroll_payable_account_currency = frappe.db.get_value('Account',  payroll_payable_account, 'account_currency')
+	company_curency = erpnext.get_company_currency(salary_structure.company)
+	if payroll_payable_account_currency != salary_structure.currency and payroll_payable_account_currency != company_curency:
+		frappe.throw(_("Invalid Payroll Payable Account. The account currency must be {0} or {1}").format(salary_structure.currency, company_curency))
+
 	assignment = frappe.new_doc("Salary Structure Assignment")
 	assignment.employee = employee
 	assignment.salary_structure = salary_structure.name
 	assignment.company = salary_structure.company
+	assignment.currency = salary_structure.currency
+	assignment.payroll_payable_account = payroll_payable_account
 	assignment.from_date = from_date
 	assignment.base = base
 	assignment.variable = variable
@@ -170,7 +183,8 @@
 			"doctype": "Salary Slip",
 			"field_map": {
 				"total_earning": "gross_pay",
-				"name": "salary_structure"
+				"name": "salary_structure",
+				"currency": "currency"
 			}
 		}
 	}, target_doc, postprocess, ignore_child_tables=True, ignore_permissions=ignore_permissions)
@@ -188,7 +202,22 @@
 		filters={'salary_structure': salary_structure, 'docstatus': 1}, fields=['employee'])
 
 	if not employees:
-		frappe.throw(_("There's no Employee with Salary Structure: {0}. \
-			Assign {1} to an Employee to preview Salary Slip").format(salary_structure, salary_structure))
+		frappe.throw(_("There's no Employee with Salary Structure: {0}. Assign {1} to an Employee to preview Salary Slip").format(
+			salary_structure, salary_structure))
 
 	return list(set([d.employee for d in employees]))
+
+@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
+def get_earning_deduction_components(doctype, txt, searchfield, start, page_len, filters):
+	if len(filters) < 3:
+		return {}
+
+	return frappe.db.sql("""
+		select t1.salary_component
+		from `tabSalary Component` t1, `tabSalary Component Account` t2
+		where t1.salary_component = t2.parent
+		and t1.type = %s 
+		and t2.company = %s
+		order by salary_component
+	""", (filters['type'], filters['company']) )
diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
index e04fda8..abb6697 100644
--- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
@@ -94,7 +94,8 @@
 			self.assertFalse(("\n" in row.formula) or ("\n" in row.condition))
 
 	def test_salary_structures_assignment(self):
-		salary_structure = make_salary_structure("Salary Structure Sample", "Monthly")
+		company_currency = erpnext.get_default_currency()
+		salary_structure = make_salary_structure("Salary Structure Sample", "Monthly", currency=company_currency)
 		employee = "test_assign_stucture@salary.com"
 		employee_doc_name = make_employee(employee)
 		# clear the already assigned stuctures
@@ -107,8 +108,13 @@
 		self.assertEqual(salary_structure_assignment.base, 5000)
 		self.assertEqual(salary_structure_assignment.variable, 200)
 
+	def test_multi_currency_salary_structure(self):
+		make_employee("test_muti_currency_employee@salary.com")
+		sal_struct = make_salary_structure("Salary Structure Multi Currency", "Monthly", currency='USD')
+		self.assertEqual(sal_struct.currency, 'USD')
+
 def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None,
-	test_tax=False, company=None):
+	test_tax=False, company=None, currency=erpnext.get_default_currency()):
 	if test_tax:
 		frappe.db.sql("""delete from `tabSalary Structure` where name=%s""",(salary_structure))
 
@@ -120,7 +126,8 @@
 			"earnings": make_earning_salary_component(test_tax=test_tax, company_list=["_Test Company"]),
 			"deductions": make_deduction_salary_component(test_tax=test_tax, company_list=["_Test Company"]),
 			"payroll_frequency": payroll_frequency,
-			"payment_account": get_random("Account")
+			"payment_account": get_random("Account", filters={'account_currency': currency}),
+			"currency": currency
 		}
 		if other_details and isinstance(other_details, dict):
 			details.update(other_details)
@@ -134,16 +141,16 @@
 
 	if employee and not frappe.db.get_value("Salary Structure Assignment",
 		{'employee':employee, 'docstatus': 1}) and salary_structure_doc.docstatus==1:
-			create_salary_structure_assignment(employee, salary_structure, company=company)
+			create_salary_structure_assignment(employee, salary_structure, company=company, currency=currency)
 
 	return salary_structure_doc
 
-def create_salary_structure_assignment(employee, salary_structure, from_date=None, company=None):
+def create_salary_structure_assignment(employee, salary_structure, from_date=None, company=None, currency=erpnext.get_default_currency()):
 	if frappe.db.exists("Salary Structure Assignment", {"employee": employee}):
 		frappe.db.sql("""delete from `tabSalary Structure Assignment` where employee=%s""",(employee))
 
 	payroll_period = create_payroll_period()
-	create_tax_slab(payroll_period, allow_tax_exemption=True)
+	create_tax_slab(payroll_period, allow_tax_exemption=True, currency=currency)
 
 	salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
 	salary_structure_assignment.employee = employee
@@ -151,8 +158,15 @@
 	salary_structure_assignment.variable = 5000
 	salary_structure_assignment.from_date = from_date or add_days(nowdate(), -1)
 	salary_structure_assignment.salary_structure = salary_structure
+	salary_structure_assignment.currency = currency
+	salary_structure_assignment.payroll_payable_account = get_payable_account(company)
 	salary_structure_assignment.company = company or erpnext.get_default_company()
 	salary_structure_assignment.save(ignore_permissions=True)
 	salary_structure_assignment.income_tax_slab = "Tax Slab: _Test Payroll Period"
 	salary_structure_assignment.submit()
 	return salary_structure_assignment
+
+def get_payable_account(company=None):
+	if not company:
+		company = erpnext.get_default_company()
+	return frappe.db.get_value("Company", company, "default_payroll_payable_account")
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js
index 818e853..6cd897e 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js
@@ -6,9 +6,6 @@
 		frm.set_query("employee", function() {
 			return {
 				query: "erpnext.controllers.queries.employee_query",
-				filters: {
-					company: frm.doc.company
-				}
 			}
 		});
 		frm.set_query("salary_structure", function() {
@@ -26,11 +23,25 @@
 				filters: {
 					company: frm.doc.company,
 					docstatus: 1,
-					disabled: 0
+					disabled: 0,
+					currency: frm.doc.currency
+				}
+			};
+		});
+
+		frm.set_query("payroll_payable_account", function() {
+			var company_currency = erpnext.get_currency(frm.doc.company);
+			return {
+				filters: {
+					"company": frm.doc.company,
+					"root_type": "Liability",
+					"is_group": 0,
+					"account_currency": ["in", [frm.doc.currency, company_currency]],
 				}
 			}
 		});
 	},
+
 	employee: function(frm) {
 		if(frm.doc.employee){
 			frappe.call({
@@ -52,5 +63,13 @@
 		else{
 			frm.set_value("company", null);
 		}
+	},
+
+	company: function(frm) {
+		if (frm.doc.company) {
+			frappe.db.get_value("Company", frm.doc.company, "default_payroll_payable_account", (r) => {
+				frm.set_value("payroll_payable_account", r.default_payroll_payable_account);
+			});
+		}
 	}
 });
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
index c84e034..92bb347 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
@@ -11,11 +11,13 @@
   "employee_name",
   "department",
   "company",
+  "payroll_payable_account",
   "column_break_6",
   "designation",
   "salary_structure",
   "from_date",
   "income_tax_slab",
+  "currency",
   "section_break_7",
   "base",
   "column_break_9",
@@ -94,7 +96,7 @@
    "fieldname": "base",
    "fieldtype": "Currency",
    "label": "Base",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   },
   {
    "fieldname": "column_break_9",
@@ -104,7 +106,7 @@
    "fieldname": "variable",
    "fieldtype": "Currency",
    "label": "Variable",
-   "options": "Company:company:default_currency"
+   "options": "currency"
   },
   {
    "fieldname": "amended_from",
@@ -116,15 +118,35 @@
    "read_only": 1
   },
   {
+   "depends_on": "salary_structure",
    "fieldname": "income_tax_slab",
    "fieldtype": "Link",
    "label": "Income Tax Slab",
    "options": "Income Tax Slab"
+  },
+  {
+   "default": "Company:company:default_currency",
+   "depends_on": "eval:(doc.docstatus==1 || doc.salary_structure)",
+   "fetch_from": "salary_structure.currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "depends_on": "employee",
+   "fieldname": "payroll_payable_account",
+   "fieldtype": "Link",
+   "label": "Payroll Payable Account",
+   "options": "Account"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 19:58:09.964692",
+ "modified": "2020-11-30 18:07:48.251311",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Structure Assignment",
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py
index 668e0ec..dccb5df 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py
@@ -13,6 +13,8 @@
 class SalaryStructureAssignment(Document):
 	def validate(self):
 		self.validate_dates()
+		self.validate_income_tax_slab()
+		self.set_payroll_payable_account()
 
 	def validate_dates(self):
 		joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
@@ -31,6 +33,24 @@
 				frappe.throw(_("From Date {0} cannot be after employee's relieving Date {1}")
 					.format(self.from_date, relieving_date))
 
+	def validate_income_tax_slab(self):
+		if not self.income_tax_slab:
+			return
+		
+		income_tax_slab_currency = frappe.db.get_value('Income Tax Slab', self.income_tax_slab, 'currency')
+		if self.currency != income_tax_slab_currency:
+			frappe.throw(_("Currency of selected Income Tax Slab should be {0} instead of {1}").format(self.currency, income_tax_slab_currency))
+
+	def set_payroll_payable_account(self):
+		if not self.payroll_payable_account:
+			payroll_payable_account = frappe.db.get_value('Company', self.company, 'default_payable_account')
+			if not payroll_payable_account:
+				payroll_payable_account = frappe.db.get_value(
+					"Account", {
+						"account_name": _("Payroll Payable"), "company": self.company, "account_currency": frappe.db.get_value(
+							"Company", self.company, "default_currency"), "is_group": 0})
+			self.payroll_payable_account = payroll_payable_account
+
 def get_assigned_salary_structure(employee, on_date):
 	if not employee or not on_date:
 		return None
@@ -43,3 +63,10 @@
 			'on_date': on_date,
 		})
 	return salary_structure[0][0] if salary_structure else None
+
+@frappe.whitelist()
+def get_employee_currency(employee):
+	employee_currency = frappe.db.get_value('Salary Structure Assignment', {'employee': employee}, 'currency')
+	if not employee_currency:
+		frappe.throw(_("There is no Salary Structure assigned to {0}. First assign a Salary Stucture.").format(employee))
+	return employee_currency
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json
index 94eda4c..65d3824 100644
--- a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json
+++ b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json
@@ -19,13 +19,15 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "From Amount",
+   "options": "currency",
    "reqd": 1
   },
   {
    "fieldname": "to_amount",
    "fieldtype": "Currency",
    "in_list_view": 1,
-   "label": "To Amount"
+   "label": "To Amount",
+   "options": "currency"
   },
   {
    "default": "0",
@@ -53,7 +55,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 18:16:07.596493",
+ "modified": "2020-10-19 13:44:39.549337",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Taxable Salary Slab",
diff --git a/erpnext/payroll/report/salary_register/salary_register.js b/erpnext/payroll/report/salary_register/salary_register.js
index 885e3d1..eb4acb9 100644
--- a/erpnext/payroll/report/salary_register/salary_register.js
+++ b/erpnext/payroll/report/salary_register/salary_register.js
@@ -8,34 +8,48 @@
 			"label": __("From"),
 			"fieldtype": "Date",
 			"default": frappe.datetime.add_months(frappe.datetime.get_today(),-1),
-			"reqd": 1
+			"reqd": 1,
+			"width": "100px"
 		},
 		{
 			"fieldname":"to_date",
 			"label": __("To"),
 			"fieldtype": "Date",
 			"default": frappe.datetime.get_today(),
-			"reqd": 1
+			"reqd": 1,
+			"width": "100px"
+		},
+		{
+			"fieldname": "currency",
+			"fieldtype": "Link",
+			"options": "Currency",
+			"label": __("Currency"),
+			"default": erpnext.get_currency(frappe.defaults.get_default("Company")),
+			"width": "50px"
 		},
 		{
 			"fieldname":"employee",
 			"label": __("Employee"),
 			"fieldtype": "Link",
-			"options": "Employee"
+			"options": "Employee",
+			"width": "100px"
 		},
 		{
 			"fieldname":"company",
 			"label": __("Company"),
 			"fieldtype": "Link",
 			"options": "Company",
-			"default": frappe.defaults.get_user_default("Company")
+			"default": frappe.defaults.get_user_default("Company"),
+			"width": "100px",
+			"reqd": 1
 		},
 		{
 			"fieldname":"docstatus",
 			"label":__("Document Status"),
 			"fieldtype":"Select",
 			"options":["Draft", "Submitted", "Cancelled"],
-			"default":"Submitted"
+			"default": "Submitted",
+			"width": "100px"
 		}
 	]
 }
diff --git a/erpnext/payroll/report/salary_register/salary_register.py b/erpnext/payroll/report/salary_register/salary_register.py
index 8701085..a1b1a8c 100644
--- a/erpnext/payroll/report/salary_register/salary_register.py
+++ b/erpnext/payroll/report/salary_register/salary_register.py
@@ -2,18 +2,22 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 from frappe.utils import flt
 from frappe import _
 
 def execute(filters=None):
 	if not filters: filters = {}
-	salary_slips = get_salary_slips(filters)
+	currency = None
+	if filters.get('currency'):
+		currency = filters.get('currency')
+	company_currency = erpnext.get_company_currency(filters.get("company"))
+	salary_slips = get_salary_slips(filters, company_currency)
 	if not salary_slips: return [], []
 
 	columns, earning_types, ded_types = get_columns(salary_slips)
-	ss_earning_map = get_ss_earning_map(salary_slips)
-	ss_ded_map = get_ss_ded_map(salary_slips)
+	ss_earning_map = get_ss_earning_map(salary_slips, currency, company_currency)
+	ss_ded_map = get_ss_ded_map(salary_slips,currency, company_currency)
 	doj_map = get_employee_doj_map()
 
 	data = []
@@ -21,24 +25,30 @@
 		row = [ss.name, ss.employee, ss.employee_name, doj_map.get(ss.employee), ss.branch, ss.department, ss.designation,
 			ss.company, ss.start_date, ss.end_date, ss.leave_without_pay, ss.payment_days]
 
-		if not ss.branch == None:columns[3] = columns[3].replace('-1','120')
-		if not ss.department  == None: columns[4] = columns[4].replace('-1','120')
-		if not ss.designation  == None: columns[5] = columns[5].replace('-1','120')
-		if not ss.leave_without_pay  == None: columns[9] = columns[9].replace('-1','130')
+		if ss.branch is not None: columns[3] = columns[3].replace('-1','120')
+		if ss.department is not None: columns[4] = columns[4].replace('-1','120')
+		if ss.designation is not None: columns[5] = columns[5].replace('-1','120')
+		if ss.leave_without_pay is not None: columns[9] = columns[9].replace('-1','130')
 
 
 		for e in earning_types:
 			row.append(ss_earning_map.get(ss.name, {}).get(e))
 
-		row += [ss.gross_pay]
+		if currency == company_currency:
+			row += [flt(ss.gross_pay) * flt(ss.exchange_rate)]
+		else:
+			row += [ss.gross_pay]
 
 		for d in ded_types:
 			row.append(ss_ded_map.get(ss.name, {}).get(d))
 
 		row.append(ss.total_loan_repayment)
 
-		row += [ss.total_deduction, ss.net_pay]
-
+		if currency == company_currency:
+			row += [flt(ss.total_deduction) * flt(ss.exchange_rate), flt(ss.net_pay) * flt(ss.exchange_rate)]
+		else:
+			row += [ss.total_deduction, ss.net_pay]
+		row.append(currency or company_currency)
 		data.append(row)
 
 	return columns, data
@@ -46,10 +56,19 @@
 def get_columns(salary_slips):
 	"""
 	columns = [
-		_("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140",
-		_("Date of Joining") + "::80", _("Branch") + ":Link/Branch:120", _("Department") + ":Link/Department:120",
-		_("Designation") + ":Link/Designation:120", _("Company") + ":Link/Company:120", _("Start Date") + "::80",
-		_("End Date") + "::80", _("Leave Without Pay") + ":Float:130", _("Payment Days") + ":Float:120"
+		_("Salary Slip ID") + ":Link/Salary Slip:150",
+		_("Employee") + ":Link/Employee:120",
+		_("Employee Name") + "::140",
+		_("Date of Joining") + "::80",
+		_("Branch") + ":Link/Branch:120",
+		_("Department") + ":Link/Department:120",
+		_("Designation") + ":Link/Designation:120",
+		_("Company") + ":Link/Company:120",
+		_("Start Date") + "::80",
+		_("End Date") + "::80",
+		_("Leave Without Pay") + ":Float:130",
+		_("Payment Days") + ":Float:120",
+		_("Currency") + ":Link/Currency:80"
 	]
 	"""
 	columns = [
@@ -73,15 +92,15 @@
 
 	return columns, salary_components[_("Earning")], salary_components[_("Deduction")]
 
-def get_salary_slips(filters):
+def get_salary_slips(filters, company_currency):
 	filters.update({"from_date": filters.get("from_date"), "to_date":filters.get("to_date")})
-	conditions, filters = get_conditions(filters)
+	conditions, filters = get_conditions(filters, company_currency)
 	salary_slips = frappe.db.sql("""select * from `tabSalary Slip` where %s
 		order by employee""" % conditions, filters, as_dict=1)
 
 	return salary_slips or []
 
-def get_conditions(filters):
+def get_conditions(filters, company_currency):
 	conditions = ""
 	doc_status = {"Draft": 0, "Submitted": 1, "Cancelled": 2}
 
@@ -92,6 +111,8 @@
 	if filters.get("to_date"): conditions += " and end_date <= %(to_date)s"
 	if filters.get("company"): conditions += " and company = %(company)s"
 	if filters.get("employee"): conditions += " and employee = %(employee)s"
+	if filters.get("currency") and filters.get("currency") != company_currency:
+		conditions += " and currency = %(currency)s"
 
 	return conditions, filters
 
@@ -103,26 +124,32 @@
 				FROM `tabEmployee`
 				"""))
 
-def get_ss_earning_map(salary_slips):
-	ss_earnings = frappe.db.sql("""select parent, salary_component, amount
-		from `tabSalary Detail` where parent in (%s)""" %
+def get_ss_earning_map(salary_slips, currency, company_currency):
+	ss_earnings = frappe.db.sql("""select sd.parent, sd.salary_component, sd.amount, ss.exchange_rate, ss.name
+		from `tabSalary Detail` sd, `tabSalary Slip` ss where sd.parent=ss.name and sd.parent in (%s)""" %
 		(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
 
 	ss_earning_map = {}
 	for d in ss_earnings:
 		ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
-		ss_earning_map[d.parent][d.salary_component] = flt(d.amount)
+		if currency == company_currency:
+			ss_earning_map[d.parent][d.salary_component] = flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1)
+		else:
+			ss_earning_map[d.parent][d.salary_component] = flt(d.amount)
 
 	return ss_earning_map
 
-def get_ss_ded_map(salary_slips):
-	ss_deductions = frappe.db.sql("""select parent, salary_component, amount
-		from `tabSalary Detail` where parent in (%s)""" %
+def get_ss_ded_map(salary_slips, currency, company_currency):
+	ss_deductions = frappe.db.sql("""select sd.parent, sd.salary_component, sd.amount, ss.exchange_rate, ss.name
+		from `tabSalary Detail` sd, `tabSalary Slip` ss where sd.parent=ss.name and sd.parent in (%s)""" %
 		(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
 
 	ss_ded_map = {}
 	for d in ss_deductions:
 		ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
-		ss_ded_map[d.parent][d.salary_component] = flt(d.amount)
+		if currency == company_currency:
+			ss_ded_map[d.parent][d.salary_component] = flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1)
+		else:
+			ss_ded_map[d.parent][d.salary_component] = flt(d.amount)
 
 	return ss_ded_map
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index 2695502..2f15cbc 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -49,7 +49,8 @@
 		"public/js/education/assessment_result_tool.html",
 		"public/js/hub/hub_factory.js",
 		"public/js/call_popup/call_popup.js",
-		"public/js/utils/dimension_tree_filter.js"
+		"public/js/utils/dimension_tree_filter.js",
+		"public/js/telephony.js"
 	],
 	"js/item-dashboard.min.js": [
 		"stock/dashboard/item_dashboard.html",
diff --git a/erpnext/public/js/call_popup/call_popup.js b/erpnext/public/js/call_popup/call_popup.js
index 5e4d4a5..aeb3b38 100644
--- a/erpnext/public/js/call_popup/call_popup.js
+++ b/erpnext/public/js/call_popup/call_popup.js
@@ -74,7 +74,7 @@
 				'click': () => {
 					const call_summary = this.dialog.get_value('call_summary');
 					if (!call_summary) return;
-					frappe.xcall('erpnext.communication.doctype.call_log.call_log.add_call_summary', {
+					frappe.xcall('erpnext.telephony.doctype.call_log.call_log.add_call_summary', {
 						'call_log': this.call_log.name,
 						'summary': call_summary,
 					}).then(() => {
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index 3f5652a..db85a3e 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -189,6 +189,7 @@
 
 			frappe.model.round_floats_in(item, ["qty", "received_qty"]);
 			item.rejected_qty = flt(item.received_qty - item.qty, precision("rejected_qty", item));
+			item.received_stock_qty = flt(item.conversion_factor, precision("conversion_factor", item)) * flt(item.received_qty);
 		}
 
 		this._super(doc, cdt, cdn);
@@ -293,69 +294,6 @@
 		this.get_terms();
 	},
 
-	link_to_mrs: function() {
-		var my_items = [];
-		for (var i in cur_frm.doc.items) {
-			if(!cur_frm.doc.items[i].material_request){
-				my_items.push(cur_frm.doc.items[i].item_code);
-			}
-		}
-		frappe.call({
-			method: "erpnext.buying.utils.get_linked_material_requests",
-			args:{
-				items: my_items
-			},
-			callback: function(r) {
-				if(!r.message || r.message.length == 0) {
-					frappe.throw(__("No pending Material Requests found to link for the given items."))
-				}
-				else {
-					var i = 0;
-					var item_length = cur_frm.doc.items.length;
-					while (i < item_length) {
-						var qty = cur_frm.doc.items[i].qty;
-						(r.message[0] || []).forEach(function(d) {
-							if (d.qty > 0 && qty > 0 && cur_frm.doc.items[i].item_code == d.item_code && !cur_frm.doc.items[i].material_request_item)
-							{
-								cur_frm.doc.items[i].material_request = d.mr_name;
-								cur_frm.doc.items[i].material_request_item = d.mr_item;
-								var my_qty = Math.min(qty, d.qty);
-								qty = qty - my_qty;
-								d.qty = d.qty  - my_qty;
-								cur_frm.doc.items[i].stock_qty = my_qty*cur_frm.doc.items[i].conversion_factor;
-								cur_frm.doc.items[i].qty = my_qty;
-
-								frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + cur_frm.doc.items[i].idx + ")");
-								if (qty > 0)
-								{
-									frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
-									var newrow = frappe.model.add_child(cur_frm.doc, cur_frm.doc.items[i].doctype, "items");
-									item_length++;
-
-									for (var key in cur_frm.doc.items[i])
-									{
-										newrow[key] = cur_frm.doc.items[i][key];
-									}
-
-									newrow.idx = item_length;
-									newrow["stock_qty"] = newrow.conversion_factor*qty;
-									newrow["qty"] = qty;
-
-									newrow["material_request"] = "";
-									newrow["material_request_item"] = "";
-
-								}
-							}
-						});
-						i++;
-					}
-					refresh_field("items");
-					//cur_frm.save();
-				}
-			}
-		});
-	},
-
 	update_auto_repeat_reference: function(doc) {
 		if (doc.auto_repeat) {
 			frappe.call({
@@ -421,6 +359,62 @@
 
 cur_frm.add_fetch('project', 'cost_center', 'cost_center');
 
+erpnext.buying.link_to_mrs = function(frm) {
+	frappe.call({
+		method: "erpnext.buying.utils.get_linked_material_requests",
+		args:{
+			items: frm.doc.items.map((item) => item.item_code)
+		},
+		callback: function(r) {
+			if (!r.message || r.message.length == 0) {
+				frappe.throw({
+					message: __("No pending Material Requests found to link for the given items."),
+					title: __("Note")
+				});
+			}
+
+			var item_length = frm.doc.items.length;
+			for (let item of frm.doc.items) {
+				var qty = item.qty;
+				(r.message[0] || []).forEach(function(d) {
+					if (d.qty > 0 && qty > 0 && item.item_code == d.item_code && !item.material_request_item)
+					{
+						item.material_request = d.mr_name;
+						item.material_request_item = d.mr_item;
+						var my_qty = Math.min(qty, d.qty);
+						qty = qty - my_qty;
+						d.qty = d.qty - my_qty;
+						item.stock_qty = my_qty*item.conversion_factor;
+						item.qty = my_qty;
+
+						frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + item.idx + ")");
+						if (qty > 0)
+						{
+							frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
+							var newrow = frappe.model.add_child(frm.doc, item.doctype, "items");
+							item_length++;
+
+							for (var key in item)
+							{
+								newrow[key] = item[key];
+							}
+
+							newrow.idx = item_length;
+							newrow["stock_qty"] = newrow.conversion_factor*qty;
+							newrow["qty"] = qty;
+
+							newrow["material_request"] = "";
+							newrow["material_request_item"] = "";
+
+						}
+					}
+				});
+			}
+			refresh_field("items");
+		}
+	});
+}
+
 erpnext.buying.get_default_bom = function(frm) {
 	$.each(frm.doc["items"] || [], function(i, d) {
 		if (d.item_code && d.bom === "") {
diff --git a/erpnext/public/js/telephony.js b/erpnext/public/js/telephony.js
new file mode 100644
index 0000000..bd7f890
--- /dev/null
+++ b/erpnext/public/js/telephony.js
@@ -0,0 +1,23 @@
+frappe.ui.form.ControlData = frappe.ui.form.ControlData.extend( {
+	make_input() {
+		this._super();
+		if (this.df.options == 'Phone') {
+			this.setup_phone();
+		}
+	},
+	setup_phone() {
+		if (frappe.phone_call.handler) {
+			this.$wrapper.find('.control-input')
+				.append(`
+					<span class="phone-btn">
+						<a class="btn-open no-decoration" title="${__('Make a call')}">
+							<i class="fa fa-phone"></i></a>
+					</span>
+				`)
+				.find('.phone-btn')
+				.click(() => {
+					frappe.phone_call.handler(this.get_value(), this.frm);
+				});
+		}
+	}
+});
\ No newline at end of file
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 787d557..68c8a0d 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -192,19 +192,20 @@
 		for d in self.report_dict["itc_elg"]["itc_avl"]:
 
 			itc_type = itc_type_map.get(d["ty"])
-			gst_category = ["Registered Regular"]
 
 			if d["ty"] == 'ISRC':
-				reverse_charge = "Y"
+				reverse_charge = ["Y"]
 				itc_type = 'All Other ITC'
 				gst_category = ['Unregistered', 'Overseas']
 			else:
-				reverse_charge = "N"
+				gst_category = ['Unregistered', 'Overseas', 'Registered Regular']
+				reverse_charge = ["N", "Y"]
 
 			for account_head in self.account_heads:
 				for category in gst_category:
-					for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]:
-						d[key[0]] += flt(itc_details.get((category, itc_type, reverse_charge, account_head.get(key[1])), {}).get("amount"), 2)
+					for charge_type in reverse_charge:
+						for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]:
+							d[key[0]] += flt(itc_details.get((category, itc_type, charge_type, account_head.get(key[1])), {}).get("amount"), 2)
 
 			for key in ['iamt', 'camt', 'samt', 'csamt']:
 				net_itc[key] += flt(d[key], 2)
@@ -264,7 +265,8 @@
 
 	def get_itc_details(self):
 		itc_amount = frappe.db.sql("""
-			select s.gst_category, sum(t.tax_amount_after_discount_amount) as tax_amount, t.account_head, s.eligibility_for_itc, s.reverse_charge
+			select s.gst_category, sum(t.base_tax_amount_after_discount_amount) as tax_amount,
+			t.account_head, s.eligibility_for_itc, s.reverse_charge
 			from `tabPurchase Invoice` s , `tabPurchase Taxes and Charges` t
 			where s.docstatus = 1 and t.parent = s.name
 			and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s
@@ -387,7 +389,7 @@
 			tax_template = 'Purchase Taxes and Charges'
 
 		tax_amounts = frappe.db.sql("""
-			select s.gst_category, sum(t.tax_amount_after_discount_amount) as tax_amount, t.account_head
+			select s.gst_category, sum(t.base_tax_amount_after_discount_amount) as tax_amount, t.account_head
 			from `tab{doctype}` s , `tab{template}` t
 			where s.docstatus = 1 and t.parent = s.name and s.reverse_charge = %s
 			and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index 3c15647..b70b2ec 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -19,6 +19,7 @@
 				'shipping_address': frm.doc.shipping_address || '',
 				'shipping_address_name': frm.doc.shipping_address_name || '',
 				'customer_address': frm.doc.customer_address || '',
+				'supplier_address': frm.doc.supplier_address,
 				'customer': frm.doc.customer,
 				'supplier': frm.doc.supplier,
 				'supplier_gstin': frm.doc.supplier_gstin,
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 62487ba..f8520c2 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -12,6 +12,7 @@
 from six import string_types
 from erpnext.accounts.general_ledger import make_gl_entries
 from erpnext.accounts.utils import get_account_currency
+from frappe.model.utils import get_fetch_values
 
 def validate_gstin_for_india(doc, method):
 	if hasattr(doc, 'gst_state') and doc.gst_state:
@@ -161,6 +162,8 @@
 		party_details = json.loads(party_details)
 		party_details = frappe._dict(party_details)
 
+	update_party_details(party_details, doctype)
+
 	party_details.place_of_supply = get_place_of_supply(party_details, doctype)
 
 	if is_internal_transfer(party_details, doctype):
@@ -209,6 +212,11 @@
 
 	return party_details
 
+def update_party_details(party_details, doctype):
+	for address_field in ['shipping_address', 'company_address', 'supplier_address', 'shipping_address_name', 'customer_address']:
+		if party_details.get(address_field):
+			party_details.update(get_fetch_values(doctype, address_field, party_details.get(address_field)))
+
 def is_internal_transfer(party_details, doctype):
 	if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
 		destination_gstin = party_details.company_gstin
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 282efe4..8379297 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -78,7 +78,7 @@
 				place_of_supply = invoice_details.get("place_of_supply")
 				ecommerce_gstin =  invoice_details.get("ecommerce_gstin")
 
-				b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin),{
+				b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin, inv),{
 					"place_of_supply": "",
 					"ecommerce_gstin": "",
 					"rate": "",
@@ -90,7 +90,7 @@
 					"invoice_value": invoice_details.get("base_grand_total"),
 				})
 
-				row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin))
+				row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin, inv))
 				row["place_of_supply"] = place_of_supply
 				row["ecommerce_gstin"] = ecommerce_gstin
 				row["rate"] = rate
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 1d890bb..d4fb07c 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -8,7 +8,7 @@
 		frm.custom_make_buttons = {
 			'Delivery Note': 'Delivery Note',
 			'Pick List': 'Pick List',
-			'Sales Invoice': 'Invoice',
+			'Sales Invoice': 'Sales Invoice',
 			'Material Request': 'Material Request',
 			'Purchase Order': 'Purchase Order',
 			'Project': 'Project',
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
index c716aa9..8473276 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
@@ -10,8 +10,8 @@
 def execute(filters=None):
 	filters = frappe._dict(filters or {})
 	if filters.from_date > filters.to_date:
-		frappe.throw(_('From Date cannot be greater than To Date'))
-	
+		frappe.throw(_("From Date cannot be greater than To Date"))
+
 	columns = get_columns(filters)
 	data = get_data(filters)
 
@@ -148,14 +148,16 @@
 	company_list.append(filters.get("company"))
 
 	customer_details = get_customer_details()
+	item_details = get_item_details()
 	sales_order_records = get_sales_order_details(company_list, filters)
 
 	for record in sales_order_records:
 		customer_record = customer_details.get(record.customer)
+		item_record = item_details.get(record.item_code)
 		row = {
 			"item_code": record.item_code,
-			"item_name": record.item_name,
-			"item_group": record.item_group,
+			"item_name": item_record.item_name,
+			"item_group": item_record.item_group,
 			"description": record.description,
 			"quantity": record.qty,
 			"uom": record.uom,
@@ -196,8 +198,8 @@
 	return conditions
 
 def get_customer_details():
-	details = frappe.get_all('Customer',
-		fields=['name', 'customer_name', "customer_group"])
+	details = frappe.get_all("Customer",
+		fields=["name", "customer_name", "customer_group"])
 	customer_details = {}
 	for d in details:
 		customer_details.setdefault(d.name, frappe._dict({
@@ -206,15 +208,25 @@
 		}))
 	return customer_details
 
+def get_item_details():
+	details = frappe.db.get_all("Item",
+		fields=["item_code", "item_name", "item_group"])
+	item_details = {}
+	for d in details:
+		item_details.setdefault(d.item_code, frappe._dict({
+			"item_name": d.item_name,
+			"item_group": d.item_group
+		}))
+	return item_details
+
 def get_sales_order_details(company_list, filters):
 	conditions = get_conditions(filters)
 
 	return frappe.db.sql("""
 		SELECT
-			so_item.item_code, so_item.item_name, so_item.item_group,
-			so_item.description, so_item.qty, so_item.uom,
-			so_item.base_rate, so_item.base_amount, so.name,
-			so.transaction_date, so.customer, so.territory,
+			so_item.item_code, so_item.description, so_item.qty,
+			so_item.uom, so_item.base_rate, so_item.base_amount,
+			so.name, so.transaction_date, so.customer,so.territory,
 			so.project, so_item.delivered_qty,
 			so_item.billed_amt, so.company
 		FROM
diff --git a/erpnext/setup/desk_page/home/home.json b/erpnext/setup/desk_page/home/home.json
index 9cf9f41..0fbd0ec 100644
--- a/erpnext/setup/desk_page/home/home.json
+++ b/erpnext/setup/desk_page/home/home.json
@@ -2,26 +2,6 @@
  "cards": [
   {
    "hidden": 0,
-   "label": "Healthcare",
-   "links": "[\n    {\n        \"label\": \"Patient\",\n        \"name\": \"Patient\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Diagnosis\",\n        \"name\": \"Diagnosis\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    }\n]"
-  },
-  {
-   "hidden": 0,
-   "label": "Agriculture",
-   "links": "[\n    {\n        \"label\": \"Crop\",\n        \"name\": \"Crop\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Crop Cycle\",\n        \"name\": \"Crop Cycle\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Location\",\n        \"name\": \"Location\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Fertilizer\",\n        \"name\": \"Fertilizer\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    }\n]"
-  },
-  {
-   "hidden": 0,
-   "label": "Education",
-   "links": "[\n    {\n        \"label\": \"Student\",\n        \"name\": \"Student\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Course\",\n        \"name\": \"Course\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Instructor\",\n        \"name\": \"Instructor\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Room\",\n        \"name\": \"Room\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    }\n]"
-  },
-  {
-   "hidden": 0,
-   "label": "Non Profit",
-   "links": "[\n    {\n        \"description\": \"Member information.\",\n        \"label\": \"Member\",\n        \"name\": \"Member\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Volunteer information.\",\n        \"label\": \"Volunteer\",\n        \"name\": \"Volunteer\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Chapter information.\",\n        \"label\": \"Chapter\",\n        \"name\": \"Chapter\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Donor information.\",\n        \"label\": \"Donor\",\n        \"name\": \"Donor\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    }\n]"
-  },
-  {
-   "hidden": 0,
    "label": "Stock",
    "links": "[\n    {\n        \"label\": \"Warehouse\",\n        \"name\": \"Warehouse\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Brand\",\n        \"name\": \"Brand\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Unit of Measure (UOM)\",\n        \"name\": \"UOM\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Stock Reconciliation\",\n        \"name\": \"Stock Reconciliation\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    }\n]"
   },
@@ -54,10 +34,11 @@
  "docstatus": 0,
  "doctype": "Desk Page",
  "extends_another_page": 0,
+ "hide_custom": 0,
  "idx": 0,
  "is_standard": 1,
  "label": "Home",
- "modified": "2020-05-11 10:20:37.358701",
+ "modified": "2020-12-07 14:22:38.667767",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Home",
@@ -96,4 +77,4 @@
    "type": "Page"
   }
  ]
-}
\ No newline at end of file
+}
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 0ccc025..c2549fe 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -345,7 +345,7 @@
 	selling_price_list = None
 
 	# check if default customer price list exists
-	if party_name:
+	if party_name and frappe.db.exists("Customer", party_name):
 		selling_price_list = get_default_price_list(frappe.get_doc("Customer", party_name))
 
 	# check default price list in shopping cart
diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json
index 390fcd9..9068e33 100644
--- a/erpnext/stock/desk_page/stock/stock.json
+++ b/erpnext/stock/desk_page/stock/stock.json
@@ -8,7 +8,7 @@
   {
    "hidden": 0,
    "label": "Stock Transactions",
-   "links": "[\n     {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"label\": \"Material Request\",\n        \"name\": \"Material Request\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"label\": \"Stock Entry\",\n        \"name\": \"Stock Entry\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\",\n            \"Customer\"\n        ],\n        \"label\": \"Delivery Note\",\n        \"name\": \"Delivery Note\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\",\n            \"Supplier\"\n        ],\n        \"label\": \"Purchase Receipt\",\n        \"name\": \"Purchase Receipt\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"label\": \"Pick List\",\n        \"name\": \"Pick List\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Delivery Trip\",\n        \"name\": \"Delivery Trip\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n     {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"label\": \"Material Request\",\n        \"name\": \"Material Request\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"label\": \"Stock Entry\",\n        \"name\": \"Stock Entry\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\",\n            \"Customer\"\n        ],\n        \"label\": \"Delivery Note\",\n        \"name\": \"Delivery Note\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\",\n            \"Supplier\"\n        ],\n        \"label\": \"Purchase Receipt\",\n        \"name\": \"Purchase Receipt\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"label\": \"Pick List\",\n        \"name\": \"Pick List\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Shipment\",\n        \"name\": \"Shipment\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Delivery Trip\",\n        \"name\": \"Delivery Trip\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -58,7 +58,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Stock",
- "modified": "2020-10-07 18:40:17.130207",
+ "modified": "2020-12-02 15:47:41.532942",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 251a26a..03921c5 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -156,6 +156,11 @@
 		}
 
 		if (!doc.is_return && doc.status!="Closed") {
+			if(doc.docstatus == 1) {
+				this.frm.add_custom_button(__('Shipment'), function() {
+					me.make_shipment() }, __('Create'));
+			}
+
 			if(flt(doc.per_installed, 2) < 100 && doc.docstatus==1)
 				this.frm.add_custom_button(__('Installation Note'), function() {
 					me.make_installation_note() }, __('Create'));
@@ -220,6 +225,13 @@
 		}
 	},
 
+	make_shipment: function() {
+		frappe.model.open_mapped_doc({
+			method: "erpnext.stock.doctype.delivery_note.delivery_note.make_shipment",
+			frm: this.frm
+		})
+	},
+
 	make_sales_invoice: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 7393c8a..c9f8d08 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -133,6 +133,7 @@
   "per_installed",
   "installation_status",
   "column_break_89",
+  "per_returned",
   "excise_page",
   "instructions",
   "subscription_section",
@@ -1099,7 +1100,7 @@
    "no_copy": 1,
    "oldfieldname": "status",
    "oldfieldtype": "Select",
-   "options": "\nDraft\nTo Bill\nCompleted\nCancelled\nClosed",
+   "options": "\nDraft\nTo Bill\nCompleted\nReturn Issued\nCancelled\nClosed",
    "print_hide": 1,
    "print_width": "150px",
    "read_only": 1,
@@ -1251,13 +1252,22 @@
    "fieldtype": "Link",
    "label": "Inter Company Reference",
    "options": "Purchase Receipt"
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "per_returned",
+   "fieldtype": "Percent",
+   "label": "% Returned",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "icon": "fa fa-truck",
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-11-11 14:57:16.388139",
+ "modified": "2020-11-30 12:54:45.407289",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index d04cf78..3f3407e 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -55,7 +55,7 @@
 			'no_allowance': 1
 		}]
 		if cint(self.is_return):
-			self.status_updater.append({
+			self.status_updater.extend([{
 				'source_dt': 'Delivery Note Item',
 				'target_dt': 'Sales Order Item',
 				'join_field': 'so_detail',
@@ -69,7 +69,19 @@
 					where name=`tabDelivery Note Item`.parent and is_return=1)""",
 				'second_source_extra_cond': """ and exists (select name from `tabSales Invoice`
 					where name=`tabSales Invoice Item`.parent and is_return=1 and update_stock=1)"""
-			})
+			},
+			{
+				'source_dt': 'Delivery Note Item',
+				'target_dt': 'Delivery Note Item',
+				'join_field': 'dn_detail',
+				'target_field': 'returned_qty',
+				'target_parent_dt': 'Delivery Note',
+				'target_parent_field': 'per_returned',
+				'target_ref_field': 'stock_qty',
+				'source_field': '-1 * stock_qty',
+				'percent_join_field_parent': 'return_against'
+			}
+		])
 
 	def before_print(self):
 		def toggle_print_hide(meta, fieldname):
@@ -569,6 +581,62 @@
 
 	return doclist
 
+@frappe.whitelist()
+def make_shipment(source_name, target_doc=None):
+	def postprocess(source, target):
+		user = frappe.db.get_value("User", frappe.session.user, ['email', 'full_name', 'phone', 'mobile_no'], as_dict=1)
+		target.pickup_contact_email = user.email
+		pickup_contact_display = '{}'.format(user.full_name)
+		if user:
+			if user.email:
+				pickup_contact_display += '<br>' + user.email
+			if user.phone:
+				pickup_contact_display += '<br>' + user.phone
+			if user.mobile_no and not user.phone:
+				pickup_contact_display += '<br>' + user.mobile_no
+		target.pickup_contact = pickup_contact_display
+
+		contact = frappe.db.get_value("Contact", source.contact_person, ['email_id', 'phone', 'mobile_no'], as_dict=1)
+		delivery_contact_display = '{}'.format(source.contact_display)
+		if contact:
+			if contact.email_id:
+				delivery_contact_display += '<br>' + contact.email_id
+			if contact.phone:
+				delivery_contact_display += '<br>' + contact.phone
+			if contact.mobile_no and not contact.phone:
+				delivery_contact_display += '<br>' + contact.mobile_no
+		target.delivery_contact = delivery_contact_display
+
+	doclist = get_mapped_doc("Delivery Note", source_name, 	{
+		"Delivery Note": {
+			"doctype": "Shipment",
+			"field_map": {
+				"grand_total": "value_of_goods",
+				"company": "pickup_company",
+				"company_address": "pickup_address_name",
+				"company_address_display": "pickup_address",
+				"address_display": "delivery_address",
+				"customer": "delivery_customer",
+				"shipping_address_name": "delivery_address_name",
+				"contact_person": "delivery_contact_name",
+				"contact_email": "delivery_contact_email"
+			},
+			"validation": {
+				"docstatus": ["=", 1]
+			}
+		},
+		"Delivery Note Item": {
+			"doctype": "Shipment Delivery Note",
+			"field_map": {
+				"name": "prevdoc_detail_docname",
+				"parent": "prevdoc_docname",
+				"parenttype": "prevdoc_doctype",
+				"base_amount": "grand_total"
+			}
+		}
+	}, target_doc, postprocess)
+	
+	return doclist
 
 @frappe.whitelist()
 def make_sales_return(source_name, target_doc=None):
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note_list.js b/erpnext/stock/doctype/delivery_note/delivery_note_list.js
index 0ae7c37..4a6500c 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note_list.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note_list.js
@@ -6,9 +6,11 @@
 			return [__("Return"), "darkgrey", "is_return,=,Yes"];
 		} else if (doc.status === "Closed") {
 			return [__("Closed"), "green", "status,=,Closed"];
+		} else if (flt(doc.per_returned, 2) === 100) {
+			return [__("Return Issued"), "grey", "per_returned,=,100"];
 		} else if (flt(doc.per_billed, 2) < 100) {
 			return [__("To Bill"), "orange", "per_billed,<,100"];
-		} else if (flt(doc.per_billed, 2) == 100) {
+		} else if (flt(doc.per_billed, 2) === 100) {
 			return [__("Completed"), "green", "per_billed,=,100"];
 		}
 	},
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 9566af7..6b4663a 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -206,7 +206,7 @@
 		for field, value in field_values.items():
 			self.assertEqual(cstr(serial_no.get(field)), value)
 
-	def test_sales_return_for_non_bundled_items(self):
+	def test_sales_return_for_non_bundled_items_partial(self):
 		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
 
 		make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100)
@@ -225,7 +225,10 @@
 
 		# return entry
 		dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500,
-			company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
+			company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1",
+			cost_center="Main - TCP1", do_not_submit=1)
+		dn1.items[0].dn_detail = dn.items[0].name
+		dn1.submit()
 
 		actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1")
 
@@ -243,6 +246,70 @@
 
 		self.assertEqual(gle_warehouse_amount, stock_value_difference)
 
+		# hack because new_doc isn't considering is_return portion of status_updater
+		returned = frappe.get_doc("Delivery Note", dn1.name)
+		returned.update_prevdoc_status()
+		dn.load_from_db()
+
+		# Check if Original DN updated
+		self.assertEqual(dn.items[0].returned_qty, 2)
+		self.assertEqual(dn.per_returned, 40)
+
+		from erpnext.controllers.sales_and_purchase_return import make_return_doc
+		return_dn_2 = make_return_doc("Delivery Note", dn.name)
+
+		# Check if unreturned amount is mapped in 2nd return
+		self.assertEqual(return_dn_2.items[0].qty, -3)
+
+		si = make_sales_invoice(dn.name)
+		si.submit()
+
+		self.assertEqual(si.items[0].qty, 3)
+
+		dn.load_from_db()
+		# DN should be completed on billing all unreturned amount
+		self.assertEqual(dn.items[0].billed_amt, 1500)
+		self.assertEqual(dn.per_billed, 100)
+		self.assertEqual(dn.status, 'Completed')
+
+		si.load_from_db()
+		si.cancel()
+
+		dn.load_from_db()
+		self.assertEqual(dn.per_billed, 0)
+
+		dn1.cancel()
+		dn.cancel()
+
+	def test_sales_return_for_non_bundled_items_full(self):
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
+
+		make_item("Box", {'is_stock_item': 1})
+
+		make_stock_entry(item_code="Box", target="Stores - TCP1", qty=10, basic_rate=100)
+
+		dn = create_delivery_note(item_code="Box", qty=5, rate=500, warehouse="Stores - TCP1", company=company,
+			expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
+
+		#return entry
+		dn1 = create_delivery_note(item_code="Box", is_return=1, return_against=dn.name, qty=-5, rate=500,
+			company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1",
+			cost_center="Main - TCP1", do_not_submit=1)
+		dn1.items[0].dn_detail = dn.items[0].name
+		dn1.submit()
+
+		# hack because new_doc isn't considering is_return portion of status_updater
+		returned = frappe.get_doc("Delivery Note", dn1.name)
+		returned.update_prevdoc_status()
+		dn.load_from_db()
+
+		# Check if Original DN updated
+		self.assertEqual(dn.items[0].returned_qty, 5)
+		self.assertEqual(dn.per_returned, 100)
+		self.assertEqual(dn.status, 'Return Issued')
+
 	def test_return_single_item_from_bundled_items(self):
 		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
 
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index 3d57f47..7b47187 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "hash",
  "creation": "2013-04-22 13:15:44",
  "doctype": "DocType",
@@ -24,7 +25,10 @@
   "col_break2",
   "uom",
   "conversion_factor",
+  "stock_qty_sec_break",
   "stock_qty",
+  "stock_qty_col_break",
+  "returned_qty",
   "section_break_17",
   "price_list_rate",
   "base_price_list_rate",
@@ -211,7 +215,7 @@
   {
    "fieldname": "stock_qty",
    "fieldtype": "Float",
-   "label": "Qty as per Stock UOM",
+   "label": "Qty in Stock UOM",
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
@@ -715,12 +719,29 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "stock_qty_sec_break",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "stock_qty_col_break",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "returned_qty",
+   "fieldname": "returned_qty",
+   "fieldtype": "Float",
+   "label": "Returned Qty in Stock UOM",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-07-20 12:25:06.177894",
+ "modified": "2020-07-31 20:12:43.054342",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note Item",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 13c8ceb..5bb3095 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -111,6 +111,7 @@
   "range",
   "column_break4",
   "per_billed",
+  "per_returned",
   "is_internal_supplier",
   "inter_company_reference",
   "subscription_detail",
@@ -895,7 +896,7 @@
    "no_copy": 1,
    "oldfieldname": "status",
    "oldfieldtype": "Select",
-   "options": "\nDraft\nTo Bill\nCompleted\nCancelled\nClosed",
+   "options": "\nDraft\nTo Bill\nCompleted\nReturn Issued\nCancelled\nClosed",
    "print_hide": 1,
    "print_width": "150px",
    "read_only": 1,
@@ -1104,13 +1105,22 @@
    "fieldtype": "Small Text",
    "label": "Billing Address",
    "read_only": 1
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "per_returned",
+   "fieldtype": "Percent",
+   "label": "% Returned",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "icon": "fa fa-truck",
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-30 14:00:08.347534",
+ "modified": "2020-11-30 12:54:23.278500",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 2cc4679..97e0fa7 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -55,20 +55,33 @@
 			'percent_join_field': 'material_request'
 		}]
 		if cint(self.is_return):
-			self.status_updater.append({
-				'source_dt': 'Purchase Receipt Item',
-				'target_dt': 'Purchase Order Item',
-				'join_field': 'purchase_order_item',
-				'target_field': 'returned_qty',
-				'source_field': '-1 * qty',
-				'second_source_dt': 'Purchase Invoice Item',
-				'second_source_field': '-1 * qty',
-				'second_join_field': 'po_detail',
-				'extra_cond': """ and exists (select name from `tabPurchase Receipt`
-					where name=`tabPurchase Receipt Item`.parent and is_return=1)""",
-				'second_source_extra_cond': """ and exists (select name from `tabPurchase Invoice`
-					where name=`tabPurchase Invoice Item`.parent and is_return=1 and update_stock=1)"""
-			})
+			self.status_updater.extend([
+				{
+					'source_dt': 'Purchase Receipt Item',
+					'target_dt': 'Purchase Order Item',
+					'join_field': 'purchase_order_item',
+					'target_field': 'returned_qty',
+					'source_field': '-1 * qty',
+					'second_source_dt': 'Purchase Invoice Item',
+					'second_source_field': '-1 * qty',
+					'second_join_field': 'po_detail',
+					'extra_cond': """ and exists (select name from `tabPurchase Receipt`
+						where name=`tabPurchase Receipt Item`.parent and is_return=1)""",
+					'second_source_extra_cond': """ and exists (select name from `tabPurchase Invoice`
+						where name=`tabPurchase Invoice Item`.parent and is_return=1 and update_stock=1)"""
+				},
+				{
+					'source_dt': 'Purchase Receipt Item',
+					'target_dt': 'Purchase Receipt Item',
+					'join_field': 'purchase_receipt_item',
+					'target_field': 'returned_qty',
+					'target_parent_dt': 'Purchase Receipt',
+					'target_parent_field': 'per_returned',
+					'target_ref_field': 'received_stock_qty',
+					'source_field': '-1 * received_stock_qty',
+					'percent_join_field_parent': 'return_against'
+				}
+			])
 
 	def validate(self):
 		self.validate_posting_time()
@@ -478,7 +491,7 @@
 			frappe.db.set_value("Asset", asset.name, "purchase_receipt_amount", flt(valuation_rate))
 
 	def update_status(self, status):
-		self.set_status(update=True, status = status)
+		self.set_status(update=True, status=status)
 		self.notify_update()
 		clear_doctype_notifications(self)
 
@@ -490,7 +503,7 @@
 
 		for pr in set(updated_pr):
 			pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
-			pr_doc.update_billing_percentage(update_modified=update_modified)
+			update_billing_percentage(pr_doc, update_modified=update_modified)
 
 		self.load_from_db()
 
@@ -500,7 +513,7 @@
 		where po_detail=%s and (pr_detail is null or pr_detail = '') and docstatus=1""", po_detail)
 	billed_against_po = billed_against_po and billed_against_po[0][0] or 0
 
-	# Get all Delivery Note Item rows against the Sales Order Item row
+	# Get all Purchase Receipt Item rows against the Purchase Order Item row
 	pr_details = frappe.db.sql("""select pr_item.name, pr_item.amount, pr_item.parent
 		from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
 		where pr.name=pr_item.parent and pr_item.purchase_order_item=%s
@@ -530,6 +543,39 @@
 
 	return updated_pr
 
+def update_billing_percentage(pr_doc, update_modified=True):
+	# Reload as billed amount was set in db directly
+	pr_doc.load_from_db()
+
+	# Update Billing % based on pending accepted qty
+	total_amount, total_billed_amount = 0, 0
+	for item in pr_doc.items:
+		return_data = frappe.db.get_list("Purchase Receipt",
+			fields = [
+				"sum(abs(`tabPurchase Receipt Item`.qty)) as qty"
+			],
+			filters = [
+				["Purchase Receipt", "docstatus", "=", 1],
+				["Purchase Receipt", "is_return", "=", 1],
+				["Purchase Receipt Item", "purchase_receipt_item", "=", item.name]
+		])
+
+		returned_qty = return_data[0].qty if return_data else 0
+		returned_amount = flt(returned_qty) * flt(item.rate)
+		pending_amount = flt(item.amount) - returned_amount
+		total_billable_amount = pending_amount if item.billed_amt <= pending_amount else item.billed_amt
+
+		total_amount += total_billable_amount
+		total_billed_amount += flt(item.billed_amt)
+
+	percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6)
+	pr_doc.db_set("per_billed", percent_billed)
+	pr_doc.load_from_db()
+
+	if update_modified:
+		pr_doc.set_status(update=True)
+		pr_doc.notify_update()
+
 @frappe.whitelist()
 def make_purchase_invoice(source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
@@ -552,6 +598,7 @@
 
 	def update_item(source_doc, target_doc, source_parent):
 		target_doc.qty, returned_qty = get_pending_qty(source_doc)
+		target_doc.stock_qty = flt(target_doc.qty) * flt(target_doc.conversion_factor, target_doc.precision("conversion_factor"))
 		returned_qty_map[source_doc.name] = returned_qty
 
 	def get_pending_qty(item_row):
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_list.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_list.js
index e81f323..c9501a4 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_list.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_list.js
@@ -6,9 +6,11 @@
 			return [__("Return"), "darkgrey", "is_return,=,Yes"];
 		} else if (doc.status === "Closed") {
 			return [__("Closed"), "green", "status,=,Closed"];
+		} else if (flt(doc.per_returned, 2) === 100) {
+			return [__("Return Issued"), "grey", "per_returned,=,100"];
 		} else if (flt(doc.grand_total) !== 0 && flt(doc.per_billed, 2) < 100) {
 			return [__("To Bill"), "orange", "per_billed,<,100"];
-		} else if (flt(doc.grand_total) === 0 || flt(doc.per_billed, 2) == 100) {
+		} else if (flt(doc.grand_total) === 0 || flt(doc.per_billed, 2) === 100) {
 			return [__("Completed"), "green", "per_billed,=,100"];
 		}
 	}
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 253edb0..9b8eeed 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -137,7 +137,10 @@
 		self.assertFalse(frappe.db.get_all('Serial No', {'batch_no': batch_no}))
 
 	def test_purchase_receipt_gl_entry(self):
-		pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True)
+		pr = make_purchase_receipt(company="_Test Company with perpetual inventory",
+			warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1",
+			get_multiple_items = True, get_taxes_and_charges = True)
+
 		self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
 
 		gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@@ -281,11 +284,15 @@
 			self.assertEqual(frappe.db.get_value("Serial No", serial_no, "warehouse"),
 				pr.get("items")[0].rejected_warehouse)
 
-	def test_purchase_return(self):
+	def test_purchase_return_partial(self):
+		pr = make_purchase_receipt(company="_Test Company with perpetual inventory",
+			warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
 
-		pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
-
-		return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, qty=-2)
+		return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory",
+			warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1",
+			is_return=1, return_against=pr.name, qty=-2, do_not_submit=1)
+		return_pr.items[0].purchase_receipt_item = pr.items[0].name
+		return_pr.submit()
 
 		# check sle
 		outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
@@ -309,6 +316,60 @@
 			self.assertEqual(expected_values[gle.account][0], gle.debit)
 			self.assertEqual(expected_values[gle.account][1], gle.credit)
 
+		# hack because new_doc isn't considering is_return portion of status_updater
+		returned = frappe.get_doc("Purchase Receipt", return_pr.name)
+		returned.update_prevdoc_status()
+		pr.load_from_db()
+
+		# Check if Original PR updated
+		self.assertEqual(pr.items[0].returned_qty, 2)
+		self.assertEqual(pr.per_returned, 40)
+
+		from erpnext.controllers.sales_and_purchase_return import make_return_doc
+		return_pr_2 = make_return_doc("Purchase Receipt", pr.name)
+
+		# Check if unreturned amount is mapped in 2nd return
+		self.assertEqual(return_pr_2.items[0].qty, -3)
+
+		# Make PI against unreturned amount
+		pi = make_purchase_invoice(pr.name)
+		pi.submit()
+
+		self.assertEqual(pi.items[0].qty, 3)
+
+		pr.load_from_db()
+		# PR should be completed on billing all unreturned amount
+		self.assertEqual(pr.items[0].billed_amt, 150)
+		self.assertEqual(pr.per_billed, 100)
+		self.assertEqual(pr.status, 'Completed')
+
+		pi.load_from_db()
+		pi.cancel()
+
+		pr.load_from_db()
+		self.assertEqual(pr.per_billed, 0)
+
+		return_pr.cancel()
+		pr.cancel()
+
+	def test_purchase_return_full(self):
+		pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1",
+			supplier_warehouse = "Work in Progress - TCP1")
+
+		return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1",
+			supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, qty=-5, do_not_submit=1)
+		return_pr.items[0].purchase_receipt_item = pr.items[0].name
+		return_pr.submit()
+
+		# hack because new_doc isn't considering is_return portion of status_updater
+		returned = frappe.get_doc("Purchase Receipt", return_pr.name)
+		returned.update_prevdoc_status()
+		pr.load_from_db()
+
+		# Check if Original PR updated
+		self.assertEqual(pr.items[0].returned_qty, 5)
+		self.assertEqual(pr.per_returned, 100)
+		self.assertEqual(pr.status, 'Return Issued')
 
 	def test_purchase_return_for_rejected_qty(self):
 		from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
@@ -416,6 +477,7 @@
 		self.assertEqual(pr1.per_billed, 100)
 		self.assertEqual(pr1.status, "Completed")
 
+		pr2.load_from_db()
 		self.assertEqual(pr2.get("items")[0].billed_amt, 2000)
 		self.assertEqual(pr2.per_billed, 80)
 		self.assertEqual(pr2.status, "To Bill")
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index c1e1f90..84c64aa 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -28,9 +28,13 @@
   "uom",
   "stock_uom",
   "conversion_factor",
-  "stock_qty",
   "retain_sample",
   "sample_quantity",
+  "tracking_section",
+  "received_stock_qty",
+  "stock_qty",
+  "col_break_tracking_section",
+  "returned_qty",
   "rate_and_amount",
   "price_list_rate",
   "discount_percentage",
@@ -526,7 +530,7 @@
   {
    "fieldname": "stock_qty",
    "fieldtype": "Float",
-   "label": "Accepted Qty as per Stock UOM",
+   "label": "Accepted Qty in Stock UOM",
    "oldfieldname": "stock_qty",
    "oldfieldtype": "Currency",
    "print_hide": 1,
@@ -834,12 +838,35 @@
    "collapsible": 1,
    "fieldname": "image_column",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "tracking_section",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "col_break_tracking_section",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "returned_qty",
+   "fieldname": "returned_qty",
+   "fieldtype": "Float",
+   "label": "Returned Qty in Stock UOM",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "received_stock_qty",
+   "fieldtype": "Float",
+   "label": "Received Qty in Stock UOM",
+   "print_hide": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-28 19:01:21.154963",
+ "modified": "2020-11-02 10:00:38.204294",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/stock/doctype/shipment/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/stock/doctype/shipment/__init__.py
diff --git a/erpnext/stock/doctype/shipment/shipment.js b/erpnext/stock/doctype/shipment/shipment.js
new file mode 100644
index 0000000..5ccb7d2
--- /dev/null
+++ b/erpnext/stock/doctype/shipment/shipment.js
@@ -0,0 +1,447 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Shipment', {
+	address_query: function(frm, link_doctype, link_name, is_your_company_address) {
+		return {
+			query: 'frappe.contacts.doctype.address.address.address_query',
+			filters: {
+				link_doctype: link_doctype,
+				link_name: link_name,
+				is_your_company_address: is_your_company_address
+			}
+		};
+	},
+	contact_query: function(frm, link_doctype, link_name) {
+		return {
+			query: 'frappe.contacts.doctype.contact.contact.contact_query',
+			filters: {
+				link_doctype: link_doctype,
+				link_name: link_name
+			}
+		};
+	},
+	onload: function(frm) {
+		frm.set_query("delivery_address_name", () => {
+			let delivery_to = `delivery_${frappe.model.scrub(frm.doc.delivery_to_type)}`;
+			return frm.events.address_query(frm, frm.doc.delivery_to_type, frm.doc[delivery_to], frm.doc.delivery_to_type === 'Company' ? 1 : 0);
+		});
+		frm.set_query("pickup_address_name", () => {
+			let pickup_from = `pickup_${frappe.model.scrub(frm.doc.pickup_from_type)}`;
+			return frm.events.address_query(frm, frm.doc.pickup_from_type, frm.doc[pickup_from], frm.doc.pickup_from_type === 'Company' ? 1 : 0);
+		});
+		frm.set_query("delivery_contact_name", () => {
+			let delivery_to = `delivery_${frappe.model.scrub(frm.doc.delivery_to_type)}`;
+			return frm.events.contact_query(frm, frm.doc.delivery_to_type, frm.doc[delivery_to]);
+		});
+		frm.set_query("pickup_contact_name", () => {
+			let pickup_from = `pickup_${frappe.model.scrub(frm.doc.pickup_from_type)}`;
+			return frm.events.contact_query(frm, frm.doc.pickup_from_type, frm.doc[pickup_from]);
+		});
+		frm.set_query("delivery_note", "shipment_delivery_note", function() {
+			let customer = '';
+			if (frm.doc.delivery_to_type == "Customer") {
+				customer = frm.doc.delivery_customer;
+			}
+			if (frm.doc.delivery_to_type == "Company") {
+				customer = frm.doc.delivery_company;
+			}
+			if (customer) {
+				return {
+					filters: {
+						customer: customer,
+						docstatus: 1,
+						status: ["not in", ["Cancelled"]]
+					}
+				};
+			}
+		});
+	},
+	refresh: function() {
+		$('div[data-fieldname=pickup_address] > div > .clearfix').hide();
+		$('div[data-fieldname=pickup_contact] > div > .clearfix').hide();
+		$('div[data-fieldname=delivery_address] > div > .clearfix').hide();
+		$('div[data-fieldname=delivery_contact] > div > .clearfix').hide();
+	},
+	before_save: function(frm) {
+		let delivery_to = `delivery_${frappe.model.scrub(frm.doc.delivery_to_type)}`;
+		frm.set_value("delivery_to", frm.doc[delivery_to]);
+		let pickup_from = `pickup_${frappe.model.scrub(frm.doc.pickup_from_type)}`;
+		frm.set_value("pickup", frm.doc[pickup_from]);
+	},
+	set_pickup_company_address: function(frm) {
+		frappe.db.get_value('Address', {
+			address_title: frm.doc.pickup_company,
+			is_your_company_address: 1
+		}, 'name', (r) => {
+			frm.set_value("pickup_address_name", r.name);
+		});
+	},
+	set_delivery_company_address: function(frm) {
+		frappe.db.get_value('Address', {
+			address_title: frm.doc.delivery_company,
+			is_your_company_address: 1
+		}, 'name', (r) => {
+			frm.set_value("delivery_address_name", r.name);
+		});
+	},
+	pickup_from_type: function(frm) {
+		if (frm.doc.pickup_from_type == 'Company') {
+			frm.set_value("pickup_company", frappe.defaults.get_default('company'));
+			frm.set_value("pickup_customer", '');
+			frm.set_value("pickup_supplier", '');
+		} else {
+			frm.trigger('clear_pickup_fields');
+		}
+		if (frm.doc.pickup_from_type == 'Customer') {
+			frm.set_value("pickup_company", '');
+			frm.set_value("pickup_supplier", '');
+		}
+		if (frm.doc.pickup_from_type == 'Supplier') {
+			frm.set_value("pickup_customer", '');
+			frm.set_value("pickup_company", '');
+		}
+	},
+	delivery_to_type: function(frm) {
+		if (frm.doc.delivery_to_type == 'Company') {
+			frm.set_value("delivery_company", frappe.defaults.get_default('company'));
+			frm.set_value("delivery_customer", '');
+			frm.set_value("delivery_supplier", '');
+		} else {
+			frm.trigger('clear_delivery_fields');
+		}
+		if (frm.doc.delivery_to_type == 'Customer') {
+			frm.set_value("delivery_company", '');
+			frm.set_value("delivery_supplier", '');
+		}
+		if (frm.doc.delivery_to_type == 'Supplier') {
+			frm.set_value("delivery_customer", '');
+			frm.set_value("delivery_company", '');
+			frm.toggle_display("shipment_delivery_note", false);
+		} else {
+			frm.toggle_display("shipment_delivery_note", true);
+		}
+	},
+	delivery_address_name: function(frm) {
+		if (frm.doc.delivery_to_type == 'Company') {
+			erpnext.utils.get_address_display(frm, 'delivery_address_name', 'delivery_address', true);
+		} else {
+			erpnext.utils.get_address_display(frm, 'delivery_address_name', 'delivery_address', false);
+		}
+	},
+	pickup_address_name: function(frm) {
+		if (frm.doc.pickup_from_type == 'Company') {
+			erpnext.utils.get_address_display(frm, 'pickup_address_name', 'pickup_address', true);
+		} else {
+			erpnext.utils.get_address_display(frm, 'pickup_address_name', 'pickup_address', false);
+		}
+	},
+	get_contact_display: function(frm, contact_name, contact_type) {
+		frappe.call({
+			method: "frappe.contacts.doctype.contact.contact.get_contact_details",
+			args: { contact: contact_name },
+			callback: function(r) {
+				if (r.message) {
+					if (!(r.message.contact_email && (r.message.contact_phone || r.message.contact_mobile))) {
+						if (contact_type == 'Delivery') {
+							frm.set_value('delivery_contact_name', '');
+							frm.set_value('delivery_contact', '');
+						} else {
+							frm.set_value('pickup_contact_name', '');
+							frm.set_value('pickup_contact', '');
+						}
+						frappe.throw(__("Email or Phone/Mobile of the Contact are mandatory to continue.") + "</br>" + __("Please set Email/Phone for the contact") + ` <a href='#Form/Contact/${contact_name}'>${contact_name}</a>`);
+					}
+					let contact_display = r.message.contact_display;
+					if (r.message.contact_email) {
+						contact_display += '<br>' + r.message.contact_email;
+					}
+					if (r.message.contact_phone) {
+						contact_display += '<br>' + r.message.contact_phone;
+					}
+					if (r.message.contact_mobile && !r.message.contact_phone) {
+						contact_display += '<br>' + r.message.contact_mobile;
+					}
+					if (contact_type == 'Delivery') {
+						frm.set_value('delivery_contact', contact_display);
+						if (r.message.contact_email) {
+							frm.set_value('delivery_contact_email', r.message.contact_email);
+						}
+					} else {
+						frm.set_value('pickup_contact', contact_display);
+						if (r.message.contact_email) {
+							frm.set_value('pickup_contact_email', r.message.contact_email);
+						}
+					}
+				}
+			}
+		});
+	},
+	delivery_contact_name: function(frm) {
+		if (frm.doc.delivery_contact_name) {
+			frm.events.get_contact_display(frm, frm.doc.delivery_contact_name, 'Delivery');
+		}
+	},
+	pickup_contact_name: function(frm) {
+		if (frm.doc.pickup_contact_name) {
+			frm.events.get_contact_display(frm, frm.doc.pickup_contact_name, 'Pickup');
+		}
+	},
+	pickup_contact_person: function(frm) {
+		if (frm.doc.pickup_contact_person) {
+			frappe.call({
+				method: "erpnext.stock.doctype.shipment.shipment.get_company_contact",
+				args: { user: frm.doc.pickup_contact_person },
+				callback: function({ message }) {
+					const r = message;
+					let contact_display = `${r.first_name} ${r.last_name}`;
+					if (r.email) {
+						contact_display += `<br>${ r.email }`;
+						frm.set_value('pickup_contact_email', r.email);
+					}
+					if (r.phone) {
+						contact_display += `<br>${ r.phone }`;
+					}
+					if (r.mobile_no && !r.phone) {
+						contact_display += `<br>${ r.mobile_no }`;
+					}
+					frm.set_value('pickup_contact', contact_display);
+				}
+			});
+		} else {
+			if (frm.doc.pickup_from_type === 'Company') {
+				frappe.call({
+					method: "erpnext.stock.doctype.shipment.shipment.get_company_contact",
+					args: { user: frappe.session.user },
+					callback: function({ message }) {
+						const r = message;
+						let contact_display = `${r.first_name} ${r.last_name}`;
+						if (r.email) {
+							contact_display += `<br>${ r.email }`;
+							frm.set_value('pickup_contact_email', r.email);
+						}
+						if (r.phone) {
+							contact_display += `<br>${ r.phone }`;
+						}
+						if (r.mobile_no && !r.phone) {
+							contact_display += `<br>${ r.mobile_no }`;
+						}
+						frm.set_value('pickup_contact', contact_display);
+					}
+				});
+			}
+		}
+	},
+	set_company_contact: function(frm, delivery_type) {
+		frappe.db.get_value('User', { name: frappe.session.user }, ['full_name', 'last_name', 'email', 'phone', 'mobile_no'], (r) => {
+			if (!(r.last_name && r.email && (r.phone || r.mobile_no))) {
+				if (delivery_type == 'Delivery') {
+					frm.set_value('delivery_company', '');
+					frm.set_value('delivery_contact', '');
+				} else {
+					frm.set_value('pickup_company', '');
+					frm.set_value('pickup_contact', '');
+				}
+				frappe.throw(__("Last Name, Email or Phone/Mobile of the user are mandatory to continue.") + "</br>" + __("Please first set Last Name, Email and Phone for the user") + ` <a href="#Form/User/${frappe.session.user}">${frappe.session.user}</a>`);
+			}
+			let contact_display = r.full_name;
+			if (r.email) {
+				contact_display += '<br>' + r.email;
+			}
+			if (r.phone) {
+				contact_display += '<br>' + r.phone;
+			}
+			if (r.mobile_no && !r.phone) {
+				contact_display += '<br>' + r.mobile_no;
+			}
+			if (delivery_type == 'Delivery') {
+				frm.set_value('delivery_contact', contact_display);
+				if (r.email) {
+					frm.set_value('delivery_contact_email', r.email);
+				}
+			} else {
+				frm.set_value('pickup_contact', contact_display);
+				if (r.email) {
+					frm.set_value('pickup_contact_email', r.email);
+				}
+			}
+		});
+		frm.set_value('pickup_contact_person', frappe.session.user);
+	},
+	pickup_company: function(frm) {
+		if (frm.doc.pickup_from_type == 'Company'  && frm.doc.pickup_company) {
+			frm.trigger('set_pickup_company_address');
+			frm.events.set_company_contact(frm, 'Pickup');
+		}
+	},
+	delivery_company: function(frm) {
+		if (frm.doc.delivery_to_type == 'Company' && frm.doc.delivery_company) {
+			frm.trigger('set_delivery_company_address');
+			frm.events.set_company_contact(frm, 'Delivery');
+		}
+	},
+	delivery_customer: function(frm) {
+		frm.trigger('clear_delivery_fields');
+		if (frm.doc.delivery_customer) {
+			frm.events.set_address_name(frm, 'Customer', frm.doc.delivery_customer, 'Delivery');
+			frm.events.set_contact_name(frm, 'Customer', frm.doc.delivery_customer, 'Delivery');
+		}
+	},
+	delivery_supplier: function(frm) {
+		frm.trigger('clear_delivery_fields');
+		if (frm.doc.delivery_supplier) {
+			frm.events.set_address_name(frm, 'Supplier', frm.doc.delivery_supplier, 'Delivery');
+			frm.events.set_contact_name(frm, 'Supplier', frm.doc.delivery_supplier, 'Delivery');
+		}
+	},
+	pickup_customer: function(frm) {
+		if (frm.doc.pickup_customer) {
+			frm.events.set_address_name(frm, 'Customer', frm.doc.pickup_customer, 'Pickup');
+			frm.events.set_contact_name(frm, 'Customer', frm.doc.pickup_customer, 'Pickup');
+		}
+	},
+	pickup_supplier: function(frm) {
+		if (frm.doc.pickup_supplier) {
+			frm.events.set_address_name(frm, 'Supplier', frm.doc.pickup_supplier, 'Pickup');
+			frm.events.set_contact_name(frm, 'Supplier', frm.doc.pickup_supplier, 'Pickup');
+		}
+	},
+	set_address_name: function(frm, ref_doctype, ref_docname, delivery_type) {
+		frappe.call({
+			method: "erpnext.stock.doctype.shipment.shipment.get_address_name",
+			args: {
+				ref_doctype: ref_doctype,
+				docname: ref_docname
+			},
+			callback: function(r) {
+				if (r.message) {
+					if (delivery_type == 'Delivery') {
+						frm.set_value('delivery_address_name', r.message);
+					} else {
+						frm.set_value('pickup_address_name', r.message);
+					}
+				}
+			}
+		});
+	},
+	set_contact_name: function(frm, ref_doctype, ref_docname, delivery_type) {
+		frappe.call({
+			method: "erpnext.stock.doctype.shipment.shipment.get_contact_name",
+			args: {
+				ref_doctype: ref_doctype,
+				docname: ref_docname
+			},
+			callback: function(r) {
+				if (r.message) {
+					if (delivery_type == 'Delivery') {
+						frm.set_value('delivery_contact_name', r.message);
+					} else {
+						frm.set_value('pickup_contact_name', r.message);
+					}
+				}
+			}
+		});
+	},
+	add_template: function(frm) {
+		if (frm.doc.parcel_template) {
+			frappe.model.with_doc("Shipment Parcel Template", frm.doc.parcel_template, () => {
+				let parcel_template = frappe.model.get_doc("Shipment Parcel Template", frm.doc.parcel_template);
+				let row = frappe.model.add_child(frm.doc, "Shipment Parcel", "shipment_parcel");
+				row.length = parcel_template.length;
+				row.width = parcel_template.width;
+				row.height = parcel_template.height;
+				row.weight = parcel_template.weight;
+				frm.refresh_fields("shipment_parcel");
+			});
+		}
+	},
+	pickup_date: function(frm) {
+		if (frm.doc.pickup_date < frappe.datetime.get_today()) {
+			frappe.throw(__("Pickup Date cannot be before this day"));
+		}
+		if (frm.doc.pickup_date == frappe.datetime.get_today()) {
+			var pickup_time = frm.events.get_pickup_time(frm);
+			frm.set_value("pickup_from", pickup_time);
+			frm.trigger('set_pickup_to_time');
+		}
+	},
+	pickup_from: function(frm) {
+		var pickup_time = frm.events.get_pickup_time(frm);
+		if (frm.doc.pickup_from && frm.doc.pickup_date == frappe.datetime.get_today()) {
+			let current_hour = pickup_time.split(':')[0];
+			let current_min = pickup_time.split(':')[1];
+			let pickup_hour = frm.doc.pickup_from.split(':')[0];
+			let pickup_min = frm.doc.pickup_from.split(':')[1];
+			if (pickup_hour < current_hour || (pickup_hour == current_hour && pickup_min < current_min)) {
+				frm.set_value("pickup_from", pickup_time);
+				frappe.throw(__("Pickup Time cannot be in the past"));
+			}
+		}
+		frm.trigger('set_pickup_to_time');
+	},
+	get_pickup_time: function() {
+		let current_hour = new Date().getHours();
+		let current_min = new Date().toLocaleString('en-US', {minute: 'numeric'});
+		if (current_min < 30) {
+			current_min = '30';
+		} else {
+			current_min = '00';
+			current_hour = Number(current_hour)+1;
+		}
+		let pickup_time = current_hour +':'+ current_min;
+		return pickup_time;
+	},
+	set_pickup_to_time: function(frm) {
+		let pickup_to_hour = Number(frm.doc.pickup_from.split(':')[0])+5;
+		let pickup_to_min = frm.doc.pickup_from.split(':')[1];
+		let pickup_to = pickup_to_hour +':'+ pickup_to_min;
+		frm.set_value("pickup_to", pickup_to);
+	},
+	clear_pickup_fields: function(frm) {
+		let fields = ["pickup_address_name", "pickup_contact_name", "pickup_address", "pickup_contact", "pickup_contact_email", "pickup_contact_person"];
+		for (let field of fields) {
+			frm.set_value(field,  '');
+		}
+	},
+	clear_delivery_fields: function(frm) {
+		let fields = ["delivery_address_name", "delivery_contact_name", "delivery_address", "delivery_contact", "delivery_contact_email"];
+		for (let field of fields) {
+			frm.set_value(field,  '');
+		}
+	},
+	remove_email_row: function(frm, table, fieldname) {
+		$.each(frm.doc[table] || [], function(i, detail) {
+			if (detail.email === fieldname) {
+				cur_frm.get_field(table).grid.grid_rows[i].remove();
+			}
+		});
+	}
+});
+
+frappe.ui.form.on('Shipment Delivery Note', {
+	delivery_note: function(frm, cdt, cdn) {
+		let row = locals[cdt][cdn];
+		if (row.delivery_note) {
+			let row_index = row.idx - 1;
+			if (validate_duplicate(frm, 'shipment_delivery_note', row.delivery_note, row_index)) {
+				frappe.throw(__("You have entered a duplicate Delivery Note on Row") + ` ${row.idx}. ` + __("Please rectify and try again."));
+			}
+		}
+	},
+	grand_total: function(frm, cdt, cdn) {
+		let row = locals[cdt][cdn];
+		if (row.grand_total) {
+			var value_of_goods = parseFloat(frm.doc.value_of_goods)+parseFloat(row.grand_total);
+			frm.set_value("value_of_goods", Math.round(value_of_goods));
+			frm.refresh_fields("value_of_goods");
+		}
+	},
+});
+
+var validate_duplicate =  function(frm, table, fieldname, index) {
+	return (
+		table === 'shipment_delivery_note'
+			? frm.doc[table].some((detail, i) => detail.delivery_note === fieldname && !(index === i))
+			: frm.doc[table].some((detail, i) => detail.email === fieldname && !(index === i))
+	);
+};
diff --git a/erpnext/stock/doctype/shipment/shipment.json b/erpnext/stock/doctype/shipment/shipment.json
new file mode 100644
index 0000000..37a9cc6
--- /dev/null
+++ b/erpnext/stock/doctype/shipment/shipment.json
@@ -0,0 +1,471 @@
+{
+ "actions": [],
+ "autoname": "SHIPMENT-.#####",
+ "creation": "2020-07-09 10:58:52.508703",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "heading_pickup_from",
+  "pickup_from_type",
+  "pickup_company",
+  "pickup_customer",
+  "pickup_supplier",
+  "pickup",
+  "pickup_address_name",
+  "pickup_address",
+  "pickup_contact_person",
+  "pickup_contact_name",
+  "pickup_contact_email",
+  "pickup_contact",
+  "column_break_2",
+  "heading_delivery_to",
+  "delivery_to_type",
+  "delivery_company",
+  "delivery_customer",
+  "delivery_supplier",
+  "delivery_to",
+  "delivery_address_name",
+  "delivery_address",
+  "delivery_contact_name",
+  "delivery_contact_email",
+  "delivery_contact",
+  "parcels_section",
+  "shipment_parcel",
+  "parcel_template",
+  "add_template",
+  "column_break_28",
+  "shipment_delivery_note",
+  "shipment_details_section",
+  "pallets",
+  "value_of_goods",
+  "pickup_date",
+  "pickup_from",
+  "pickup_to",
+  "column_break_36",
+  "shipment_type",
+  "pickup_type",
+  "incoterm",
+  "description_of_content",
+  "section_break_40",
+  "shipment_information_section",
+  "service_provider",
+  "shipment_id",
+  "shipment_amount",
+  "status",
+  "tracking_url",
+  "column_break_55",
+  "carrier",
+  "carrier_service",
+  "awb_number",
+  "tracking_status",
+  "tracking_status_info",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "heading_pickup_from",
+   "fieldtype": "Heading",
+   "label": "Pickup from"
+  },
+  {
+   "default": "Company",
+   "fieldname": "pickup_from_type",
+   "fieldtype": "Select",
+   "label": "Pickup from",
+   "options": "Company\nCustomer\nSupplier"
+  },
+  {
+   "depends_on": "eval:doc.pickup_from_type == 'Company'",
+   "fieldname": "pickup_company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company"
+  },
+  {
+   "depends_on": "eval:doc.pickup_from_type == 'Customer'",
+   "fieldname": "pickup_customer",
+   "fieldtype": "Link",
+   "label": "Customer",
+   "options": "Customer"
+  },
+  {
+   "depends_on": "eval:doc.pickup_from_type == 'Supplier'",
+   "fieldname": "pickup_supplier",
+   "fieldtype": "Link",
+   "label": "Supplier",
+   "options": "Supplier"
+  },
+  {
+   "fieldname": "pickup",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "in_list_view": 1,
+   "label": "Pickup From",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.pickup_customer || doc.pickup_supplier || doc.pickup_from_type == \"Company\"",
+   "fieldname": "pickup_address_name",
+   "fieldtype": "Link",
+   "label": "Address",
+   "options": "Address",
+   "reqd": 1
+  },
+  {
+   "fieldname": "pickup_address",
+   "fieldtype": "Small Text",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.pickup_customer || doc.pickup_supplier || doc.pickup_from_type !== \"Company\"",
+   "fieldname": "pickup_contact_name",
+   "fieldtype": "Link",
+   "label": "Contact",
+   "mandatory_depends_on": "eval: doc.pickup_from_type !== 'Company'",
+   "options": "Contact"
+  },
+  {
+   "fieldname": "pickup_contact_email",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Contact Email",
+   "read_only": 1
+  },
+  {
+   "fieldname": "pickup_contact",
+   "fieldtype": "Small Text",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "heading_delivery_to",
+   "fieldtype": "Heading",
+   "label": "Delivery to"
+  },
+  {
+   "default": "Customer",
+   "fieldname": "delivery_to_type",
+   "fieldtype": "Select",
+   "label": "Delivery to",
+   "options": "Company\nCustomer\nSupplier"
+  },
+  {
+   "depends_on": "eval:doc.delivery_to_type == 'Company'",
+   "fieldname": "delivery_company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company"
+  },
+  {
+   "depends_on": "eval:doc.delivery_to_type == 'Customer'",
+   "fieldname": "delivery_customer",
+   "fieldtype": "Link",
+   "label": "Customer",
+   "options": "Customer"
+  },
+  {
+   "depends_on": "eval:doc.delivery_to_type == 'Supplier'",
+   "fieldname": "delivery_supplier",
+   "fieldtype": "Link",
+   "label": "Supplier",
+   "options": "Supplier"
+  },
+  {
+   "fieldname": "delivery_to",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "in_list_view": 1,
+   "label": "Delivery To",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.delivery_customer || doc.delivery_supplier || doc.delivery_to_type == \"Company\"",
+   "fieldname": "delivery_address_name",
+   "fieldtype": "Link",
+   "label": "Address",
+   "options": "Address",
+   "reqd": 1
+  },
+  {
+   "fieldname": "delivery_address",
+   "fieldtype": "Small Text",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.delivery_customer || doc.delivery_supplier || doc.delivery_to_type == \"Company\"",
+   "fieldname": "delivery_contact_name",
+   "fieldtype": "Link",
+   "label": "Contact",
+   "mandatory_depends_on": "eval: doc.delivery_from_type !== 'Company'",
+   "options": "Contact"
+  },
+  {
+   "fieldname": "delivery_contact_email",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Contact Email",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.delivery_contact_name",
+   "fieldname": "delivery_contact",
+   "fieldtype": "Small Text",
+   "read_only": 1
+  },
+  {
+   "fieldname": "parcels_section",
+   "fieldtype": "Section Break",
+   "label": "Parcels"
+  },
+  {
+   "fieldname": "shipment_parcel",
+   "fieldtype": "Table",
+   "label": "Shipment Parcel",
+   "options": "Shipment Parcel"
+  },
+  {
+   "fieldname": "parcel_template",
+   "fieldtype": "Link",
+   "label": "Parcel Template",
+   "options": "Shipment Parcel Template"
+  },
+  {
+   "depends_on": "eval:doc.docstatus !== 1\n",
+   "fieldname": "add_template",
+   "fieldtype": "Button",
+   "label": "Add Template"
+  },
+  {
+   "fieldname": "column_break_28",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "shipment_details_section",
+   "fieldtype": "Section Break",
+   "label": "Shipment details"
+  },
+  {
+   "default": "No",
+   "fieldname": "pallets",
+   "fieldtype": "Select",
+   "label": "Pallets",
+   "options": "No\nYes"
+  },
+  {
+   "fieldname": "value_of_goods",
+   "fieldtype": "Currency",
+   "label": "Value of Goods",
+   "precision": "2",
+   "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "pickup_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Pickup Date",
+   "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "09:00",
+   "fieldname": "pickup_from",
+   "fieldtype": "Time",
+   "label": "Pickup from"
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "17:00",
+   "fieldname": "pickup_to",
+   "fieldtype": "Time",
+   "label": "Pickup to"
+  },
+  {
+   "fieldname": "column_break_36",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "Goods",
+   "fieldname": "shipment_type",
+   "fieldtype": "Select",
+   "label": "Shipment Type",
+   "options": "Goods\nDocuments"
+  },
+  {
+   "default": "Pickup",
+   "fieldname": "pickup_type",
+   "fieldtype": "Select",
+   "label": "Pickup Type",
+   "options": "Pickup\nSelf delivery"
+  },
+  {
+   "fieldname": "description_of_content",
+   "fieldtype": "Small Text",
+   "label": "Description of Content",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_40",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "shipment_information_section",
+   "fieldtype": "Section Break",
+   "label": "Shipment Information"
+  },
+  {
+   "fieldname": "service_provider",
+   "fieldtype": "Data",
+   "label": "Service Provider",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "shipment_id",
+   "fieldtype": "Data",
+   "label": "Shipment ID",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "shipment_amount",
+   "fieldtype": "Currency",
+   "label": "Shipment Amount",
+   "no_copy": 1,
+   "precision": "2",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "label": "Status",
+   "no_copy": 1,
+   "options": "Draft\nSubmitted\nBooked\nCancelled\nCompleted",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "tracking_url",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Tracking URL",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "carrier",
+   "fieldtype": "Data",
+   "label": "Carrier",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "carrier_service",
+   "fieldtype": "Data",
+   "label": "Carrier Service",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "awb_number",
+   "fieldtype": "Data",
+   "label": "AWB Number",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "tracking_status",
+   "fieldtype": "Select",
+   "label": "Tracking Status",
+   "no_copy": 1,
+   "options": "\nIn Progress\nDelivered\nReturned\nLost",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "tracking_status_info",
+   "fieldtype": "Data",
+   "label": "Tracking Status Info",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Shipment",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_55",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "incoterm",
+   "fieldtype": "Select",
+   "label": "Incoterm",
+   "options": "EXW (Ex Works)\nFCA (Free Carrier)\nCPT (Carriage Paid To)\nCIP (Carriage and Insurance Paid to)\nDPU (Delivered At Place Unloaded)\nDAP (Delivered At Place)\nDDP (Delivered Duty Paid)"
+  },
+  {
+   "fieldname": "shipment_delivery_note",
+   "fieldtype": "Table",
+   "label": "Shipment Delivery Note",
+   "options": "Shipment Delivery Note"
+  },
+  {
+   "depends_on": "eval:doc.pickup_from_type === 'Company'",
+   "fieldname": "pickup_contact_person",
+   "fieldtype": "Link",
+   "label": "Pickup Contact Person",
+   "mandatory_depends_on": "eval:doc.pickup_from_type === 'Company'",
+   "options": "User"
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-12-02 15:43:44.607039",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Shipment",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Stock Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/shipment/shipment.py b/erpnext/stock/doctype/shipment/shipment.py
new file mode 100644
index 0000000..de0c243
--- /dev/null
+++ b/erpnext/stock/doctype/shipment/shipment.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import flt
+from frappe.model.document import Document
+from erpnext.accounts.party import get_party_shipping_address
+from frappe.contacts.doctype.contact.contact import get_default_contact
+
+class Shipment(Document):
+	def validate(self):
+		self.validate_weight()
+		self.set_value_of_goods()
+		if self.docstatus == 0:
+			self.status = 'Draft'
+
+	def on_submit(self):
+		if not self.shipment_parcel:
+			frappe.throw(_('Please enter Shipment Parcel information'))
+		if self.value_of_goods == 0:
+			frappe.throw(_('Value of goods cannot be 0'))
+		self.status = 'Submitted'
+
+	def on_cancel(self):
+		self.status = 'Cancelled'
+
+	def validate_weight(self):
+		for parcel in self.shipment_parcel:
+			if flt(parcel.weight) <= 0:
+				frappe.throw(_('Parcel weight cannot be 0'))
+
+	def set_value_of_goods(self):
+		value_of_goods = 0
+		for entry in self.get("shipment_delivery_note"):
+			value_of_goods += flt(entry.get("grand_total"))
+		self.value_of_goods = value_of_goods if value_of_goods else self.value_of_goods
+
+@frappe.whitelist()
+def get_address_name(ref_doctype, docname):
+	# Return address name
+	return get_party_shipping_address(ref_doctype, docname)
+
+@frappe.whitelist()
+def get_contact_name(ref_doctype, docname):
+	# Return address name
+	return get_default_contact(ref_doctype, docname)
+
+@frappe.whitelist()
+def get_company_contact(user):
+	contact = frappe.db.get_value('User', user, [
+		'first_name',
+		'last_name',
+		'email',
+		'phone',
+		'mobile_no',
+		'gender',
+	], as_dict=1)
+	if not contact.phone:
+		contact.phone = contact.mobile_no
+	return contact
diff --git a/erpnext/stock/doctype/shipment/shipment_list.js b/erpnext/stock/doctype/shipment/shipment_list.js
new file mode 100644
index 0000000..52b052c
--- /dev/null
+++ b/erpnext/stock/doctype/shipment/shipment_list.js
@@ -0,0 +1,8 @@
+frappe.listview_settings['Shipment'] = {
+	add_fields: ["status"],
+	get_indicator: function(doc) {
+		if (doc.status=='Booked') {
+			return [__("Booked"), "green"];
+		}
+	}
+};
\ No newline at end of file
diff --git a/erpnext/stock/doctype/shipment/test_shipment.py b/erpnext/stock/doctype/shipment/test_shipment.py
new file mode 100644
index 0000000..e1fa207
--- /dev/null
+++ b/erpnext/stock/doctype/shipment/test_shipment.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+from datetime import date, timedelta
+
+import frappe
+import unittest
+from erpnext.stock.doctype.delivery_note.delivery_note import make_shipment
+
+class TestShipment(unittest.TestCase):
+	def test_shipment_from_delivery_note(self):
+		delivery_note = create_test_delivery_note()
+		delivery_note.submit()
+		shipment = create_test_shipment([ delivery_note ])
+		shipment.submit()
+		second_shipment = make_shipment(delivery_note.name)
+		self.assertEqual(second_shipment.value_of_goods, delivery_note.grand_total)
+		self.assertEqual(len(second_shipment.shipment_delivery_note), 1)
+		self.assertEqual(second_shipment.shipment_delivery_note[0].delivery_note, delivery_note.name)
+
+def create_test_delivery_note():
+	company = get_shipment_company()
+	customer = get_shipment_customer()
+	item = get_shipment_item(company.name)
+	posting_date = date.today() + timedelta(days=1)
+	
+	create_material_receipt(item, company.name)
+	delivery_note = frappe.new_doc("Delivery Note")
+	delivery_note.company = company.name
+	delivery_note.posting_date = posting_date.strftime("%Y-%m-%d")
+	delivery_note.posting_time = '10:00'
+	delivery_note.customer = customer.name
+	delivery_note.append('items',
+		{
+			"item_code": item.name,
+			"item_name": item.item_name,
+			"description": 'Test delivery note for shipment',
+			"qty": 5,
+			"uom": 'Nos',
+			"warehouse": 'Stores - SC',
+			"rate": item.standard_rate,
+			"cost_center": 'Main - SC'
+		}
+	)
+	delivery_note.insert()
+	frappe.db.commit()
+	return delivery_note
+
+
+def create_test_shipment(delivery_notes = None):
+	company = get_shipment_company()
+	company_address = get_shipment_company_address(company.name)
+	customer = get_shipment_customer()
+	customer_address = get_shipment_customer_address(customer.name)
+	customer_contact = get_shipment_customer_contact(customer.name)
+	posting_date = date.today() + timedelta(days=5)
+
+	shipment = frappe.new_doc("Shipment")
+	shipment.pickup_from_type = 'Company'
+	shipment.pickup_company = company.name
+	shipment.pickup_address_name = company_address.name
+	shipment.delivery_to_type = 'Customer'
+	shipment.delivery_customer = customer.name
+	shipment.delivery_address_name = customer_address.name
+	shipment.delivery_contact_name = customer_contact.name
+	shipment.pallets = 'No'
+	shipment.shipment_type = 'Goods'
+	shipment.value_of_goods = 1000
+	shipment.pickup_type = 'Pickup'
+	shipment.pickup_date = posting_date.strftime("%Y-%m-%d")
+	shipment.pickup_from = '09:00'
+	shipment.pickup_to = '17:00'
+	shipment.description_of_content = 'unit test entry'
+	for delivery_note in delivery_notes:
+		shipment.append('shipment_delivery_note', 
+			{
+				"delivery_note": delivery_note.name
+			}
+		)
+	shipment.append('shipment_parcel',
+		{
+			"length": 5,
+			"width": 5,
+			"height": 5,
+			"weight": 5,
+			"count": 5
+		}
+	)
+	shipment.insert()
+	frappe.db.commit()
+	return shipment
+
+
+def get_shipment_customer_contact(customer_name):
+	contact_fname = 'Customer Shipment'
+	contact_lname = 'Testing'
+	customer_name = contact_fname + ' ' + contact_lname
+	contacts = frappe.get_all("Contact", fields=["name"], filters = {"name": customer_name})
+	if len(contacts):
+		return contacts[0]
+	else:
+		return create_customer_contact(contact_fname, contact_lname)
+
+
+def get_shipment_customer_address(customer_name):
+	address_title = customer_name + ' address 123'
+	customer_address = frappe.get_all("Address", fields=["name"], filters = {"address_title": address_title})
+	if len(customer_address):
+		return customer_address[0]
+	else:
+		return create_shipment_address(address_title, customer_name, 81929)
+
+def get_shipment_customer():
+	customer_name = 'Shipment Customer'
+	customer = frappe.get_all("Customer", fields=["name"], filters = {"name": customer_name})
+	if len(customer):
+		return customer[0]
+	else:
+		return create_shipment_customer(customer_name)
+
+def get_shipment_company_address(company_name):
+	address_title = company_name + ' address 123'
+	addresses = frappe.get_all("Address", fields=["name"], filters = {"address_title": address_title})
+	if len(addresses):
+		return addresses[0]
+	else:
+		return create_shipment_address(address_title, company_name, 80331)
+
+def get_shipment_company():
+	company_name = 'Shipment Company'
+	abbr = 'SC'
+	companies = frappe.get_all("Company", fields=["name"], filters = {"company_name": company_name})
+	if len(companies):
+		return companies[0]
+	else:
+		return create_shipment_company(company_name, abbr)
+
+def get_shipment_item(company_name):
+	item_name = 'Testing Shipment item'
+	items = frappe.get_all("Item",
+		fields=["name", "item_name", "item_code", "standard_rate"],
+		filters = {"item_name": item_name}
+	)
+	if len(items):
+		return items[0]
+	else:
+		return create_shipment_item(item_name, company_name)
+
+def create_shipment_address(address_title, company_name, postal_code):
+	address = frappe.new_doc("Address")
+	address.address_title = address_title
+	address.address_type = 'Shipping'
+	address.address_line1 = company_name + ' address line 1'
+	address.city = 'Random City'
+	address.postal_code = postal_code
+	address.country = 'Germany'
+	address.insert()
+	return address
+
+
+def create_customer_contact(fname, lname):
+	customer = frappe.new_doc("Contact")
+	customer.customer_name = fname + ' ' + lname
+	customer.first_name = fname
+	customer.last_name = lname
+	customer.is_primary_contact = 1
+	customer.is_billing_contact = 1
+	customer.append('email_ids',
+		{
+			'email_id': 'randomme@email.com',
+			'is_primary': 1
+		}
+	)
+	customer.append('phone_nos',
+		{
+			'phone': '123123123',
+			'is_primary_phone': 1,
+			'is_primary_mobile_no': 1
+		}
+	)
+	customer.status = 'Passive'
+	customer.insert()
+	return customer
+
+
+def create_shipment_company(company_name, abbr):
+	company = frappe.new_doc("Company")
+	company.company_name = company_name
+	company.abbr = abbr
+	company.default_currency = 'EUR'
+	company.country = 'Germany'
+	company.insert()
+	return company
+
+def create_shipment_customer(customer_name):
+	customer = frappe.new_doc("Customer")
+	customer.customer_name = customer_name
+	customer.customer_type = 'Company'
+	customer.customer_group = 'All Customer Groups'
+	customer.territory = 'All Territories'
+	customer.gst_category = 'Unregistered'
+	customer.insert()
+	return customer
+
+def create_material_receipt(item, company):
+	posting_date = date.today()
+	stock = frappe.new_doc("Stock Entry")
+	stock.company = company
+	stock.stock_entry_type = 'Material Receipt'
+	stock.posting_date = posting_date.strftime("%Y-%m-%d")
+	stock.append('items',
+		{
+			"t_warehouse": 'Stores - SC',
+			"item_code": item.name,
+			"qty": 5,
+			"uom": 'Nos',
+			"basic_rate": item.standard_rate,
+			"cost_center": 'Main - SC'
+		}
+	)
+	stock.insert()
+	stock.submit()
+	
+
+def create_shipment_item(item_name, company_name):
+	item = frappe.new_doc("Item")
+	item.item_name = item_name
+	item.item_code = item_name
+	item.item_group = 'All Item Groups'
+	item.stock_uom = 'Nos'
+	item.standard_rate = 50
+	item.append('item_defaults',
+		{
+			"company": company_name,
+			"default_warehouse": 'Stores - SC'
+		}
+	)
+	item.insert()
+	return item
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/stock/doctype/shipment_delivery_note/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/stock/doctype/shipment_delivery_note/__init__.py
diff --git a/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.json b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.json
new file mode 100644
index 0000000..8625913
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.json
@@ -0,0 +1,40 @@
+{
+ "actions": [],
+ "creation": "2020-07-09 11:52:57.939021",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "delivery_note",
+  "grand_total"
+ ],
+ "fields": [
+  {
+   "fieldname": "delivery_note",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Delivery Note",
+   "options": "Delivery Note",
+   "reqd": 1
+  },
+  {
+   "fieldname": "grand_total",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Value",
+   "read_only": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-12-02 15:44:34.028703",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Shipment Delivery Note",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py
new file mode 100644
index 0000000..4342151
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ShipmentDeliveryNote(Document):
+	pass
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/stock/doctype/shipment_parcel/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/stock/doctype/shipment_parcel/__init__.py
diff --git a/erpnext/stock/doctype/shipment_parcel/shipment_parcel.json b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.json
new file mode 100644
index 0000000..6943edc
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.json
@@ -0,0 +1,65 @@
+{
+ "actions": [],
+ "creation": "2020-07-09 11:28:48.887737",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "length",
+  "width",
+  "height",
+  "weight",
+  "count"
+ ],
+ "fields": [
+  {
+   "fieldname": "length",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Length (cm)",
+   "reqd": 1
+  },
+  {
+   "fieldname": "width",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Width (cm)",
+   "reqd": 1
+  },
+  {
+   "fieldname": "height",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Height (cm)",
+   "reqd": 1
+  },
+  {
+   "fieldname": "weight",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Weight (kg)",
+   "precision": "1",
+   "reqd": 1
+  },
+  {
+   "default": "1",
+   "fieldname": "count",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Count",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-09 12:54:14.847170",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Shipment Parcel",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py
new file mode 100644
index 0000000..53e6ed5
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ShipmentParcel(Document):
+	pass
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/stock/doctype/shipment_parcel_template/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/stock/doctype/shipment_parcel_template/__init__.py
diff --git a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.js b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.js
new file mode 100644
index 0000000..785a3b3
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Shipment Parcel Template', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.json b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.json
new file mode 100644
index 0000000..4735d9f
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.json
@@ -0,0 +1,78 @@
+{
+ "actions": [],
+ "autoname": "field:parcel_template_name",
+ "creation": "2020-07-09 11:43:43.470339",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "parcel_template_name",
+  "length",
+  "width",
+  "height",
+  "weight"
+ ],
+ "fields": [
+  {
+   "fieldname": "length",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Length (cm)",
+   "reqd": 1
+  },
+  {
+   "fieldname": "width",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Width (cm)",
+   "reqd": 1
+  },
+  {
+   "fieldname": "height",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Height (cm)",
+   "reqd": 1
+  },
+  {
+   "fieldname": "weight",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Weight (kg)",
+   "precision": "1",
+   "reqd": 1
+  },
+  {
+   "fieldname": "parcel_template_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Parcel Template Name",
+   "reqd": 1,
+   "unique": 1
+  }
+ ],
+ "links": [],
+ "modified": "2020-09-28 12:51:00.320421",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Shipment Parcel Template",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py
new file mode 100644
index 0000000..2a8d58d
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ShipmentParcelTemplate(Document):
+	pass
diff --git a/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py b/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py
new file mode 100644
index 0000000..6e2caa7
--- /dev/null
+++ b/erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestShipmentParcelTemplate(unittest.TestCase):
+	pass
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index 4c7828b..3b9608b 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -55,7 +55,7 @@
 			""")
 
 			if sle:
-				frappe.throw(_("Can't change valuation method, as there are transactions against some items which does not have it's own valuation method"))
+				frappe.throw(_("Can't change the valuation method, as there are transactions against some items which do not have its own valuation method"))
 
 	def validate_clean_description_html(self):
 		if int(self.clean_description_html or 0) \
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 1339d9b..ccd0100 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -164,7 +164,7 @@
 		select
 			sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate,
 			sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference,
-			sle.item_code as name, sle.voucher_no
+			sle.item_code as name, sle.voucher_no, sle.stock_value
 		from
 			`tabStock Ledger Entry` sle force index (posting_sort_index)
 		where sle.docstatus < 2 %s %s
@@ -197,7 +197,7 @@
 		else:
 			qty_diff = flt(d.actual_qty)
 
-		value_diff = flt(d.stock_value_difference)
+		value_diff = flt(d.stock_value) - flt(qty_dict.bal_val)
 
 		if d.posting_date < from_date:
 			qty_dict.opening_qty += qty_diff
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index fe01d4b..086755b 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -1,6 +1,13 @@
 frappe.ui.form.on("Issue", {
 	onload: function(frm) {
 		frm.email_field = "raised_by";
+		frm.set_query("customer", function () {
+			return {
+				filters: {
+					"disabled": 0
+				}
+			};
+		});
 
 		frappe.db.get_value("Support Settings", {name: "Support Settings"},
 			["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
@@ -21,14 +28,14 @@
 				},
 				callback: function (r) {
 					if (r && r.message) {
-						frm.set_query('priority', function() {
+						frm.set_query("priority", function() {
 							return {
 								filters: {
 									"name": ["in", r.message.priority],
 								}
 							};
 						});
-						frm.set_query('service_level_agreement', function() {
+						frm.set_query("service_level_agreement", function() {
 							return {
 								filters: {
 									"name": ["in", r.message.service_level_agreements],
@@ -45,9 +52,9 @@
 		if (frm.doc.status !== "Closed" && frm.doc.agreement_status === "Ongoing") {
 			if (frm.doc.service_level_agreement) {
 				frappe.call({
-					'method': 'frappe.client.get',
+					"method": "frappe.client.get",
 					args: {
-						doctype: 'Service Level Agreement',
+						doctype: "Service Level Agreement",
 						name: frm.doc.service_level_agreement
 					},
 					callback: function(data) {
@@ -127,8 +134,8 @@
 				reset_sla.clear();
 
 				frappe.show_alert({
-					indicator: 'green',
-					message: __('Resetting Service Level Agreement.')
+					indicator: "green",
+					message: __("Resetting Service Level Agreement.")
 				});
 
 				frm.call("reset_service_level_agreement", {
@@ -145,35 +152,36 @@
 		reset_sla.show();
 	},
 
+
 	timeline_refresh: function(frm) {
 		// create button for "Help Article"
-		if(frappe.model.can_create('Help Article')) {
+		if (frappe.model.can_create("Help Article")) {
 			// Removing Help Article button if exists to avoid multiple occurance
 			frm.timeline.wrapper.find('.comment-header .asset-details .btn-add-to-kb').remove();
 			$('<button class="btn btn-xs btn-link btn-add-to-kb text-muted hidden-xs pull-right">'+
 				__('Help Article') + '</button>')
 				.appendTo(frm.timeline.wrapper.find('.comment-header .asset-details:not([data-communication-type="Comment"])'))
-				.on('click', function() {
-					var content = $(this).parents('.timeline-item:first').find('.timeline-item-content').html();
-					var doc = frappe.model.get_new_doc('Help Article');
+				.on("click", function() {
+					var content = $(this).parents(".timeline-item:first").find(".timeline-item-content").html();
+					var doc = frappe.model.get_new_doc("Help Article");
 					doc.title = frm.doc.subject;
 					doc.content = content;
-					frappe.set_route('Form', 'Help Article', doc.name);
+					frappe.set_route("Form", "Help Article", doc.name);
 				});
 		}
 
-		if (!frm.timeline.wrapper.find('.btn-split-issue').length) {
+		if (!frm.timeline.wrapper.find(".btn-split-issue").length) {
 			let split_issue = __("Split Issue")
 			$(`<button class="btn btn-xs btn-link btn-add-to-kb text-muted hidden-xs btn-split-issue pull-right" style="display:inline-block; margin-right: 15px">
 				${split_issue}
 			</button>`)
 				.appendTo(frm.timeline.wrapper.find('.comment-header .asset-details:not([data-communication-type="Comment"])'))
 			if (!frm.timeline.wrapper.data("split-issue-event-attached")){
-				frm.timeline.wrapper.on('click', '.btn-split-issue', (e) => {
+				frm.timeline.wrapper.on("click", ".btn-split-issue", (e) => {
 					var dialog = new frappe.ui.Dialog({
 						title: __("Split Issue"),
 						fields: [
-							{fieldname: 'subject', fieldtype: 'Data', reqd:1, label: __('Subject'), description: __('All communications including and above this shall be moved into the new Issue')}
+							{fieldname: "subject", fieldtype: "Data", reqd: 1, label: __("Subject"), description: __("All communications including and above this shall be moved into the new Issue")}
 						],
 						primary_action_label: __("Split"),
 						primary_action: function() {
@@ -226,7 +234,7 @@
 function get_time_left(timestamp, agreement_status) {
 	const diff = moment(timestamp).diff(moment());
 	const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : "Failed";
-	let indicator = (diff_display == 'Failed' && agreement_status != "Fulfilled") ? "red" : "green";
+	let indicator = (diff_display == "Failed" && agreement_status != "Fulfilled") ? "red" : "green";
 	return {"diff_display": diff_display, "indicator": indicator};
 }
 
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/telephony/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/telephony/__init__.py
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/telephony/doctype/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/telephony/doctype/__init__.py
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/telephony/doctype/call_log/__init__.py
similarity index 100%
rename from erpnext/communication/doctype/call_log/__init__.py
rename to erpnext/telephony/doctype/call_log/__init__.py
diff --git a/erpnext/telephony/doctype/call_log/call_log.js b/erpnext/telephony/doctype/call_log/call_log.js
new file mode 100644
index 0000000..977f86d
--- /dev/null
+++ b/erpnext/telephony/doctype/call_log/call_log.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Call Log', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/communication/doctype/call_log/call_log.json b/erpnext/telephony/doctype/call_log/call_log.json
similarity index 96%
rename from erpnext/communication/doctype/call_log/call_log.json
rename to erpnext/telephony/doctype/call_log/call_log.json
index 31e79f1..55ad2ba 100644
--- a/erpnext/communication/doctype/call_log/call_log.json
+++ b/erpnext/telephony/doctype/call_log/call_log.json
@@ -137,12 +137,11 @@
    "read_only": 1
   }
  ],
- "in_create": 1,
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-08-25 17:08:34.085731",
+ "modified": "2020-11-25 14:32:44.407815",
  "modified_by": "Administrator",
- "module": "Communication",
+ "module": "Telephony",
  "name": "Call Log",
  "owner": "Administrator",
  "permissions": [
diff --git a/erpnext/communication/doctype/call_log/call_log.py b/erpnext/telephony/doctype/call_log/call_log.py
similarity index 100%
rename from erpnext/communication/doctype/call_log/call_log.py
rename to erpnext/telephony/doctype/call_log/call_log.py
diff --git a/erpnext/telephony/doctype/call_log/test_call_log.py b/erpnext/telephony/doctype/call_log/test_call_log.py
new file mode 100644
index 0000000..faa6304
--- /dev/null
+++ b/erpnext/telephony/doctype/call_log/test_call_log.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestCallLog(unittest.TestCase):
+	pass
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/telephony/doctype/incoming_call_handling_schedule/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/telephony/doctype/incoming_call_handling_schedule/__init__.py
diff --git a/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.json b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.json
new file mode 100644
index 0000000..6d46b4e
--- /dev/null
+++ b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.json
@@ -0,0 +1,60 @@
+{
+ "actions": [],
+ "creation": "2020-11-19 11:15:54.967710",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "day_of_week",
+  "from_time",
+  "to_time",
+  "agent_group"
+ ],
+ "fields": [
+  {
+   "fieldname": "day_of_week",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Day Of Week",
+   "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday",
+   "reqd": 1
+  },
+  {
+   "default": "9:00:00",
+   "fieldname": "from_time",
+   "fieldtype": "Time",
+   "in_list_view": 1,
+   "label": "From Time",
+   "reqd": 1
+  },
+  {
+   "default": "17:00:00",
+   "fieldname": "to_time",
+   "fieldtype": "Time",
+   "in_list_view": 1,
+   "label": "To Time",
+   "reqd": 1
+  },
+  {
+   "fieldname": "agent_group",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Agent Group",
+   "options": "Employee Group",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-11-19 11:15:54.967710",
+ "modified_by": "Administrator",
+ "module": "Telephony",
+ "name": "Incoming Call Handling Schedule",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py
new file mode 100644
index 0000000..fcf2974
--- /dev/null
+++ b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class IncomingCallHandlingSchedule(Document):
+	pass
diff --git a/erpnext/communication/doctype/call_log/__init__.py b/erpnext/telephony/doctype/incoming_call_settings/__init__.py
similarity index 100%
copy from erpnext/communication/doctype/call_log/__init__.py
copy to erpnext/telephony/doctype/incoming_call_settings/__init__.py
diff --git a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.js b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.js
new file mode 100644
index 0000000..1bcc846
--- /dev/null
+++ b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.js
@@ -0,0 +1,102 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+function time_to_seconds(time_str) {
+	// Convert time string of format HH:MM:SS into seconds.
+	let seq = time_str.split(':');
+	seq = seq.map((n) => parseInt(n));
+	return (seq[0]*60*60) + (seq[1]*60) + seq[2];
+}
+
+function number_sort(array, ascending=true) {
+	let array_copy = [...array];
+	if (ascending) {
+		array_copy.sort((a, b) => a-b); // ascending order
+	} else {
+		array_copy.sort((a, b) => b-a); // descending order
+	}
+	return array_copy;
+}
+
+function groupby(items, key) {
+	// Group the list of items using the given key.
+	const obj = {};
+	items.forEach((item) => {
+		if (item[key] in obj) {
+			obj[item[key]].push(item);
+		} else {
+			obj[item[key]] = [item];
+		}
+	});
+	return obj;
+}
+
+function check_timeslot_overlap(ts1, ts2) {
+	/// Timeslot is a an array of length 2 ex: [from_time, to_time]
+	/// time in timeslot is an integer represents number of seconds.
+	if ((ts1[0] < ts2[0] && ts1[1] <= ts2[0]) || (ts1[0] >= ts2[1] && ts1[1] > ts2[1])) {
+		return false;
+	}
+	return true;
+}
+
+function validate_call_schedule(schedule) {
+	validate_call_schedule_timeslot(schedule);
+	validate_call_schedule_overlaps(schedule);
+}
+
+function validate_call_schedule_timeslot(schedule) {
+	// Make sure that to time slot is ahead of from time slot.
+	let errors = [];
+
+	for (let row in schedule) {
+		let record = schedule[row];
+		let from_time_in_secs = time_to_seconds(record.from_time);
+		let to_time_in_secs = time_to_seconds(record.to_time);
+		if (from_time_in_secs >= to_time_in_secs) {
+			errors.push(__('Call Schedule Row {0}: To time slot should always be ahead of From time slot.', [row]));
+		}
+	}
+
+	if (errors.length > 0) {
+		frappe.throw(errors.join("<br/>"));
+	}
+}
+
+function is_call_schedule_overlapped(day_schedule) {
+	// Check if any time slots are overlapped in a day schedule.
+	let timeslots = [];
+	day_schedule.forEach((record)=> {
+		timeslots.push([time_to_seconds(record.from_time), time_to_seconds(record.to_time)]);
+	});
+
+	if (timeslots.length < 2) {
+		return false;
+	}
+
+	timeslots = number_sort(timeslots);
+
+	// Sorted timeslots will be in ascending order if not overlapped.
+	for (let i=1; i < timeslots.length; i++) {
+		if (check_timeslot_overlap(timeslots[i-1], timeslots[i])) {
+			return true;
+		}
+	}
+	return false;
+}
+
+function validate_call_schedule_overlaps(schedule) {
+	let group_by_day = groupby(schedule, 'day_of_week');
+	for (const [day, day_schedule] of Object.entries(group_by_day)) {
+		if (is_call_schedule_overlapped(day_schedule)) {
+			frappe.throw(__('Please fix overlapping time slots for {0}', [day]));
+		}
+	}
+}
+
+frappe.ui.form.on('Incoming Call Settings', {
+	validate(frm) {
+		validate_call_schedule(frm.doc.call_handling_schedule);
+	}
+});
+
diff --git a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.json b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.json
new file mode 100644
index 0000000..3ffb3e4
--- /dev/null
+++ b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.json
@@ -0,0 +1,82 @@
+{
+ "actions": [],
+ "autoname": "Prompt",
+ "creation": "2020-11-19 10:37:20.734245",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "call_routing",
+  "column_break_2",
+  "greeting_message",
+  "agent_busy_message",
+  "agent_unavailable_message",
+  "section_break_6",
+  "call_handling_schedule"
+ ],
+ "fields": [
+  {
+   "default": "Sequential",
+   "fieldname": "call_routing",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Call Routing",
+   "options": "Sequential\nSimultaneous"
+  },
+  {
+   "fieldname": "greeting_message",
+   "fieldtype": "Data",
+   "label": "Greeting Message"
+  },
+  {
+   "fieldname": "agent_busy_message",
+   "fieldtype": "Data",
+   "label": "Agent Busy Message"
+  },
+  {
+   "fieldname": "agent_unavailable_message",
+   "fieldtype": "Data",
+   "label": "Agent Unavailable Message"
+  },
+  {
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "call_handling_schedule",
+   "fieldtype": "Table",
+   "label": "Call Handling Schedule",
+   "options": "Incoming Call Handling Schedule",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-11-19 11:17:14.527862",
+ "modified_by": "Administrator",
+ "module": "Telephony",
+ "name": "Incoming Call Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py
new file mode 100644
index 0000000..2b2008a
--- /dev/null
+++ b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from datetime import datetime
+from typing import Tuple
+from frappe import _
+
+class IncomingCallSettings(Document):
+	def validate(self):
+		"""List of validations
+		* Make sure that to time slot is ahead of from time slot in call schedule
+		* Make sure that no overlapping timeslots for a given day
+		"""
+		self.validate_call_schedule_timeslot(self.call_handling_schedule)
+		self.validate_call_schedule_overlaps(self.call_handling_schedule)
+
+	def validate_call_schedule_timeslot(self, schedule: list):
+		"""	Make sure that to time slot is ahead of from time slot.
+		"""
+		errors = []
+		for record in schedule:
+			from_time = self.time_to_seconds(record.from_time)
+			to_time = self.time_to_seconds(record.to_time)
+			if from_time >= to_time:
+				errors.append(
+					_('Call Schedule Row {0}: To time slot should always be ahead of From time slot.').format(record.idx)
+				)
+
+		if errors:
+			frappe.throw('<br/>'.join(errors))
+
+	def validate_call_schedule_overlaps(self, schedule: list):
+		"""Check if any time slots are overlapped in a day schedule.
+		"""
+		week_days = set([each.day_of_week for each in schedule])
+
+		for day in week_days:
+			timeslots = [(record.from_time, record.to_time) for record in schedule if record.day_of_week==day]
+
+			# convert time in timeslot into an integer represents number of seconds
+			timeslots = sorted(map(lambda seq: tuple(map(self.time_to_seconds, seq)), timeslots))
+			if len(timeslots) < 2: continue
+
+			for i in range(1, len(timeslots)):
+				if self.check_timeslots_overlap(timeslots[i-1], timeslots[i]):
+					frappe.throw(_('Please fix overlapping time slots for {0}.').format(day))
+
+	@staticmethod
+	def check_timeslots_overlap(ts1: Tuple[int, int], ts2: Tuple[int, int]) -> bool:
+		if (ts1[0] < ts2[0] and ts1[1] <= ts2[0]) or (ts1[0] >= ts2[1] and ts1[1] > ts2[1]):
+			return False
+		return True
+
+	@staticmethod
+	def time_to_seconds(time: str) -> int:
+		"""Convert time string of format HH:MM:SS into seconds
+		"""
+		date_time = datetime.strptime(time, "%H:%M:%S")
+		return date_time - datetime(1900, 1, 1)
diff --git a/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py b/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py
new file mode 100644
index 0000000..c058c11
--- /dev/null
+++ b/erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestIncomingCallSettings(unittest.TestCase):
+	pass